代币做什么?为什么需要在C++编程中创建代币

What does Tokens do and why they need to be created in C++ programming?

本文关键字:C++ 编程 创建 什么 为什么      更新时间:2023-10-16

我正在读一本书(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"}

它不必像上面那样解释(注意,在我的情况下,kindvalue都是字符串),这只是如何做到这一点的一个例子。您通常通过一些正则表达式来完成此操作。

无论如何,对于机器来说,令牌比原始文本更容易理解。编译器的下一步是基于标记化创建所谓的抽象语法树,并最终为所有内容添加意义。

还要注意,除非您正在编写解析器,否则您不太可能使用这个概念。

正如其他人所说,Bjrane指的是词法分析。

一般来说,标记化||创建标记是一个处理输入流并将其划分为块的过程,而不必担心空白等问题,@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

这将被称为令牌,并且源文件中的大多数代码将被分解为类似的结构。