mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-20 09:43:03 +00:00
Clean up handling of %destructor for the end token (token 0).
Discussed starting at <http://lists.gnu.org/archive/html/bison-patches/2006-07/msg00019.html> and <http://lists.gnu.org/archive/html/help-bison/2006-07/msg00013.html>. Make the skeletons consistent in how they pop the end token and invoke its %destructor. * data/glr.c (yyrecoverSyntaxError, yyparse): Don't pop the start state, which has token number 0, since this would invoke the %destructor for the end token. * data/lalr1.cc (yy::parser::parse): Don't check for the final state until after shifting the end token, or else it won't be popped. * data/yacc.c (yyparse): Likewise. * data/glr.c (yyparse): Clear the lookahead after shifting it even when it's the end token. Upon termination, destroy an unshifted lookahead even when it's the end token. * data/lalr1.cc (yy::parser::parse): Likewise. * data/yacc.c (yyparse): Likewise. * src/reader.c (packgram): Don't check rule 0. This suppresses unused value warnings for the end token when the user gives the end token a %destructor. * tests/actions.at (Printers and Destructors): Test all the above.
This commit is contained in:
29
ChangeLog
29
ChangeLog
@@ -1,3 +1,32 @@
|
|||||||
|
2006-07-29 Joel E. Denny <jdenny@ces.clemson.edu>
|
||||||
|
|
||||||
|
Clean up handling of %destructor for the end token (token 0).
|
||||||
|
Discussed starting at
|
||||||
|
<http://lists.gnu.org/archive/html/bison-patches/2006-07/msg00019.html>
|
||||||
|
and
|
||||||
|
<http://lists.gnu.org/archive/html/help-bison/2006-07/msg00013.html>.
|
||||||
|
|
||||||
|
Make the skeletons consistent in how they pop the end token and invoke
|
||||||
|
its %destructor.
|
||||||
|
* data/glr.c (yyrecoverSyntaxError, yyparse): Don't pop the start
|
||||||
|
state, which has token number 0, since this would invoke the
|
||||||
|
%destructor for the end token.
|
||||||
|
* data/lalr1.cc (yy::parser::parse): Don't check for the final state
|
||||||
|
until after shifting the end token, or else it won't be popped.
|
||||||
|
* data/yacc.c (yyparse): Likewise.
|
||||||
|
|
||||||
|
* data/glr.c (yyparse): Clear the lookahead after shifting it even when
|
||||||
|
it's the end token. Upon termination, destroy an unshifted lookahead
|
||||||
|
even when it's the end token.
|
||||||
|
* data/lalr1.cc (yy::parser::parse): Likewise.
|
||||||
|
* data/yacc.c (yyparse): Likewise.
|
||||||
|
|
||||||
|
* src/reader.c (packgram): Don't check rule 0. This suppresses unused
|
||||||
|
value warnings for the end token when the user gives the end token a
|
||||||
|
%destructor.
|
||||||
|
|
||||||
|
* tests/actions.at (Printers and Destructors): Test all the above.
|
||||||
|
|
||||||
2006-07-24 Paul Eggert <eggert@cs.ucla.edu>
|
2006-07-24 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
Update to latest gnulib and gettext versions.
|
Update to latest gnulib and gettext versions.
|
||||||
|
|||||||
11
data/glr.c
11
data/glr.c
@@ -2261,7 +2261,8 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]b4_locations_if([[ yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
|
]b4_locations_if([[ yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
|
||||||
yydestroyGLRState ("Error: popping", yys]b4_user_args[);
|
if (yys->yypred != NULL)
|
||||||
|
yydestroyGLRState ("Error: popping", yys]b4_user_args[);
|
||||||
yystackp->yytops.yystates[0] = yys->yypred;
|
yystackp->yytops.yystates[0] = yys->yypred;
|
||||||
yystackp->yynextFree -= 1;
|
yystackp->yynextFree -= 1;
|
||||||
yystackp->yyspaceLeft += 1;
|
yystackp->yyspaceLeft += 1;
|
||||||
@@ -2373,8 +2374,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
if (yyisShiftAction (yyaction))
|
if (yyisShiftAction (yyaction))
|
||||||
{
|
{
|
||||||
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
||||||
if (yychar != YYEOF)
|
yychar = YYEMPTY;
|
||||||
yychar = YYEMPTY;
|
|
||||||
yyposn += 1;
|
yyposn += 1;
|
||||||
yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
|
yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
|
||||||
if (0 < yystack.yyerrState)
|
if (0 < yystack.yyerrState)
|
||||||
@@ -2490,7 +2490,7 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
goto yyreturn;
|
goto yyreturn;
|
||||||
|
|
||||||
yyreturn:
|
yyreturn:
|
||||||
if (yychar != YYEOF && yychar != YYEMPTY)
|
if (yychar != YYEMPTY)
|
||||||
yydestruct ("Cleanup: discarding lookahead",
|
yydestruct ("Cleanup: discarding lookahead",
|
||||||
YYTRANSLATE (yychar),
|
YYTRANSLATE (yychar),
|
||||||
&yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
|
&yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
|
||||||
@@ -2512,7 +2512,8 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
{
|
{
|
||||||
yyGLRState *yys = yystates[yyk];
|
yyGLRState *yys = yystates[yyk];
|
||||||
]b4_locations_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
|
]b4_locations_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
|
||||||
)[ yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
)[ if (yys->yypred != NULL)
|
||||||
|
yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
||||||
yystates[yyk] = yys->yypred;
|
yystates[yyk] = yys->yypred;
|
||||||
yystack.yynextFree -= 1;
|
yystack.yynextFree -= 1;
|
||||||
yystack.yyspaceLeft += 1;
|
yystack.yyspaceLeft += 1;
|
||||||
|
|||||||
@@ -567,6 +567,11 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
yynewstate:
|
yynewstate:
|
||||||
yystate_stack_.push (yystate);
|
yystate_stack_.push (yystate);
|
||||||
YYCDEBUG << "Entering state " << yystate << std::endl;
|
YYCDEBUG << "Entering state " << yystate << std::endl;
|
||||||
|
|
||||||
|
/* Accept? */
|
||||||
|
if (yystate == yyfinal_)
|
||||||
|
goto yyacceptlab;
|
||||||
|
|
||||||
goto yybackup;
|
goto yybackup;
|
||||||
|
|
||||||
/* Backup. */
|
/* Backup. */
|
||||||
@@ -616,16 +621,11 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
|
|||||||
goto yyreduce;
|
goto yyreduce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accept? */
|
|
||||||
if (yyn == yyfinal_)
|
|
||||||
goto yyacceptlab;
|
|
||||||
|
|
||||||
/* Shift the lookahead token. */
|
/* Shift the lookahead token. */
|
||||||
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
||||||
|
|
||||||
/* Discard the token being shifted unless it is eof. */
|
/* Discard the token being shifted. */
|
||||||
if (yychar != yyeof_)
|
yychar = yyempty_;
|
||||||
yychar = yyempty_;
|
|
||||||
|
|
||||||
yysemantic_stack_.push (yylval);
|
yysemantic_stack_.push (yylval);
|
||||||
yylocation_stack_.push (yylloc);
|
yylocation_stack_.push (yylloc);
|
||||||
@@ -780,9 +780,6 @@ b4_error_verbose_if([, yytoken])[));
|
|||||||
YY_STACK_PRINT ();
|
YY_STACK_PRINT ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyn == yyfinal_)
|
|
||||||
goto yyacceptlab;
|
|
||||||
|
|
||||||
yyerror_range[1] = yylloc;
|
yyerror_range[1] = yylloc;
|
||||||
// Using YYLLOC is tempting, but would change the location of
|
// Using YYLLOC is tempting, but would change the location of
|
||||||
// the lookahead. YYLOC is available though.
|
// the lookahead. YYLOC is available though.
|
||||||
@@ -808,7 +805,7 @@ b4_error_verbose_if([, yytoken])[));
|
|||||||
goto yyreturn;
|
goto yyreturn;
|
||||||
|
|
||||||
yyreturn:
|
yyreturn:
|
||||||
if (yychar != yyeof_ && yychar != yyempty_)
|
if (yychar != yyempty_)
|
||||||
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
|
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
|
||||||
|
|
||||||
/* Do not reclaim the symbols of the rule which action triggered
|
/* Do not reclaim the symbols of the rule which action triggered
|
||||||
|
|||||||
16
data/yacc.c
16
data/yacc.c
@@ -1164,6 +1164,9 @@ m4_ifdef([b4_at_dollar_used], [[ yylsp[0] = yylloc;
|
|||||||
|
|
||||||
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
|
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
|
||||||
|
|
||||||
|
if (yystate == YYFINAL)
|
||||||
|
YYACCEPT;
|
||||||
|
|
||||||
goto yybackup;
|
goto yybackup;
|
||||||
|
|
||||||
/*-----------.
|
/*-----------.
|
||||||
@@ -1213,9 +1216,6 @@ yybackup:
|
|||||||
goto yyreduce;
|
goto yyreduce;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyn == YYFINAL)
|
|
||||||
YYACCEPT;
|
|
||||||
|
|
||||||
/* Count tokens shifted since error; after three, turn off error
|
/* Count tokens shifted since error; after three, turn off error
|
||||||
status. */
|
status. */
|
||||||
if (yyerrstatus)
|
if (yyerrstatus)
|
||||||
@@ -1224,9 +1224,8 @@ yybackup:
|
|||||||
/* Shift the lookahead token. */
|
/* Shift the lookahead token. */
|
||||||
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
||||||
|
|
||||||
/* Discard the shifted token unless it is eof. */
|
/* Discard the shifted token. */
|
||||||
if (yychar != YYEOF)
|
yychar = YYEMPTY;
|
||||||
yychar = YYEMPTY;
|
|
||||||
|
|
||||||
yystate = yyn;
|
yystate = yyn;
|
||||||
*++yyvsp = yylval;
|
*++yyvsp = yylval;
|
||||||
@@ -1418,9 +1417,6 @@ yyerrlab1:
|
|||||||
YY_STACK_PRINT (yyss, yyssp);
|
YY_STACK_PRINT (yyss, yyssp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyn == YYFINAL)
|
|
||||||
YYACCEPT;
|
|
||||||
|
|
||||||
*++yyvsp = yylval;
|
*++yyvsp = yylval;
|
||||||
]b4_locations_if([[
|
]b4_locations_if([[
|
||||||
yyerror_range[1] = yylloc;
|
yyerror_range[1] = yylloc;
|
||||||
@@ -1461,7 +1457,7 @@ yyexhaustedlab:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
yyreturn:
|
yyreturn:
|
||||||
if (yychar != YYEOF && yychar != YYEMPTY)
|
if (yychar != YYEMPTY)
|
||||||
yydestruct ("Cleanup: discarding lookahead",
|
yydestruct ("Cleanup: discarding lookahead",
|
||||||
yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
|
yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
|
||||||
/* Do not reclaim the symbols of the rule which action triggered
|
/* Do not reclaim the symbols of the rule which action triggered
|
||||||
|
|||||||
@@ -488,7 +488,11 @@ packgram (void)
|
|||||||
rule. Thus, the midrule actions have already been scanned in order to
|
rule. Thus, the midrule actions have already been scanned in order to
|
||||||
set `used' flags for this rule's rhs, so grammar_rule_check will work
|
set `used' flags for this rule's rhs, so grammar_rule_check will work
|
||||||
properly. */
|
properly. */
|
||||||
grammar_rule_check (p);
|
/* Don't check the generated rule 0. It has no action, so some rhs
|
||||||
|
symbols may appear unused, but the parsing algorithm ensures that
|
||||||
|
%destructor's are invoked appropriately. */
|
||||||
|
if (p != grammar)
|
||||||
|
grammar_rule_check (p);
|
||||||
|
|
||||||
for (p = p->next; p && p->sym; p = p->next)
|
for (p = p->next; p && p->sym; p = p->next)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -197,8 +197,9 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;
|
|||||||
]AT_LALR1_CC_IF([], [static void yyerror (const char *msg);])
|
]AT_LALR1_CC_IF([], [static void yyerror (const char *msg);])
|
||||||
[}
|
[}
|
||||||
|
|
||||||
]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input])[
|
]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input END])[
|
||||||
|
|
||||||
|
/* FIXME: This %printer isn't actually tested. */
|
||||||
%printer
|
%printer
|
||||||
{
|
{
|
||||||
]AT_LALR1_CC_IF([debug_stream () << $$;],
|
]AT_LALR1_CC_IF([debug_stream () << $$;],
|
||||||
@@ -226,6 +227,11 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;
|
|||||||
{ printf ("Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
|
{ printf ("Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
|
||||||
'y'
|
'y'
|
||||||
|
|
||||||
|
%token END 0
|
||||||
|
%destructor
|
||||||
|
{ printf ("Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
|
||||||
|
END
|
||||||
|
|
||||||
%%
|
%%
|
||||||
/*
|
/*
|
||||||
This grammar is made to exercise error recovery.
|
This grammar is made to exercise error recovery.
|
||||||
@@ -241,7 +247,7 @@ input:
|
|||||||
printf ("input (%d@%d-%d): /* Nothing */\n", $$, RANGE (@$));
|
printf ("input (%d@%d-%d): /* Nothing */\n", $$, RANGE (@$));
|
||||||
}
|
}
|
||||||
| line input /* Right recursive to load the stack so that popping at
|
| line input /* Right recursive to load the stack so that popping at
|
||||||
EOF can be exercised. */
|
END can be exercised. */
|
||||||
{
|
{
|
||||||
$$ = 2;
|
$$ = 2;
|
||||||
printf ("input (%d@%d-%d): line (%d@%d-%d) input (%d@%d-%d)\n",
|
printf ("input (%d@%d-%d): line (%d@%d-%d) input (%d@%d-%d)\n",
|
||||||
@@ -308,7 +314,7 @@ yylex (]AT_LEX_FORMALS[)
|
|||||||
if (source[c])
|
if (source[c])
|
||||||
printf ("sending: '%c'", source[c]);
|
printf ("sending: '%c'", source[c]);
|
||||||
else
|
else
|
||||||
printf ("sending: EOF");
|
printf ("sending: END");
|
||||||
printf (" (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
|
printf (" (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
|
||||||
return source[c];
|
return source[c];
|
||||||
}
|
}
|
||||||
@@ -372,9 +378,10 @@ sending: 'x' (1@10-19)
|
|||||||
thing (1@10-19): 'x' (1@10-19)
|
thing (1@10-19): 'x' (1@10-19)
|
||||||
sending: ')' (2@20-29)
|
sending: ')' (2@20-29)
|
||||||
line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
|
line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
|
||||||
sending: EOF (3@30-39)
|
sending: END (3@30-39)
|
||||||
input (0@29-29): /* Nothing */
|
input (0@29-29): /* Nothing */
|
||||||
input (2@0-29): line (0@0-29) input (0@29-29)
|
input (2@0-29): line (0@0-29) input (0@29-29)
|
||||||
|
Freeing token END (3@30-39)
|
||||||
Freeing nterm input (2@0-29)
|
Freeing nterm input (2@0-29)
|
||||||
Successful parse.
|
Successful parse.
|
||||||
]])
|
]])
|
||||||
@@ -391,9 +398,10 @@ sending: 'y' (1@10-19)
|
|||||||
Freeing token 'y' (1@10-19)
|
Freeing token 'y' (1@10-19)
|
||||||
sending: ')' (2@20-29)
|
sending: ')' (2@20-29)
|
||||||
line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
|
line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
|
||||||
sending: EOF (3@30-39)
|
sending: END (3@30-39)
|
||||||
input (0@29-29): /* Nothing */
|
input (0@29-29): /* Nothing */
|
||||||
input (2@0-29): line (-1@0-29) input (0@29-29)
|
input (2@0-29): line (-1@0-29) input (0@29-29)
|
||||||
|
Freeing token END (3@30-39)
|
||||||
Freeing nterm input (2@0-29)
|
Freeing nterm input (2@0-29)
|
||||||
Successful parse.
|
Successful parse.
|
||||||
]])
|
]])
|
||||||
@@ -445,12 +453,45 @@ input (0@129-129): /* Nothing */
|
|||||||
input (2@100-129): line (10@100-129) input (0@129-129)
|
input (2@100-129): line (10@100-129) input (0@129-129)
|
||||||
input (2@70-129): line (7@70-99) input (2@100-129)
|
input (2@70-129): line (7@70-99) input (2@100-129)
|
||||||
input (2@0-129): line (-1@0-69) input (2@70-129)
|
input (2@0-129): line (-1@0-69) input (2@70-129)
|
||||||
130-139: syntax error, unexpected 'y', expecting $end
|
130-139: syntax error, unexpected 'y', expecting END
|
||||||
Freeing nterm input (2@0-129)
|
Freeing nterm input (2@0-129)
|
||||||
Freeing token 'y' (13@130-139)
|
Freeing token 'y' (13@130-139)
|
||||||
Parsing FAILED.
|
Parsing FAILED.
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
# Syntax error caught by the parser where lookahead = END
|
||||||
|
# --------------------------------------------------------
|
||||||
|
# Load the stack and provoke an error that cannot be caught by the
|
||||||
|
# grammar, to check that the stack is cleared. And make sure the
|
||||||
|
# lookahead is freed.
|
||||||
|
#
|
||||||
|
# '(', 'x', ')',
|
||||||
|
# '(', 'x', ')',
|
||||||
|
# 'x'
|
||||||
|
AT_PARSER_CHECK([./input '(x)(x)x'], 1,
|
||||||
|
[[sending: '(' (0@0-9)
|
||||||
|
sending: 'x' (1@10-19)
|
||||||
|
thing (1@10-19): 'x' (1@10-19)
|
||||||
|
sending: ')' (2@20-29)
|
||||||
|
line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
|
||||||
|
sending: '(' (3@30-39)
|
||||||
|
sending: 'x' (4@40-49)
|
||||||
|
thing (4@40-49): 'x' (4@40-49)
|
||||||
|
sending: ')' (5@50-59)
|
||||||
|
line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
|
||||||
|
sending: 'x' (6@60-69)
|
||||||
|
thing (6@60-69): 'x' (6@60-69)
|
||||||
|
sending: END (7@70-79)
|
||||||
|
70-79: syntax error, unexpected END, expecting 'x'
|
||||||
|
Freeing nterm thing (6@60-69)
|
||||||
|
Freeing nterm line (3@30-59)
|
||||||
|
Freeing nterm line (0@0-29)
|
||||||
|
Freeing token END (7@70-79)
|
||||||
|
Parsing FAILED.
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
# Check destruction upon stack overflow
|
# Check destruction upon stack overflow
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
# Upon stack overflow, all symbols on the stack should be destroyed.
|
# Upon stack overflow, all symbols on the stack should be destroyed.
|
||||||
|
|||||||
Reference in New Issue
Block a user