规则:
%%
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的错误吗?
答案 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没有发生这样的惊喜;所以我建议按原样采用规则。