mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
least one user action succeeds but a later one cuts the parse, then destroy the semantic value before returning rather than leaking it. (yyresolveStates): If a user action cuts the parse and thus yyresolveValue fails, ignore the (unset) semantic value rather than corrupting the yyGLRState, and empty the semantic options list since the user actions should have called all necessary destructors. Simplify code with YYCHK. * tests/glr-regression.at (Corrupted semantic options if user action cuts parse): New test case. (Undesirable destructors if user action cuts parse): New test case. Before applying any of this patch, this test case never actually failed for me... but only because the corrupted semantic options usually masked this bug. (Leaked merged semantic value if user action cuts parse): New test case.
1018 lines
19 KiB
Plaintext
1018 lines
19 KiB
Plaintext
# Checking GLR Parsing: Regression Tests -*- Autotest -*-
|
|
# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2, or (at your option)
|
|
# any later version.
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
# 02110-1301, USA.
|
|
|
|
AT_BANNER([[GLR Regression Tests]])
|
|
|
|
## --------------------------- ##
|
|
## Badly Collapsed GLR States. ##
|
|
## --------------------------- ##
|
|
|
|
AT_SETUP([Badly Collapsed GLR States])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr1.y],
|
|
[[/* Regression Test: Improper state compression */
|
|
/* Reported by Scott McPeak */
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
|
|
#define YYSTYPE int
|
|
static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1);
|
|
int yylex (void);
|
|
void yyerror (char const *msg);
|
|
%}
|
|
|
|
|
|
%glr-parser
|
|
|
|
|
|
/* -------- productions ------ */
|
|
%%
|
|
|
|
StartSymbol: E { $$=0; } %merge <exprMerge>
|
|
;
|
|
|
|
E: E 'P' E { $$=1; printf("E -> E 'P' E\n"); } %merge <exprMerge>
|
|
| 'B' { $$=2; printf("E -> 'B'\n"); } %merge <exprMerge>
|
|
;
|
|
|
|
|
|
|
|
/* ---------- C code ----------- */
|
|
%%
|
|
|
|
static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1)
|
|
{
|
|
(void) x0;
|
|
(void) x1;
|
|
printf ("<OR>\n");
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse ();
|
|
}
|
|
|
|
void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
|
|
int
|
|
yylex (void)
|
|
{
|
|
for (;;)
|
|
{
|
|
int ch = getchar ();
|
|
if (ch == EOF)
|
|
return 0;
|
|
else if (ch == 'B' || ch == 'P')
|
|
return ch;
|
|
}
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr1.c glr-regr1.y]], 0, [],
|
|
[glr-regr1.y: conflicts: 1 shift/reduce
|
|
])
|
|
AT_COMPILE([glr-regr1])
|
|
AT_CHECK([[echo BPBPB | ./glr-regr1]], 0,
|
|
[[E -> 'B'
|
|
E -> 'B'
|
|
E -> E 'P' E
|
|
E -> 'B'
|
|
E -> E 'P' E
|
|
E -> 'B'
|
|
E -> E 'P' E
|
|
E -> E 'P' E
|
|
<OR>
|
|
]], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------------------------------------------ ##
|
|
## Improper handling of embedded actions and $-N in GLR parsers ##
|
|
## ------------------------------------------------------------ ##
|
|
|
|
AT_SETUP([Improper handling of embedded actions and dollar(-N) in GLR parsers])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr2a.y],
|
|
[[/* Regression Test: Improper handling of embedded actions and $-N */
|
|
/* Reported by S. Eken */
|
|
|
|
%{
|
|
#define YYSTYPE char *
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
int yylex (void);
|
|
void yyerror (char const *);
|
|
%}
|
|
|
|
%glr-parser
|
|
|
|
%%
|
|
|
|
command:
|
|
's' var 't'
|
|
{ printf ("Variable: '%s'\n", $2); }
|
|
'v' 'x' 'q'
|
|
{ free ($2); }
|
|
| 's' var_list 't' 'e'
|
|
{ printf ("Varlist: '%s'\n", $2); free ($2); }
|
|
| 's' var 't' var_printer 'x'
|
|
{ free ($2); }
|
|
;
|
|
|
|
var:
|
|
'V'
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
var_list:
|
|
var
|
|
{ $$ = $1; }
|
|
| var ',' var_list
|
|
{
|
|
char *s = (char *) realloc ($1, strlen ($1) + 1 + strlen ($3) + 1);
|
|
strcat (s, ",");
|
|
strcat (s, $3);
|
|
free ($3);
|
|
$$ = s;
|
|
}
|
|
;
|
|
|
|
var_printer: 'v'
|
|
{ printf ("Variable: '%s'\n", $-1); }
|
|
|
|
%%
|
|
|
|
FILE *input = NULL;
|
|
|
|
int
|
|
yylex (void)
|
|
{
|
|
char buf[50];
|
|
char *s;
|
|
switch (fscanf (input, " %1[a-z,]", buf)) {
|
|
case 1:
|
|
return buf[0];
|
|
case EOF:
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
if (fscanf (input, "%49s", buf) != 1)
|
|
return 0;
|
|
if (sizeof buf - 1 <= strlen (buf))
|
|
abort ();
|
|
s = (char *) malloc (strlen (buf) + 1);
|
|
strcpy (s, buf);
|
|
yylval = s;
|
|
return 'V';
|
|
}
|
|
|
|
void
|
|
yyerror (char const *s)
|
|
{ printf ("%s\n", s);
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
input = stdin;
|
|
if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
|
|
return yyparse ();
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr2a.c glr-regr2a.y]], 0, [],
|
|
[glr-regr2a.y: conflicts: 2 shift/reduce
|
|
])
|
|
AT_COMPILE([glr-regr2a])
|
|
|
|
AT_CHECK([[echo s VARIABLE_1 t v x q | ./glr-regr2a]], 0,
|
|
[[Variable: 'VARIABLE_1'
|
|
]], [])
|
|
AT_CHECK([[echo s VARIABLE_1 , ANOTHER_VARIABLE_2 t e | ./glr-regr2a]], 0,
|
|
[[Varlist: 'VARIABLE_1,ANOTHER_VARIABLE_2'
|
|
]])
|
|
AT_CHECK([[echo s VARIABLE_3 t v x | ./glr-regr2a]], 0,
|
|
[[Variable: 'VARIABLE_3'
|
|
]], [])
|
|
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------------------------------------------ ##
|
|
## Improper merging of GLR delayed action sets ##
|
|
## ------------------------------------------------------------ ##
|
|
|
|
AT_SETUP([Improper merging of GLR delayed action sets])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr3.y],
|
|
[[/* Regression Test: Improper merging of GLR delayed action sets. */
|
|
/* Reported by M. Rosien */
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
static int MergeRule (int x0, int x1);
|
|
static void yyerror(char const * s);
|
|
int yylex (void);
|
|
|
|
#define RULE(x) (1 << (x))
|
|
|
|
%}
|
|
|
|
%glr-parser
|
|
|
|
%token BAD_CHAR
|
|
%token P1 P2 T1 T2 T3 T4 O1 O2
|
|
|
|
%%
|
|
|
|
S : P1 T4 O2 NT6 P2 { printf ("Result: %x\n", $4); }
|
|
;
|
|
|
|
NT1 : P1 T1 O1 T2 P2 { $$ = RULE(2); } %merge<MergeRule>
|
|
;
|
|
|
|
NT2 : NT1 { $$ = RULE(3); } %merge<MergeRule>
|
|
| P1 NT1 O1 T3 P2 { $$ = RULE(4); } %merge<MergeRule>
|
|
;
|
|
|
|
NT3 : T3 { $$ = RULE(5); } %merge<MergeRule>
|
|
| P1 NT1 O1 T3 P2 { $$ = RULE(6); } %merge<MergeRule>
|
|
;
|
|
|
|
NT4 : NT3 { $$ = RULE(7); } %merge<MergeRule>
|
|
| NT2 { $$ = RULE(8); } %merge<MergeRule>
|
|
| P1 NT2 O1 NT3 P2 { $$ = RULE(9); } %merge<MergeRule>
|
|
;
|
|
|
|
NT5 : NT4 { $$ = RULE(10); } %merge<MergeRule>
|
|
;
|
|
|
|
NT6 : P1 NT1 O1 T3 P2 { $$ = RULE(11) | $2; } %merge<MergeRule>
|
|
| NT5 { $$ = RULE(12) | $1; } %merge<MergeRule>
|
|
;
|
|
|
|
%%
|
|
|
|
static int MergeRule (int x0, int x1) {
|
|
return x0 | x1;
|
|
}
|
|
|
|
static void yyerror(char const * s) {
|
|
fprintf(stderr,"error: %s\n",s);
|
|
}
|
|
|
|
FILE *input = NULL;
|
|
|
|
int P[] = { P1, P2 };
|
|
int O[] = { O1, O2 };
|
|
int T[] = { T1, T2, T3, T4 };
|
|
|
|
int yylex (void)
|
|
{
|
|
char inp[3];
|
|
if (fscanf (input, "%2s", inp) == EOF)
|
|
return 0;
|
|
switch (inp[0])
|
|
{
|
|
case 'p': return P[inp[1] - '1'];
|
|
case 't': return T[inp[1] - '1'];
|
|
case 'o': return O[inp[1] - '1'];
|
|
}
|
|
return BAD_CHAR;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
input = stdin;
|
|
if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
|
|
return yyparse ();
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr3.c glr-regr3.y]], 0, [],
|
|
[glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr3])
|
|
|
|
AT_CHECK([[echo p1 t4 o2 p1 p1 t1 o1 t2 p2 o1 t3 p2 p2 | ./glr-regr3]], 0,
|
|
[[Result: 1c04
|
|
]], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------------------------------------------------------- ##
|
|
## Duplicate representation of merged trees ##
|
|
## Thanks to Joel E. Denny for this test; see ##
|
|
## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00013.html>. ##
|
|
## ---------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Duplicate representation of merged trees])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr4.y],
|
|
[[
|
|
%union { char *ptr; }
|
|
%type <ptr> S A A1 A2 B
|
|
%glr-parser
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
static char *merge (YYSTYPE, YYSTYPE);
|
|
static char *make_value (char const *, char const *);
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
%}
|
|
|
|
%%
|
|
|
|
tree: S { printf ("%s\n", $1); } ;
|
|
|
|
S:
|
|
A %merge<merge> { $$ = make_value ("S", $1); }
|
|
| B %merge<merge> { $$ = make_value ("S", $1); }
|
|
;
|
|
|
|
A:
|
|
A1 %merge<merge> { $$ = make_value ("A", $1); }
|
|
| A2 %merge<merge> { $$ = make_value ("A", $1); }
|
|
;
|
|
|
|
A1: 'a' { $$ = make_value ("A1", "'a'"); } ;
|
|
A2: 'a' { $$ = make_value ("A2", "'a'"); } ;
|
|
B: 'a' { $$ = make_value ("B", "'a'"); } ;
|
|
|
|
%%
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
static char const *input = "a";
|
|
return *input++;
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse ();
|
|
}
|
|
|
|
static char *
|
|
make_value (char const *parent, char const *child)
|
|
{
|
|
char const format[] = "%s <- %s";
|
|
char *value =
|
|
(char *) malloc (strlen (parent) + strlen (child) + sizeof format);
|
|
sprintf (value, format, parent, child);
|
|
return value;
|
|
}
|
|
|
|
static char *
|
|
merge (YYSTYPE s1, YYSTYPE s2)
|
|
{
|
|
char const format[] = "merge{ %s and %s }";
|
|
char *value =
|
|
(char *) malloc (strlen (s1.ptr) + strlen (s2.ptr) + sizeof format);
|
|
sprintf (value, format, s1.ptr, s2.ptr);
|
|
return value;
|
|
}
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr4.c glr-regr4.y]], 0, [],
|
|
[glr-regr4.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr4])
|
|
|
|
AT_CHECK([[./glr-regr4]], 0,
|
|
[[merge{ S <- merge{ A <- A1 <- 'a' and A <- A2 <- 'a' } and S <- B <- 'a' }
|
|
]], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## User destructor for unresolved GLR semantic value ##
|
|
## Thanks to Joel E. Denny for this test; see ##
|
|
## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00016.html>. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([User destructor for unresolved GLR semantic value])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr5.y],
|
|
[[
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
enum { MAGIC_VALUE = -1057808125 }; /* originally chosen at random */
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { int value; }
|
|
%type <value> start
|
|
|
|
%destructor {
|
|
if ($$ != MAGIC_VALUE)
|
|
{
|
|
fprintf (stderr, "Bad destructor call.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
} start
|
|
|
|
%%
|
|
|
|
start:
|
|
'a' { $$ = MAGIC_VALUE; }
|
|
| 'a' { $$ = MAGIC_VALUE; }
|
|
;
|
|
|
|
%%
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
static char const *input = "a";
|
|
return *input++;
|
|
}
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse () != 1;
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr5.c glr-regr5.y]], 0, [],
|
|
[glr-regr5.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr5])
|
|
|
|
AT_CHECK([[./glr-regr5]], 0, [],
|
|
[syntax is ambiguous
|
|
])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## User destructor after an error during a split parse ##
|
|
## Thanks to Joel E. Denny for this test; see ##
|
|
## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00029.html>. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([User destructor after an error during a split parse])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr6.y],
|
|
[[
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { int value; }
|
|
%type <value> 'a'
|
|
|
|
%destructor {
|
|
printf ("Destructor called.\n");
|
|
} 'a'
|
|
|
|
%%
|
|
|
|
start: 'a' | 'a' ;
|
|
|
|
%%
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
static char const *input = "a";
|
|
return *input++;
|
|
}
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse () != 1;
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr6.c glr-regr6.y]], 0, [],
|
|
[glr-regr6.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr6])
|
|
|
|
AT_CHECK([[./glr-regr6]], 0,
|
|
[Destructor called.
|
|
],
|
|
[syntax is ambiguous
|
|
])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## Duplicated user destructor for lookahead ##
|
|
## Thanks to Joel E. Denny for this test; see ##
|
|
## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00035.html>. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Duplicated user destructor for lookahead])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr7.y],
|
|
[[
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
#define YYSTACKEXPANDABLE 0
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { int *count; }
|
|
%type <count> 'a'
|
|
|
|
%destructor {
|
|
if ((*$$)++)
|
|
fprintf (stderr, "Destructor called on same value twice.\n");
|
|
} 'a'
|
|
|
|
%%
|
|
|
|
start:
|
|
stack1 start
|
|
| stack2 start
|
|
| /* empty */
|
|
;
|
|
stack1: 'a' ;
|
|
stack2: 'a' ;
|
|
|
|
%%
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
yylval.count = (int *) malloc (sizeof (int));
|
|
if (!yylval.count)
|
|
{
|
|
fprintf (stderr, "Test inconclusive.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
*yylval.count = 0;
|
|
return 'a';
|
|
}
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse ();
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr7.c glr-regr7.y]], 0, [],
|
|
[glr-regr7.y: conflicts: 2 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr7])
|
|
|
|
AT_CHECK([[./glr-regr7]], 2, [],
|
|
[memory exhausted
|
|
])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## Incorrect default location for empty right-hand sides. Adapted from bug ##
|
|
## report by Claudia Hermann. ##
|
|
## See http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00069.html and ##
|
|
## http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00072.html ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Incorrectly initialized location for empty right-hand side in GLR])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr8.y],
|
|
[[
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
static void yyerror(const char *msg);
|
|
%}
|
|
|
|
%token T_CONSTANT
|
|
%token T_PORT
|
|
%token T_SIGNAL
|
|
|
|
%glr-parser
|
|
|
|
%%
|
|
|
|
|
|
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,
|
|
@3.first_column, @3.last_column); }
|
|
;
|
|
|
|
InterfaceDeclaration : OptConstantWord %dprec 1
|
|
| OptSignalWord %dprec 2
|
|
;
|
|
|
|
OptConstantWord : /* empty */
|
|
| T_CONSTANT
|
|
;
|
|
|
|
OptSignalWord : /* empty */
|
|
{ printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
|
|
| T_SIGNAL
|
|
;
|
|
|
|
%%
|
|
|
|
void yyerror(const char *msg)
|
|
{
|
|
fprintf (stderr, "error\n");
|
|
}
|
|
|
|
static int lexIndex;
|
|
|
|
int yylex (void)
|
|
{
|
|
lexIndex += 1;
|
|
switch (lexIndex)
|
|
{
|
|
case 1:
|
|
yylloc.first_column = 1;
|
|
yylloc.last_column = 9;
|
|
return T_PORT;
|
|
case 2:
|
|
yylloc.first_column = 13;
|
|
yylloc.last_column = 17;
|
|
return T_PORT;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
yyparse();
|
|
return 0;
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -o glr-regr8.c glr-regr8.y]], 0, [],
|
|
[glr-regr8.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr8])
|
|
|
|
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;
|
|
# define USE(Var)
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { int dummy; }
|
|
%type <dummy> 'a'
|
|
|
|
%destructor {
|
|
destructors += 1;
|
|
} 'a'
|
|
|
|
%%
|
|
|
|
start:
|
|
ambig0 'a' { destructors += 2; USE ($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
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## Corrupted semantic options if user action cuts parse. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Corrupted semantic options if user action cuts parse.])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr10.y],
|
|
[[
|
|
%{
|
|
# include <stdio.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
#define GARBAGE_SIZE 50
|
|
static char garbage[GARBAGE_SIZE];
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { char *ptr; }
|
|
%type <ptr> start
|
|
|
|
%%
|
|
|
|
start:
|
|
%dprec 2 { $$ = garbage; YYACCEPT; }
|
|
| %dprec 1 { $$ = garbage; YYACCEPT; }
|
|
;
|
|
|
|
%%
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
int index;
|
|
for (index = 0; index < GARBAGE_SIZE; index+=1)
|
|
garbage[index] = 132;
|
|
return yyparse ();
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -t -o glr-regr10.c glr-regr10.y]], 0, [],
|
|
[glr-regr10.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr10])
|
|
|
|
AT_CHECK([[./glr-regr10]], 0, [], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## Undesirable destructors if user action cuts parse. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Undesirable destructors if user action cuts parse.])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr11.y],
|
|
[[
|
|
%{
|
|
# include <stdlib.h>
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
static int destructors = 0;
|
|
# define USE(val)
|
|
%}
|
|
|
|
%glr-parser
|
|
%union { int dummy; }
|
|
%type <int> 'a'
|
|
%destructor { destructors += 1; } 'a'
|
|
|
|
%%
|
|
|
|
start:
|
|
'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
|
|
| 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
|
|
;
|
|
|
|
%%
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
static char const *input = "a";
|
|
return *input++;
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
int exit_status = yyparse ();
|
|
if (destructors != 1)
|
|
{
|
|
fprintf (stderr, "Destructor calls: %d\n", destructors);
|
|
return 1;
|
|
}
|
|
return exit_status;
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -t -o glr-regr11.c glr-regr11.y]], 0, [],
|
|
[glr-regr11.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr11])
|
|
|
|
AT_CHECK([[./glr-regr11]], 0, [], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------------------------------- ##
|
|
## Leaked merged semantic value if user action cuts parse. ##
|
|
## ------------------------------------------------------------------------- ##
|
|
|
|
AT_SETUP([Leaked merged semantic value if user action cuts parse.])
|
|
|
|
AT_DATA_GRAMMAR([glr-regr12.y],
|
|
[[
|
|
%glr-parser
|
|
%union { int dummy; }
|
|
%type <dummy> start
|
|
%destructor { has_value = 0; } start
|
|
|
|
%{
|
|
# include <stdlib.h>
|
|
static int merge (YYSTYPE, YYSTYPE);
|
|
static void yyerror (char const *);
|
|
static int yylex (void);
|
|
static int has_value = 0;
|
|
# define USE(val)
|
|
%}
|
|
|
|
%%
|
|
|
|
start:
|
|
%merge<merge> { has_value = 1; USE ($$); }
|
|
| %merge<merge> { USE ($$); YYACCEPT; }
|
|
;
|
|
|
|
%%
|
|
|
|
static int
|
|
merge (YYSTYPE s1, YYSTYPE s2)
|
|
{
|
|
/* Not invoked. */
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
yyerror (char const *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
int exit_status = yyparse ();
|
|
if (has_value)
|
|
{
|
|
fprintf (stderr, "Destructor not called.\n");
|
|
return 1;
|
|
}
|
|
return exit_status;
|
|
}
|
|
]])
|
|
|
|
AT_CHECK([[bison -t -o glr-regr12.c glr-regr12.y]], 0, [],
|
|
[glr-regr12.y: conflicts: 1 reduce/reduce
|
|
])
|
|
AT_COMPILE([glr-regr12])
|
|
|
|
AT_CHECK([[./glr-regr12]], 0, [], [])
|
|
|
|
AT_CLEANUP
|