mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
yacc.c: add custom error message generation
When parse.error is custom, let users define a yyreport_syntax_error function, and use it. * data/skeletons/bison.m4 (b4_error_verbose_if): Accept 'custom'. * data/skeletons/yacc.c: Implement it. * examples/c/calc/calc.y: Experiment with it.
This commit is contained in:
@@ -1018,13 +1018,14 @@ m4_define([b4_bison_locations_if],
|
||||
|
||||
# b4_error_verbose_if([IF-ERRORS-ARE-VERBOSE], [IF-NOT])
|
||||
# ------------------------------------------------------
|
||||
# Map %define parse.error "(simple|verbose)" to b4_error_verbose_if and
|
||||
# Map %define parse.error "(custom|simple|verbose)" to b4_error_verbose_if and
|
||||
# b4_error_verbose_flag.
|
||||
b4_percent_define_default([[parse.error]], [[simple]])
|
||||
b4_percent_define_check_values([[[[parse.error]],
|
||||
[[simple]], [[verbose]]]])
|
||||
[[custom]], [[simple]], [[verbose]]]])
|
||||
m4_define([b4_error_verbose_flag],
|
||||
[m4_case(b4_percent_define_get([[parse.error]]),
|
||||
[custom], [[1]],
|
||||
[simple], [[0]],
|
||||
[verbose], [[1]])])
|
||||
b4_define_flag_if([error_verbose])
|
||||
|
||||
@@ -1136,7 +1136,11 @@ yysyntax_error_arguments (const yyparse_context_t *yyctx,
|
||||
}
|
||||
]])[
|
||||
|
||||
]m4_case(b4_percent_define_get([[parse.error]]), [verbose],
|
||||
]m4_case(b4_percent_define_get([[parse.error]]),
|
||||
[custom],
|
||||
[[static int
|
||||
yyreport_syntax_error (const yyparse_context_t *yyctx);]],
|
||||
[verbose],
|
||||
[[# ifndef yystrlen
|
||||
# if defined __GLIBC__ && defined _STRING_H
|
||||
# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
|
||||
@@ -1786,6 +1790,15 @@ yyerrlab:
|
||||
{
|
||||
++yynerrs;
|
||||
]m4_case(b4_percent_define_get([[parse.error]]),
|
||||
[custom],
|
||||
[[ {
|
||||
yyparse_context_t yyctx
|
||||
= {yyssp, yytoken]b4_lac_if([[, yyesa, &yyes, &yyes_capacity]])[};]b4_lac_if([[
|
||||
if (yychar != YYEMPTY)
|
||||
YY_LAC_ESTABLISH;]])[
|
||||
if (yyreport_syntax_error (]b4_yyerror_args[&yyctx) == 2)
|
||||
goto yyexhaustedlab;
|
||||
}]],
|
||||
[simple],
|
||||
[[ yyerror (]b4_yyerror_args[YY_("syntax error"));]],
|
||||
[verbose],
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
%define api.header.include {"calc.h"}
|
||||
%define api.value.type union /* Generate YYSTYPE from these types: */
|
||||
%define parse.error custom
|
||||
%token <double> NUM "number"
|
||||
%type <double> expr term fact
|
||||
|
||||
@@ -51,6 +52,28 @@ fact:
|
||||
|
||||
%%
|
||||
|
||||
int
|
||||
yyreport_syntax_error (const yyparse_context_t *ctx)
|
||||
{
|
||||
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 10 };
|
||||
/* Arguments of yyformat: reported tokens (one for the "unexpected",
|
||||
one per "expected"). */
|
||||
int arg[YYERROR_VERBOSE_ARGS_MAXIMUM];
|
||||
int n = yysyntax_error_arguments (ctx, arg, sizeof arg / sizeof *arg);
|
||||
if (n == -2)
|
||||
return 2;
|
||||
fprintf (stderr, "SYNTAX ERROR on token [%s]", yysymbol_name (arg[0]));
|
||||
if (1 < n)
|
||||
{
|
||||
fprintf (stderr, " (expected:");
|
||||
for (int i = 1; i < n; ++i)
|
||||
fprintf (stderr, " [%s]", yysymbol_name (arg[i]));
|
||||
fprintf (stderr, ")");
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
yylex (void)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user