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

How can I instruct the parser not to continue processing unterminated comments?

我正在努力改进编译器分配的错误报告。我正在使用以下代码在 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

如何让解析器停止工作?在 BEGIN(INITIAL) 后加一个 exit 给了我想要的,但它似乎不是处理它的方法。

你当然应该 return 0(或其他)来自 <<EOF>> 动作,因为如果你不这样做,词法分析器将尝试继续扫描(这是未定义的行为;扫描器应该在发出 EOF 信号后不要继续读取输入,除非它已经安排了一个新的输入缓冲区。)

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

Bison 本身有一种机制,通过在报告语法错误后抑制 "syntax error" 对三个标记的 yyerror 调用来减少虚假错误报告。从解析器操作中只能有限地访问此功能,但不能从解析器外部访问,因此无法从扫描器操作中启用它。

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

  1. 在您的词法分析器中,当检测到未终止的注释时,return 一个未使用的标记,比如 UNTERMINATED_COMMENT。

  2. 当解析器接收到 UNTERMINATED_COMMENT 标记时,它将立即发出语法错误信号(或几乎立即发出信号。在某些情况下,它甚至可能在检查前瞻性内容之前执行一些归约token 是。)当调用 yyerror 时,yychar 全局变量的值将是先行标记,因此它将是 UNTERMINATED_COMMENTyyerror 可以使用此事实生成更精确的错误消息,而不是通用的 "syntax error".

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