代币做什么?为什么需要在C++编程中创建代币
What does Tokens do and why they need to be created in C++ programming?
我正在读一本书(Bjarne Stroustrup的《编程原理与实践》)。
他在其中介绍了代币:
"标记是一系列字符,代表我们认为是一个单位的东西,比如数字或运算符。这就是C++编译器处理其源代码的方式。实际上,以某种形式"标记化"是大多数文本分析的开始方式。">
class Token {
public:
char kind;
double value;
};
我确实知道它们是什么,但他从来没有详细解释过这一点,这让我很困惑
标记化对于了解程序功能的过程非常重要。Bjarne所指的与C++源代码有关的内容涉及程序含义如何受到标记化规则的影响。特别是,我们必须知道令牌是什么,以及它们是如何确定的。具体来说,当一个令牌出现在其他字符旁边时,我们如何识别它,以及如果存在歧义,我们应该如何界定令牌。
例如,考虑前缀运算符++
和+
。让我们假设我们只有一个令牌+
可以使用。以下片段的含义是什么?
int i = 1;
++i;
仅使用+
,以上内容是否仅将一元+
应用于i
两次?还是要增加一次?这自然是模棱两可的。我们需要一个额外的标记,因此在语言中引入++
作为它自己的"单词"。
但现在又出现了另一个(尽管规模较小)问题。如果程序员希望只应用一元+
两次,而不是增量,该怎么办?需要令牌处理规则。因此,如果我们确定空白区始终是令牌的分隔符,我们的程序员可能会写道:
int i = 1;
+ +i;
粗略地说,C++实现从一个充满字符的文件开始,最初将它们转换为一系列标记(在C++语言中具有意义的"单词"),然后检查标记是否出现在具有某种有效意义的"句子"中。
他指的是词法分析,这是每个编译器所必需的部分。它是编译器以有意义的方式处理文本(如:字节序列)的工具。例如,考虑C++中的以下行
double x = (15*3.0); // my variable
当编译器查看文本时,它首先将行拆分为一系列标记,这些标记可能如下所示:
Token {"identifier", "double"}
Token {"space", " "}
Token {"identifier", "x"}
Token {"space", " "}
Token {"operator", "="}
Token {"space", " "}
Token {"separator", "("}
Token {"literal_integer", "15"}
Token {"operator", "*"}
Token {"literal_float", "3.0"}
Token {"separator", ")"}
Token {"separator", ";"}
Token {"space", " "}
Token {"comment", "// my variable"}
Token {"end_of_line"}
它不必像上面那样解释(注意,在我的情况下,kind
和value
都是字符串),这只是如何做到这一点的一个例子。您通常通过一些正则表达式来完成此操作。
无论如何,对于机器来说,令牌比原始文本更容易理解。编译器的下一步是基于标记化创建所谓的抽象语法树,并最终为所有内容添加意义。
还要注意,除非您正在编写解析器,否则您不太可能使用这个概念。
一般来说,标记化||创建标记是一个处理输入流并将其划分为块的过程,而不必担心空白等问题,@StoryTeller在前面描述得最好。"或者正如bjrane所说:是一系列字符,代表我们认为是一个单位的东西"。
令牌本身是C++用户定义类型"UDT"(如int或char)的一个示例,因此令牌可以用于定义变量和保存值。
UDT既可以具有成员函数,也可以具有数据成员。在代码中,您定义了两个成员函数,这是非常基本的。
1) 种类,2)价值
class Token {
public:
char kind;
double value;
};
基于它,我们可以初始化或构造它的对象。
Token token_kind_one{'+'};
正在初始化具有其种类(运算符)"+"的token_kind_one。
Token token_kind_two{'8',3.14};
其种类(整数/数字)为'8'且值为3.14的token_kind_two。
让我们假设我们有一个由10个字符1+2*3(5/4)组成的表达式,它转换为10个标记。
代币:
|----------------------|---------------------|
Kind |'8' |'+' |'8' |'*'|'8'|'('|'8' |'/'|'8' |')'|
|----------------------|---------------------|
Value | 1 | | 2 | | 3 | | 5 | | 4 | |
|----------------------|---------------------|
C++编译器跳过所有空白将文件数据传输到令牌序列。让它自己理解。
一般来说,编译器在将给定的源代码转换为二进制格式之前,会对其运行多个操作。第一个阶段之一是运行令牌化器,将源文件的内容转换为令牌,这是编译器可以理解的单元。例如,如果您编写一个语句int a
,则标记化器可能会创建一个结构来存储这些信息。
Type: integer
Identifier: A
Reserved Word: No
Line number: 10
这将被称为令牌,并且源文件中的大多数代码将被分解为类似的结构。
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 模板元编程:如何将参数包组合成新的参数包
- Qt Q串行端口未编程设备未关闭
- 模板元编程 - 尝试实现维度分析
- 我是编程新手
- C++编程从外部文本文件定义数组大小
- 了解算法的性能差异(如果以不同的编程语言实现)
- 使用 Gtkmm 以编程方式选择 Gtk::TextView 中的文本
- 如何将可变参数模板转换为多个单个模板?(C++竞争编程调试模板)
- 使用命名空间正确编程
- C++编程:运算符重载中的引用如何工作?
- Arduino 模块化编程与全局和设置
- C++ 运算符修改/元编程策略,用于不那么冗长的语法
- 在没有管理员权限的情况下,在 c++ 中以编程方式将程序添加到启动
- 如何以编程方式将音频从任何录制设备路由到任何播放设备
- 试图修复一个错误,该错误不会让我开始编程其余部分
- C++模板编程设计问题 - 根据输入文件返回不同的类型
- Frank Luna 在他的书"使用 DirectX12 进行 3D 游戏编程"的介绍中盒子示例的问题
- 如何使用可变参数模板类使用模板元编程获得最大值