From: Akim Demaille Date: Wed, 25 Jan 2012 15:57:58 +0000 (+0100) Subject: yacc: fix YYBACKUP. X-Git-Tag: v2.7.90~549 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/d115aad9112fb4e2fe1b268c9db7390732d39539?ds=sidebyside yacc: fix YYBACKUP. Reported by David Kastrup: https://lists.gnu.org/archive/html/bug-bison/2011-10/msg00002.html. * data/yacc.c (YYBACKUP): Accept rhs size. Restore the proper state value. * TODO (YYBACKUP): Make it... * tests/actions.at: a new test case. * NEWS, THANKS: Update. --- diff --git a/NEWS b/NEWS index 5c2783f9..a9922c09 100644 --- a/NEWS +++ b/NEWS @@ -66,6 +66,8 @@ Bison News ** Minor improvements have been made to the manual. +** YYBACKUP works as expected. + * Changes in version 2.5 (2011-05-14): ** Grammar symbol names can now contain non-initial dashes: diff --git a/THANKS b/THANKS index 1ec0fb37..d25e6f70 100644 --- a/THANKS +++ b/THANKS @@ -29,6 +29,7 @@ Csaba Raduly csaba_22@yahoo.co.uk Dagobert Michelsen dam@baltic-online.de Daniel Hagerty hag@gnu.org David J. MacKenzie djm@gnu.org +David Kastrup dak@gnu.org Derek M. Jones derek@knosof.co.uk Di-an Jan dianj@freeshell.org Dick Streefland dick.streefland@altium.nl diff --git a/TODO b/TODO index 404317f9..588bf468 100644 --- a/TODO +++ b/TODO @@ -118,50 +118,6 @@ so both 256 and 257 are "mysterious". ** YYFAIL It is seems to be *really* obsolete now, shall we remove it? -** YYBACKUP -There is no test about it, no examples in the doc, and I'm not sure -what it should look like. For instance what follows crashes. - - %error-verbose - %debug - %pure-parser - %code { - # include - # include - # include - - static void yyerror (const char *msg); - static int yylex (YYSTYPE *yylval); - } - %% - exp: - 'a' { printf ("a: %d\n", $1); } - | 'b' { YYBACKUP('a', 123); } - ; - %% - static int - yylex (YYSTYPE *yylval) - { - static char const input[] = "b"; - static size_t toknum; - assert (toknum < sizeof input); - *yylval = (toknum + 1) * 10; - return input[toknum++]; - } - - static void - yyerror (const char *msg) - { - fprintf (stderr, "%s\n", msg); - } - - int - main (void) - { - yydebug = !!getenv("YYDEBUG"); - return yyparse (); - } - ** yychar == yyempty_ The code in yyerrlab reads: diff --git a/data/yacc.c b/data/yacc.c index 1866a66a..b6137c2b 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -646,11 +646,12 @@ static const ]b4_int_type_for([b4_toknum])[ yytoknum[] = #define YYBACKUP(Token, Value) \ do \ - if (yychar == YYEMPTY && yylen == 1) \ + if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ - YYPOPSTACK (1); \]b4_lac_if([[ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \]b4_lac_if([[ YY_LAC_DISCARD ("YYBACKUP"); \]])[ goto yybackup; \ } \ diff --git a/tests/actions.at b/tests/actions.at index 4e2e6107..4199a3ef 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -1525,3 +1525,68 @@ AT_PARSER_CHECK([[./input]], [[0]], [], ]]) AT_CLEANUP + +## ---------- ## +## YYBACKUP. ## +## ---------- ## + +AT_SETUP([[YYBACKUP]]) + +AT_DATA_GRAMMAR([input.y], +[[ +%error-verbose +%debug +%pure-parser +%code { +# include +# include +# include + + static void yyerror (const char *msg); + static int yylex (YYSTYPE *yylval); +} +%% +input: + exp exp {} +; + +exp: + 'a' { printf ("a: %d\n", $1); } +| 'b' { YYBACKUP('a', 123); } +| 'c' 'd' { YYBACKUP('a', 456); } +; + +%% +static int +yylex (YYSTYPE *yylval) +{ + static char const input[] = "bcd"; + static size_t toknum; + assert (toknum < sizeof input); + *yylval = (toknum + 1) * 10; + return input[toknum++]; +} + +static void +yyerror (const char *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +main (void) +{ + yydebug = !!getenv("YYDEBUG"); + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-o input.c input.y]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[0]], +[[a: 123 +a: 456 +a: 789 +]]) + +AT_CLEANUP