编译器的词法分析器/标记器如何从 : 中“有意义” a+++b
?如:
int a=0,b=0,x=0;
x = a+++b;
我假设它使用一些后缀树,也许是通用后缀树,但如果是这样,那么为什么较长的标记 ( ++
) 在较短的 ( +
) 之前被解释,反之亦然?意思是为什么它被解释为:
(a++) + b
并不是:
a + (++b)
?
我需要自己编写某种标记器,并且想知道它。
语言设计者知道这样的歧义,并在参考手册中禁止“错误的情况”。
对于词法分析器来说,这很容易:选择最长的合法词位。遇到“++”和“+”时,选择“++”。大多数词法分析器生成器直接实现此策略,并且在手动编码的词法分析器中执行此操作并不难,因为您必须在看到第一个“+”之后检查是否存在第二个“+”。
词法分析器通常是贪婪的,这意味着如果一个标记可以匹配一个比另一个字符串更大的字符串也匹配另一个(或相同的)标记,它将匹配更大的字符串。
在这个例子中,词法分析器将首先匹配“a”字符并认为“标识符”(或“变量”)是一个潜在的标记(也可以是任何其他可以以字母开头的标记,如“抽象”或“作为” ),之后词法分析器将读取以下字符(“+”),并且作为 a+ 不能是标识符,“抽象”也不是“as”,他将停止搜索“a”的候选并将其标记为一个标识符。
之后,他将“+”作为当前符号,并考虑与(“+”、“++”、“+=”)匹配的潜在标记,因为“贪婪”,词法分析器试图继续下一个char 并获得以下“+”,因此他得出结论,唯一可以匹配的标记是“++”(如果“+++”是一个有效的标记,则词法分析器需要丢弃以下符号是 +)
接下来的步骤采用以下字符(再次为“+”)并考虑可能的标记(“+”,“++”,“+=”),他将采用以下字符(“b”)并作为“+ b" 不是任何标记的潜在前缀,他确定后面的标记是 "+" 。
然后他继续使用“b”(可能是标识符或任何 b 起始关键字(“base”、“bool”、“break”、“byte”),但读取以下字符(“;”),词法分析器确定这是一个标识符。
所以词法分析器产生以下标记
标识符 ++ + 标识符;