我一直在努力了解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
谢谢!
答案 0 :(得分:0)
Flex(以及大多数其他词法分析器生成器)根据最大修改规则工作。该规则表明,如果可以在当前输入上匹配多个模式,则选择产生最长匹配的模式。如果多个模式产生相同大小的匹配项,则选择在.l文件中最先出现的模式。
因此,在您的工作解决方案中,模式buzz
和[a-zA-Z0-9]+
都与buzz
匹配,因此选择buzz
是因为它首先出现在文件中(如果您切换了两者)行,则将打印str
。在您无法使用的解决方案中,buzz
仍会匹配buzz
,但是[^\n]+
分别匹配buzz lightyear
和buzz aldren
,这是更长的匹配。因此,它会根据最大的规则来获胜。