我正在尝试创建一个正则表达式,只有在给出有效的标识符名称时才能使用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)
答案 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
作为调试或学习辅助工具。这将自动以一致和完整的方式输出调试信息;它会告诉你默认规则是匹配的,例如。
%option nodefault
告诉flex不要插入默认规则。我建议一直使用它,因为它可以让你免于麻烦。 warn
选项确保在这种情况下发出警告;我认为warn
是默认的弹性行为,但the manual建议使用它并且它不会受到伤害。
使用标准字符类表达式是一种很好的风格。在字符类([
... ]
)内,[:xxx:]
匹配标准库函数isxxx
将返回true的任何内容。因此[[:space:]]+
匹配一个或多个空格字符,包括空格,制表符和换行符(以及其他一些字符),[[:alpha:]_]
匹配任何字母或下划线,[[:alnum:]_]*
匹配任何数字(包括0) )字母,数字或下划线。请参阅手册的Patterns部分。