flex -l 最长模式匹配策略 - 不在这里?
flex -l longest pattern match strategy - not here?
我有两个 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 兼容性)表现得 "right",至少我希望它表现得如此。
这是与 Posix-/lex- 兼容性相关的几个 "gotchas" 之一 [注 1]。由于历史原因,(Posix-标准)lex 正则表达式方言不同于(Posix-标准)ERE("extended regular expressions"),即使 Posix 使用相同的缩写来描述 lex 方言。
区别在于大括号重复运算符的优先级。在标准 ERE 以及我所知道的所有其他正则表达式变体中,abc{3}
会匹配 abccc
。这也是 flex 解释它的方式,除非您指定 -l
或 --posix
标志。如果您要求 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 模式中大括号的另一个陷阱是,当它们用作宏替换时,不会添加隐式括号。所以在 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 */
}
备注:
-l
(和--posix
)标志是我建议避免的选项。仅在绝对必要时才使用它们来编译根据 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 兼容性)表现得 "right",至少我希望它表现得如此。
这是与 Posix-/lex- 兼容性相关的几个 "gotchas" 之一 [注 1]。由于历史原因,(Posix-标准)lex 正则表达式方言不同于(Posix-标准)ERE("extended regular expressions"),即使 Posix 使用相同的缩写来描述 lex 方言。
区别在于大括号重复运算符的优先级。在标准 ERE 以及我所知道的所有其他正则表达式变体中,abc{3}
会匹配 abccc
。这也是 flex 解释它的方式,除非您指定 -l
或 --posix
标志。如果您要求 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 模式中大括号的另一个陷阱是,当它们用作宏替换时,不会添加隐式括号。所以在 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 */
}
备注:
-l
(和--posix
)标志是我建议避免的选项。仅在绝对必要时才使用它们来编译根据lex
标准开发的遗留代码。