mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
Destructor cleanups and regularization among the three skeletons.
* NEWS: Document the behavior changes. * data/glr.c (yyrecoverSyntaxError): Don't bother to pop the stack before failing, as the cleanup code will do it for us now. * data/lalr1.cc (yyerrlab): Likewise. * data/glr.c (yyparse): Pop everything off the stack before freeing it, so that destructors get called properly. * data/lalr1.cc (yyreturn): Likewise. * data/yacc.c (yyreturn): Pop and destroy the start symbol, too. This is more consistent. * doc/bison.texinfo (Destructor Decl): Mention more reasons why destructors might be called. 1.875 -> 2.1. (Destructor Decl, Decl Summary, Table of Symbols): Some English-language cleanups for %destructor. * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Add output line for destructor of start symbol. * tests/calc.at (AT_CHECK_CALC): Add one to line counts, because of that same extra output line.
This commit is contained in:
19
ChangeLog
19
ChangeLog
@@ -1,5 +1,24 @@
|
||||
2005-07-18 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Destructor cleanups and regularization among the three skeletons.
|
||||
* NEWS: Document the behavior changes.
|
||||
* data/glr.c (yyrecoverSyntaxError): Don't bother to pop the
|
||||
stack before failing, as the cleanup code will do it for us now.
|
||||
* data/lalr1.cc (yyerrlab): Likewise.
|
||||
* data/glr.c (yyparse): Pop everything off the stack before
|
||||
freeing it, so that destructors get called properly.
|
||||
* data/lalr1.cc (yyreturn): Likewise.
|
||||
* data/yacc.c (yyreturn): Pop and destroy the start symbol, too.
|
||||
This is more consistent.
|
||||
* doc/bison.texinfo (Destructor Decl): Mention more reasons
|
||||
why destructors might be called. 1.875 -> 2.1.
|
||||
(Destructor Decl, Decl Summary, Table of Symbols):
|
||||
Some English-language cleanups for %destructor.
|
||||
* tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR):
|
||||
Add output line for destructor of start symbol.
|
||||
* tests/calc.at (AT_CHECK_CALC): Add one to line counts,
|
||||
because of that same extra output line.
|
||||
|
||||
* NEWS: Document minor wording changes in diagnostics of
|
||||
Bison-generated parsers.
|
||||
* data/glr.c (yyMemoryExhausted): Renamed from yyStackOverflow.
|
||||
|
||||
4
NEWS
4
NEWS
@@ -15,6 +15,10 @@ Changes in the next version (not yet released):
|
||||
has replaced "parser stack overflow", as the old message was not
|
||||
always accurate for modern Bison-generated parsers.
|
||||
|
||||
* Destructors are now called when the parser aborts, for all symbols left
|
||||
behind on the stack. Also, the start symbol is now destroyed after a
|
||||
successful parse. In both cases, the behavior was formerly inconsistent.
|
||||
|
||||
The following change was also in version 2.0a, 2005-05-22:
|
||||
|
||||
* When generating verbose diagnostics, Bison-generated parsers no longer
|
||||
|
||||
29
data/glr.c
29
data/glr.c
@@ -1846,21 +1846,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
|
||||
while (yytrue)
|
||||
{
|
||||
if (*yytokenp == YYEOF)
|
||||
{
|
||||
/* Now pop stack until empty and fail. */
|
||||
while (yystack->yytops.yystates[0] != NULL)
|
||||
{
|
||||
yyGLRState *yys = yystack->yytops.yystates[0];
|
||||
]b4_location_if([[ yystack->yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
|
||||
yydestruct ("Error: popping",
|
||||
yystos[yys->yylrState],
|
||||
&yys->yysemantics.yysval]b4_location_if([, &yys->yyloc])[);
|
||||
yystack->yytops.yystates[0] = yys->yypred;
|
||||
yystack->yynextFree -= 1;
|
||||
yystack->yyspaceLeft += 1;
|
||||
}
|
||||
yyFail (yystack][]b4_lpure_args[, NULL);
|
||||
}
|
||||
yyFail (yystack][]b4_lpure_args[, NULL);
|
||||
if (*yytokenp != YYEMPTY)
|
||||
{]b4_location_if([[
|
||||
/* We throw away the lookahead, but the error range
|
||||
@@ -2122,6 +2108,19 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
yydestruct ("Error: discarding lookahead",
|
||||
yytoken, yylvalp]b4_location_if([, yyllocp])[);
|
||||
|
||||
/* Now pop stack until empty, destroying its entries as we go. */
|
||||
while (yystack.yytops.yystates[0] != NULL)
|
||||
{
|
||||
yyGLRState *yys = yystack.yytops.yystates[0];
|
||||
]b4_location_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
|
||||
yydestruct ("Error: popping",
|
||||
yystos[yys->yylrState],
|
||||
&yys->yysemantics.yysval]b4_location_if([, &yys->yyloc])[);
|
||||
yystack.yytops.yystates[0] = yys->yypred;
|
||||
yystack.yynextFree -= 1;
|
||||
yystack.yyspaceLeft += 1;
|
||||
}
|
||||
|
||||
yyfreeGLRStack (&yystack);
|
||||
return yyresult;
|
||||
}
|
||||
|
||||
@@ -729,23 +729,11 @@ yyerrlab:
|
||||
/* If just tried and failed to reuse look-ahead token after an
|
||||
error, discard it. */
|
||||
|
||||
/* Return failure if at end of input. */
|
||||
if (yylooka_ <= yyeof_)
|
||||
{
|
||||
/* If at end of input, pop the error token,
|
||||
then the rest of the stack, then return failure. */
|
||||
/* Return failure if at end of input. */
|
||||
if (yylooka_ == yyeof_)
|
||||
for (;;)
|
||||
{
|
||||
yyerror_range_[0] = yylocation_stack_[0];
|
||||
yypop_ ();
|
||||
if (yystate_stack_.height () == 1)
|
||||
YYABORT;
|
||||
yydestruct_ ("Error: popping",
|
||||
yystos_[yystate_stack_[0]],
|
||||
&yysemantic_stack_[0],
|
||||
&yylocation_stack_[0]);
|
||||
}
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -768,7 +756,7 @@ yyerrorlab:
|
||||
YYERROR and the label yyerrorlab therefore never appears in user
|
||||
code. */
|
||||
if (false)
|
||||
goto yyerrorlab;
|
||||
goto yyerrorlab;
|
||||
|
||||
yyerror_range_[0] = yylocation_stack_[yylen_ - 1];
|
||||
yypop_ (yylen_);
|
||||
@@ -838,6 +826,16 @@ yyabortlab:
|
||||
yyreturn:
|
||||
if (yylooka_ != yyeof_ && yylooka_ != yyempty_)
|
||||
yydestruct_ ("Error: discarding lookahead", yyilooka_, &yylval, &yylloc);
|
||||
|
||||
while (yystate_stack_.height () != 1)
|
||||
{
|
||||
yydestruct_ ("Error: popping",
|
||||
yystos_[yystate_stack_[0]],
|
||||
&yysemantic_stack_[0],
|
||||
&yylocation_stack_[0]);
|
||||
yypop_ ();
|
||||
}
|
||||
|
||||
return yyresult_;
|
||||
}
|
||||
|
||||
|
||||
19
data/yacc.c
19
data/yacc.c
@@ -1220,8 +1220,7 @@ yyerrlab:
|
||||
|
||||
if (yychar <= YYEOF)
|
||||
{
|
||||
/* If at end of input, pop the error token,
|
||||
then the rest of the stack, then return failure. */
|
||||
/* Return failure if at end of input. */
|
||||
if (yychar == YYEOF)
|
||||
YYABORT;
|
||||
}
|
||||
@@ -1333,16 +1332,12 @@ yyreturn:
|
||||
if (yychar != YYEOF && yychar != YYEMPTY)
|
||||
yydestruct ("Error: discarding lookahead",
|
||||
yytoken, &yylval]b4_location_if([, &yylloc])[);
|
||||
if (yyssp != yyss)
|
||||
for (;;)
|
||||
{
|
||||
]b4_location_if([[ yyerror_range[0] = *yylsp;]])[
|
||||
YYPOPSTACK;
|
||||
if (yyssp == yyss)
|
||||
break;
|
||||
yydestruct ("Error: popping",
|
||||
yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
|
||||
}
|
||||
while (yyssp != yyss)
|
||||
{
|
||||
yydestruct ("Error: popping",
|
||||
yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
|
||||
YYPOPSTACK;
|
||||
}
|
||||
#ifndef yyoverflow
|
||||
if (yyss != yyssa)
|
||||
YYSTACK_FREE (yyss);
|
||||
|
||||
@@ -3792,28 +3792,31 @@ For instance, if your locations use a file name, you may use
|
||||
@cindex freeing discarded symbols
|
||||
@findex %destructor
|
||||
|
||||
Some symbols can be discarded by the parser. For instance, during error
|
||||
recovery (@pxref{Error Recovery}), embarrassing symbols already pushed
|
||||
on the stack, and embarrassing tokens coming from the rest of the file
|
||||
are thrown away until the parser falls on its feet. If these symbols
|
||||
convey heap based information, this memory is lost. While this behavior
|
||||
can be tolerable for batch parsers, such as in compilers, it is not for
|
||||
possibly ``never ending'' parsers such as shells, or implementations of
|
||||
communication protocols.
|
||||
Some symbols can be discarded by the parser. During error
|
||||
recovery (@pxref{Error Recovery}), symbols already pushed
|
||||
on the stack and tokens coming from the rest of the file
|
||||
are discarded until the parser falls on its feet. If the parser
|
||||
runs out of memory, all the symbols on the stack must be discarded.
|
||||
Even if the parser succeeds, it must discard the start symbol.
|
||||
|
||||
The @code{%destructor} directive allows for the definition of code that
|
||||
is called when a symbol is thrown away.
|
||||
When discarded symbols convey heap based information, this memory is
|
||||
lost. While this behavior can be tolerable for batch parsers, such as
|
||||
in traditional compilers, it is unacceptable for programs like shells
|
||||
or protocol implementations that may parse and execute indefinitely.
|
||||
|
||||
The @code{%destructor} directive defines code that
|
||||
is called when a symbol is discarded.
|
||||
|
||||
@deffn {Directive} %destructor @{ @var{code} @} @var{symbols}
|
||||
@findex %destructor
|
||||
Declare that the @var{code} must be invoked for each of the
|
||||
@var{symbols} that will be discarded by the parser. The @var{code}
|
||||
should use @code{$$} to designate the semantic value associated to the
|
||||
@var{symbols}. The additional parser parameters are also available
|
||||
Invoke @var{code} whenever the parser discards one of the
|
||||
@var{symbols}. Within @var{code}, @code{$$} designates the semantic
|
||||
value associated with the discarded symbol. The additional
|
||||
parser parameters are also available
|
||||
(@pxref{Parser Function, , The Parser Function @code{yyparse}}).
|
||||
|
||||
@strong{Warning:} as of Bison 1.875, this feature is still considered as
|
||||
experimental, as there was not enough user feedback. In particular,
|
||||
@strong{Warning:} as of Bison 2.1, this feature is still
|
||||
experimental, as there has not been enough user feedback. In particular,
|
||||
the syntax might still change.
|
||||
@end deffn
|
||||
|
||||
@@ -3830,7 +3833,7 @@ For instance:
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
guarantees that when a @code{STRING} or a @code{string} will be discarded,
|
||||
guarantees that when a @code{STRING} or a @code{string} is discarded,
|
||||
its associated memory will be freed.
|
||||
|
||||
Note that in the future, Bison might also consider that right hand side
|
||||
@@ -3862,8 +3865,11 @@ stacked symbols popped during the first phase of error recovery,
|
||||
@item
|
||||
incoming terminals during the second phase of error recovery,
|
||||
@item
|
||||
the current look-ahead when the parser aborts (either via an explicit
|
||||
call to @code{YYABORT}, or as a consequence of a failed error recovery).
|
||||
the current look-ahead and the entire stack when the parser aborts
|
||||
(either via an explicit call to @code{YYABORT}, or as a consequence of
|
||||
a failed error recovery or of memory exhaustion), and
|
||||
@item
|
||||
the start symbol, when the parser succeeds.
|
||||
@end itemize
|
||||
|
||||
|
||||
@@ -4085,7 +4091,7 @@ above-mentioned declarations and to the token type codes.
|
||||
@end deffn
|
||||
|
||||
@deffn {Directive} %destructor
|
||||
Specifying how the parser should reclaim the memory associated to
|
||||
Specify how the parser should reclaim the memory associated to
|
||||
discarded symbols. @xref{Destructor Decl, , Freeing Discarded Symbols}.
|
||||
@end deffn
|
||||
|
||||
@@ -7821,7 +7827,7 @@ Bison declaration to create a header file meant for the scanner.
|
||||
@end deffn
|
||||
|
||||
@deffn {Directive} %destructor
|
||||
Specifying how the parser should reclaim the memory associated to
|
||||
Specify how the parser should reclaim the memory associated to
|
||||
discarded symbols. @xref{Destructor Decl, , Freeing Discarded Symbols}.
|
||||
@end deffn
|
||||
|
||||
|
||||
@@ -373,6 +373,7 @@ line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
|
||||
sending: EOF (3@30-39)
|
||||
input (0@29-29): /* Nothing */
|
||||
input (2@0-29): line (0@0-29) input (0@29-29)
|
||||
Freeing nterm input (2@0-29)
|
||||
Successful parse.
|
||||
]])
|
||||
|
||||
@@ -391,6 +392,7 @@ line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
|
||||
sending: EOF (3@30-39)
|
||||
input (0@29-29): /* Nothing */
|
||||
input (2@0-29): line (-1@0-29) input (0@29-29)
|
||||
Freeing nterm input (2@0-29)
|
||||
Successful parse.
|
||||
]])
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ _AT_CHECK_CALC([$1],
|
||||
|
||||
2^2^3 = 256
|
||||
(2^2)^3 = 64],
|
||||
[570])
|
||||
[571])
|
||||
|
||||
# Some syntax errors.
|
||||
_AT_CHECK_CALC_ERROR([$1], [1], [0 0], [13],
|
||||
@@ -501,7 +501,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
|
||||
#
|
||||
_AT_CHECK_CALC_ERROR([$1], [0],
|
||||
[() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
|
||||
[188],
|
||||
[189],
|
||||
[1.1: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
|
||||
1.17: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
|
||||
1.22: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
||||
@@ -510,10 +510,10 @@ calc: error: 4444 != 1])
|
||||
|
||||
# The same, but this time exercising explicitly triggered syntax errors.
|
||||
# POSIX says the look-ahead causing the error should not be discarded.
|
||||
_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (0 0) = 1], [75],
|
||||
_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (0 0) = 1], [76],
|
||||
[1.9: syntax error, unexpected number
|
||||
calc: error: 2222 != 1])
|
||||
_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (0 0) = 1], [85],
|
||||
_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (0 0) = 1], [86],
|
||||
[1.3: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
||||
1.11: syntax error, unexpected number
|
||||
calc: error: 2222 != 1])
|
||||
|
||||
Reference in New Issue
Block a user