Flex 匹配错误的规则

Flex matching wrong rule

我正在为 mini-L 语言编写一个编译器。我几乎完成了扫描部分。这是您基本上可以在输入中找到标记的地方。我的问题是,当我输入“函数”时,它会将其作为标识符进行匹配。我真的说不出哪里不对。

ident           [a-zA-Z][a-zA-Z0-9_]+[^_]

%{
#include <stdio.h>
#include <stdlib.h>

int col = 0;
int row = 0;
%}
%%

"function"      {printf("FUNCTION\n"); col += yyleng;}
{ident}    {printf("IDENT %s\n", yytext); col += yyleng;}
.               {printf("Error at line %d, column %d: unrecognized symbol \"%s\"\n", row, col, yytext);}

%%
int main(int argc, char** argv){
    
    if(argc > 1){
        FILE *fp = fopen(argv[1], "r"); 
        if(fp){
            yyin = fp;
        }
    }

    printf("Give me the input:\n");
    yylex();
}

我尝试重新排列规则,但没有用,而且这似乎也不是问题所在。我认为这是我的正则表达式的问题。非常感谢任何帮助。

这是您的 ident 模式:[a-zA-Z][a-zA-Z0-9_]+[^_]。让我们分解一下:

  • [a-zA-Z]一个字母。
  • [a-zA-Z0-9_]+ 一个或多个 (+) 字母、数字或 _
  • [^_] _ 以外的任何值。任何事物。比如一个space.

一个简单的观察是模式不能匹配少于三个字符。另一方面,最后一个几乎可以是任何东西。可以是一封信。但它也可以是逗号,或 space,甚至是换行符。只是不是下划线。

因此不会匹配通常被认为是有效标识符的 x。但它将匹配 function 。 (也就是说,单词 function 后跟一个 space。)因为它比 function 长,标识符模式将获胜,除非你碰巧写了 function_.

所以这可能不是您想要的。

请注意,如果要避免标识符以下划线结尾,则必须处理两个问题。

  1. 明显的模式[[:alpha:]][[:alnum:]_]*[[:alnum:]]不能匹配单个字母。所以你需要 [[:alpha:]]([[:alnum:]_]*[[:alnum:]])?.

  2. 如果您的标识符模式与尾随下划线不匹配,则下划线将保留在下一个标记中。也许你对此没有意见。但最好匹配下划线并发出错误消息。或者重新考虑限制。

注意:模式语法是 documented in the Flex manual,包括我上面使用的内置字符集。