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();
}
在代码中,buzz 应该是一个关键字,后面的任何内容都应该被读取为一个字符串。
对于第一个示例,buzz 与剩余的单词一起被消耗为“str”。
在第二个例子中,buzz 被正确识别,剩下的单词变成了“str”。
我知道这两种情况下的第三条规则也是包含字符 Buzz 的令牌的有效定义。这四个字母中的每一个都在 [^\n]+ 以及 [a-zA-Z]+ 中。那么到底为什么行为不同呢?
示例输入为:
buzz lightyear
buzz aldren
谢谢!
解决方案
Flex(以及大多数其他词法分析器生成器)根据最大咀嚼规则工作。该规则表示,如果多个模式可以在当前输入上匹配,则选择产生最长匹配的模式。如果多个模式产生相同大小的匹配,则选择 .l 文件中第一个出现的模式。
因此,在您的工作解决方案中,模式buzz
和[a-zA-Z0-9]+
两者都匹配buzz
,因此buzz
被选中,因为它首先出现在文件中(如果您切换了两行,str
则会打印出来)。在您的非工作解决方案中buzz
仍然会匹配buzz
,但分别[^\n]+
匹配buzz lightyear
和buzz aldren
,这是更长的匹配。因此它根据最大咀嚼规则获胜。
推荐阅读
- linux - makefile 在其依赖项中两次替换目标模式
- java - 有没有更好的方法从 InputStream 中获取 Avro 记录列表?
- python - 基于pandas中的列索引在csv文件导入期间定义数据类型
- javascript - 当 HTML5 视频元素在页面上时,滚动动画 (AOS) 动画不起作用
- ios - Touch ID 认证周期是多久?
- angular - 浏览器发送不存在的 cookie
- server - 如何允许本地资源访问远程服务器,即端口
- python-3.x - 将 Python GUI 控制器文件转换为 EXE (Python 3.6) 的问题
- reactjs - 迭代 React 子组件
- sql - SQL:自某个值首次出现以来的行数