Bison 总是打印 "syntax error"

Bison always prints "syntax error"

好的。所以我的任务是在我的编译器 class 中做一个玩具编译器,因此我选择了 Bison 和 Flex。我已经掌握了有关 Bison 的大部分基础知识,并且在某种程度上了解了 LR、LALR 和 SLR 解析器的工作原理。然而,这更多是一个技术问题。在我的语法中,我已经开始使用 error 标记添加错误产生式。现在我的问题是,每次 Bison 使用带有 error 的规则时,它会打印 syntax erroryyerror。我不想要这个,因为我想要显示更好的消息。一个例子:

我有以下规则来检测不匹配的大括号(请记住大写字母是终结符,小写字母是非终结符):

program_start: 
PROGRAM IDENTIFIER '{' translation_unit '}'
| error '}'                                   {yyerror("Mismatched }");}
;

所以如果我使用这样的示例:

program p { 

}
}

那显然是括号不平衡。然而,这输出:

LINE: 26 AT }
ERROR: syntax error
LINE: 26 AT }
ERROR: Mismatched }

我的yyerror函数是

void yyerror(const char* error_str) {
    fprintf(stderr, "LINE: %d AT %c\nERROR: %s\n",yylineno, yytext[0], error_str);
}

所以我的问题真的是我不希望 Bison 打印 "syntax error" 而只是打印我传递给 yyerror 的错误消息。我环顾了 Lex & Yacc 的书(我知道它不一样)并搜索了 Google 没有任何结果。

yacc/bison 中的

error 产品用于 语法错误中恢复,而不是用于检测它们。所以你的规则 program_start: error '}' 基本上是说 "when there's a syntax error in a program_start, recover from it by throwing away everything up to the next '}' token"。如果你给它一个像 program p { ..something with a syntax error.. } 这样的输入,即使没有不平衡的括号,你的规则也可以用来从错误中恢复。

考虑到这一点,bison 正在做的事情就有意义了——它检测语法错误,调用 yyerror 输出消息,然后尝试恢复,寻找可以应用的错误规则。

如果你想change/suppress错误信息,你应该yyerror,而不是在错误恢复规则中。