【问题标题】:bison end of file野牛文件结尾
【发布时间】:2010-12-17 21:30:10
【问题描述】:

如果我忘记在我的任何文件的末尾放置一个空行,我的程序就会出现语法错误。问题是我的语法需要换行符来结束当前行。由于换行符不存在,因此野牛会生成语法错误,因为它没有完成规则。

我该如何解决这个问题?我尝试让<<EOF>> 返回MY_EOF 但是当我这样做时,lex 会导致可怕的死亡。我猜它的默认 EOF 中有我没有调用的代码。我不知道它们可能是什么功能。使用 EOF 创建错误symbol EOF is used, but is not defined as a token and has no rules

【问题讨论】:

    标签: yacc bison lex eof


    【解决方案1】:

    您可以使用 flex EOF 规则将换行符附加到输入:

    <<EOF>> { static int once = 0; return once++ ? 0 : '\n' }
    

    【讨论】:

    • 请注意,如果您想在可重入词法分析器中执行此操作,则必须改用 { static int once = 0; return (once = !once) ? NEWLINE : 0; },否则第一个文件将阻止在以后的任何调用中识别换行符。
    • @Hach-Que 好点 - 在这种情况下,使用:{ if( !yyextra-&gt;eof ) { yyextra-&gt;eof = true; return NEWLINE; } else { yyterminate(); } } 并在您的上下文中添加一个“eof”字段。
    • 我们什么时候会有多个 EOF ?
    • @AnkurGautam: 如果在获得EOF 之后,您重置输入(使用yyrestartyy_scan_string 或类似的),您可以重新开始阅读,稍后将获得另一个EOF
    【解决方案2】:

    在你的 lex 文件中

    #define yyterminate() return token::END
    

    在你的 yacc 文件中

    %token END 0 "end of file"
    

    【讨论】:

    • 我之前没见过token::,你用的是C++版本吗?我不得不将其更改为返回 MY_END 但是 %token MY_END 0 "end of file" 让我收到警告 ./test.y:90.11-75: warning: rule never reduced because of conflicts: $accept: program "end of file"。它似乎有效,但我不是 100% 确定。
    【解决方案3】:

    事实上,要在 lex|flex 中捕获文件结尾,您可以使用 yywrap() 函数,如果到达输入文件结尾,词法分析器会调用该函数。

    lex 和 flex 都可以使用此解决方案。yywrap() 的回调表示 EOF,因此您可以重新实现此函数并在输入流的末尾注入您需要做的工作。

    【讨论】:

    • @blueshift 不,我没有拼错 yywarp,它是宏,当我们到达当前缓冲区的末尾时自动调用它在没有要读取的缓冲区时返回 1,如果有则返回 0
    • 我使用 flex 并且有 yywrap() 但没有 yywarp()。你确定吗?
    • @blueshift OMG 对不起,我从一开始就没有明白这一点,它是 yywrap()
    【解决方案4】:

    以前的对我来说很好。

    如果您使用 C Bizon(不是 C++),只需将 END 用于 token::END 并在 yacc 文件中使用 %token END

    之后还有一个问题,如果宏返回的不是 YY_NULL,它永远不会终止(无限循环)

    可以这样解决:

    bool term = false;
    #define yyterminate() return (term = !term)?END : YY_NULL
    

    【讨论】:

      【解决方案5】:

      另一种方法是重组语法,使其末尾不需要换行符。只要您的语言允许空行(通常是这种情况),您就可以使用换行符作为行分隔符而不是行终止符

      来编写语法
      input: line | input '\n' line ;
      line: /* empty */
          | ... various other rules ...
      

      现在如果您确实在输入的末尾有一个换行符,这将被视为该换行符之后的一个空白行,这可能没问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多