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

时间:2015-08-13 13:31:46

标签: flex-lexer lex lexical-analysis

我正在尝试创建一个正则表达式,只有在给出有效的标识符名称时才能使用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)

1 个答案:

答案 0 :(得分:3)

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

在这种情况下,(f)lex会添加一个默认的catch-all规则,格式为

.|\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 */ }

我强烈建议您在构建扫描仪时使用-T (or --trace) option,而不是在操作中将信息打印到stdout作为调试或学习辅助工具。这将自动以一致和完整的方式输出调试信息;它会告诉你默认规则是匹配的,例如。

注意:

  1. %option nodefault告诉flex不要插入默认规则。我建议一直使用它,因为它可以让你免于麻烦。 warn选项确保在这种情况下发出警告;我认为warn是默认的弹性行为,但the manual建议使用它并且它不会受到伤害。

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