为什么以及如何将`a +++ b`解释为`(a ++)+ b`而不是'a +(++ b)`?

时间:2013-10-01 16:12:08

标签: c# algorithm language-agnostic tokenize

编译器的词法分析器/标记器如何“有意义”:a+++b?如:

int a=0,b=0,x=0;
x = a+++b;

我认为它使用了一些suffix tree,可能是generalized suffix tree,但如果是,那么为什么较长的令牌(++)在较短的(+)之前被解释,反之亦然?意思是为什么它被解释为:

(a++) + b

而不是:

a + (++b)

我需要自己编写某种标记器,并且想知道它。

2 个答案:

答案 0 :(得分:3)

语言设计者知道这样的含糊之处,并在参考手册中将“错误的案例”排除在外。

对于词法分析者来说,这很简单:选择最长的法律词汇。当遇到“++”和“+”时,选择“++”。大多数lexer生成器直接实现这个策略,并且在手动编码词法分析器中这样做并不难,因为在你看到第一个之后你必须检查第二个“+”的可能性。

答案 1 :(得分:0)

词法分析器通常是贪婪的,这意味着如果一个令牌可以匹配大于其他字符串的字符串也匹配另一个(或相同的)令牌,它将匹配更大的字符串。

在这个例子中,词法分析器将首先匹配“a”字符并认为“标识符”(或“变量”)是一个潜在的标记(也可以是任何其他可以以字母开头的标记,如“abstract”或“as”)之后,词法分析器将读取以下字符(“+”)并且+不能是和标识符,也不是“抽象”也不是“as”,他将停止搜索候选人“a”和将其标记为标识符。

之后他将“+”作为当前符号,并考虑匹配(“+”,“++”,“+ =”)的潜在令牌,因为词法分析者试图继续“贪婪”使用下一个char并得到以下“+”,因此他得出​​结论,唯一可以匹配的标记是“++”(如果“+++”是lexer需要丢弃的有效标记,如果以下符号是+)

下面的步骤采用以下字符(再次为“+”)并考虑可能的标记(“+”,“++”,“+ =”),他将采用以下字符(“b”)和因为“+ b”不是任何令牌的潜在前缀,他确定以下令牌是“+”。

然后他继续使用“b”(可能是标识符或任何b起始关键字(“base”,“bool”,“break”,“byte”)但是读取以下字符(“;”),词法分析器确定是标识符。

所以词法分子产生以下代币

标识符++ +标识符;