flex将无法识别我的正则表达式定义

时间:2014-03-15 09:49:27

标签: regex flex-lexer

我在L文件中在flex中编写定义时遇到问题。出于某种原因,flex无法识别我给正则表达式的名称,例如

LETTER [A-Za-z]
DIGIT[0-9]
SPACE  (" ") +
ID     {LETTER} ({LETTER} | {DIGIT})* (("."| "#"|"$" | "_")? ({LETTER} | {DIGIT})+)?
NUM    ({DIGIT} + | {DIGIT}+ "." {DIGIT} *)(((E |e) (+|-)? {DIGIT} +))?
%%
{LETTER}  {printf("letter");}
%%

但除非我这样写,否则它不会执行规则:

[A-Za-z] {printf("letter");}

任何人都可以告诉我为什么会这样吗?谢谢

1 个答案:

答案 0 :(得分:0)

此flex程序中有几个错误,但它们都不是您要问的问题。也许你对你所看到的错误的原因和症状感到困惑。

我可以确认您所询问的内容适用于所有版本的flex:

LETTER [A-Za-z]
%%
{LETTER}  {printf("letter");}
%%

错误在其他正则表达式中,在您的示例中未引用。如果你确实引用它们,那么它确实会产生你可能无意中对字母模式做出贡献的错误。让我们通过对其他模式采取行动来检查为什么会这样:

LETTER [A-Za-z]
DIGIT[0-9]
SPACE  (" ") +
ID     {LETTER} ({LETTER} | {DIGIT})* (("."| "#"|"$" | "_")? ({LETTER} | {DIGIT})+)?
NUM    ({DIGIT} + | {DIGIT}+ "." {DIGIT} *)(((E |e) (+|-)? {DIGIT} +))?
%%
{LETTER}    {printf("letter");}
{SPACE} {printf("space");}
{ID}    {printf("id");}
{NUM}   {printf("num");}
%%

我们从flex获得此回复:

SO.l:8: unrecognized rule
SO.l:9: unrecognized rule
SO.l:10: unrecognized rule

这是因为正则表达式中存在错误。你犯了把空白放在里面的错误。在大多数代码中,空格被忽略,但初学者在flex(以及使用正则表达式的其他工具)中常见的错误是增加间距以提高可读性。这不是一个好主意,因为它通常会导致指定空格应该出现在模式中!因此,假设您的规范需要{space}模式中的两个空格,并且该空格出现在{ID}{NUM}中。

删除我们最终的空格:

LETTER  [A-Za-z]
DIGIT   [0-9]
SPACE  (" ")+
ID     {LETTER}({LETTER}|{DIGIT})*(("."|"#"|"$"|"_")?({LETTER}|{DIGIT})+)?
NUM    ({DIGIT}+|{DIGIT}+"."{DIGIT}*)(((E|e)(+|-)?{DIGIT}+))?
%%
{LETTER}    {printf("letter");}
{SPACE} {printf("space");}
{ID}    {printf("id");}
{NUM}   {printf("num");}
%%

这解决了大多数错误,再留下一个:

SO.l:11: unrecognized rule

这是由NUM模式中的错误引起的。模式中使用了+符号来显示符号在数字中的使用位置。但是,加号在正则表达式中用于表示重复一个或多个。 +需要加上引号:

LETTER  [A-Za-z]
DIGIT   [0-9]
SPACE  (" ")+
ID     {LETTER}({LETTER}|{DIGIT})*(("."|"#"|"$"|"_")?({LETTER}|{DIGIT})+)?
NUM    ({DIGIT}+|{DIGIT}+"."{DIGIT}*)(((E|e)("+"|"-")?{DIGIT}+))?
%%
{LETTER}    {printf("letter");}
{SPACE} {printf("space");}
{ID}    {printf("id");}
{NUM}   {printf("num");}
%%

此代码现在可以构建,甚至可以使用gcc进行编译。我们可以在一些例子上运行代码:

a123
id
123
num
123.456
num
123.456e-78
num

space
a
letter
aa
id

您还应该注意,拥有{LETTER}规则和{ID}规则可能会出现问题。单个字母与LETTER匹配,但多个字符与“ID”匹配。这是因为flex尝试实现最长匹配。如果您尝试更改匹配顺序以优先使用ID,则会因flex诊断出这种情况而出现错误:

LETTER  [A-Za-z]
DIGIT   [0-9]
SPACE  (" ")+
ID     {LETTER}({LETTER}|{DIGIT})*(("."|"#"|"$"|"_")?({LETTER}|{DIGIT})+)?
NUM    ({DIGIT}+|{DIGIT}+"."{DIGIT}*)(((E|e)("+"|"-")?{DIGIT}+))?
%%
{SPACE} {printf("space");}
{ID}    {printf("id");}
{NUM}   {printf("num");}
{LETTER}    {printf("letter");}
%%

给出了:

SO.l:10: warning, rule cannot be matched

这是初学者的另一个常见错误来源,有一个匹配多个模式的字符串。