更新(2021 年 9 月)
由于版本 3.7 Bison 支持用户定义的错误消息:指定%define parse.error custom
,并提供一个yyreport_syntax_error
函数,例如:
int
yyreport_syntax_error (const yypcontext_t *ctx)
{
int res = 0;
YYLOCATION_PRINT (stderr, *yypcontext_location (ctx));
fprintf (stderr, ": syntax error");
// Report the tokens expected at this point.
{
enum { TOKENMAX = 10 };
yysymbol_kind_t expected[TOKENMAX];
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
if (n < 0)
// Forward errors to yyparse.
res = n;
else
for (int i = 0; i < n; ++i)
fprintf (stderr, "%s %s",
i == 0 ? ": expected" : " or", yysymbol_name (expected[i]));
}
// Report the unexpected token.
{
yysymbol_kind_t lookahead = yypcontext_token (ctx);
if (lookahead != YYSYMBOL_YYEMPTY)
fprintf (stderr, " before %s", yysymbol_name (lookahead));
}
fprintf (stderr, "\n");
return res;
}
在文档的语法错误报告函数 yyreport_syntax_error部分中了解更多信息。
原始答案(2013 年 3 月)
Bison 不是生成自定义错误消息的合适工具,但它的标准错误消息也不错,只要您启用%error-verbose
. 查看文档:http ://www.gnu.org/software/bison/manual/bison.html#Error-Reporting 。
如果您真的想提供自定义错误消息,请阅读有关 YYERROR 的文档,并为您想要捕获的模式生成规则,并自己引发错误。例如,这里除以 0 被视为语法错误(这是可疑的,但提供了自定义语法错误消息的示例)。
exp:
NUM { $$ = $1; }
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp
{
if ($3)
$$ = $1 / $3;
else
{
$$ = 1;
fprintf (stderr, "%d.%d-%d.%d: division by zero",
@3.first_line, @3.first_column,
@3.last_line, @3.last_column);
}
}
另请注意,为令牌提供字符串会生成更好的错误消息:
%token NUM
会产生unexpected NUM
,而
%token NUM "number"
会产生unexpected number
.