and Akim Demaille <akim@epita.fr>

* data/bison.simple.new (yyerrlab1): Be sure to pop and destroy
what's left on the stack when the error recovery hits EOF.
* tests/actions.at (Destructors): Complete to exercise this case.
This commit is contained in:
Akim Demaille
2002-06-18 09:12:58 +00:00
parent 271efced67
commit 5719c1092f
4 changed files with 128 additions and 37 deletions

View File

@@ -1,3 +1,10 @@
2002-06-18 Cris Bailiff <c.bailiff@awayweb.com>
and Akim Demaille <akim@epita.fr>
* data/bison.simple.new (yyerrlab1): Be sure to pop and destroy
what's left on the stack when the error recovery hits EOF.
* tests/actions.at (Destructors): Complete to exercise this case.
2002-06-17 Akim Demaille <akim@epita.fr> 2002-06-17 Akim Demaille <akim@epita.fr>
* data/m4sugar/m4sugar.m4 (m4_map): Recognize when the list of * data/m4sugar/m4sugar.m4 (m4_map): Recognize when the list of

1
THANKS
View File

@@ -9,6 +9,7 @@ Andreas Schwab schwab@suse.de
Arnold Robbins arnold@skeeve.com Arnold Robbins arnold@skeeve.com
Benoit Perrot benoit.perrot@epita.fr Benoit Perrot benoit.perrot@epita.fr
Bruce Lilly blilly@erols.com Bruce Lilly blilly@erols.com
Cris Bailiff c.bailiff+bison@awayweb.com
Cris van Pelt cris@amf03054.office.wxs.nl Cris van Pelt cris@amf03054.office.wxs.nl
Daniel Hagerty hag@gnu.org Daniel Hagerty hag@gnu.org
David J. MacKenzie djm@gnu.org David J. MacKenzie djm@gnu.org

View File

@@ -1123,7 +1123,38 @@ yyerrlab1:
/* Return failure if at end of input. */ /* Return failure if at end of input. */
if (yychar == YYEOF) if (yychar == YYEOF)
YYABORT; {
/* Pop the error token. */
YYPOPSTACK;
/* Pop the rest of the stack. */
while (yyssp > yyss)
{
#if YYDEBUG
if (yydebug)
{
if (yystos[*yyssp] < YYNTOKENS)
{
YYFPRINTF (stderr, "Error: popping token %d (%s",
yytoknum[yystos[*yyssp]],
yytname[yystos[*yyssp]]);
# ifdef YYPRINT
YYPRINT (stderr, yytoknum[yystos[*yyssp]], *yyvsp);
# endif
YYFPRINTF (stderr, ")\n");
}
else
{
YYFPRINTF (stderr, "Error: popping nonterminal (%s)\n",
yytname[yystos[*yyssp]]);
}
}
#endif
yydestructor (yystos[*yyssp], *yyvsp);
YYPOPSTACK;
}
YYABORT;
}
YYDPRINTF ((stderr, "Discarding token %d (%s).\n", YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
yychar, yytname[yychar1])); yychar, yytname[yychar1]));
yydestructor (yychar1, yylval); yydestructor (yychar1, yylval);
@@ -1263,8 +1294,8 @@ yydestructor (int symbol_type, YYSTYPE symbol_value)
{ {
m4_map([b4_symbol_destructor], m4_defn([b4_symbol_destructors]))dnl m4_map([b4_symbol_destructor], m4_defn([b4_symbol_destructors]))dnl
default: default:
YYDPRINTF ((stderr, "yydestructor: unknown symbol type: %s\n", YYDPRINTF ((stderr, "yydestructor: unknown symbol type: %d (%s)\n",
yytname[[symbol_type]])); symbol_type, yytname[[symbol_type]]));
break; break;
} }
} }

View File

@@ -169,61 +169,100 @@ AT_DATA([[input.y]],
#define YYERROR_VERBOSE 1 #define YYERROR_VERBOSE 1
#define YYDEBUG 1 #define YYDEBUG 1
/* #define YYPRINT yyprint */ #define YYPRINT yyprint
static int yylex (void);
static void yyerror (const char *msg);
static void yyprint (FILE *out, int toknum, int tokval);
%} %}
%verbose
%union %union
{ {
int ival; int ival;
} }
%type <ival> thing 'x' %type <ival> 'x' thing line input
%destructor { printf ("Freeing input %d\n", $$); } input
%destructor { printf ("Freeing line %d\n", $$); } line
%destructor { printf ("Freeing thing %d\n", $$); } thing %destructor { printf ("Freeing thing %d\n", $$); } thing
%destructor { printf ("Freeing 'x' %d\n", $$); } 'x' %destructor { printf ("Freeing 'x' %d\n", $$); } 'x'
%{
static int yylex (void);
static void yyerror (const char *msg);
static void yyprint (FILE *out, int num, YYSTYPE val);
%}
%% %%
input: input:
/* Nothing. */ /* Nothing. */
| input line {
$$ = 0;
printf ("input(%d): /* Nothing */';'\n", $$);
}
| line input /* Right recursive to load the stack so that popping at
EOF can be exercised. */
{
$$ = 2;
printf ("input(%d): line(%d) input(%d)';'\n", $$, $1, $2);
}
; ;
line: line:
thing thing thing ';' thing thing thing ';'
{ printf ("input: thing(%d) thing(%d) thing(%d) ';'\n", $1, $2, $3); } {
$$ = $1;
printf ("line(%d): thing(%d) thing(%d) thing(%d) ';'\n", $$, $1, $2, $3);
}
| thing thing ';' | thing thing ';'
{ printf ("input: thing(%d) thing(%d) ';'\n", $1, $2); } {
$$ = $1;
printf ("line(%d): thing(%d) thing(%d) ';'\n", $$, $1, $2);
}
| thing ';' | thing ';'
{ printf ("input: thing(%d) ';'\n", $1); } {
$$ = $1;
printf ("line(%d): thing(%d) ';'\n", $$, $1);
}
| error ';' | error ';'
{ printf ("input: error ';'\n"); } {
$$ = -1;
printf ("line(%d): error ';'\n", $$);
}
; ;
thing: thing:
'x' { printf ("thing: 'x' (%d)\n", $1); $$ = $1; } 'x'
{
$$ = $1;
printf ("thing(%d): 'x'(%d)\n", $$, $1);
}
; ;
%% %%
static int static int
yylex (void) yylex (void)
{ {
static const int input[] = static const unsigned int input[] =
{ {
/* Exericise the discarding of stack top and input until `error'
can be reduced. */
'x', 'x', 'x', 'x', 'x', 'x', ';', 'x', 'x', 'x', 'x', 'x', 'x', ';',
/* Load the stack and provoke an error that cannot be caught be
the grammar, and check that the stack is cleared. */
'x', 'x', ';', 'x', 'x', ';',
'x', ';', 'x', ';',
'x', 'y', ';' 'y'
}; };
static int counter = 0; static int counter = 0;
if (counter < (sizeof(input) / sizeof (input[0]))) if (counter < (sizeof(input) / sizeof (input[0])))
{ {
yylval.ival = counter; yylval.ival = counter;
printf ("sending: '%c'(%d)\n", input[counter], counter);
return input[counter++]; return input[counter++];
} }
else else
return EOF; {
printf ("sending: EOF\n");
return EOF;
}
} }
static void static void
@@ -233,10 +272,9 @@ yyerror (const char *msg)
} }
static void static void
yyprint (FILE *out, int toknum, int tokval) yyprint (FILE *out, int num, YYSTYPE val)
{ {
if (0 < toknum && toknum < 256) fprintf (out, " = %d", val.ival);
fprintf (out, " = %d", tokval);
} }
int int
@@ -255,28 +293,42 @@ main (void)
AT_CHECK([bison input.y -d -v -o input.c]) AT_CHECK([bison input.y -d -v -o input.c])
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore])
AT_CHECK([./input], 0, AT_CHECK([./input], 1,
[[thing: 'x' (0) [[sending: 'x'(0)
thing: 'x' (1) thing(0): 'x'(0)
thing: 'x' (2) sending: 'x'(1)
thing(1): 'x'(1)
sending: 'x'(2)
thing(2): 'x'(2)
sending: 'x'(3)
parse error, unexpected 'x', expecting ';' parse error, unexpected 'x', expecting ';'
Freeing thing 2 Freeing thing 2
Freeing thing 1 Freeing thing 1
Freeing thing 0 Freeing thing 0
Freeing 'x' 3 Freeing 'x' 3
sending: 'x'(4)
Freeing 'x' 4 Freeing 'x' 4
sending: 'x'(5)
Freeing 'x' 5 Freeing 'x' 5
input: error ';' sending: ';'(6)
thing: 'x' (7) line(-1): error ';'
thing: 'x' (8) sending: 'x'(7)
input: thing(7) thing(8) ';' thing(7): 'x'(7)
thing: 'x' (10) sending: 'x'(8)
input: thing(10) ';' thing(8): 'x'(8)
thing: 'x' (12) sending: ';'(9)
parse error, unexpected $undefined., expecting 'x' or ';' line(7): thing(7) thing(8) ';'
Freeing thing 12 sending: 'x'(10)
input: error ';' thing(10): 'x'(10)
Successful parse. sending: ';'(11)
line(10): thing(10) ';'
sending: 'y'(12)
parse error, unexpected $undefined., expecting $ or error or 'x'
sending: EOF
Freeing line 10
Freeing line 7
Freeing line -1
Parsing FAILED.
]]) ]])
AT_CLEANUP AT_CLEANUP