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:
Paul Eggert
2005-07-19 06:56:44 +00:00
parent 6088a2a04d
commit 258b75caaa
8 changed files with 90 additions and 67 deletions

View File

@@ -1,5 +1,24 @@
2005-07-18 Paul Eggert <eggert@cs.ucla.edu> 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 * NEWS: Document minor wording changes in diagnostics of
Bison-generated parsers. Bison-generated parsers.
* data/glr.c (yyMemoryExhausted): Renamed from yyStackOverflow. * data/glr.c (yyMemoryExhausted): Renamed from yyStackOverflow.

4
NEWS
View File

@@ -15,6 +15,10 @@ Changes in the next version (not yet released):
has replaced "parser stack overflow", as the old message was not has replaced "parser stack overflow", as the old message was not
always accurate for modern Bison-generated parsers. 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: The following change was also in version 2.0a, 2005-05-22:
* When generating verbose diagnostics, Bison-generated parsers no longer * When generating verbose diagnostics, Bison-generated parsers no longer

View File

@@ -1846,21 +1846,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
while (yytrue) while (yytrue)
{ {
if (*yytokenp == YYEOF) if (*yytokenp == YYEOF)
{ yyFail (yystack][]b4_lpure_args[, NULL);
/* 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);
}
if (*yytokenp != YYEMPTY) if (*yytokenp != YYEMPTY)
{]b4_location_if([[ {]b4_location_if([[
/* We throw away the lookahead, but the error range /* We throw away the lookahead, but the error range
@@ -2122,6 +2108,19 @@ b4_syncline([@oline@], [@ofile@])])dnl
yydestruct ("Error: discarding lookahead", yydestruct ("Error: discarding lookahead",
yytoken, yylvalp]b4_location_if([, yyllocp])[); 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); yyfreeGLRStack (&yystack);
return yyresult; return yyresult;
} }

View File

@@ -729,23 +729,11 @@ yyerrlab:
/* If just tried and failed to reuse look-ahead token after an /* If just tried and failed to reuse look-ahead token after an
error, discard it. */ error, discard it. */
/* Return failure if at end of input. */
if (yylooka_ <= yyeof_) if (yylooka_ <= yyeof_)
{ {
/* If at end of input, pop the error token, /* Return failure if at end of input. */
then the rest of the stack, then return failure. */
if (yylooka_ == yyeof_) if (yylooka_ == yyeof_)
for (;;) YYABORT;
{
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]);
}
} }
else else
{ {
@@ -768,7 +756,7 @@ yyerrorlab:
YYERROR and the label yyerrorlab therefore never appears in user YYERROR and the label yyerrorlab therefore never appears in user
code. */ code. */
if (false) if (false)
goto yyerrorlab; goto yyerrorlab;
yyerror_range_[0] = yylocation_stack_[yylen_ - 1]; yyerror_range_[0] = yylocation_stack_[yylen_ - 1];
yypop_ (yylen_); yypop_ (yylen_);
@@ -838,6 +826,16 @@ yyabortlab:
yyreturn: yyreturn:
if (yylooka_ != yyeof_ && yylooka_ != yyempty_) if (yylooka_ != yyeof_ && yylooka_ != yyempty_)
yydestruct_ ("Error: discarding lookahead", yyilooka_, &yylval, &yylloc); 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_; return yyresult_;
} }

View File

@@ -1220,8 +1220,7 @@ yyerrlab:
if (yychar <= YYEOF) if (yychar <= YYEOF)
{ {
/* If at end of input, pop the error token, /* Return failure if at end of input. */
then the rest of the stack, then return failure. */
if (yychar == YYEOF) if (yychar == YYEOF)
YYABORT; YYABORT;
} }
@@ -1333,16 +1332,12 @@ yyreturn:
if (yychar != YYEOF && yychar != YYEMPTY) if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Error: discarding lookahead", yydestruct ("Error: discarding lookahead",
yytoken, &yylval]b4_location_if([, &yylloc])[); yytoken, &yylval]b4_location_if([, &yylloc])[);
if (yyssp != yyss) while (yyssp != yyss)
for (;;) {
{ yydestruct ("Error: popping",
]b4_location_if([[ yyerror_range[0] = *yylsp;]])[ yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
YYPOPSTACK; YYPOPSTACK;
if (yyssp == yyss) }
break;
yydestruct ("Error: popping",
yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
}
#ifndef yyoverflow #ifndef yyoverflow
if (yyss != yyssa) if (yyss != yyssa)
YYSTACK_FREE (yyss); YYSTACK_FREE (yyss);

View File

@@ -3792,28 +3792,31 @@ For instance, if your locations use a file name, you may use
@cindex freeing discarded symbols @cindex freeing discarded symbols
@findex %destructor @findex %destructor
Some symbols can be discarded by the parser. For instance, during error Some symbols can be discarded by the parser. During error
recovery (@pxref{Error Recovery}), embarrassing symbols already pushed recovery (@pxref{Error Recovery}), symbols already pushed
on the stack, and embarrassing tokens coming from the rest of the file on the stack and tokens coming from the rest of the file
are thrown away until the parser falls on its feet. If these symbols are discarded until the parser falls on its feet. If the parser
convey heap based information, this memory is lost. While this behavior runs out of memory, all the symbols on the stack must be discarded.
can be tolerable for batch parsers, such as in compilers, it is not for Even if the parser succeeds, it must discard the start symbol.
possibly ``never ending'' parsers such as shells, or implementations of
communication protocols.
The @code{%destructor} directive allows for the definition of code that When discarded symbols convey heap based information, this memory is
is called when a symbol is thrown away. 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} @deffn {Directive} %destructor @{ @var{code} @} @var{symbols}
@findex %destructor @findex %destructor
Declare that the @var{code} must be invoked for each of the Invoke @var{code} whenever the parser discards one of the
@var{symbols} that will be discarded by the parser. The @var{code} @var{symbols}. Within @var{code}, @code{$$} designates the semantic
should use @code{$$} to designate the semantic value associated to the value associated with the discarded symbol. The additional
@var{symbols}. The additional parser parameters are also available parser parameters are also available
(@pxref{Parser Function, , The Parser Function @code{yyparse}}). (@pxref{Parser Function, , The Parser Function @code{yyparse}}).
@strong{Warning:} as of Bison 1.875, this feature is still considered as @strong{Warning:} as of Bison 2.1, this feature is still
experimental, as there was not enough user feedback. In particular, experimental, as there has not been enough user feedback. In particular,
the syntax might still change. the syntax might still change.
@end deffn @end deffn
@@ -3830,7 +3833,7 @@ For instance:
@end smallexample @end smallexample
@noindent @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. its associated memory will be freed.
Note that in the future, Bison might also consider that right hand side 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 @item
incoming terminals during the second phase of error recovery, incoming terminals during the second phase of error recovery,
@item @item
the current look-ahead when the parser aborts (either via an explicit the current look-ahead and the entire stack when the parser aborts
call to @code{YYABORT}, or as a consequence of a failed error recovery). (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 @end itemize
@@ -4085,7 +4091,7 @@ above-mentioned declarations and to the token type codes.
@end deffn @end deffn
@deffn {Directive} %destructor @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}. discarded symbols. @xref{Destructor Decl, , Freeing Discarded Symbols}.
@end deffn @end deffn
@@ -7821,7 +7827,7 @@ Bison declaration to create a header file meant for the scanner.
@end deffn @end deffn
@deffn {Directive} %destructor @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}. discarded symbols. @xref{Destructor Decl, , Freeing Discarded Symbols}.
@end deffn @end deffn

View File

@@ -373,6 +373,7 @@ line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
sending: EOF (3@30-39) sending: EOF (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 nterm input (2@0-29)
Successful parse. Successful parse.
]]) ]])
@@ -391,6 +392,7 @@ line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
sending: EOF (3@30-39) sending: EOF (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 nterm input (2@0-29)
Successful parse. Successful parse.
]]) ]])

View File

@@ -463,7 +463,7 @@ _AT_CHECK_CALC([$1],
2^2^3 = 256 2^2^3 = 256
(2^2)^3 = 64], (2^2)^3 = 64],
[570]) [571])
# Some syntax errors. # Some syntax errors.
_AT_CHECK_CALC_ERROR([$1], [1], [0 0], [13], _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], _AT_CHECK_CALC_ERROR([$1], [0],
[() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1], [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
[188], [189],
[1.1: syntax error, unexpected ')', expecting number or '-' or '(' or '!' [1.1: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
1.17: 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 '!' 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. # The same, but this time exercising explicitly triggered syntax errors.
# POSIX says the look-ahead causing the error should not be discarded. # 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 [1.9: syntax error, unexpected number
calc: error: 2222 != 1]) 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.3: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
1.11: syntax error, unexpected number 1.11: syntax error, unexpected number
calc: error: 2222 != 1]) calc: error: 2222 != 1])