mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
multistart: also give access to yynerrs
This is something that has always bothered me: with pure parsers (and they all should be) the user does not have an (easy) access to yynerrs at the end of the parse. In the case of error recovery, that's the only direct means to know if there were errors. The usual approach being having the user maintain a counter incremented each time yyerror is called. So here, also capture yynerrs in the return value of the start-symbol parsing functions. * data/skeletons/yacc.c (yy_parse_impl_t): New. (yy_parse_impl): Use it. (b4_accept): Fill it. * examples/c/lexcalc/parse.y, examples/c/lexcalc/scan.l: No longer pass nerrs as lex- and parse-param, just use the resulting yynerrs. bistromathic and reccalc both demonstrate %param.
This commit is contained in:
@@ -123,7 +123,7 @@ m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
|
|||||||
# before, using the slot of SYMBOL-NUM.
|
# before, using the slot of SYMBOL-NUM.
|
||||||
m4_define([b4_accept],
|
m4_define([b4_accept],
|
||||||
[m4_ifval([$1],
|
[m4_ifval([$1],
|
||||||
[b4_symbol_value((*yyvalue), [$1]) = b4_rhs_value(2, 1, [$1]); ])YYACCEPT])
|
[b4_symbol_value(yyimpl->yyvalue, [$1]) = b4_rhs_value(2, 1, [$1]); ]) YYACCEPT])
|
||||||
|
|
||||||
|
|
||||||
# b4_lhs_value(SYMBOL-NUM, [TYPE])
|
# b4_lhs_value(SYMBOL-NUM, [TYPE])
|
||||||
@@ -176,6 +176,7 @@ typedef struct
|
|||||||
{]b4_symbol_if([$1], [has_type], [[
|
{]b4_symbol_if([$1], [has_type], [[
|
||||||
]_b4_symbol($1, type)[ yyvalue;]])[
|
]_b4_symbol($1, type)[ yyvalue;]])[
|
||||||
int yystatus;
|
int yystatus;
|
||||||
|
int yynerrs;
|
||||||
} ]b4_prefix[parse_]_b4_symbol($1, id)[_t;
|
} ]b4_prefix[parse_]_b4_symbol($1, id)[_t;
|
||||||
|
|
||||||
// Parse one ]_b4_symbol($1, tag)[.
|
// Parse one ]_b4_symbol($1, tag)[.
|
||||||
@@ -200,10 +201,11 @@ m4_define([_b4_define_sub_yyparse],
|
|||||||
yyparse_]_b4_symbol($1, id)[ (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
|
yyparse_]_b4_symbol($1, id)[ (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
|
||||||
{
|
{
|
||||||
]b4_prefix[parse_]_b4_symbol($1, id)[_t yyres;
|
]b4_prefix[parse_]_b4_symbol($1, id)[_t yyres;
|
||||||
YYSTYPE yyvalue;
|
yy_parse_impl_t yyimpl;
|
||||||
yyres.yystatus = yy_parse_impl (]b4_symbol($2, id)[, &yyvalue]m4_ifset([b4_parse_param],
|
yyres.yystatus = yy_parse_impl (]b4_symbol($2, id)[, &yyimpl]m4_ifset([b4_parse_param],
|
||||||
[[, ]b4_args(b4_parse_param)])[);]b4_symbol_if([$1], [has_type], [[
|
[[, ]b4_args(b4_parse_param)])[);]b4_symbol_if([$1], [has_type], [[
|
||||||
yyres.yyvalue = yyvalue.]b4_symbol($1, slot)[;]])[
|
yyres.yyvalue = yyimpl.yyvalue.]b4_symbol($1, slot)[;]])[
|
||||||
|
yyres.yynerrs = yyimpl.yynerrs;
|
||||||
return yyres;
|
return yyres;
|
||||||
}
|
}
|
||||||
]])
|
]])
|
||||||
@@ -1595,9 +1597,16 @@ yypush_parse (yypstate *yyps]b4_pure_if([[,
|
|||||||
`----------*/
|
`----------*/
|
||||||
|
|
||||||
]m4_ifdef([b4_start_symbols],
|
]m4_ifdef([b4_start_symbols],
|
||||||
[[
|
[[// Extract data from the parser.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
YYSTYPE yyvalue;
|
||||||
|
int yynerrs;
|
||||||
|
} yy_parse_impl_t;
|
||||||
|
|
||||||
|
// Run a full parse, using YYCHAR as switching token.
|
||||||
static int
|
static int
|
||||||
yy_parse_impl (int yychar, YYSTYPE *yyvalue]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[);
|
yy_parse_impl (int yychar, yy_parse_impl_t *yyimpl]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[);
|
||||||
|
|
||||||
]m4_map([_b4_define_sub_yyparse], m4_defn([b4_start_symbols]))[
|
]m4_map([_b4_define_sub_yyparse], m4_defn([b4_start_symbols]))[
|
||||||
|
|
||||||
@@ -1609,7 +1618,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
yy_parse_impl (int yychar, YYSTYPE *yyvalue]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[)]],
|
yy_parse_impl (int yychar, yy_parse_impl_t *yyimpl]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[)]],
|
||||||
[[int
|
[[int
|
||||||
yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])])[
|
yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])])[
|
||||||
{]b4_pure_if([b4_declare_scanner_communication_variables
|
{]b4_pure_if([b4_declare_scanner_communication_variables
|
||||||
@@ -2172,7 +2181,8 @@ yypushreturn:]], [[
|
|||||||
YYSTACK_FREE (yyes);]])])[
|
YYSTACK_FREE (yyes);]])])[
|
||||||
]b4_parse_error_bmatch([detailed\|verbose],
|
]b4_parse_error_bmatch([detailed\|verbose],
|
||||||
[[ if (yymsg != yymsgbuf)
|
[[ if (yymsg != yymsgbuf)
|
||||||
YYSTACK_FREE (yymsg);]])[
|
YYSTACK_FREE (yymsg);]])[]m4_ifdef([b4_start_symbols], [[
|
||||||
|
yyimpl->yynerrs = yynerrs;]])[
|
||||||
return yyresult;
|
return yyresult;
|
||||||
}
|
}
|
||||||
]b4_push_if([b4_parse_state_variable_macros([b4_macro_undef])])[
|
]b4_push_if([b4_parse_state_variable_macros([b4_macro_undef])])[
|
||||||
|
|||||||
@@ -38,12 +38,14 @@ run -noerr 0 9 -p
|
|||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
(1+2) *
|
(1+2) *
|
||||||
EOF
|
EOF
|
||||||
run 1 'err: 1.8-2.0: syntax error, unexpected end of line, expecting ( or number'
|
run 1 'err: 1.8-2.0: syntax error, unexpected end of line, expecting ( or number
|
||||||
|
err: errors: 1'
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
1 / (2 - 2)
|
1 / (2 - 2)
|
||||||
EOF
|
EOF
|
||||||
run 1 'err: 1.1-11: error: division by zero'
|
run 1 'err: 1.1-11: error: division by zero
|
||||||
|
err: errors: 1'
|
||||||
|
|
||||||
|
|
||||||
# Multistart: parse "expression" instead of "input".
|
# Multistart: parse "expression" instead of "input".
|
||||||
@@ -57,4 +59,5 @@ cat >input <<EOF
|
|||||||
2
|
2
|
||||||
EOF
|
EOF
|
||||||
run 1 'expression: failure
|
run 1 'expression: failure
|
||||||
err: 2.1: syntax error, unexpected number, expecting end of file' -e
|
err: 2.1: syntax error, unexpected number, expecting end of file
|
||||||
|
err: errors: 1' -e
|
||||||
|
|||||||
@@ -25,10 +25,10 @@
|
|||||||
{
|
{
|
||||||
// Tell Flex the expected prototype of yylex.
|
// Tell Flex the expected prototype of yylex.
|
||||||
#define YY_DECL \
|
#define YY_DECL \
|
||||||
yytoken_kind_t yylex (YYSTYPE* yylval, YYLTYPE *yylloc, int *nerrs)
|
yytoken_kind_t yylex (YYSTYPE* yylval, YYLTYPE *yylloc)
|
||||||
YY_DECL;
|
YY_DECL;
|
||||||
|
|
||||||
void yyerror (YYLTYPE *loc, int *nerrs, const char *msg);
|
void yyerror (YYLTYPE *loc, const char *msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emitted on top of the implementation file.
|
// Emitted on top of the implementation file.
|
||||||
@@ -62,9 +62,6 @@
|
|||||||
// Enable debug traces (see yydebug in main).
|
// Enable debug traces (see yydebug in main).
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
|
|
||||||
// Error count, exchanged between main, yyparse and yylex.
|
|
||||||
%param {int *nerrs}
|
|
||||||
|
|
||||||
%token
|
%token
|
||||||
PLUS "+"
|
PLUS "+"
|
||||||
MINUS "-"
|
MINUS "-"
|
||||||
@@ -109,7 +106,7 @@ exp:
|
|||||||
{
|
{
|
||||||
if ($3 == 0)
|
if ($3 == 0)
|
||||||
{
|
{
|
||||||
yyerror (&@$, nerrs, "error: division by zero");
|
yyerror (&@$, "error: division by zero");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -121,19 +118,19 @@ exp:
|
|||||||
%%
|
%%
|
||||||
// Epilogue (C code).
|
// Epilogue (C code).
|
||||||
|
|
||||||
void yyerror (YYLTYPE *loc, int *nerrs, const char *msg)
|
void yyerror (YYLTYPE *loc, const char *msg)
|
||||||
{
|
{
|
||||||
YY_LOCATION_PRINT (stderr, *loc);
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
fprintf (stderr, ": %s\n", msg);
|
fprintf (stderr, ": %s\n", msg);
|
||||||
++*nerrs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, const char *argv[])
|
int main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int nerrs = 0;
|
|
||||||
// Possibly enable parser runtime debugging.
|
// Possibly enable parser runtime debugging.
|
||||||
yydebug = !!getenv ("YYDEBUG");
|
yydebug = !!getenv ("YYDEBUG");
|
||||||
int parse_expression_p = 0;
|
int parse_expression_p = 0;
|
||||||
|
int nerrs = 0;
|
||||||
|
|
||||||
// Enable parse traces on option -p.
|
// Enable parse traces on option -p.
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
if (1 < argc && strcmp (argv[1], "-p") == 0)
|
if (1 < argc && strcmp (argv[1], "-p") == 0)
|
||||||
@@ -143,14 +140,19 @@ int main (int argc, const char *argv[])
|
|||||||
|
|
||||||
if (parse_expression_p)
|
if (parse_expression_p)
|
||||||
{
|
{
|
||||||
yyparse_expression_t res = yyparse_expression (&nerrs);
|
yyparse_expression_t res = yyparse_expression ();
|
||||||
|
nerrs = res.yynerrs;
|
||||||
if (res.yystatus == 0)
|
if (res.yystatus == 0)
|
||||||
printf ("expression: %d\n", res.yyvalue);
|
printf ("expression: %d\n", res.yyvalue);
|
||||||
else
|
else
|
||||||
printf ("expression: failure\n");
|
printf ("expression: failure\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
yyparse_input (&nerrs);
|
nerrs = yyparse_input ().yynerrs;
|
||||||
|
|
||||||
|
if (nerrs)
|
||||||
|
fprintf (stderr, "errors: %d\n", nerrs);
|
||||||
|
|
||||||
// Exit on failure if there were errors.
|
// Exit on failure if there were errors.
|
||||||
return !!nerrs;
|
return !!nerrs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
long n = strtol (yytext, NULL, 10);
|
long n = strtol (yytext, NULL, 10);
|
||||||
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
|
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
|
||||||
yyerror (yylloc, nerrs, "integer is out of range");
|
yyerror (yylloc, "integer is out of range");
|
||||||
yylval->TOK_NUM = (int) n;
|
yylval->TOK_NUM = (int) n;
|
||||||
return TOK_NUM;
|
return TOK_NUM;
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
/* Ignore white spaces. */
|
/* Ignore white spaces. */
|
||||||
[ \t]+ LOCATION_STEP (); continue;
|
[ \t]+ LOCATION_STEP (); continue;
|
||||||
|
|
||||||
. yyerror (yylloc, nerrs, "syntax error, invalid character"); continue;
|
. yyerror (yylloc, "syntax error, invalid character"); continue;
|
||||||
|
|
||||||
<<EOF>> return TOK_YYEOF;
|
<<EOF>> return TOK_YYEOF;
|
||||||
%%
|
%%
|
||||||
|
|||||||
Reference in New Issue
Block a user