[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 5/6] yacc.c: push: initialize the pstate variables in pstate_new
From: |
Akim Demaille |
Subject: |
[PATCH 5/6] yacc.c: push: initialize the pstate variables in pstate_new |
Date: |
Tue, 3 Mar 2020 18:35:25 +0100 |
Currently pstate_new does not set up its variables, this task is left
to yypush_parse. This was probably to share more code with usual pull
parsers, where these (local) variables are indeed initialized by
yyparse.
But as a consequence yyexpected_tokens crashes at the very beginning
of the parse, since, for instance, the stacks are not even set up.
See https://lists.gnu.org/r/bison-patches/2020-03/msg00001.html.
The fix could have very simple, but the documentation actually makes
it very clear that we can reuse a pstate for several parses:
After yypush_parse returns a status other than YYPUSH_MORE, the
parser instance yyps may be reused for a new parse.
so we need to restore the parser to its pristine state so that (i) it
is ready to run the next parse, (ii) it properly supports
yyexpected_tokens for the next run.
* data/skeletons/yacc.c (b4_initialize_parser_state_variables): New,
extracted from the top of yyparse/yypush_parse.
(yypstate_clear): New.
(yypstate_new): Use it when push parsers are enabled.
Define after the yyps macros so that we can use the same code as the
regular pull parsers.
(yyparse): Use it when push parsers are _not_ enabled.
* examples/c/bistromathic/bistromathic.test: Check the completion on
the beginning of the line.
---
TODO | 3 +
data/skeletons/yacc.c | 105 +++++++++++++---------
examples/c/bistromathic/bistromathic.test | 10 +++
examples/c/bistromathic/local.mk | 2 +-
4 files changed, 76 insertions(+), 44 deletions(-)
diff --git a/TODO b/TODO
index 65f9148d..46cc29ad 100644
--- a/TODO
+++ b/TODO
@@ -95,6 +95,9 @@ See also the item "$undefined" below.
Consider deprecating impure push parsers. They add a lot of complexity, for
a bad feature.
+It's not clear to me that yyerror_range really needs to be in pstate,
+instead of just being a local variable.
+
* Bison 3.7
** Unit rules / Injection rules (Akim Demaille)
Maybe we could expand unit rules (or "injections", see
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 9de6f7b0..38c73977 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -195,6 +195,9 @@ m4_define([b4_declare_parser_state_variables],
Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
+ /* Their size. */
+ YYPTRDIFF_T yystacksize;
+
/* The state stack. */
yy_state_t yyssa[YYINITDEPTH];
yy_state_t *yyss;
@@ -211,15 +214,34 @@ m4_define([b4_declare_parser_state_variables],
YYLTYPE *yylsp;
/* The locations where the error started and ended. */
- YYLTYPE yyerror_range[3];]])[
-
- YYPTRDIFF_T yystacksize;]b4_lac_if([[
+ YYLTYPE yyerror_range[3];]])[]b4_lac_if([[
yy_state_t
yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@};
yy_state_t *yyes;
YYPTRDIFF_T yyes_capacity;]])])
+# b4_initialize_parser_state_variables
+# ------------------------------------
+# Initialize these variables.
+m4_define([b4_initialize_parser_state_variables],
+[[ yynerrs = 0;
+ yystate = 0;
+ yyerrstatus = 0;
+
+ yystacksize = YYINITDEPTH;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;]b4_locations_if([[
+ yylsp = yyls = yylsa;]])[]b4_lac_if([[
+
+ yyes = yyesa;
+ yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
+ if (YYMAXDEPTH < yyes_capacity)
+ yyes_capacity = YYMAXDEPTH;]])[
+]])
+
+
+
# _b4_declare_yyparse_push
# ------------------------
# Declaration of yyparse (and dependencies) when using the push parser
@@ -328,6 +350,7 @@ m4_if(b4_api_prefix, [yy], [],
#define yypush_parse ]b4_prefix[push_parse]b4_pull_if([[
#define yypull_parse ]b4_prefix[pull_parse]])[
#define yypstate_new ]b4_prefix[pstate_new
+#define yypstate_clear ]b4_prefix[pstate_clear
#define yypstate_delete ]b4_prefix[pstate_delete
#define yypstate ]b4_prefix[pstate]])[
#define yylex ]b4_prefix[lex
@@ -1382,8 +1405,7 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
]b4_push_if([[
struct yypstate
{]b4_declare_parser_state_variables[
- /* Used to determine if this is the first time this instance has
- been used. */
+ /* Whether this instance has not started parsing yet. */
int yynew;
};]b4_pure_if([], [[
@@ -1425,6 +1447,31 @@ yypull_parse (yypstate *yyps]b4_user_formals[)
return yystatus;
}]])[
+]b4_pure_if([[#define ]b4_prefix[nerrs yyps->]b4_prefix[nerrs]])[
+#define yystate yyps->yystate
+#define yyerrstatus yyps->yyerrstatus
+#define yyssa yyps->yyssa
+#define yyss yyps->yyss
+#define yyssp yyps->yyssp
+#define yyvsa yyps->yyvsa
+#define yyvs yyps->yyvs
+#define yyvsp yyps->yyvsp]b4_locations_if([[
+#define yylsa yyps->yylsa
+#define yyls yyps->yyls
+#define yylsp yyps->yylsp
+#define yyerror_range yyps->yyerror_range]])[
+#define yystacksize yyps->yystacksize]b4_lac_if([[
+#define yyesa yyps->yyesa
+#define yyes yyps->yyes
+#define yyes_capacity yyps->yyes_capacity]])[
+
+/* Initialize the parser data structure. */
+void
+yypstate_clear (yypstate *yyps)
+{
+]b4_initialize_parser_state_variables[
+}
+
/* Initialize the parser data structure. */
yypstate *
yypstate_new (void)
@@ -1437,6 +1484,7 @@ yypstate_new (void)
return YY_NULLPTR;
yyps->yynew = 1;]b4_pure_if([], [[
yypstate_allocated = 1;]])[
+ yypstate_clear (yyps);
return yyps;
}
@@ -1448,33 +1496,15 @@ yypstate_delete (yypstate *yyps)
#ifndef yyoverflow
/* If the stack was reallocated but the parse did not complete, then the
stack still needs to be freed. */
- if (!yyps->yynew && yyps->yyss != yyps->yyssa)
- YYSTACK_FREE (yyps->yyss);
+ if (!yyps->yynew && yyss != yyssa)
+ YYSTACK_FREE (yyss);
#endif]b4_lac_if([[
- if (!yyps->yynew && yyps->yyes != yyps->yyesa)
- YYSTACK_FREE (yyps->yyes);]])[
+ if (!yyps->yynew && yyes != yyesa)
+ YYSTACK_FREE (yyes);]])[
free (yyps);]b4_pure_if([], [[
yypstate_allocated = 0;]])[
}
}
-]b4_pure_if([[
-#define ]b4_prefix[nerrs yyps->]b4_prefix[nerrs]])[
-#define yystate yyps->yystate
-#define yyerrstatus yyps->yyerrstatus
-#define yyssa yyps->yyssa
-#define yyss yyps->yyss
-#define yyssp yyps->yyssp
-#define yyvsa yyps->yyvsa
-#define yyvs yyps->yyvs
-#define yyvsp yyps->yyvsp]b4_locations_if([[
-#define yylsa yyps->yylsa
-#define yyls yyps->yyls
-#define yylsp yyps->yylsp
-#define yyerror_range yyps->yyerror_range]])[
-#define yystacksize yyps->yystacksize]b4_lac_if([[
-#define yyesa yyps->yyesa
-#define yyes yyps->yyes
-#define yyes_capacity yyps->yyes_capacity]])[
]])[
]b4_push_if([[
@@ -1522,29 +1552,17 @@ yyparse (]m4_ifset([b4_parse_param],
[b4_formals(b4_parse_param)], [void])[)]])[
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
- int yylen = 0;]b4_push_if([[
-
+ int yylen = 0;
+]b4_push_if([[
if (!yyps->yynew)
{
yyn = yypact[yystate];
goto yyread_pushed_token;
- }]])[
-
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;]b4_locations_if([[
- yylsp = yyls = yylsa;]])[
- yystacksize = YYINITDEPTH;]b4_lac_if([[
-
- yyes = yyesa;
- yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
- if (YYMAXDEPTH < yyes_capacity)
- yyes_capacity = YYMAXDEPTH;]])[
+ }]], [
+b4_initialize_parser_state_variables])[
YYDPRINTF ((stderr, "Starting parse\n"));
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [], [],
@@ -2033,6 +2051,7 @@ yyreturn:
#endif]b4_lac_if([[
if (yyes != yyesa)
YYSTACK_FREE (yyes);]])b4_push_if([[
+ yypstate_clear (yyps);
yyps->yynew = 1;
diff --git a/examples/c/bistromathic/bistromathic.test
b/examples/c/bistromathic/bistromathic.test
index a877bea3..4f64b1a1 100755
--- a/examples/c/bistromathic/bistromathic.test
+++ b/examples/c/bistromathic/bistromathic.test
@@ -102,3 +102,13 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF
run 0 '> (atan ( ''
> err: 1.9: syntax error: expected - or ( or double precision number or
> function or variable before end of file'
+
+# Check the completion at the very beginning.
+sed -e 's/\\t/ /g' >input <<EOF
+e\t\t
+EOF
+run 0 '> e
+end of file exit exp ''
+> e
+0
+> err: '
diff --git a/examples/c/bistromathic/local.mk b/examples/c/bistromathic/local.mk
index 920265f6..cab026e2 100644
--- a/examples/c/bistromathic/local.mk
+++ b/examples/c/bistromathic/local.mk
@@ -23,7 +23,7 @@ check_PROGRAMS += %D%/bistromathic
TESTS += %D%/bistromathic.test
EXTRA_DIST += %D%/bistromathic.test
nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h
-%D%/calc.c: $(dependencies)
+%D%/parse.c: $(dependencies)
# Don't use gnulib's system headers.
%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
--
2.25.1
- [PATCH 0/6] Address some limitations in the bistro example, Akim Demaille, 2020/03/03
- [PATCH 1/6] bistromathic: check completion, Akim Demaille, 2020/03/03
- [PATCH 2/6] bistromathic: don't require spaces after operators for completion, Akim Demaille, 2020/03/03
- [PATCH 3/6] bistromathic: properly compute the lcp, as expected by readline, Akim Demaille, 2020/03/03
- [PATCH 4/6] style: formatting changes, Akim Demaille, 2020/03/03
- [PATCH 6/6] yacc.c: push: undefine the pstate macros for the epilogue, Akim Demaille, 2020/03/03
- [PATCH 5/6] yacc.c: push: initialize the pstate variables in pstate_new,
Akim Demaille <=