奇怪的词法问题关键字与标识符正则表达式匹配
Strange lexing issue keywords vs identifiers regex matching
我一直在努力理解 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();
}
在代码中,buzz 应该是一个关键字,后面的任何内容都应该作为字符串读取。
对于第一个示例,buzz 与剩余的单词一起被消耗为 "str"。
在第二个例子中,buzz 被正确识别,剩下的词变成了 "str"。
我知道在这两种情况下,第三条规则也是包含字符 b-u-z-z 的标记的有效定义。这四个字母中的每一个都在 [^\n]+ 以及 [a-zA-Z]+ 中。那么到底为什么行为会有所不同呢?
示例输入为:
buzz lightyear
buzz aldren
谢谢!
Flex(以及大多数其他词法分析器生成器)根据最大咀嚼规则工作。该规则表示,如果多个模式可以匹配当前输入,则选择产生最长匹配的模式。如果多个模式产生相同大小的匹配项,则选择 .l 文件中第一个出现的模式。
因此在您的工作解决方案中,模式 buzz
和 [a-zA-Z0-9]+
都匹配 buzz
,因此选择 buzz
是因为它首先出现在文件中(如果您切换这两行 str
将被打印出来)。在您的 non-working 解决方案中,buzz
仍然会匹配 buzz
,但 [^\n]+
分别匹配 buzz lightyear
和 buzz aldren
,这是更长的匹配。因此它根据最大 munch 规则获胜。
我一直在努力理解 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();
}
在代码中,buzz 应该是一个关键字,后面的任何内容都应该作为字符串读取。
对于第一个示例,buzz 与剩余的单词一起被消耗为 "str"。
在第二个例子中,buzz 被正确识别,剩下的词变成了 "str"。
我知道在这两种情况下,第三条规则也是包含字符 b-u-z-z 的标记的有效定义。这四个字母中的每一个都在 [^\n]+ 以及 [a-zA-Z]+ 中。那么到底为什么行为会有所不同呢?
示例输入为:
buzz lightyear
buzz aldren
谢谢!
Flex(以及大多数其他词法分析器生成器)根据最大咀嚼规则工作。该规则表示,如果多个模式可以匹配当前输入,则选择产生最长匹配的模式。如果多个模式产生相同大小的匹配项,则选择 .l 文件中第一个出现的模式。
因此在您的工作解决方案中,模式 buzz
和 [a-zA-Z0-9]+
都匹配 buzz
,因此选择 buzz
是因为它首先出现在文件中(如果您切换这两行 str
将被打印出来)。在您的 non-working 解决方案中,buzz
仍然会匹配 buzz
,但 [^\n]+
分别匹配 buzz lightyear
和 buzz aldren
,这是更长的匹配。因此它根据最大 munch 规则获胜。