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

How to match input according to the order of regular expressions instead of longest length match?

我是新的 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

我在Windows10:

中通过以下命令编译程序
flex Scanner1.l
mingw32-gcc -c lex.yy.c -o Scanner1.yy.o
mingw32-g++ -o Scanner1.yy.exe Scanner1.yy.o
Scanner1.yy

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

因此,您应该更换

.*{spacetab}

.

那么,永远是最后一个检查。

编辑

根据您想要的输出,您还错过了运算符中的“===”。

EDIT2 最后一个问题是,在 float 定义中

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

点被解释为任何符号。通过将其替换为“。”我们解决了最后一个问题。