使用flex的标识符的有效正则表达式



我试图使一个正则表达式,将只工作时,一个有效的标识符名称是给定的,使用flex(名称不能以数字开头)。我使用以下代码:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
%}
%%
"if"                        { printf("IF "); }
[a-zA-Z_][a-zA-Z_0-9]*      { printf("%s ", yytext); }
%%
int main() {
    yylex();
} 

,但它不工作。如何确保flex只接受有效的标识符?

当我提供输入时:

if
abc
9abc

我看到如下输出:

IF
abc
9abc

但我期望:

IF
abc
(nothing)

您的模式与所有可能的输入不匹配。

在这种情况下,(f)lex添加一个默认的捕获规则,格式为

.|n   { ECHO; }

换句话说,任何不能被您的模式识别的字符将被简单地打印在stdout上。输入中的换行字符以及数字9就是这种情况。在9被默认规则识别之后,您的标识符规则将再次识别剩余的输入。

所以你可能想要这样的东西:

%option warn nodefault
%%
[[:space:]]+                ; /* Ignore whitespace */
"if"                        { /* TODO: Handle an "if" token */ }
[[:alpha:]_][[:alnum:]_]*   { /* TODO: Handle an identifier token */ }
.                           { /* TODO: Handle an error */ }

与其将信息打印到stdout作为调试或学习辅助,我强烈建议您在构建扫描仪时使用-T(或--trace)选项。自动输出一致完整的调试信息;例如,它会告诉您正在匹配默认规则。

指出:

  1. %option nodefault告诉flex不要插入默认规则。我建议经常使用它,因为它会让你远离麻烦。warn选项确保在这种情况下发出警告;我认为warn是默认的flex行为,但手册建议使用它,它不会伤害。

  2. 使用标准字符类表达式是很好的风格。在字符类([])中,[:xxx:]匹配标准库函数isxxx返回true的任何内容。因此,[[:space:]]+匹配一个或多个空白字符,包括空格、制表符和换行符(以及其他一些字符),[[:alpha:]_]匹配任何字母或下划线,[[:alnum:]_]*匹配字母、数字或下划线的任何数字(包括0)。请参阅手册中的模式部分。

最新更新