在 Aho Ullman 和 Sethi 的 Compiler Construction 中,给出了将源程序的输入字符串划分为具有逻辑意义的字符序列,称为标记,词位是组成标记的序列,所以是基本的区别吗?
13 回答
使用Aho、Lam、Sethi 和 Ullman 的“编译器原理、技术和工具,第 2 版” (WorldCat) ,又名紫龙书,
词素 pg。111
词位是源程序中与标记模式匹配的字符序列,并被词法分析器识别为该标记的实例。
令牌 pg。111
令牌是由令牌名称和可选属性值组成的对。令牌名称是表示一种词汇单元的抽象符号,例如,特定关键字或表示标识符的输入字符序列。标记名称是解析器处理的输入符号。
模式 pg。111
模式是对标记的词位可能采用的形式的描述。在关键字作为记号的情况下,模式只是形成关键字的字符序列。对于标识符和其他一些标记,模式是由许多字符串匹配的更复杂的结构。
图 3.2:令牌示例 pg.112
[Token] [Informal Description] [Sample Lexemes]
if characters i, f if
else characters e, l, s, e else
comparison < or > or <= or >= or == or != <=, !=
id letter followed by letters and digits pi, score, D2
number any numeric constant 3.14159, 0, 6.02e23
literal anything but ", surrounded by "'s "core dumped"
为了更好地理解这种与词法分析器和解析器的关系,我们将从解析器开始,然后逆向输入。
为了更容易设计解析器,解析器不直接处理输入,而是接收由词法分析器生成的标记列表。查看图 3.2 中的标记列,我们看到诸如if、else、comparison、和;之类的标记id。这些是令牌的名称。通常,对于词法分析器/解析器,标记是一种结构,它不仅包含标记的名称,还包含组成标记的字符/符号以及组成标记的字符串的开始和结束位置,其中用于错误报告、突出显示等的开始和结束位置。numberliteral
现在词法分析器接受字符/符号的输入,并使用词法分析器的规则将输入的字符/符号转换为标记。现在使用词法分析器/解析器的人对他们经常使用的东西有自己的说法。您认为构成标记的字符/符号序列是使用词法分析器/解析器的人所说的词素。因此,当您看到词素时,只需想到代表令牌的一系列字符/符号。在比较示例中,字符/符号的序列可以是不同的模式,例如<or>或elseor3.14等。
考虑两者之间关系的另一种方法是,令牌是解析器使用的编程结构,具有称为词素的属性,用于保存输入中的字符/符号。现在,如果您查看代码中标记的大多数定义,您可能不会将词位视为标记的属性之一。这是因为标记更有可能保存表示标记和词位的字符/符号的开始和结束位置,字符/符号的序列可以根据需要从开始和结束位置导出,因为输入是静态的。
当一个源程序被输入词法分析器时,它首先将字符分解为词素序列。然后将词位用于构建标记,其中词位被映射到标记中。一个名为myVar的变量将被映射到一个表示 < id , "num"> 的标记中,其中 "num" 应该指向变量在符号表中的位置。
简单地说:
- 词位是从字符输入流派生的词。
- 标记是映射到标记名称和属性值的词位。
一个例子包括:
x = a + b * 2
产生词位:{x, =, a, +, b, *, 2}
对应的记号:{< id , 0>, <=>, < id , 1 >, <+>, < id , 2>, <*>, < id , 3>}
LEXEME - 由形成 TOKEN 的 PATTERN 匹配的字符序列
PATTERN - 定义 TOKEN 的规则集
TOKEN - 编程语言字符集上有意义的字符集合,例如:ID、常量、关键字、运算符、标点符号、文字字符串
a) 标记是构成程序文本的实体的符号名称;例如,if 用于关键字 if,id 用于任何标识符。这些构成了词法分析器的输出。5
(b) 模式是指定输入中的字符序列何时构成记号的规则;例如,令牌 if 的序列 i、f 以及令牌 id 以字母开头的任何字母数字序列。
(c) 词位是来自输入的与模式匹配的字符序列(因此构成记号的实例);例如 if 匹配 if 的模式,而 foo123bar 匹配 id 的模式。
Lexeme - 词位是源程序中与标记的模式匹配的字符序列,并被词法分析器识别为该标记的实例。
令牌- 令牌是由令牌名称和可选令牌值组成的对。令牌名称是词汇单元的一个类别。常见的令牌名称是
- 标识符:程序员选择的名称
- 关键字:已经在编程语言中的名称
- 分隔符(也称为标点符号):标点符号和成对分隔符
- 运算符:对参数进行运算并产生结果的符号
- 文字:数字、逻辑、文本、参考文字
考虑编程语言 C 中的这个表达式:
总和 = 3 + 2;
标记化并由下表表示:
Lexeme Token category
------------------------------
sum | Identifier
= | Assignment operator
3 | Integer literal
+ | Addition operator
2 | Integer literal
; | End of statement
Token:(关键字、标识符、标点符号、多字符运算符)的种类,简单来说就是一个Token。
模式:从输入字符形成标记的规则。
Lexeme :它是 SOURCE PROGRAM 中的字符序列,与令牌的模式匹配。基本上,它是 Token 的一个元素。
令牌: 令牌是可以被视为单个逻辑实体的字符序列。典型的标记是,
1) 标识符
2) 关键字
3) 运算符
4) 特殊符号
5) 常量
模式:输入中的一组字符串,为其生成相同的标记作为输出。这组字符串由称为与令牌关联的模式的规则描述。
词位:词位是源程序中与标记模式匹配的字符序列。
让我们看看词法分析器(也称为 Scanner )的工作原理
让我们举个例子:
INPUT : cout << 3+2+3;
FORMATTING PERFORMED BY SCANNER : {cout}|space|{<<}|space|{3}{+}{2}{+}{3}{;}
虽然不是实际输出。
扫描仪简单地重复查找源程序文本中的词汇,直到输入用尽
Lexeme 是输入的子串,形成语法中存在的有效终端字符串。每个词位都遵循最后解释的模式(读者可以跳过的部分)
(重要的规则是寻找形成有效终端字符串的最长可能前缀,直到遇到下一个空格......下面解释)
词法:
- 考特
- <<
(虽然“<”也是有效的终端字符串,但上述规则应选择词位“<<”的模式,以便生成扫描仪返回的令牌)
- 3
- +
- 2
- ;
TOKENS :每次 Scanner 找到一个(有效的)词位时,一次返回一个令牌(当 Parser 请求时由 Scanner )。扫描器创建一个符号表条目(如果尚未存在)(具有属性:主要是令牌类别和少数其他属性),当它找到一个词素时,以生成它的令牌
'#' 表示符号表条目。为了便于理解,我在上面的列表中指出了词位编号,但从技术上讲,它应该是符号表中记录的实际索引。
扫描仪按上述示例的指定顺序将以下标记返回给解析器。
<标识符,#1>
< 运算符 , #2 >
< 字面量 , #3 >
< 运算符 , #4 >
< 字面量 , #5 >
< 运算符 , #4 >
< 字面量 , #3 >
< 标点符号 , #6 >
正如你所看到的不同,一个标记是一对不像词素,词素是输入的子串。
该对的第一个元素是令牌类/类别
下面列出了令牌类:
还有一件事,Scanner 检测到空格,忽略它们并且根本不为空格形成任何标记。并非所有分隔符都是空格,空格是扫描仪用于其目的的分隔符的一种形式。输入中的 Tabs 、 Newlines 、 Spaces 、 Escaped Characters 统称为空白分隔符。很少有其他分隔符是';' ',' ':' 等,它们被广泛认为是形成标记的词位。
此处返回的记号总数为 8,但仅为词位创建了 6 个符号表条目。词素也是8个(见词素的定义)
--- 你可以跳过这部分
A ***pattern*** is a rule ( say, a regular expression ) that is used to check if a string-of-terminals is valid or not.
If a substring of input composed only of grammar terminals isfollowing the rule specified by any of the listed patterns , it isvalidated as a lexeme and selected pattern will identify the categoryof lexeme, else a lexical error is reported due to either (i) notfollowing any of the rules or (ii) input consists of a badterminal-character not present in grammar itself.
for example :
1. No Pattern Exists : In C++ , "99Id_Var" is grammar-supported string-of-terminals but is not recognised by any of patterns hence lexical error is reported .
2. Bad Input Character : $,@,unicode characters may not be supported as a valid character in few programming languages.`
CS 研究人员,就像来自数学的研究人员一样,喜欢创造“新”术语。上面的答案都很好,但显然,没有那么大的需要区分令牌和词位恕我直言。它们就像代表同一事物的两种方式。一个词位是具体的——这里是一组字符;另一方面,标记是抽象的——如果有意义的话,通常指的是词位的类型及其语义值。只是我的两分钱。
Lexeme Lexemes 被称为是记号中的一系列字符(字母数字)。
标记 标记是可以被识别为单个逻辑实体的字符序列。通常,标记是关键字、标识符、常量、字符串、标点符号、运算符。数字。
模式 由称为模式的规则描述的一组字符串。模式解释了什么可以是标记,这些模式是通过与标记相关联的正则表达式定义的。
词法分析器采用一系列字符识别与正则表达式匹配的词位,并将其进一步分类为标记。因此,Lexeme 是匹配的字符串,而 Token 名称是该词位的类别。
例如,考虑下面带有输入“int foo, bar;”的标识符的正则表达式
字母(字母|数字|_)*
在这里,foo和bar匹配正则表达式因此都是词位,但被归类为一个标记,ID即标识符。
还要注意,下一阶段,即语法分析器不必知道词素而是一个标记。
Lexeme 基本上是标记的单元,它基本上是与标记匹配的字符序列,有助于将源代码分解为标记。
例如:如果源是x=b,则词位是x, =,b而标记是<id, 0>, <=>, <id, 1>。
