如何根据正则表达式的顺序匹配输入而不是最长的匹配?

时间:2015-11-02 14:07:11

标签: regex flex-lexer lex

我是一名新的FLEX学习者。我想为以下模式和操作编写Scanner1.l文件。

我的节目每次接受输入时都会进行最长时间的比赛。

但我想解析输入文件的方式是逐个遍历正则表达式并为第一次匹配事件工作。

如何解决这个问题?

Pattern                         Action
Blank Space, tab Space          Do nothing
New line                        Count number of line
C identifier                    Print ID
if/else/switch/case/while/for   Print KEYWORD
Any integer number              Print INTEGER
Any float/double number         Print DOUBLE
Any operator                    Print OPERATOR
Anything else                   Print NOT_RECOGNIZED

Scanner1.l文件:

%{
    /* comments */
    #define ECHO fwrite(yytext, yyleng,1,yyout);
    int yylineno = 0;
%}
keyword (if|else|switch|case|while|for)
letter_ [a-zA-Z_]
digit [0-9]
digits {digit}+
id {letter_}({letter_}|{digit})*
integer {digits}
operator (\+\+|--|\+|-|>>|<<|\*|\/|%|==|!=|>|<|>=|<=|&&|!|\|\||~|\^|&|\||\+=|-=|\/=|%=|<<=|>>=|&=|\|=|\^=)
float {digits}((.{digits})|((.{digits})((E|e)[+-]?{digits}))|((E|e)[+-]?{digits}))
spacetab [\t ]+
%option noyywrap
%%
{spacetab} { ECHO;/* do nothing */}
\n {yylineno++; ECHO; }
{keyword} {fprintf(yyout,"KEYWORD ");}
{id} { fprintf(yyout,"ID ");}
{float} { fprintf(yyout,"DOUBLE ");}
{integer} {fprintf(yyout,"INTEGER ");}
{operator} { fprintf(yyout,"OPERATOR ");}
(.*{spacetab}) { fprintf(yyout,"NOT_RECOGNIGED ");}
%%
int main(){
    yyin = fopen("Input1.txt","r");
    yyout = fopen("Output1.txt","w");
    yylex();
    fprintf(yyout, "%d\n", yylineno);
    fclose(yyin);
    fclose(yyout);
    return 0;
}

Input1.txt:

^= !=   === == 100.0 100E54 100e+23
0e-90 0 0.9003430000
54.87 77e98 if
if while __ _ _007  wow

Output1.txt:

NOT_RECOGNIGED DOUBLE 
NOT_RECOGNIGED DOUBLE 
NOT_RECOGNIGED KEYWORD 
NOT_RECOGNIGED ID 
4

预期的Output1.txt:

OPERATOR OPERATOR OPERATOR OPERATOR DOUBLE DOUBLE DOUBLE 
DOUBLE INTEGER DOUBLE 
DOUBLE DOUBLE KEYWORD 
KEYWORD KEYWORD ID ID ID  ID

我正在通过Windows 10中的以下命令编译程序:

flex Scanner1.l
mingw32-gcc -c lex.yy.c -o Scanner1.yy.o
mingw32-g++ -o Scanner1.yy.exe Scanner1.yy.o
Scanner1.yy

1 个答案:

答案 0 :(得分:2)

嗯,问题是,FLEX将始终尝试匹配longes匹配。这意味着,如果您最后一条规则匹配的文本将是最长的文本。如果有两个具有相同长度的匹配项,则它将匹配代码中较早的规则。

因此,您应该替换

.*{spacetab}

.

然后,它总是最后检查。

修改

根据您所需的输出,您还会在操作员中错过“===”。

<强> EDIT2 最后一个问题是浮动定义中的事实

float {digits}((.{digits})|((.{digits})((E|e)[+-]?{digits}))|((E|e)[+-]?{digits}))

点被解释为任何符号。用“。”代替。我们解决了最后一个问题。