我该如何处理Flex词法分析器中的词法错误?

时间:2013-09-16 21:44:03

标签: bison yacc lex flex-lexer lexer

我目前正在尝试使用Flex + Bison编写一个小编译器但是我在错误处理方面有点迷失,特别是如何使所有东西都融合在一起。为了激发讨论,请考虑我用于字符串文字的以下词法分析器:

["]          { BEGIN(STRING_LITERAL); init_string_buffer(); }
<STRING_LITERAL>{
    \\\\    { add_char_to_buffer('\\'); }
    \\\"    { add_char_to_buffer('\"'); }
    \\.     { /*Invalid escape. How do I treat this error?*/ }
    ["]     { BEGIN(INITIAL); yylval = get_string_buffer(); return TK_STRING; }
}

如何处理无效转义的情况?现在我只是打印一条错误消息并调用exit但我更愿意继续前进并在可能的情况下检测每个文件的多个错误。

我的问题:

  • 我用什么功能打印出错误信息?以后野牛预计会出现同样的错误吗?如果我有词法分析器和解析器的单独文件,我在哪里放置yyerror的定义?
  • 我应该从动作中返回什么令牌代码? 0为“文件结束”?一些特殊的TK_INVALID_STRING令牌?
  • 如何确保解析器在词法错误(无效文字,流浪标点字符等)之后可以继续解析?

3 个答案:

答案 0 :(得分:8)

有很多选择。哪一个最好可能是意见问题。 (并且请注意,SO不会对那些答案是意见而不是事实的问题表示友善。)

这在很大程度上取决于您在应用程序中处理错误消息的方式。但这里有几种可能性:

  1. 直接从词法分析器打印错误消息。告诉您错误检测系统编译不成功:您可以使用全局错误计数(yuk,globals!)或传递给yylex的共享数据结构作为附加参数。然后忽略这个角色并继续lexing。

  2. TK_INVALID_STRING之类的内容返回给解析器。解析器需要具有适当的error产品才能正确处理和从这个错误中恢复,这是一项更多的工作,但具有将所有错误处理放入解析器的优点。但是,在字符串的特殊情况下,您可能希望完成字符串直到结束引用;否则,继续解析将毫无结果。

  3. 关于yyerroryyerror没有什么神奇之处。这个功能完全是你的责任。野牛唯一做的就是用一组指定的参数调用它。如果你发现它对记录词法分析器中注意到的错误很有用(我认为可能是这样),那么继续使用它。您完全负责声明yyerror,因此将其定义放在词法分析器和解析器中的#include共享头文件中。或者使用野牛代码生成选项,以便将定义包含在使用bison创建的头文件中。无论什么都比较容易。一旦你弄明白如何声明yyerror,就可以在任何你想要的地方定义它:在lexer文件中,在bison文件中,或者(我的偏好)在一个单独的支持函数库中。

    (FWIW,我已经尝试过选项2,在我看来它似乎工作太多了;选项1对我来说很好。但味道各不相同,YMMV;我不打算在这里捍卫我的选择,但我不介意承认。)

答案 1 :(得分:2)

最简单的事情就是拥有最终规则

. return yytext[0];

这涵盖了所有单个特殊字符和所有非法字符。在你的语法中直接使用特殊字符,如“:”,“;”等。然后,如果你得到一个非法字符,调用解析器的错误处理,这给了一些恢复的前景。如果你在词法分析器中处理它们,你所能做的就是打印错误并忽略它们。

它还会减少你的lex文件的大小。

答案 2 :(得分:1)

如果您正在使用带有C ++输出的Bison,则另一个选项是抛出异常。

.   throw yy::parser::syntax_error("invalid character: " + std::string(yytext, yyleng);