如何指示解析器不继续处理未终止的注释?

时间:2015-05-09 18:18:19

标签: bison yacc flex-lexer

我正致力于改进编译器分配的错误报告。我使用以下代码在Flex中处理未终止的注释:

<INITIAL>"/*"       {BEGIN(COMMENT);}
<COMMENT>"*/"       {BEGIN(INITIAL);}
<COMMENT>([^*]|\n)+   {}
<COMMENT><<EOF>>    {yyerror("UNTERMINATED COMMENT"); BEGIN(INITIAL);}

问题是解析器也在打印错误消息:

 $ ./comp tests/comments.cf 
 ERROR: UNTERMINATED COMMENT: 27
 ERROR: syntax error: 27

如何指示解析器不要继续工作?在exit之后添加BEGIN(INITIAL)可以提供我想要的内容,但似乎不是解决问题的方法。

1 个答案:

答案 0 :(得分:1)

你当然应该从<<EOF>>动作返回0(或其他东西),因为如果你不这样做,词法分析器会尝试继续扫描(这是未定义的行为;扫描仪不应该继续阅读在发出EOF信号后输入,除非它已安排有新的输入缓冲区。)

未终止的评论肯定会导致语法错误,因为程序的结尾很可能已被评论中吞没。如果您不希望报告此错误,则可以在打印错误消息之前设置yyerror检查的标志。在这种简单的情况下,不需要重置该标志,因为未终止的注释错误只能在输入结束时发生,并且此时不能进行错误恢复。

Bison本身有一种通过抑制&#34;语法错误来减少虚假错误报告的机制。报告语法错误后,调用yyerror三个令牌。解析器操作中对此功能的访问权限有限,但无法从解析器外部访问,因此无法通过扫描程序操作启用此功能。

如果您想要在扫描仪和解析器之间使用更清晰的接口的解决方案,您可能会考虑以下可能性:

  1. 在词法分析器中,当检测到未终止的注释时,返回一个未使用的令牌,例如UNTERMINATED_COMMENT。

  2. 当解析器收到UNTERMINATED_COMMENT标记时,它会立即发出语法错误信号(或几乎立即发出信号。在某些情况下,它甚至可以在检查前瞻标记之前执行一些减少。)当{{1调用yyerror全局的值将是先行标记,因此它将是yychar; UNTERMINATED_COMMENT可以使用此事实来生成更准确的错误消息,而不是通用的#34;语法错误&#34;。

  3. 此时立即终止解析非常重要,因为再次调用扫描程序将是未定义的行为。这可以通过在yyerror函数中将yychar设置为YYEOF来完成。 (另一种方法是在rhs中包含yyerror的错误生成,其行为为YYABORT。)