mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
yacc.c: push: initialize the pstate variables in pstate_new
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.
This commit is contained in:
@@ -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,40 +1447,7 @@ yypull_parse (yypstate *yyps]b4_user_formals[)
|
||||
return yystatus;
|
||||
}]])[
|
||||
|
||||
/* Initialize the parser data structure. */
|
||||
yypstate *
|
||||
yypstate_new (void)
|
||||
{
|
||||
yypstate *yyps;]b4_pure_if([], [[
|
||||
if (yypstate_allocated)
|
||||
return YY_NULLPTR;]])[
|
||||
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
|
||||
if (!yyps)
|
||||
return YY_NULLPTR;
|
||||
yyps->yynew = 1;]b4_pure_if([], [[
|
||||
yypstate_allocated = 1;]])[
|
||||
return yyps;
|
||||
}
|
||||
|
||||
void
|
||||
yypstate_delete (yypstate *yyps)
|
||||
{
|
||||
if (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);
|
||||
#endif]b4_lac_if([[
|
||||
if (!yyps->yynew && yyps->yyes != yyps->yyesa)
|
||||
YYSTACK_FREE (yyps->yyes);]])[
|
||||
free (yyps);]b4_pure_if([], [[
|
||||
yypstate_allocated = 0;]])[
|
||||
}
|
||||
}
|
||||
]b4_pure_if([[
|
||||
#define ]b4_prefix[nerrs yyps->]b4_prefix[nerrs]])[
|
||||
]b4_pure_if([[#define ]b4_prefix[nerrs yyps->]b4_prefix[nerrs]])[
|
||||
#define yystate yyps->yystate
|
||||
#define yyerrstatus yyps->yyerrstatus
|
||||
#define yyssa yyps->yyssa
|
||||
@@ -1475,6 +1464,50 @@ yypstate_delete (yypstate *yyps)
|
||||
#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 state stack, in case yyexpected_tokens is called
|
||||
before the first call to yyparse. */
|
||||
*yyssp = 0;
|
||||
}
|
||||
|
||||
/* Initialize the parser data structure. */
|
||||
yypstate *
|
||||
yypstate_new (void)
|
||||
{
|
||||
yypstate *yyps;]b4_pure_if([], [[
|
||||
if (yypstate_allocated)
|
||||
return YY_NULLPTR;]])[
|
||||
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
|
||||
if (!yyps)
|
||||
return YY_NULLPTR;
|
||||
yyps->yynew = 1;]b4_pure_if([], [[
|
||||
yypstate_allocated = 1;]])[
|
||||
yypstate_clear (yyps);
|
||||
return yyps;
|
||||
}
|
||||
|
||||
void
|
||||
yypstate_delete (yypstate *yyps)
|
||||
{
|
||||
if (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 && yyss != yyssa)
|
||||
YYSTACK_FREE (yyss);
|
||||
#endif]b4_lac_if([[
|
||||
if (!yyps->yynew && yyes != yyesa)
|
||||
YYSTACK_FREE (yyes);]])[
|
||||
free (yyps);]b4_pure_if([], [[
|
||||
yypstate_allocated = 0;]])[
|
||||
}
|
||||
}
|
||||
]])[
|
||||
|
||||
]b4_push_if([[
|
||||
@@ -1522,29 +1555,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 +2054,7 @@ yyreturn:
|
||||
#endif]b4_lac_if([[
|
||||
if (yyes != yyesa)
|
||||
YYSTACK_FREE (yyes);]])b4_push_if([[
|
||||
yypstate_clear (yyps);
|
||||
yyps->yynew = 1;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user