flex -l最长模式匹配策略 - 不在这里?

时间:2015-05-12 16:45:33

标签: compatibility flex-lexer lex

我有两个lex规则,并且想知道为什么我从未匹配第二条规则。相反,规则1总是触发模式 2005-05-09-11.23.04.790000

<data>[-]?[0-9]*[.][0-9]*  { comma=0;
             printf("DEBUG: data 1 %s\n",yytext);
                strcat(data_line,yytext); }
<data>[0-9]{4}[-][01][0-9][-][0-3][0-9][-][0-9]{2}[.][0-9]{2}[.][0-9]{2}[.][0-9]{6} {
printf("DEBUG: data 2[%s]\n",yytext);
/* 1996-07-15-hh.00.00*/

我想,flex / lex会遵循最长的字符串匹配规则吗?

有趣的是,flex(没有-l lex兼容性)表现“正确”,至少我希望它具有行为。

1 个答案:

答案 0 :(得分:3)

这是与Posix- / lex兼容性[注1]相关的几个“问题”之一。由于历史原因,(Posix标准)lex正则表达式方言与(Posix-standard)EREs(“扩展正则表达式”)不同,即使Posix使用相同的缩写来描述lex方言。

不同之处在于大括号重复运算符的优先级。在标准的ERE中,以及我所知道的所有其他正则表达式,abc{3}都匹配abccc。除非您指定-l--posix标志,否则这也是由flex解释的方式。如果请求lex兼容性,则大括号运算符的优先级低于串联的优先级,因此abc{3}匹配abcabcabc

如果要编写适用于正则表达式的正则表达式,则必须将重复运算符的所有(或几乎所有)用法括起来。所以你的第二个模式需要写成:

[0-9]{4}[-][01][0-9][-][0-3][0-9][-]([0-9]{2})[.]([0-9]{2})[.]([0-9]{2})[.]([0-9]{6})

如上所述,它与指定的输入不匹配,而第一条规则将与前一年相匹配。

对于它的价值,其他后缀重复运算符 - + * - 在lex中具有正常的高优先级模式。 (在某种程度上,这种不一致使得支撑重复的行为更加令人困惑。)

在lex-mode中使用大括号的另一个问题是,当它们用作宏替换时,不会添加隐式括号。所以在flex:

foo     [fF][oO][oO]
%%
{foo}+  {
          /* yytext is some number of case-insensitive repetitions of foo */
        }

而在lex兼容模式下

foo     [fF][oO][oO]
%%
{foo}+  {
          /* yytext is an 'f' or 'F' followed by at least two 'o' or 'O's */
        }

注意:

  1. -l(和--posix)标志是我建议避免使用的选项。只有在绝对必要时才使用它们来编译开发为lex标准的遗留代码。