mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
* data/glr.c (yyprocessOneStack): Synchronize the shift for all
stacks, and iterate another stack in order to call user destructors. * tests/glr-regression.at (No users destructors if stack 0 deleted): New test case. (Duplicated user destructor for lookahead): This test now is expected to succeed.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
||||
2005-12-06 "Joel E. Denny" <jdenny@ces.clemson.edu>
|
||||
|
||||
* data/glr.c (yyprocessOneStack): Synchronize the shift for all
|
||||
stacks, and iterate another stack in order to call user
|
||||
destructors.
|
||||
* tests/glr-regression.at (No users destructors if stack 0 deleted):
|
||||
New test case.
|
||||
(Duplicated user destructor for lookahead): This test now is expected
|
||||
to succeed.
|
||||
|
||||
2005-12-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* NEWS: Document the following change.
|
||||
|
||||
137
data/glr.c
137
data/glr.c
@@ -507,8 +507,8 @@ static const ]b4_int_type_for([b4_stos])[ yystos[] =
|
||||
|
||||
# define YY_LOCATION_PRINT(File, Loc) \
|
||||
fprintf (File, "%d.%d-%d.%d", \
|
||||
(Loc).first_line, (Loc).first_column, \
|
||||
(Loc).last_line, (Loc).last_column)
|
||||
(Loc).first_line, (Loc).first_column, \
|
||||
(Loc).last_line, (Loc).last_column)
|
||||
#endif
|
||||
]],[
|
||||
#ifndef YYLLOC_DEFAULT
|
||||
@@ -566,7 +566,7 @@ do { \
|
||||
{ \
|
||||
YYFPRINTF (stderr, "%s ", Title); \
|
||||
yysymprint (stderr, \
|
||||
Type, Value]b4_location_if([, Location])[]b4_user_args[); \
|
||||
Type, Value]b4_location_if([, Location])[]b4_user_args[); \
|
||||
YYFPRINTF (stderr, "\n"); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
@@ -867,7 +867,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
|
||||
YYSTYPE* yyvalp,
|
||||
YYLTYPE* YYOPTIONAL_LOC (yylocp),
|
||||
yyGLRStack* yystack
|
||||
]b4_user_formals[)
|
||||
]b4_user_formals[)
|
||||
{
|
||||
yybool yynormal __attribute__ ((__unused__)) =
|
||||
(yystack->yysplitPoint == NULL);
|
||||
@@ -962,15 +962,15 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys]b4_user_formals[)
|
||||
#endif
|
||||
|
||||
if (yys->yysemantics.yyfirstVal)
|
||||
{
|
||||
yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
|
||||
yyGLRState *yyrh;
|
||||
int yyn;
|
||||
for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
|
||||
yyn > 0;
|
||||
yyrh = yyrh->yypred, yyn -= 1)
|
||||
yydestroyGLRState (yymsg, yyrh]b4_user_args[);
|
||||
}
|
||||
{
|
||||
yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
|
||||
yyGLRState *yyrh;
|
||||
int yyn;
|
||||
for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
|
||||
yyn > 0;
|
||||
yyrh = yyrh->yypred, yyn -= 1)
|
||||
yydestroyGLRState (yymsg, yyrh]b4_user_args[);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,7 +1016,7 @@ yydefaultAction (yyStateNum yystate)
|
||||
*/
|
||||
static inline void
|
||||
yygetLRActions (yyStateNum yystate, int yytoken,
|
||||
int* yyaction, const short int** yyconflicts)
|
||||
int* yyaction, const short int** yyconflicts)
|
||||
{
|
||||
int yyindex = yypact[yystate] + yytoken;
|
||||
if (yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
|
||||
@@ -1340,7 +1340,7 @@ yydoAction (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
|
||||
= yystack->yytops.yystates[yyk];]b4_location_if([[
|
||||
if (yynrhs == 0)
|
||||
/* Set default location. */
|
||||
yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[
|
||||
yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[
|
||||
for (yyi = 0; yyi < yynrhs; yyi += 1)
|
||||
{
|
||||
yys = yys->yypred;
|
||||
@@ -1387,9 +1387,9 @@ yy_reduce_print (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
|
||||
{
|
||||
fprintf (stderr, " $%d = ", yyi + 1);
|
||||
yysymprint (stderr, yyrhs[yyprhs[yyrule] + yyi],
|
||||
&]b4_rhs_value(yynrhs, yyi + 1)[
|
||||
]b4_location_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
|
||||
b4_user_args[);
|
||||
&]b4_rhs_value(yynrhs, yyi + 1)[
|
||||
]b4_location_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
|
||||
b4_user_args[);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
@@ -1408,7 +1408,7 @@ yy_reduce_print (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
|
||||
*/
|
||||
static inline YYRESULTTAG
|
||||
yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
|
||||
yybool yyforceEval]b4_user_formals[)
|
||||
yybool yyforceEval]b4_user_formals[)
|
||||
{
|
||||
size_t yyposn = yystack->yytops.yystates[yyk]->yyposn;
|
||||
|
||||
@@ -1623,7 +1623,7 @@ yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack]b4_user_formals[)
|
||||
|
||||
static YYRESULTTAG
|
||||
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
|
||||
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
|
||||
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
|
||||
{
|
||||
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
|
||||
int yynrhs;
|
||||
@@ -1748,7 +1748,7 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
|
||||
break;
|
||||
default:
|
||||
/* This cannot happen so it is not worth a YYASSERT (yyfalse),
|
||||
but some compilers complain if the default case is
|
||||
but some compilers complain if the default case is
|
||||
omitted. */
|
||||
break;
|
||||
}
|
||||
@@ -1827,7 +1827,7 @@ yycompressStack (yyGLRStack* yystack)
|
||||
|
||||
static YYRESULTTAG
|
||||
yyprocessOneStack (yyGLRStack* yystack, size_t yyk,
|
||||
size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
|
||||
size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
|
||||
]b4_pure_formals[)
|
||||
{
|
||||
int yyaction;
|
||||
@@ -1880,16 +1880,7 @@ yyprocessOneStack (yyGLRStack* yystack, size_t yyk,
|
||||
}
|
||||
|
||||
if (yyisShiftAction (yyaction))
|
||||
{
|
||||
YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yyk));
|
||||
YY_SYMBOL_PRINT ("shifting", *yytokenp, yylvalp, yyllocp);
|
||||
yyglrShift (yystack, yyk, yyaction, yyposn+1,
|
||||
*yylvalp, yyllocp);
|
||||
YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
|
||||
(unsigned long int) yyk,
|
||||
yystack->yytops.yystates[yyk]->yylrState));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
else if (yyisErrorAction (yyaction))
|
||||
{
|
||||
YYDPRINTF ((stderr, "Stack %lu dies.\n",
|
||||
@@ -2187,7 +2178,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
const short int* yyconflicts;
|
||||
|
||||
yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
|
||||
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
|
||||
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
|
||||
if (yystate == YYFINAL)
|
||||
goto yyacceptlab;
|
||||
if (yyisDefaultedState (yystate))
|
||||
@@ -2208,7 +2199,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
YYDPRINTF ((stderr, "Reading a token: "));
|
||||
yychar = YYLEX;
|
||||
yytoken = YYTRANSLATE (yychar);
|
||||
YY_SYMBOL_PRINT ("Next token is", yytoken, yylvalp, yyllocp);
|
||||
YY_SYMBOL_PRINT ("Next token is", yytoken, yylvalp, yyllocp);
|
||||
}
|
||||
yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
|
||||
if (*yyconflicts != 0)
|
||||
@@ -2236,14 +2227,59 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
|
||||
while (yytrue)
|
||||
{
|
||||
yySymbol yytoken_to_shift;
|
||||
size_t yys;
|
||||
size_t yyn = yystack.yytops.yysize;
|
||||
|
||||
/* yyprocessOneStack returns one of three things:
|
||||
|
||||
- An error flag. If the caller is yyprocessOneStack, it
|
||||
immediately returns as well. When the caller is finally
|
||||
yyparse, it jumps to an error label via YYCHK1.
|
||||
|
||||
- yyok, but yyprocessOneStack has invoked yymarkStackDeleted
|
||||
(&yystack, yys), which sets the top state of yys to NULL. Thus,
|
||||
yyparse's following invocation of yyremoveDeletes will remove
|
||||
the stack.
|
||||
|
||||
- yyok, when ready to shift a token.
|
||||
|
||||
Except in the first case, yyparse will invoke yyremoveDeletes and
|
||||
then shift the next token onto all remaining stacks. This
|
||||
synchronization of the shift (that is, after all preceding
|
||||
reductions on all stacks) helps prevents double destructor calls
|
||||
on yylval in the event of memory exhaustion. */
|
||||
|
||||
for (yys = 0; yys < yyn; yys += 1)
|
||||
YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
|
||||
yylvalp, yyllocp]b4_lpure_args[));
|
||||
yyremoveDeletes (&yystack);
|
||||
yyn = yystack.yytops.yysize;
|
||||
|
||||
/* If any yyglrShift call fails, it will fail after shifting. Thus,
|
||||
a copy of yylval will already be on stack 0 in the event of a
|
||||
failure in the following loop. Thus, yytoken is set to YYEMPTY
|
||||
before the loop to make sure the user destructor for yylval isn't
|
||||
called twice. */
|
||||
yytoken_to_shift = yytoken;
|
||||
yytoken = YYEMPTY;
|
||||
yyposn += 1;
|
||||
yyremoveDeletes (&yystack);
|
||||
for (yys = 0; yys < yyn; yys += 1)
|
||||
{
|
||||
int yyaction;
|
||||
const short int* yyconflicts;
|
||||
yyStateNum yystate = yystack.yytops.yystates[yys]->yylrState;
|
||||
yygetLRActions (yystate, yytoken_to_shift, &yyaction,
|
||||
&yyconflicts);
|
||||
/* Note that yyconflicts were handled by yyprocessOneStack. */
|
||||
YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yys));
|
||||
YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, yylvalp, yyllocp);
|
||||
yyglrShift (&yystack, yys, yyaction, yyposn,
|
||||
*yylvalp, yyllocp);
|
||||
YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
|
||||
(unsigned long int) yys,
|
||||
yystack.yytops.yystates[yys]->yylrState));
|
||||
}
|
||||
if (yystack.yytops.yysize == 0)
|
||||
{
|
||||
yyundeleteLastStack (&yystack);
|
||||
@@ -2289,7 +2325,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
yyreturn:
|
||||
if (yytoken != YYEOF && yytoken != YYEMPTY)
|
||||
yydestruct ("Cleanup: discarding lookahead",
|
||||
yytoken, yylvalp]b4_location_if([, yyllocp])[]b4_user_args[);
|
||||
yytoken, yylvalp]b4_location_if([, yyllocp])[]b4_user_args[);
|
||||
|
||||
/* If the stack is well-formed, pop the stack until it is empty,
|
||||
destroying its entries as we go. But free the stack regardless
|
||||
@@ -2298,15 +2334,24 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
||||
{
|
||||
yyGLRState** yystates = yystack.yytops.yystates;
|
||||
if (yystates)
|
||||
while (yystates[0])
|
||||
{
|
||||
yyGLRState *yys = yystates[0];
|
||||
]b4_location_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
|
||||
)[ yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
||||
yystates[0] = yys->yypred;
|
||||
yystack.yynextFree -= 1;
|
||||
yystack.yyspaceLeft += 1;
|
||||
}
|
||||
{
|
||||
size_t yysize = yystack.yytops.yysize;
|
||||
size_t yyk;
|
||||
for (yyk = 0; yyk < yysize; yyk += 1)
|
||||
if (yystates[yyk])
|
||||
{
|
||||
while (yystates[yyk])
|
||||
{
|
||||
yyGLRState *yys = yystates[yyk];
|
||||
]b4_location_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
|
||||
)[ yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
||||
yystates[yyk] = yys->yypred;
|
||||
yystack.yynextFree -= 1;
|
||||
yystack.yyspaceLeft += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
yyfreeGLRStack (&yystack);
|
||||
}
|
||||
|
||||
@@ -2390,7 +2435,7 @@ b4_epilogue
|
||||
m4_if(b4_defines_flag, 0, [],
|
||||
[@output @output_header_name@
|
||||
b4_copyright([Skeleton parser for GLR parsing with Bison],
|
||||
[2002, 2003, 2004, 2005])[
|
||||
[2002, 2003, 2004, 2005])[
|
||||
|
||||
/* As a special exception, when this parser skeleton is copied by
|
||||
Bison into a Bison output file, you may use that output file
|
||||
|
||||
@@ -633,8 +633,6 @@ AT_CHECK([[./glr-regr7]], 2, [],
|
||||
[memory exhausted
|
||||
])
|
||||
|
||||
AT_XFAIL_IF(:)
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
@@ -667,9 +665,9 @@ AT_DATA_GRAMMAR([glr-regr8.y],
|
||||
|
||||
|
||||
PortClause : T_PORT InterfaceDeclaration T_PORT
|
||||
{ printf("%d/%d - %d/%d - %d/%d\n",
|
||||
@1.first_column, @1.last_column,
|
||||
@2.first_column, @2.last_column,
|
||||
{ printf("%d/%d - %d/%d - %d/%d\n",
|
||||
@1.first_column, @1.last_column,
|
||||
@2.first_column, @2.last_column,
|
||||
@3.first_column, @3.last_column); }
|
||||
;
|
||||
|
||||
@@ -695,7 +693,7 @@ void yyerror(const char *msg)
|
||||
|
||||
static int lexIndex;
|
||||
|
||||
int yylex()
|
||||
int yylex (void)
|
||||
{
|
||||
lexIndex += 1;
|
||||
switch (lexIndex)
|
||||
@@ -714,7 +712,7 @@ int yylex()
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
main (void)
|
||||
{
|
||||
yyparse();
|
||||
return 0;
|
||||
@@ -726,10 +724,91 @@ AT_CHECK([[bison -o glr-regr8.c glr-regr8.y]], 0, [],
|
||||
])
|
||||
AT_COMPILE([glr-regr8])
|
||||
|
||||
AT_CHECK([[./glr-regr8]], 0,
|
||||
AT_CHECK([[./glr-regr8]], 0,
|
||||
[empty: 9/9
|
||||
1/9 - 9/9 - 13/17
|
||||
],
|
||||
[])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------------------------------------------------------- ##
|
||||
## No users destructors if stack 0 deleted ##
|
||||
## Thanks to Joel E. Denny for this test; see ##
|
||||
## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>. ##
|
||||
## ------------------------------------------------------------------------- ##
|
||||
|
||||
AT_SETUP([No users destructors if stack 0 deleted])
|
||||
|
||||
AT_DATA_GRAMMAR([glr-regr9.y],
|
||||
[[
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static void yyerror (char const *);
|
||||
static int yylex (void);
|
||||
#define YYSTACKEXPANDABLE 0
|
||||
static int tokens = 0;
|
||||
static int destructors = 0;
|
||||
%}
|
||||
|
||||
%glr-parser
|
||||
%union { int dummy; }
|
||||
%type <dummy> 'a'
|
||||
|
||||
%destructor {
|
||||
destructors += 1;
|
||||
} 'a'
|
||||
|
||||
%%
|
||||
|
||||
start:
|
||||
ambig0 'a' { destructors += 2; }
|
||||
| ambig1 start { destructors += 1; }
|
||||
| ambig2 start { destructors += 1; }
|
||||
;
|
||||
|
||||
ambig0: 'a' ;
|
||||
ambig1: 'a' ;
|
||||
ambig2: 'a' ;
|
||||
|
||||
%%
|
||||
|
||||
static int
|
||||
yylex (void)
|
||||
{
|
||||
tokens += 1;
|
||||
return 'a';
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror (char const *msg)
|
||||
{
|
||||
fprintf (stderr, "%s\n", msg);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int exit_status;
|
||||
exit_status = yyparse ();
|
||||
if (tokens != destructors)
|
||||
{
|
||||
fprintf (stderr, "Tokens = %d, Destructors = %d\n", tokens, destructors);
|
||||
return 1;
|
||||
}
|
||||
return !exit_status;
|
||||
}
|
||||
]])
|
||||
|
||||
AT_CHECK([[bison -o glr-regr9.c glr-regr9.y]], 0, [],
|
||||
[glr-regr9.y: conflicts: 1 reduce/reduce
|
||||
])
|
||||
AT_COMPILE([glr-regr9])
|
||||
|
||||
AT_CHECK([[./glr-regr9]], 0, [],
|
||||
[memory exhausted
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
Reference in New Issue
Block a user