From a85284cfbd1334c940e65b59c44ada379029e074 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 21 Dec 2005 15:28:30 +0000 Subject: [PATCH] YYACCEPT, YYERROR, and YYABORT, as user actions, should not destroy the RHS symbols of a rule. * data/yacc.c (yylen): Initialize to 0. Keep its value to the number of items to possibly shift. In particular, a regular successful parse that ends on YYFINAL by a (internal) YYACCEPT must not have yylen != 0. (yyerrorlab, yyreturn): Pop the RHS. Reorder a bit to emphasize the `shifting' bits of code. (YYPOPSTACK): Now accept a number of items to pop. * data/lalr1.cc: Likewise. * data/glr.c: Formatting changes. Use goto instead of fall through. * doc/bison.texinfo (Destructor Decl): Complete. --- ChangeLog | 16 +++++++++++++ NEWS | 5 ++++ data/glr.c | 16 ++++++------- data/lalr1.cc | 18 +++++++++----- data/yacc.c | 60 +++++++++++++++++++++++------------------------ doc/bison.texinfo | 49 +++++++++++++------------------------- 6 files changed, 87 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index acc1daa4..30d15330 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2005-12-21 Akim Demaille + + YYACCEPT, YYERROR, and YYABORT, as user actions, should not + destroy the RHS symbols of a rule. + * data/yacc.c (yylen): Initialize to 0. + Keep its value to the number of items to possibly shift. + In particular, a regular successful parse that ends on YYFINAL by + a (internal) YYACCEPT must not have yylen != 0. + (yyerrorlab, yyreturn): Pop the RHS. + Reorder a bit to emphasize the `shifting' bits of code. + (YYPOPSTACK): Now accept a number of items to pop. + * data/lalr1.cc: Likewise. + * data/glr.c: Formatting changes. + Use goto instead of fall through. + * doc/bison.texinfo (Destructor Decl): Complete. + 2005-12-20 Juan Manuel Guerrero * Makefile.am: DJGPP specific files added to EXTRA_DIST. diff --git a/NEWS b/NEWS index 2aeeaf8a..29310169 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,11 @@ Bison News Changes in version 2.1a: +* %destructor vs. YYACCEPT, YYERROR, and YYABORT. + When the parsing/action is cut by the user using one of these + special actions, the stack is freed except the right-hand side + symbols of the current rule. + * GLR, C++ LALR(1) parsers. These parser skeletons are now distributed with the same special license exception that the C LALR(1) parser skeleton has had since diff --git a/data/glr.c b/data/glr.c index 9a441883..c17eb3c2 100644 --- a/data/glr.c +++ b/data/glr.c @@ -909,10 +909,12 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp, *yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval; YYLLOC_DEFAULT (*yylocp, yyvsp - yyrhslen, yyrhslen); ]b4_location_if([[ yystackp->yyerror_range[1].yystate.yyloc = *yylocp; -]]) +]])[ switch (yyn) { - b4_actions + ]b4_actions +/* Line __line__ of glr.c. */ +b4_syncline([@oline@], [@ofile@])[ default: break; } @@ -924,8 +926,6 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp, # undef YYBACKUP # undef yyclearin # undef YYRECOVERING -/* Line __line__ of glr.c. */ -b4_syncline([@oline@], [@ofile@]) } @@ -937,11 +937,11 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1) switch (yyn) { - b4_mergers + ]b4_mergers[ default: break; } } -[ + /* Bison grammar-table manipulation. */ ]b4_yydestruct_generate([b4_c_ansi_function_def])[ @@ -2324,7 +2324,7 @@ b4_syncline([@oline@], [@ofile@])])dnl yybuglab: YYASSERT (yyfalse); - /* Fall through. */ + goto yyabortlab; yyabortlab: yyresult = 1; @@ -2333,7 +2333,7 @@ b4_syncline([@oline@], [@ofile@])])dnl yyexhaustedlab: yyerror (]b4_lyyerror_args[YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ + goto yyreturn; yyreturn: if (yytoken != YYEOF && yytoken != YYEMPTY) diff --git a/data/lalr1.cc b/data/lalr1.cc index d0f3a730..d9d9af9d 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -509,7 +509,7 @@ namespace yy /* State. */ int yyn; - int yylen; + int yylen = 0; int yystate = 0; /* Error handling. */ @@ -641,7 +641,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; `-----------------------------*/ yyreduce: yylen = yyr2_[yyn]; - /* If LEN_ is nonzero, implement the default value of the action: + /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. Otherwise, the following line sets YYVAL to garbage. @@ -659,15 +659,15 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[; YY_REDUCE_PRINT (yyn); switch (yyn) { - ]b4_actions[ + ]b4_actions + /* Line __line__ of lalr1.cc. */ +b4_syncline([@oline@], [@ofile@])[ default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc); - /* Line __line__ of lalr1.cc. */ -]b4_syncline([@oline@], [@ofile@])[ yypop_ (yylen); - + yylen = 0; YY_STACK_PRINT (); yysemantic_stack_.push (yyval); @@ -731,7 +731,10 @@ b4_error_verbose_if([, yytoken])[)); goto yyerrorlab; yyerror_range[0] = yylocation_stack_[yylen - 1]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ yypop_ (yylen); + yylen = 0; yystate = yystate_stack_[0]; goto yyerrlab1; @@ -799,6 +802,9 @@ b4_error_verbose_if([, yytoken])[)); if (yychar != yyeof_ && yychar != yyempty_) yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + yypop_ (yylen); while (yystate_stack_.height () != 1) { yydestruct_ ("Cleanup: popping", diff --git a/data/yacc.c b/data/yacc.c index 79fc63dc..4e21c5e2 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -564,7 +564,7 @@ do \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ + YYPOPSTACK (1); \ goto yybackup; \ } \ else \ @@ -1042,7 +1042,7 @@ b4_c_function_def([yyparse], [int], b4_parse_param) /* The locations where the error started and ended. */ YYLTYPE yyerror_range[2];]])[ -#define YYPOPSTACK (yyvsp--, yyssp--]b4_location_if([, yylsp--])[) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)]b4_location_if([, yylsp -= (N)])[) YYSIZE_T yystacksize = YYINITDEPTH; @@ -1051,9 +1051,9 @@ b4_c_function_def([yyparse], [int], b4_parse_param) YYSTYPE yyval; ]b4_location_if([ YYLTYPE yyloc;])[ - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped off. */ + int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1178,12 +1178,10 @@ m4_ifdef([b4_at_dollar_used], [[ yylsp[0] = yylloc; `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a look-ahead token if we need one and don't already have one. */ -/* yyresume: */ + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ - yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; @@ -1225,22 +1223,21 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the token being shifted unless it is eof. */ + /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; + yystate = yyn; *++yyvsp = yylval; ]b4_location_if([ *++yylsp = yylloc;])[ - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - yystate = yyn; goto yynewstate; @@ -1277,18 +1274,15 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - ]b4_actions[ + ]b4_actions +/* Line __line__ of yacc.c. */ +b4_syncline([@oline@], [@ofile@])[ default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); -/* Line __line__ of yacc.c. */ -]b4_syncline([@oline@], [@ofile@])[ - - yyvsp -= yylen; - yyssp -= yylen; -]b4_location_if([ yylsp -= yylen;])[ - + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; @@ -1392,9 +1386,11 @@ yyerrorlab: goto yyerrorlab; ]b4_location_if([[ yyerror_range[0] = yylsp[1-yylen]; - yylsp -= yylen; - ]])[yyvsp -= yylen; - yyssp -= yylen; +]])[ /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; @@ -1426,7 +1422,7 @@ yyerrlab1: ]b4_location_if([[ yyerror_range[0] = *yylsp;]])[ yydestruct ("Error: popping", yystos[yystate], yyvsp]b4_location_if([, yylsp])[]b4_user_args[); - YYPOPSTACK; + YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } @@ -1477,11 +1473,15 @@ yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval]b4_location_if([, &yylloc])[]b4_user_args[); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[]b4_user_args[); - YYPOPSTACK; + YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) diff --git a/doc/bison.texinfo b/doc/bison.texinfo index 641e6db5..acc3be5d 100644 --- a/doc/bison.texinfo +++ b/doc/bison.texinfo @@ -3810,20 +3810,20 @@ 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. 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. +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, +or if the parsing is cut by @code{YYACCEPT} or @code{YYABORT}, 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. +The @code{%destructor} directive defines code that is called when a +symbol is automatically discarded. @deffn {Directive} %destructor @{ @var{code} @} @var{symbols} @findex %destructor @@ -3832,10 +3832,6 @@ 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 2.1, this feature is still -experimental, as there has not been enough user feedback. In particular, -the syntax might still change. @end deffn For instance: @@ -3854,24 +3850,6 @@ For instance: 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 -members that are not mentioned in the action can be destroyed. For -instance, in: - -@smallexample -comment: "/*" STRING "*/"; -@end smallexample - -@noindent -the parser is entitled to destroy the semantic value of the -@code{string}. Of course, this will not apply to the default action; -compare: - -@smallexample -typeless: string; // $$ = $1 does not apply; $1 is destroyed. -typefull: string; // $$ = $1 applies, $1 is not destroyed. -@end smallexample - @sp 1 @cindex discarded symbols @@ -3883,13 +3861,18 @@ 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 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 +the current look-ahead and the entire stack (except the current +right-hand side symbols) when the parser aborts (either via an explicit +call to @code{YYABORT} or @code{YYACCEPT}, or as a consequence of a +failed error recovery or of memory exhaustion), and @item the start symbol, when the parser succeeds. @end itemize +Note that right-hand size symbols of a rule that explicitly triggers a +syntax error via @code{YYERROR} are not reclaimed. As a thumb rule, +destructors are invoked only when you do not have other means to manage +the memory. @node Expect Decl @subsection Suppressing Conflict Warnings -- 2.45.2