Yacc 中如何打印出错的行?

How to print the line that error occurs in Yacc?

现在我有以下代码:

int yyerror( char *s ) 
{ 
    numberOfErrors ++;
    fprintf( stderr, "%s in line %d \n", s, yylineno ); 
}

此代码打印错误原因和行号,如 syntax error in line 9 但我想做的是,打印发生错误的那一行。例如,如果第 9 行是:printf("Hello World";(有一个错字。缺少“)”)它应该打印

syntax error in line 9: printf("Hello World";

有办法吗?谢谢

不容易。

输入由扫描器而不是解析器读取。此外,扫描器并没有真正与解析器同步:它通常致力于识别尚未被解析器分析的标记。因此,即使扫描器有一个包含“当前行”的变量,该行也通常是包含解析器正在查看的标记的那一行之后的行。如果扫描仪跳过了长注释,它甚至可能是后续行。

通常,扫描器实际上没有包含当前行的缓冲区,因为它不需要它。它只需要它当前正在扫描的令牌。扫描器通常读取 fixed-length 块中的输入,而不是行,因为这样效率更高,所以不能保证所有当前行都包含在当前块中。

如果您使用的是 flex,您可以更改其输入法,使其显示为 line-by-line。但这还不够,因为如前所述,scanner的当前行往往不是我们感兴趣的行。

这里值得注意的是,扫描器通常提前读取的事实会影响解析器错误消息中 yylineno 的使用。在许多情况下,这将导致错误报告识别错误之后的行,甚至更晚。然而,这可以更容易地解决,因为 bison 提供了为每个标记保留一个位置对象的可能性。不幸的是,flex 扫描器不会自动填充位置对象,但几行代码就足够了。有关代码示例,请参阅 this answer

如果输入的是常规文件,则很容易重新读取文件以找到特定行。例如,如果输入是管道,那将不起作用,但这可能是一个好的开始。