[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 17/17] multistart: also give access to yynerrs
From: |
Akim Demaille |
Subject: |
[PATCH 17/17] multistart: also give access to yynerrs |
Date: |
Sun, 20 Sep 2020 10:37:49 +0200 |
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 (yyparse_yyimpl_t): New.
(yyparse_yyimpl): 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.
---
data/skeletons/yacc.c | 26 ++++++++++++++++++--------
examples/c/lexcalc/lexcalc.test | 9 ++++++---
examples/c/lexcalc/parse.y | 24 +++++++++++++-----------
examples/c/lexcalc/scan.l | 4 ++--
4 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index ff1cdb79..2a824c5f 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -123,7 +123,7 @@ m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
# before, using the slot of SYMBOL-NUM.
m4_define([b4_accept],
[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])
@@ -176,6 +176,7 @@ typedef struct
{]b4_symbol_if([$1], [has_type], [[
]_b4_symbol($1, type)[ yyvalue;]])[
int yystatus;
+ int yynerrs;
} ]b4_prefix[parse_]_b4_symbol($1, id)[_t;
// Parse one ]_b4_symbol($1, tag)[.
@@ -192,10 +193,11 @@ m4_define([_b4_define_sub_yyparse],
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;
- YYSTYPE yyvalue;
- yyres.yystatus = yyparse_yyimpl (]b4_symbol($2, id)[,
&yyvalue]m4_ifset([b4_parse_param],
+ yyparse_yyimpl_t yyimpl;
+ yyres.yystatus = yyparse_yyimpl (]b4_symbol($2, id)[,
&yyimpl]m4_ifset([b4_parse_param],
[[,
]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;
}
]])
@@ -1587,9 +1589,16 @@ yypush_parse (yypstate *yyps]b4_pure_if([[,
`----------*/
]m4_ifdef([b4_start_symbols],
-[[
+[[// Extract data from the parser.
+typedef struct
+{
+ YYSTYPE yyvalue;
+ int yynerrs;
+} yyparse_yyimpl_t;
+
+// Run a full parse, using YYCHAR as switching token.
static int
-yyparse_yyimpl (int yychar, YYSTYPE *yyvalue]m4_ifset([b4_parse_param], [,
b4_formals(b4_parse_param)])[);
+yyparse_yyimpl (int yychar, yyparse_yyimpl_t
*yyimpl]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[);
]m4_map([_b4_define_sub_yyparse], m4_defn([b4_start_symbols]))[
@@ -1602,7 +1611,7 @@ yyparse (]m4_ifset([b4_parse_param],
[b4_formals(b4_parse_param)], [void])[)
}
static int
-yyparse_yyimpl (int yychar, YYSTYPE *yyvalue]m4_ifset([b4_parse_param], [,
b4_formals(b4_parse_param)])[)]],
+yyparse_yyimpl (int yychar, yyparse_yyimpl_t
*yyimpl]m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])[)]],
[[int
yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)],
[void])[)]])])[
{]b4_pure_if([b4_declare_scanner_communication_variables
@@ -2165,7 +2174,8 @@ yypushreturn:]], [[
YYSTACK_FREE (yyes);]])])[
]b4_parse_error_bmatch([detailed\|verbose],
[[ if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);]])[
+ YYSTACK_FREE (yymsg);]])[]m4_ifdef([b4_start_symbols], [[
+ yyimpl->yynerrs = yynerrs;]])[
return yyresult;
}
]b4_push_if([b4_parse_state_variable_macros([b4_macro_undef])])[
diff --git a/examples/c/lexcalc/lexcalc.test b/examples/c/lexcalc/lexcalc.test
index 794676de..0eb4ebee 100644
--- a/examples/c/lexcalc/lexcalc.test
+++ b/examples/c/lexcalc/lexcalc.test
@@ -38,12 +38,14 @@ run -noerr 0 9 -p
cat >input <<EOF
(1+2) *
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
1 / (2 - 2)
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".
@@ -57,4 +59,5 @@ cat >input <<EOF
2
EOF
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
diff --git a/examples/c/lexcalc/parse.y b/examples/c/lexcalc/parse.y
index 59708115..1da92a3e 100644
--- a/examples/c/lexcalc/parse.y
+++ b/examples/c/lexcalc/parse.y
@@ -25,10 +25,10 @@
{
// Tell Flex the expected prototype of yylex.
#define YY_DECL \
- yytoken_kind_t yylex (YYSTYPE* yylval, YYLTYPE *yylloc, int *nerrs)
+ yytoken_kind_t yylex (YYSTYPE* yylval, YYLTYPE *yylloc)
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.
@@ -62,9 +62,6 @@
// Enable debug traces (see yydebug in main).
%define parse.trace
-// Error count, exchanged between main, yyparse and yylex.
-%param {int *nerrs}
-
%token
PLUS "+"
MINUS "-"
@@ -109,7 +106,7 @@ exp:
{
if ($3 == 0)
{
- yyerror (&@$, nerrs, "error: division by zero");
+ yyerror (&@$, "error: division by zero");
YYERROR;
}
else
@@ -121,19 +118,19 @@ exp:
%%
// Epilogue (C code).
-void yyerror (YYLTYPE *loc, int *nerrs, const char *msg)
+void yyerror (YYLTYPE *loc, const char *msg)
{
YY_LOCATION_PRINT (stderr, *loc);
fprintf (stderr, ": %s\n", msg);
- ++*nerrs;
}
int main (int argc, const char *argv[])
{
- int nerrs = 0;
// Possibly enable parser runtime debugging.
yydebug = !!getenv ("YYDEBUG");
int parse_expression_p = 0;
+ int nerrs = 0;
+
// Enable parse traces on option -p.
for (int i = 0; i < argc; ++i)
if (1 < argc && strcmp (argv[1], "-p") == 0)
@@ -143,14 +140,19 @@ int main (int argc, const char *argv[])
if (parse_expression_p)
{
- yyparse_expression_t res = yyparse_expression (&nerrs);
+ yyparse_expression_t res = yyparse_expression ();
+ nerrs = res.yynerrs;
if (res.yystatus == 0)
printf ("expression: %d\n", res.yyvalue);
else
printf ("expression: failure\n");
}
else
- yyparse_input (&nerrs);
+ nerrs = yyparse_input ().yynerrs;
+
+ if (nerrs)
+ fprintf (stderr, "errors: %d\n", nerrs);
+
// Exit on failure if there were errors.
return !!nerrs;
}
diff --git a/examples/c/lexcalc/scan.l b/examples/c/lexcalc/scan.l
index 3d71a381..baf0798d 100644
--- a/examples/c/lexcalc/scan.l
+++ b/examples/c/lexcalc/scan.l
@@ -61,7 +61,7 @@
errno = 0;
long n = strtol (yytext, NULL, 10);
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;
return TOK_NUM;
}
@@ -71,7 +71,7 @@
/* Ignore white spaces. */
[ \t]+ LOCATION_STEP (); continue;
-. yyerror (yylloc, nerrs, "syntax error, invalid character"); continue;
+. yyerror (yylloc, "syntax error, invalid character"); continue;
<<EOF>> return TOK_YYEOF;
%%
--
2.28.0
- [PATCH 07/17] multistart: adjust computation of initial core and adjust reports, (continued)
- [PATCH 07/17] multistart: adjust computation of initial core and adjust reports, Akim Demaille, 2020/09/20
- [PATCH 08/17] multistart: also check the HTML report, Akim Demaille, 2020/09/20
- [PATCH 09/17] multistart: pass the list of start symbols to the backend, Akim Demaille, 2020/09/20
- [PATCH 10/17] multistart: equip yacc.c, Akim Demaille, 2020/09/20
- [PATCH 11/17] multistart: toy with it in lexcalc, Akim Demaille, 2020/09/20
- [PATCH 12/17] todo: more, Akim Demaille, 2020/09/20
- [PATCH 13/17] multistart: adjust reader checks for generated rules, Akim Demaille, 2020/09/20
- [PATCH 14/17] multistart: use b4_accept instead of action post-processing, Akim Demaille, 2020/09/20
- [PATCH 15/17] multistart: allow tokens as start symbols, Akim Demaille, 2020/09/20
- [PATCH 16/17] yacc.c: also count calls to YYERROR in yynerrs, Akim Demaille, 2020/09/20
- [PATCH 17/17] multistart: also give access to yynerrs,
Akim Demaille <=
- Re: [PATCH 00/17] RFC: multiple start symbols, Paul Eggert, 2020/09/20
- Re: [PATCH 00/17] RFC: multiple start symbols, Akim Demaille, 2020/09/23
- Re: [PATCH 00/17] RFC: multiple start symbols, Adrian Vogelsgesang, 2020/09/23
- Re: [PATCH 00/17] RFC: multiple start symbols, Akim Demaille, 2020/09/27
- Re: [PATCH 00/17] RFC: multiple start symbols, Rici Lake, 2020/09/27
- Re: multistart: returning structs, Akim Demaille, 2020/09/29
- Re: multistart: yynerrs, Akim Demaille, 2020/09/29
- Re: multistart: free choice of the start symbol, Akim Demaille, 2020/09/29