命名变量与其他标记标识符不明确

时间:2015-04-24 02:10:03

标签: regex yacc flex-lexer lex

我使用的词法分析器需要能够识别命名变量和关键字之间的区别。

详细说明,在我的.l文件中,我有一些定义,如

"QUIT" {return QUIT;}
"AND"  {return AND;}
"XOR"  {return XOR;}

我也有一个名称的定义(对于一个变量)

[a-zA-Z][a-zA-Z0-9]* {memcpy(yylval.name, yytext, strlen(yytext) + 1); return NAME;}

我的问题是我的关键字,如QUIT,AND,XOR都满足NAME的规则,让我产生歧义问题。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

将关键字放在第一位。

Flex生成的扫描仪总是选择最长的匹配;如果可以应用多个模式,则选择第一个模式。所以如果你有:

QUIT {return QUIT;}
AND  {return AND;}
XOR  {return XOR;}
[a-zA-Z][a-zA-Z0-9]* { memcpy(yylval.name, yytext, yyleng + 1); return NAME; }
[[:space:]]+  /* Ignore */

,您的输入是:

QUITAND QUIT AND

然后您的扫描仪将返回三个令牌:NAMEQUITAND。如果您先放置NAME模式,那么您将获得三个NAME个令牌。 (不需要在flex模式中引用字母数字字符。需要引用的是正则表达式运算符。)

memcpy不是个好主意。我修改了它以避免对strlen的冗余调用,这实际上是最不重要的问题。我假设你将它与yylval.name的声明组合为一个固定长度的字符数组。如果是这样,您应该验证NAME是否太长,以至于不适合所提供的空间。但它仍然是一个坏主意,因为野牛生成的解析器假设堆积值不是太大;当它使生成的代码更方便时,它不会试图避免复制它们。