这是lex的错误吗?

时间:2010-12-10 08:26:03

标签: lex

规则:

%%
AAAA     print("AAAA     : %s\n",yytext);
AAA     print("AAA     : %s\n",yytext);
AA     print("AA     : %s\n",yytext);

输入为AAAAA,输出为:

AAAA     : AAAA
A

而不是:

AAA     : AAA
AA      : AAA

这是lex的错误吗?

1 个答案:

答案 0 :(得分:1)

不,它符合规范。

规则是(man 1p lex

  

在模式匹配期间,lex将搜索模式集以寻找单个最长匹配。在匹配相同数量字符的规则中,应首先选择给定的规则。

因此,它总是贪婪地首先搜索最长的AAAA。这个规则在许多语言的词汇约定中很常见。例如。 C ++:

void f(void*=0);

将无法解析,因为字符*=被解释为assign-multiplication运算符(这是最长匹配),而不是*然后=

这条规则背后的原因是它可以有效地实施。具有此规则的扫描仪仅需要O(1)空间(包括输入,即输入不需要适合存储器)和O(N)时间。如果要检查输入的其余部分是否也可以被标记化,则需要O(N)空间和O(N ^ 2)时间。特别是当所有编译都是在线性传递中完成时,内存消耗在计算的中世纪是至关重要的。而且我确信在解析今天的几十万行源文件(例如包括头文件的C文件)时,你不会欣赏O(N ^ 2)运行时间。其次,这样生成的扫描仪非常快,解析时帮助很多。

最后,但并非最不重要的是,规则很容易理解。作为相反的示例,请考虑ANTLR的标记化规则,即使当前标记的前缀是标记,有时也无法匹配,输入减去该前缀是可标记的。例如:

TOK1 : 12
TOK2 : (13)+

将无法匹配'12131312'。 lex没有发生这样的惊喜;所以我建议按原样采用规则。