当我使用 yymore() 时在 EOF 处"end of buffer missed" flex 错误



我正在写一个flex程序来处理字符串常量。

当输入文件在字符串中遇到EOF时,我想返回一个ERROR令牌。

在文件满足EOF并且打印" error "之后,我得到了以下错误:

致命的flex扫描器内部错误——end of buffer missed

下面是我的代码:(一个简化的版本,可以重现这个错误)

%option noyywrap
    #define ERROR 300
    #define STRING 301
    char *text;
%x str
%%
"            {BEGIN(str); yymore();}
<str>"       {BEGIN(INITIAL); text=yytext; return STRING;}
<str>.        {yymore();}
<str><<EOF>>  {BEGIN(INITIAL); return ERROR;}
%%
int main(){
    int token;
    while((token=yylex())!=0){
        if(token==STRING)
            printf("string:%sn",text);
        else if(token==ERROR)
            printf("ERRORn");
    }
    return 0;
}

删除yymore()函数调用后,错误消失,程序正常退出,打印"error"。

我想知道为什么会发生这种情况,我想解决它而不删除yymore()

在收到EOF指示后不能继续词法扫描,因此您的<str><<EOF>>规则不正确,这就是错误消息所指示的。

与任何未定义的行为一样,在某些情况下错误可能导致任意行为,包括您错误地假设它会工作。(对于flex版本,如果您不使用yymore,则会发生这种情况,例如。)

您需要确保在收到EOF后不会重新进入扫描仪循环。例如,您可以返回一个错误代码,指示不能再读取令牌(如果需要,与可重新启动的错误指示相反)。或者您可以为词法分析器设置一个标志,使它在出现不可恢复的错误后立即返回0。

下面是第二个策略的例子(只是规则,因为没有其他变化):

%%
              /* indented code before the first pattern is inserted
               * at the beginning of yylex, allowing declaration of 
               * variables. The fatal_error flag is declared static,
               * since this is not a reentrable lexer. If it were 
               * reentrable, we'd put the flag in the lexer context
               * (as part of the "extra data"), which would be a lot cleaner.
               */
              static int fatal_error = 0;
              /* If the error we last returned was fatal, we do
               * not re-enter the scanner loop; we just return EOF
               */
              if (fatal_error) {
                  fatal_error = 0; /* reset the flag for reuse */
                  return 0;
              }
"            {BEGIN(str); yymore();}
<str>"       {BEGIN(INITIAL); text=yytext; return STRING;}
<str>.        {yymore();}
<str><<EOF>>  {BEGIN(INITIAL);
               fatal_error = 1; /* Set the fatal error flag */
               return ERROR;}
%%

另一个可能的解决方案是使用"推送解析器",其中yylex使用每个令牌调用解析器,而不是反过来。bison支持这种风格,而且通常更方便;特别是,它允许一个操作向解析器发送多个令牌,在这种情况下,这将消除对静态本地标志的需要。

相关内容

最新更新