mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-23 19:23:02 +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>
|
2005-12-01 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
* NEWS: Document the following change.
|
* NEWS: Document the following change.
|
||||||
|
|||||||
71
data/glr.c
71
data/glr.c
@@ -1880,16 +1880,7 @@ yyprocessOneStack (yyGLRStack* yystack, size_t yyk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (yyisShiftAction (yyaction))
|
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))
|
else if (yyisErrorAction (yyaction))
|
||||||
{
|
{
|
||||||
YYDPRINTF ((stderr, "Stack %lu dies.\n",
|
YYDPRINTF ((stderr, "Stack %lu dies.\n",
|
||||||
@@ -2236,14 +2227,59 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
|||||||
|
|
||||||
while (yytrue)
|
while (yytrue)
|
||||||
{
|
{
|
||||||
|
yySymbol yytoken_to_shift;
|
||||||
size_t yys;
|
size_t yys;
|
||||||
size_t yyn = yystack.yytops.yysize;
|
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)
|
for (yys = 0; yys < yyn; yys += 1)
|
||||||
YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
|
YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
|
||||||
yylvalp, yyllocp]b4_lpure_args[));
|
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;
|
yytoken = YYEMPTY;
|
||||||
yyposn += 1;
|
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)
|
if (yystack.yytops.yysize == 0)
|
||||||
{
|
{
|
||||||
yyundeleteLastStack (&yystack);
|
yyundeleteLastStack (&yystack);
|
||||||
@@ -2298,15 +2334,24 @@ b4_syncline([@oline@], [@ofile@])])dnl
|
|||||||
{
|
{
|
||||||
yyGLRState** yystates = yystack.yytops.yystates;
|
yyGLRState** yystates = yystack.yytops.yystates;
|
||||||
if (yystates)
|
if (yystates)
|
||||||
while (yystates[0])
|
|
||||||
{
|
{
|
||||||
yyGLRState *yys = yystates[0];
|
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;]]
|
]b4_location_if([[ yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
|
||||||
)[ yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
)[ yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
|
||||||
yystates[0] = yys->yypred;
|
yystates[yyk] = yys->yypred;
|
||||||
yystack.yynextFree -= 1;
|
yystack.yynextFree -= 1;
|
||||||
yystack.yyspaceLeft += 1;
|
yystack.yyspaceLeft += 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
yyfreeGLRStack (&yystack);
|
yyfreeGLRStack (&yystack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -633,8 +633,6 @@ AT_CHECK([[./glr-regr7]], 2, [],
|
|||||||
[memory exhausted
|
[memory exhausted
|
||||||
])
|
])
|
||||||
|
|
||||||
AT_XFAIL_IF(:)
|
|
||||||
|
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
|
||||||
@@ -695,7 +693,7 @@ void yyerror(const char *msg)
|
|||||||
|
|
||||||
static int lexIndex;
|
static int lexIndex;
|
||||||
|
|
||||||
int yylex()
|
int yylex (void)
|
||||||
{
|
{
|
||||||
lexIndex += 1;
|
lexIndex += 1;
|
||||||
switch (lexIndex)
|
switch (lexIndex)
|
||||||
@@ -733,3 +731,84 @@ AT_CHECK([[./glr-regr8]], 0,
|
|||||||
[])
|
[])
|
||||||
|
|
||||||
AT_CLEANUP
|
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