奇怪的词法问题关键字与标识符正则表达式匹配

时间:2019-06-23 20:54:46

标签: flex-lexer

我一直在努力了解flex的某些行为。

我开始定义一个类似于玩具的小型示例程序,它将标记为关键字和字符串。

一个正则表达式的定义符合预期,但另一个行为却与我的预期相反。

我玩这些东西已经有好几年了,希望有人能指出我正确的方向。

我修改了令牌正则表达式以使其正常工作,但我真的很想了解为什么我最初的选择会表现出不同的行为。

第一个示例是无效代码

%{
#include <iostream>
using namespace std;
%}
%option noyywrap
%%
[ \t\n]                   {cout << "ws" << endl;};
buzz                      {cout << "kw" << endl;};
[^\n]+                    {cout << "str" << endl;};
%%
int main(){
yylex();
}

第二个示例是行为正确的修改版本。

%{
#include <iostream>
using namespace std;
%}
%option noyywrap
%%
[ \t\n]                   {cout << "ws" << endl;};
buzz                      {cout << "kw" << endl;};
[a-zA-Z]+                 {cout << "str" << endl;};
%%
int main(){
yylex();
}

在代码中,“嗡嗡声”应该是一个关键字,后面的所有内容都应作为字符串读取。

对于第一个示例,嗡嗡声与其余单词一起被消耗为“ str”。

在第二个示例中,嗡嗡声被正确识别,剩下的单词变成“ str”。

我了解到,在两种情况下,第三条规则也是对包含字符b-u-z-z的令牌的有效定义。这四个字母分别以[^ \ n] +和[a-zA-Z] +开头。那么为什么地球上的行为不同呢?

示例输入为:

buzz lightyear
buzz aldren

谢谢!

1 个答案:

答案 0 :(得分:0)

Flex(以及大多数其他词法分析器生成器)根据最大修改规则工作。该规则表明,如果可以在当前输入上匹配多个模式,则选择产生最长匹配的模式。如果多个模式产生相同大小的匹配项,则选择在.l文件中最先出现的模式。

因此,在您的工作解决方案中,模式buzz[a-zA-Z0-9]+都与buzz匹配,因此选择buzz是因为它首先出现在文件中(如果您切换了两者)行,则将打印str。在您无法使用的解决方案中,buzz仍会匹配buzz,但是[^\n]+分别匹配buzz lightyearbuzz aldren,这是更长的匹配。因此,它会根据最大的规则来获胜。