From: Paul Eggert Date: Tue, 19 Jul 2005 06:56:44 +0000 (+0000) Subject: Destructor cleanups and regularization among the three skeletons. X-Git-Tag: BISON-2_1~73 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/258b75caaa517febf55e1f6e479cbf298f9e5cde 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. --- diff --git a/ChangeLog b/ChangeLog index fca00022..65d48d64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2005-07-18 Paul Eggert + 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. diff --git a/NEWS b/NEWS index 52064e7f..ac3587eb 100644 --- a/NEWS +++ b/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 diff --git a/data/glr.c b/data/glr.c index a137bbf7..9cfaba6c 100644 --- a/data/glr.c +++ b/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; } diff --git a/data/lalr1.cc b/data/lalr1.cc index e42a2e5d..26fb920c 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -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_; } diff --git a/data/yacc.c b/data/yacc.c index a9c3cf0e..c046e5e2 100644 --- a/data/yacc.c +++ b/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); diff --git a/doc/bison.texinfo b/doc/bison.texinfo index 5f6f597a..6198c280 100644 --- a/doc/bison.texinfo +++ b/doc/bison.texinfo @@ -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. - -The @code{%destructor} directive allows for the definition of code that -is called when a symbol is thrown away. +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. + +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 diff --git a/tests/actions.at b/tests/actions.at index 8ca79669..7d7109f9 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -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. ]]) diff --git a/tests/calc.at b/tests/calc.at index 65148fc9..69b91964 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -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])