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.
This commit is contained in:
Akim Demaille
2005-12-21 15:28:30 +00:00
parent e14d0ab687
commit a85284cfbd
6 changed files with 89 additions and 79 deletions

View File

@@ -1,3 +1,19 @@
2005-12-21 Akim Demaille <akim@epita.fr>
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 <juan.guerrero@gmx.de>
* Makefile.am: DJGPP specific files added to EXTRA_DIST.

5
NEWS
View File

@@ -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

View File

@@ -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)

View File

@@ -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",

View File

@@ -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;
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
/* Discard the token being shifted unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
*++yyvsp = yylval;
]b4_location_if([ *++yylsp = yylloc;])[
/* 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 shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
yystate = yyn;
*++yyvsp = yylval;
]b4_location_if([ *++yylsp = yylloc;])[
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)

View File

@@ -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