During deterministic GLR operation, user actions should be able to

influence the parse by changing yychar.  To make this easier to fix and
to make glr.c easier to evolve in general, don't maintain yytoken in
parallel with yychar; just compute yytoken when needed.
* tests/glr-regression.at (Incorrect lookahead during deterministic
GLR): Check that setting yychar in a user action has the intended
effect.
* data/glr.c (yyGLRStack): Remove yytokenp member.
(yyclearin): Don't set *yytokenp.
(yyprocessOneStack, yyreportSyntaxError, yyrecoverSyntaxError): Examine
yychar rather than *yytokenp to determine the current lookahead.
Compute yytoken locally when needed.
(yyparse): Likewise.  Remove the local yytoken that yytokenp used to
point to.

* doc/bison.texinfo (Bison Options): Remove stray sentence fragment
after `--report' documentation.
This commit is contained in:
Joel E. Denny
2006-01-30 11:15:15 +00:00
parent e2a8c0f591
commit 3f0014152b
6 changed files with 63 additions and 39 deletions

View File

@@ -1,3 +1,23 @@
2006-01-30 Joel E. Denny <jdenny@ces.clemson.edu>
During deterministic GLR operation, user actions should be able to
influence the parse by changing yychar. To make this easier to fix and
to make glr.c easier to evolve in general, don't maintain yytoken in
parallel with yychar; just compute yytoken when needed.
* tests/glr-regression.at (Incorrect lookahead during deterministic
GLR): Check that setting yychar in a user action has the intended
effect.
* data/glr.c (yyGLRStack): Remove yytokenp member.
(yyclearin): Don't set *yytokenp.
(yyprocessOneStack, yyreportSyntaxError, yyrecoverSyntaxError): Examine
yychar rather than *yytokenp to determine the current lookahead.
Compute yytoken locally when needed.
(yyparse): Likewise. Remove the local yytoken that yytokenp used to
point to.
* doc/bison.texinfo (Bison Options): Remove stray sentence fragment
after `--report' documentation.
2006-01-30 Paul Eggert <eggert@cs.ucla.edu> 2006-01-30 Paul Eggert <eggert@cs.ucla.edu>
* src/parse-gram.y (grammar_declaration): Location of printer * src/parse-gram.y (grammar_declaration): Location of printer

View File

@@ -803,7 +803,6 @@ struct yyGLRStack {
YYSTYPE yyval; YYSTYPE yyval;
YYLTYPE yyloc; YYLTYPE yyloc;
])[ ])[
yySymbol* yytokenp;
YYJMP_BUF yyexception_buffer; YYJMP_BUF yyexception_buffer;
yyGLRStackItem* yyitems; yyGLRStackItem* yyitems;
yyGLRStackItem* yynextFree; yyGLRStackItem* yynextFree;
@@ -910,7 +909,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
# undef YYRECOVERING # undef YYRECOVERING
# define YYRECOVERING (yystackp->yyerrState != 0) # define YYRECOVERING (yystackp->yyerrState != 0)
# undef yyclearin # undef yyclearin
# define yyclearin (yychar = *(yystackp->yytokenp) = YYEMPTY) # define yyclearin (yychar = YYEMPTY)
# undef YYFILL # undef YYFILL
# define YYFILL(N) yyfill (yyvsp, &yylow, N, yynormal) # define YYFILL(N) yyfill (yyvsp, &yylow, N, yynormal)
# undef YYBACKUP # undef YYBACKUP
@@ -1929,7 +1928,6 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
int yyaction; int yyaction;
const short int* yyconflicts; const short int* yyconflicts;
yyRuleNum yyrule; yyRuleNum yyrule;
yySymbol* const yytokenp = yystackp->yytokenp;
while (yystackp->yytops.yystates[yyk] != NULL) while (yystackp->yytops.yystates[yyk] != NULL)
{ {
@@ -1953,15 +1951,18 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
} }
else else
{ {
yySymbol yytoken;
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue; yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
if (*yytokenp == YYEMPTY) if (yychar == YYEMPTY)
{ {
YYDPRINTF ((stderr, "Reading a token: ")); YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX; yychar = YYLEX;
*yytokenp = YYTRANSLATE (yychar); yytoken = YYTRANSLATE (yychar);
YY_SYMBOL_PRINT ("Next token is", *yytokenp, &yylval, &yylloc); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
} }
yygetLRActions (yystate, *yytokenp, &yyaction, &yyconflicts); else
yytoken = YYTRANSLATE (yychar);
yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
while (*yyconflicts != 0) while (*yyconflicts != 0)
{ {
@@ -1999,12 +2000,12 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
if (yystackp->yyerrState == 0) if (yystackp->yyerrState == 0)
{ {
#if YYERROR_VERBOSE #if YYERROR_VERBOSE
yySymbol* const yytokenp = yystackp->yytokenp;
int yyn; int yyn;
yyn = yypact[yystackp->yytops.yystates[0]->yylrState]; yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
if (YYPACT_NINF < yyn && yyn < YYLAST) if (YYPACT_NINF < yyn && yyn < YYLAST)
{ {
size_t yysize0 = yytnamerr (NULL, yytokenName (*yytokenp)); yySymbol yytoken = YYTRANSLATE (yychar);
size_t yysize0 = yytnamerr (NULL, yytokenName (yytoken));
size_t yysize = yysize0; size_t yysize = yysize0;
size_t yysize1; size_t yysize1;
yybool yysize_overflow = yyfalse; yybool yysize_overflow = yyfalse;
@@ -2032,7 +2033,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1; int yycount = 1;
yyarg[0] = yytokenName (*yytokenp); yyarg[0] = yytokenName (yytoken);
yyfmt = yystpcpy (yyformat, yyunexpected); yyfmt = yystpcpy (yyformat, yyunexpected);
for (yyx = yyxbegin; yyx < yyxend; ++yyx) for (yyx = yyxbegin; yyx < yyxend; ++yyx)
@@ -2100,7 +2101,6 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/*ARGSUSED*/ static void /*ARGSUSED*/ static void
yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[) yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
{ {
yySymbol* const yytokenp = yystackp->yytokenp;
size_t yyk; size_t yyk;
int yyj; int yyj;
@@ -2109,9 +2109,10 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
reductions. Skip tokens until we can proceed. */ reductions. Skip tokens until we can proceed. */
while (YYID (yytrue)) while (YYID (yytrue))
{ {
if (*yytokenp == YYEOF) yySymbol yytoken;
if (yychar == YYEOF)
yyFail (yystackp][]b4_lpure_args[, NULL); yyFail (yystackp][]b4_lpure_args[, NULL);
if (*yytokenp != YYEMPTY) if (yychar != YYEMPTY)
{]b4_location_if([[ {]b4_location_if([[
/* We throw away the lookahead, but the error range /* We throw away the lookahead, but the error range
of the shifted error token must take it into account. */ of the shifted error token must take it into account. */
@@ -2120,18 +2121,19 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
yyerror_range[1].yystate.yyloc = yys->yyloc; yyerror_range[1].yystate.yyloc = yys->yyloc;
yyerror_range[2].yystate.yyloc = yylloc; yyerror_range[2].yystate.yyloc = yylloc;
YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[ YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[
yytoken = YYTRANSLATE (yychar);
yydestruct ("Error: discarding", yydestruct ("Error: discarding",
*yytokenp, &yylval]b4_location_if([, &yylloc])[]b4_user_args[); yytoken, &yylval]b4_location_if([, &yylloc])[]b4_user_args[);
} }
YYDPRINTF ((stderr, "Reading a token: ")); YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX; yychar = YYLEX;
*yytokenp = YYTRANSLATE (yychar); yytoken = YYTRANSLATE (yychar);
YY_SYMBOL_PRINT ("Next token is", *yytokenp, &yylval, &yylloc); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
yyj = yypact[yystackp->yytops.yystates[0]->yylrState]; yyj = yypact[yystackp->yytops.yystates[0]->yylrState];
if (yyis_pact_ninf (yyj)) if (yyis_pact_ninf (yyj))
return; return;
yyj += *yytokenp; yyj += yytoken;
if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != *yytokenp) if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != yytoken)
{ {
if (yydefact[yystackp->yytops.yystates[0]->yylrState] != 0) if (yydefact[yystackp->yytops.yystates[0]->yylrState] != 0)
return; return;
@@ -2209,7 +2211,6 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[ ]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[
{ {
int yyresult; int yyresult;
yySymbol yytoken;
yyGLRStack yystack; yyGLRStack yystack;
yyGLRStack* const yystackp = &yystack; yyGLRStack* const yystackp = &yystack;
size_t yyposn; size_t yyposn;
@@ -2217,7 +2218,6 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
YYDPRINTF ((stderr, "Starting parse\n")); YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; yychar = YYEMPTY;
yytoken = YYEMPTY;
yylval = yyval_default; yylval = yyval_default;
]b4_location_if([ ]b4_location_if([
#if YYLTYPE_IS_TRIVIAL #if YYLTYPE_IS_TRIVIAL
@@ -2244,7 +2244,6 @@ b4_syncline([@oline@], [@ofile@])])dnl
case 2: goto yyexhaustedlab; case 2: goto yyexhaustedlab;
default: goto yybuglab; default: goto yybuglab;
} }
yystack.yytokenp = &yytoken;
yyglrShift (&yystack, 0, 0, 0, &yylval, &yylloc); yyglrShift (&yystack, 0, 0, 0, &yylval, &yylloc);
yyposn = 0; yyposn = 0;
@@ -2277,24 +2276,24 @@ b4_syncline([@oline@], [@ofile@])])dnl
} }
else else
{ {
if (yytoken == YYEMPTY) yySymbol yytoken;
if (yychar == YYEMPTY)
{ {
YYDPRINTF ((stderr, "Reading a token: ")); YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX; yychar = YYLEX;
yytoken = YYTRANSLATE (yychar); yytoken = YYTRANSLATE (yychar);
YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
} }
else
yytoken = YYTRANSLATE (yychar);
yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts); yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
if (*yyconflicts != 0) if (*yyconflicts != 0)
break; break;
if (yyisShiftAction (yyaction)) if (yyisShiftAction (yyaction))
{ {
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
if (yytoken != YYEOF) if (yychar != YYEOF)
{ yychar = YYEMPTY;
yychar = YYEMPTY;
yytoken = YYEMPTY;
}
yyposn += 1; yyposn += 1;
yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc); yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
if (0 < yystack.yyerrState) if (0 < yystack.yyerrState)
@@ -2346,12 +2345,11 @@ b4_syncline([@oline@], [@ofile@])])dnl
/* If any yyglrShift call fails, it will fail after shifting. Thus, /* 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 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 failure in the following loop. Thus, yychar is set to YYEMPTY
before the loop to make sure the user destructor for yylval isn't before the loop to make sure the user destructor for yylval isn't
called twice. */ called twice. */
yytoken_to_shift = yytoken; yytoken_to_shift = YYTRANSLATE (yychar);
yychar = YYEMPTY; yychar = YYEMPTY;
yytoken = YYEMPTY;
yyposn += 1; yyposn += 1;
for (yys = 0; yys < yyn; yys += 1) for (yys = 0; yys < yyn; yys += 1)
{ {
@@ -2412,9 +2410,10 @@ b4_syncline([@oline@], [@ofile@])])dnl
goto yyreturn; goto yyreturn;
yyreturn: yyreturn:
if (yytoken != YYEOF && yytoken != YYEMPTY) if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead", yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval]b4_location_if([, &yylloc])[]b4_user_args[); YYTRANSLATE (yychar),
&yylval]b4_location_if([, &yylloc])[]b4_user_args[);
/* If the stack is well-formed, pop the stack until it is empty, /* If the stack is well-formed, pop the stack until it is empty,
destroying its entries as we go. But free the stack regardless destroying its entries as we go. But free the stack regardless

View File

@@ -6889,8 +6889,6 @@ Implies @code{state} and augments the description of the automaton with
the full set of items for each state, instead of its core only. the full set of items for each state, instead of its core only.
@end table @end table
For instance, on the following grammar
@item -v @item -v
@itemx --verbose @itemx --verbose
Pretend that @code{%verbose} was specified, i.e, write an extra output Pretend that @code{%verbose} was specified, i.e, write an extra output

View File

@@ -1912,7 +1912,7 @@ yyreduce:
{ {
symbol_list *list; symbol_list *list;
for (list = (yyvsp[(2) - (2)].list); list; list = list->next) for (list = (yyvsp[(2) - (2)].list); list; list = list->next)
symbol_printer_set (list->sym, (yyvsp[(1) - (2)].chars), list->location); symbol_printer_set (list->sym, (yyvsp[(1) - (2)].chars), (yylsp[(1) - (2)]));
symbol_list_free ((yyvsp[(2) - (2)].list)); symbol_list_free ((yyvsp[(2) - (2)].list));
} }
break; break;

View File

@@ -148,7 +148,7 @@ typedef union YYSTYPE
uniqstr uniqstr; uniqstr uniqstr;
} }
/* Line 1536 of yacc.c. */ /* Line 1536 of yacc.c. */
#line 152 "parse-gram.h" #line 152 "y.tab.h"
YYSTYPE; YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1

View File

@@ -1016,7 +1016,8 @@ AT_CLEANUP
## ------------------------------------------------------------------------- ## ## ------------------------------------------------------------------------- ##
## Incorrect lookahead during deterministic GLR. See ## ## Incorrect lookahead during deterministic GLR. See ##
## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html>. ## ## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html> and ##
## <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00060.html>. ##
## ------------------------------------------------------------------------- ## ## ------------------------------------------------------------------------- ##
AT_SETUP([Incorrect lookahead during deterministic GLR]) AT_SETUP([Incorrect lookahead during deterministic GLR])
@@ -1027,7 +1028,8 @@ AT_DATA_GRAMMAR([glr-regr13.y],
- Defaulted state with initial yychar: yychar == YYEMPTY. - Defaulted state with initial yychar: yychar == YYEMPTY.
- Nondefaulted state: yychar != YYEMPTY. - Nondefaulted state: yychar != YYEMPTY.
- Defaulted state after lookahead: yychar != YYEMPTY. - Defaulted state after lookahead: yychar != YYEMPTY.
- Defaulted state after shift: yychar == YYEMPTY. */ - Defaulted state after shift: yychar == YYEMPTY.
- User action changing the lookahead. */
%{ %{
#include <stdio.h> #include <stdio.h>
@@ -1045,7 +1047,7 @@ AT_DATA_GRAMMAR([glr-regr13.y],
%% %%
start: start:
defstate_init defstate_shift 'b' { defstate_init defstate_shift 'b' change_lookahead 'a' {
USE ($3); USE ($3);
print_look_ahead ("start <- defstate_init defstate_shift 'b'"); print_look_ahead ("start <- defstate_init defstate_shift 'b'");
} }
@@ -1075,6 +1077,11 @@ nondefstate:
print_look_ahead ("nondefstate <- 'b'"); print_look_ahead ("nondefstate <- 'b'");
} }
; ;
change_lookahead:
{
yychar = 'a';
}
;
%% %%