我在网站上有一个相关主题(My lex pattern doesn't work to match my input file, how to correct it?)
我遇到的问题是关于“贪婪”的lex如何进行模式匹配,例如:我有我的lex文件:
$ cat b.l
%{
#include<stdio.h>
%}
%%
"12" {printf("head\n");}
"34" {printf("tail\n");}
.* {printf("content\n");}
%%
我想说的是,当遇到“12”时,打印“头”;遇到“34”时,打印“尾巴”,否则打印“内容”表示不包含“12”或“34”的最长匹配。
但事实是,“。*”是一个贪婪的比赛,无论我输入什么,它都会打印“内容”。
我的要求是,当我使用
时12sdf2dfsd3sd34
作为输入,输出应为
head
content
tail
所以似乎有两种可能的方式:
1,要为“。*”指定匹配优先级,它只应在“12”和“34”都不匹配时才有效。 lex是否支持“优先”?
2,更改第3个表达式,以匹配任何不包含“12”或“34”子字符串的连续字符串。但是如何写这个正则表达式?
答案 0 :(得分:1)
(F)lex总是产生最长的匹配。如果多个规则匹配相同的最长匹配,则选择第一个匹配,因此在这种情况下它支持优先级。但它不支持较短匹配的优先级,也不支持非贪婪匹配。
您可以通过一些工作创建一个匹配不包含指定子字符串的字符串的正则表达式,但这并不是特别容易,并且(f)lex不为这些正则表达式提供简单的语法。
更简单(但效率稍低)的解决方案是将字符串与片段进行匹配。粗略地说,您可以执行以下操作:
"12" { return HEAD; }
"34" { if (yyleng > 2) {
yyless(yyleng - 2);
return CONTENT;
}
else
return TAIL;
}
.|\n { yymore(); }
当没有机会跳过分隔符时,可以通过匹配多个字符来提高效率;将最后一条规则更改为:
.|[^13]+ { yymore(); }
yymore()
导致保留当前令牌,以便下一个匹配附加到当前令牌而不是启动新令牌。 yyless(x)
将除了第一个x
个字符之外的所有字符返回到输入流;在这种情况下,用于在识别CONTENT令牌后重新扫描结束定界符34
。
(假设您实际上想要对输入流进行标记,而不是仅仅打印调试消息,这就是我将其称为大纲解决方案的原因。)