]> git.saurik.com Git - bison.git/blame - tests/glr-regression.at
Bench the three-stack lalr1.cc.
[bison.git] / tests / glr-regression.at
CommitLineData
ede3d3bc 1# Checking GLR Parsing: Regression Tests -*- Autotest -*-
279cabb6 2# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
ede3d3bc 3
f16b0819 4# This program is free software: you can redistribute it and/or modify
ede3d3bc 5# it under the terms of the GNU General Public License as published by
f16b0819
PE
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
ede3d3bc
PH
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
f16b0819 13#
ede3d3bc 14# You should have received a copy of the GNU General Public License
f16b0819 15# along with this program. If not, see <http://www.gnu.org/licenses/>.
ede3d3bc
PH
16
17AT_BANNER([[GLR Regression Tests]])
18
19## --------------------------- ##
20## Badly Collapsed GLR States. ##
21## --------------------------- ##
22
23AT_SETUP([Badly Collapsed GLR States])
24
25AT_DATA_GRAMMAR([glr-regr1.y],
26[[/* Regression Test: Improper state compression */
27/* Reported by Scott McPeak */
28
29%{
30#include <stdio.h>
cf806753 31#include <stdlib.h>
ede3d3bc
PH
32
33#define YYSTYPE int
34static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1);
35int yylex (void);
ac8c5689 36void yyerror (char const *msg);
ede3d3bc
PH
37%}
38
39
40%glr-parser
41
42
43/* -------- productions ------ */
44%%
45
46StartSymbol: E { $$=0; } %merge <exprMerge>
47 ;
48
49E: E 'P' E { $$=1; printf("E -> E 'P' E\n"); } %merge <exprMerge>
50 | 'B' { $$=2; printf("E -> 'B'\n"); } %merge <exprMerge>
51 ;
52
53
54
55/* ---------- C code ----------- */
56%%
57
58static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1)
59{
60 (void) x0;
61 (void) x1;
62 printf ("<OR>\n");
63 return 0;
64}
65
66int
67main (void)
68{
69 return yyparse ();
70}
71
ac8c5689 72void
ede3d3bc
PH
73yyerror (char const *msg)
74{
75 fprintf (stderr, "%s\n", msg);
ede3d3bc
PH
76}
77
78
79int
80yylex (void)
81{
82 for (;;)
83 {
cf806753
PE
84 int ch;
85 if (feof (stdin))
86 abort ();
87 ch = getchar ();
ede3d3bc
PH
88 if (ch == EOF)
89 return 0;
90 else if (ch == 'B' || ch == 'P')
91 return ch;
92 }
93}
94]])
95
da730230 96AT_BISON_CHECK([[-o glr-regr1.c glr-regr1.y]], 0, [],
ede3d3bc
PH
97[glr-regr1.y: conflicts: 1 shift/reduce
98])
99AT_COMPILE([glr-regr1])
7d2d521f 100AT_PARSER_CHECK([[echo BPBPB | ./glr-regr1]], 0,
ede3d3bc
PH
101[[E -> 'B'
102E -> 'B'
103E -> E 'P' E
104E -> 'B'
105E -> E 'P' E
106E -> 'B'
107E -> E 'P' E
108E -> E 'P' E
109<OR>
110]], [])
111
112AT_CLEANUP
113
114## ------------------------------------------------------------ ##
115## Improper handling of embedded actions and $-N in GLR parsers ##
116## ------------------------------------------------------------ ##
117
d6d67dbd 118AT_SETUP([Improper handling of embedded actions and dollar(-N) in GLR parsers])
ede3d3bc
PH
119
120AT_DATA_GRAMMAR([glr-regr2a.y],
121[[/* Regression Test: Improper handling of embedded actions and $-N */
122/* Reported by S. Eken */
123
124%{
f5228370 125 #define YYSTYPE char *
ede3d3bc
PH
126
127 #include <ctype.h>
128 #include <stdio.h>
f508a6a0 129 #include <stdlib.h>
ede3d3bc
PH
130 #include <string.h>
131 int yylex (void);
132 void yyerror (char const *);
133%}
134
135%glr-parser
136
137%%
138
139command:
140 's' var 't'
d6d67dbd 141 { printf ("Variable: '%s'\n", $2); }
ede3d3bc 142 'v' 'x' 'q'
f5228370 143 { free ($2); }
ede3d3bc 144 | 's' var_list 't' 'e'
f5228370 145 { printf ("Varlist: '%s'\n", $2); free ($2); }
ede3d3bc 146 | 's' var 't' var_printer 'x'
f5228370 147 { free ($2); }
ede3d3bc
PH
148 ;
149
150var:
151 'V'
152 { $$ = $1; }
153 ;
154
155var_list:
156 var
157 { $$ = $1; }
158 | var ',' var_list
159 {
f5228370 160 char *s = (char *) realloc ($1, strlen ($1) + 1 + strlen ($3) + 1);
c70fdfcd
PE
161 strcat (s, ",");
162 strcat (s, $3);
f5228370 163 free ($3);
c70fdfcd 164 $$ = s;
d6d67dbd 165 }
ede3d3bc
PH
166 ;
167
168var_printer: 'v'
169 { printf ("Variable: '%s'\n", $-1); }
170
171%%
172
cf806753 173FILE *input;
ede3d3bc
PH
174
175int
176yylex (void)
d6d67dbd 177{
ede3d3bc 178 char buf[50];
c70fdfcd 179 char *s;
cf806753
PE
180 if (feof (stdin))
181 abort ();
a9739e7c 182 switch (fscanf (input, " %1[a-z,]", buf)) {
ede3d3bc
PH
183 case 1:
184 return buf[0];
185 case EOF:
186 return 0;
187 default:
188 break;
189 }
a9739e7c 190 if (fscanf (input, "%49s", buf) != 1)
ac8c5689 191 return 0;
f508a6a0
PE
192 if (sizeof buf - 1 <= strlen (buf))
193 abort ();
c70fdfcd
PE
194 s = (char *) malloc (strlen (buf) + 1);
195 strcpy (s, buf);
196 yylval = s;
ede3d3bc
PH
197 return 'V';
198}
199
200void
201yyerror (char const *s)
202{ printf ("%s\n", s);
203}
204
205int
206main (int argc, char **argv)
d6d67dbd 207{
a9739e7c
PE
208 input = stdin;
209 if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
ede3d3bc
PH
210 return yyparse ();
211}
212]])
213
da730230 214AT_BISON_CHECK([[-o glr-regr2a.c glr-regr2a.y]], 0, [],
ede3d3bc
PH
215[glr-regr2a.y: conflicts: 2 shift/reduce
216])
217AT_COMPILE([glr-regr2a])
218
7d2d521f 219AT_PARSER_CHECK([[echo s VARIABLE_1 t v x q | ./glr-regr2a]], 0,
ede3d3bc
PH
220[[Variable: 'VARIABLE_1'
221]], [])
7d2d521f
JD
222AT_PARSER_CHECK([[echo s VARIABLE_1 , ANOTHER_VARIABLE_2 t e | ./glr-regr2a]],
2230,
ede3d3bc
PH
224[[Varlist: 'VARIABLE_1,ANOTHER_VARIABLE_2'
225]])
7d2d521f 226AT_PARSER_CHECK([[echo s VARIABLE_3 t v x | ./glr-regr2a]], 0,
ede3d3bc
PH
227[[Variable: 'VARIABLE_3'
228]], [])
229
230
5e6f62f2
PH
231AT_CLEANUP
232
233## ------------------------------------------------------------ ##
234## Improper merging of GLR delayed action sets ##
235## ------------------------------------------------------------ ##
236
237AT_SETUP([Improper merging of GLR delayed action sets])
238
239AT_DATA_GRAMMAR([glr-regr3.y],
240[[/* Regression Test: Improper merging of GLR delayed action sets. */
241/* Reported by M. Rosien */
242
243%{
244#include <stdio.h>
cf806753 245#include <stdlib.h>
5e6f62f2
PH
246#include <stdarg.h>
247
248static int MergeRule (int x0, int x1);
c66dfadd 249static void yyerror (char const * s);
1beb0b24 250int yylex (void);
5e6f62f2
PH
251
252#define RULE(x) (1 << (x))
253
254%}
255
256%glr-parser
257
258%token BAD_CHAR
259%token P1 P2 T1 T2 T3 T4 O1 O2
260
261%%
262
263S : P1 T4 O2 NT6 P2 { printf ("Result: %x\n", $4); }
264;
265
266NT1 : P1 T1 O1 T2 P2 { $$ = RULE(2); } %merge<MergeRule>
267;
268
269NT2 : NT1 { $$ = RULE(3); } %merge<MergeRule>
270 | P1 NT1 O1 T3 P2 { $$ = RULE(4); } %merge<MergeRule>
271;
272
273NT3 : T3 { $$ = RULE(5); } %merge<MergeRule>
274 | P1 NT1 O1 T3 P2 { $$ = RULE(6); } %merge<MergeRule>
275;
276
277NT4 : NT3 { $$ = RULE(7); } %merge<MergeRule>
278 | NT2 { $$ = RULE(8); } %merge<MergeRule>
279 | P1 NT2 O1 NT3 P2 { $$ = RULE(9); } %merge<MergeRule>
280;
281
282NT5 : NT4 { $$ = RULE(10); } %merge<MergeRule>
283;
284
285NT6 : P1 NT1 O1 T3 P2 { $$ = RULE(11) | $2; } %merge<MergeRule>
286 | NT5 { $$ = RULE(12) | $1; } %merge<MergeRule>
287;
288
289%%
290
291static int MergeRule (int x0, int x1) {
292 return x0 | x1;
293}
294
295static void yyerror(char const * s) {
296 fprintf(stderr,"error: %s\n",s);
297}
298
a9739e7c 299FILE *input = NULL;
5e6f62f2
PH
300
301int P[] = { P1, P2 };
302int O[] = { O1, O2 };
303int T[] = { T1, T2, T3, T4 };
304
305int yylex (void)
306{
307 char inp[3];
cf806753
PE
308 if (feof (stdin))
309 abort ();
a9739e7c 310 if (fscanf (input, "%2s", inp) == EOF)
5e6f62f2 311 return 0;
1beb0b24 312 switch (inp[0])
5e6f62f2
PH
313 {
314 case 'p': return P[inp[1] - '1'];
315 case 't': return T[inp[1] - '1'];
316 case 'o': return O[inp[1] - '1'];
317 }
318 return BAD_CHAR;
319}
320
321int main(int argc, char* argv[]) {
a9739e7c
PE
322 input = stdin;
323 if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
5e6f62f2
PH
324 return yyparse ();
325}
326]])
327
da730230 328AT_BISON_CHECK([[-o glr-regr3.c glr-regr3.y]], 0, [],
5e6f62f2
PH
329[glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
330])
331AT_COMPILE([glr-regr3])
332
7d2d521f
JD
333AT_PARSER_CHECK([[echo p1 t4 o2 p1 p1 t1 o1 t2 p2 o1 t3 p2 p2 | ./glr-regr3]],
3340,
5e6f62f2
PH
335[[Result: 1c04
336]], [])
337
ede3d3bc 338AT_CLEANUP
f9315de5
PE
339
340
4158e0a1
JD
341## ------------------------------------------------------------------------- ##
342## Duplicate representation of merged trees. See ##
343## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00013.html>. ##
344## ------------------------------------------------------------------------- ##
f9315de5
PE
345
346AT_SETUP([Duplicate representation of merged trees])
347
348AT_DATA_GRAMMAR([glr-regr4.y],
1bd0deda
PE
349[[
350%union { char *ptr; }
f9315de5
PE
351%type <ptr> S A A1 A2 B
352%glr-parser
353
354%{
355 #include <stdio.h>
356 #include <stdlib.h>
357 #include <string.h>
358 static char *merge (YYSTYPE, YYSTYPE);
1bd0deda 359 static char *make_value (char const *, char const *);
f9315de5
PE
360 static void yyerror (char const *);
361 static int yylex (void);
7d2d521f
JD
362 static char *ptrs[100];
363 static char **ptrs_next = ptrs;
f9315de5
PE
364%}
365
366%%
367
368tree: S { printf ("%s\n", $1); } ;
369
370S:
371 A %merge<merge> { $$ = make_value ("S", $1); }
372 | B %merge<merge> { $$ = make_value ("S", $1); }
373 ;
374
375A:
376 A1 %merge<merge> { $$ = make_value ("A", $1); }
377 | A2 %merge<merge> { $$ = make_value ("A", $1); }
378 ;
379
380A1: 'a' { $$ = make_value ("A1", "'a'"); } ;
381A2: 'a' { $$ = make_value ("A2", "'a'"); } ;
382B: 'a' { $$ = make_value ("B", "'a'"); } ;
383
384%%
385
386static int
387yylex (void)
388{
cf806753
PE
389 static char const input[] = "a";
390 static size_t toknum;
391 if (! (toknum < sizeof input))
392 abort ();
393 return input[toknum++];
f9315de5
PE
394}
395
396int
397main (void)
398{
7d2d521f
JD
399 int status = yyparse ();
400 while (ptrs_next != ptrs)
401 free (*--ptrs_next);
402 return status;
f9315de5
PE
403}
404
405static char *
1bd0deda 406make_value (char const *parent, char const *child)
f9315de5
PE
407{
408 char const format[] = "%s <- %s";
7d2d521f 409 char *value = *ptrs_next++ =
7812f299 410 (char *) malloc (strlen (parent) + strlen (child) + sizeof format);
f9315de5
PE
411 sprintf (value, format, parent, child);
412 return value;
413}
414
415static char *
416merge (YYSTYPE s1, YYSTYPE s2)
417{
418 char const format[] = "merge{ %s and %s }";
7d2d521f 419 char *value = *ptrs_next++ =
7812f299 420 (char *) malloc (strlen (s1.ptr) + strlen (s2.ptr) + sizeof format);
f9315de5
PE
421 sprintf (value, format, s1.ptr, s2.ptr);
422 return value;
423}
424
425static void
426yyerror (char const *msg)
427{
42a6501d 428 fprintf (stderr, "%s\n", msg);
f9315de5
PE
429}
430]])
431
da730230 432AT_BISON_CHECK([[-o glr-regr4.c glr-regr4.y]], 0, [],
f9315de5
PE
433[glr-regr4.y: conflicts: 1 reduce/reduce
434])
435AT_COMPILE([glr-regr4])
436
7d2d521f 437AT_PARSER_CHECK([[./glr-regr4]], 0,
f9315de5
PE
438[[merge{ S <- merge{ A <- A1 <- 'a' and A <- A2 <- 'a' } and S <- B <- 'a' }
439]], [])
440
441AT_CLEANUP
adc90f13
PE
442
443
4158e0a1
JD
444## -------------------------------------------------------------------------- ##
445## User destructor for unresolved GLR semantic value. See ##
446## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00016.html>. ##
447## -------------------------------------------------------------------------- ##
adc90f13
PE
448
449AT_SETUP([User destructor for unresolved GLR semantic value])
450
451AT_DATA_GRAMMAR([glr-regr5.y],
1bd0deda
PE
452[[
453%{
adc90f13
PE
454 #include <stdio.h>
455 #include <stdlib.h>
456 static void yyerror (char const *);
457 static int yylex (void);
458 enum { MAGIC_VALUE = -1057808125 }; /* originally chosen at random */
459%}
460
461%glr-parser
462%union { int value; }
463%type <value> start
464
465%destructor {
466 if ($$ != MAGIC_VALUE)
467 {
468 fprintf (stderr, "Bad destructor call.\n");
469 exit (EXIT_FAILURE);
470 }
471} start
472
473%%
474
475start:
476 'a' { $$ = MAGIC_VALUE; }
477 | 'a' { $$ = MAGIC_VALUE; }
478 ;
479
480%%
481
482static int
483yylex (void)
484{
cf806753
PE
485 static char const input[] = "a";
486 static size_t toknum;
487 if (! (toknum < sizeof input))
488 abort ();
489 return input[toknum++];
adc90f13
PE
490}
491
492static void
493yyerror (char const *msg)
494{
42a6501d 495 fprintf (stderr, "%s\n", msg);
adc90f13
PE
496}
497
498int
499main (void)
500{
501 return yyparse () != 1;
502}
503]])
504
da730230 505AT_BISON_CHECK([[-o glr-regr5.c glr-regr5.y]], 0, [],
adc90f13
PE
506[glr-regr5.y: conflicts: 1 reduce/reduce
507])
508AT_COMPILE([glr-regr5])
509
7d2d521f 510AT_PARSER_CHECK([[./glr-regr5]], 0, [],
42a6501d
PE
511[syntax is ambiguous
512])
513
514AT_CLEANUP
515
516
4158e0a1
JD
517## -------------------------------------------------------------------------- ##
518## User destructor after an error during a split parse. See ##
519## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00029.html>. ##
520## -------------------------------------------------------------------------- ##
42a6501d
PE
521
522AT_SETUP([User destructor after an error during a split parse])
523
524AT_DATA_GRAMMAR([glr-regr6.y],
1bd0deda
PE
525[[
526%{
42a6501d
PE
527 #include <stdio.h>
528 #include <stdlib.h>
529 static void yyerror (char const *);
530 static int yylex (void);
531%}
532
533%glr-parser
534%union { int value; }
535%type <value> 'a'
536
537%destructor {
538 printf ("Destructor called.\n");
539} 'a'
540
541%%
542
543start: 'a' | 'a' ;
544
545%%
546
547static int
548yylex (void)
549{
cf806753
PE
550 static char const input[] = "a";
551 static size_t toknum;
552 if (! (toknum < sizeof input))
553 abort ();
554 return input[toknum++];
42a6501d
PE
555}
556
557static void
558yyerror (char const *msg)
559{
560 fprintf (stderr, "%s\n", msg);
561}
562
563int
564main (void)
565{
566 return yyparse () != 1;
567}
568]])
569
da730230 570AT_BISON_CHECK([[-o glr-regr6.c glr-regr6.y]], 0, [],
42a6501d
PE
571[glr-regr6.y: conflicts: 1 reduce/reduce
572])
573AT_COMPILE([glr-regr6])
574
7d2d521f 575AT_PARSER_CHECK([[./glr-regr6]], 0,
42a6501d
PE
576[Destructor called.
577],
adc90f13
PE
578[syntax is ambiguous
579])
580
581AT_CLEANUP
1bd0deda
PE
582
583
584## ------------------------------------------------------------------------- ##
4158e0a1 585## Duplicated user destructor for lookahead. See ##
1bd0deda
PE
586## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00035.html>. ##
587## ------------------------------------------------------------------------- ##
588
589AT_SETUP([Duplicated user destructor for lookahead])
590
591AT_DATA_GRAMMAR([glr-regr7.y],
592[[
593%{
594 #include <stdio.h>
595 #include <stdlib.h>
596 static void yyerror (char const *);
597 static int yylex (void);
598 #define YYSTACKEXPANDABLE 0
7d2d521f
JD
599 typedef struct count_node {
600 int count;
601 struct count_node *prev;
602 } count_node;
603 static count_node *tail;
1bd0deda
PE
604%}
605
606%glr-parser
7d2d521f
JD
607%union { count_node *node; }
608%type <node> 'a'
1bd0deda
PE
609
610%destructor {
7d2d521f 611 if ($$->count++)
1bd0deda
PE
612 fprintf (stderr, "Destructor called on same value twice.\n");
613} 'a'
614
615%%
616
617start:
618 stack1 start
619 | stack2 start
620 | /* empty */
621 ;
622stack1: 'a' ;
623stack2: 'a' ;
624
625%%
626
627static int
628yylex (void)
629{
7d2d521f
JD
630 yylval.node = (count_node*) malloc (sizeof *yylval.node);
631 if (!yylval.node)
1bd0deda
PE
632 {
633 fprintf (stderr, "Test inconclusive.\n");
634 exit (EXIT_FAILURE);
635 }
7d2d521f
JD
636 yylval.node->count = 0;
637 yylval.node->prev = tail;
638 tail = yylval.node;
1bd0deda
PE
639 return 'a';
640}
641
642static void
643yyerror (char const *msg)
644{
645 fprintf (stderr, "%s\n", msg);
646}
647
648int
649main (void)
650{
7d2d521f
JD
651 int status = yyparse ();
652 while (tail)
653 {
654 count_node *prev = tail->prev;
655 free (tail);
656 tail = prev;
657 }
658 return status;
1bd0deda
PE
659}
660]])
661
da730230 662AT_BISON_CHECK([[-o glr-regr7.c glr-regr7.y]], 0, [],
1bd0deda
PE
663[glr-regr7.y: conflicts: 2 reduce/reduce
664])
665AT_COMPILE([glr-regr7])
666
7d2d521f 667AT_PARSER_CHECK([[./glr-regr7]], 2, [],
1bd0deda
PE
668[memory exhausted
669])
670
671AT_CLEANUP
44e7ead1
PH
672
673
674## ------------------------------------------------------------------------- ##
675## Incorrect default location for empty right-hand sides. Adapted from bug ##
676## report by Claudia Hermann. ##
677## See http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00069.html and ##
678## http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00072.html ##
679## ------------------------------------------------------------------------- ##
680
681AT_SETUP([Incorrectly initialized location for empty right-hand side in GLR])
682
683AT_DATA_GRAMMAR([glr-regr8.y],
684[[
685%{
686 #include <stdio.h>
687 #include <stdlib.h>
688 static void yyerror (char const *);
689 static int yylex (void);
c66dfadd 690 static void yyerror (char const *msg);
44e7ead1
PH
691%}
692
693%token T_CONSTANT
694%token T_PORT
695%token T_SIGNAL
696
697%glr-parser
698
699%%
700
701
702PortClause : T_PORT InterfaceDeclaration T_PORT
69ce078b
PE
703 { printf("%d/%d - %d/%d - %d/%d\n",
704 @1.first_column, @1.last_column,
705 @2.first_column, @2.last_column,
44e7ead1
PH
706 @3.first_column, @3.last_column); }
707 ;
708
709InterfaceDeclaration : OptConstantWord %dprec 1
710 | OptSignalWord %dprec 2
711 ;
712
713OptConstantWord : /* empty */
714 | T_CONSTANT
715 ;
716
717OptSignalWord : /* empty */
718 { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
719 | T_SIGNAL
720 ;
721
722%%
723
c66dfadd
PE
724void
725yyerror (char const *msg)
44e7ead1 726{
c66dfadd 727 fprintf (stderr, "%s\n", msg);
44e7ead1
PH
728}
729
730static int lexIndex;
731
69ce078b 732int yylex (void)
44e7ead1
PH
733{
734 lexIndex += 1;
735 switch (lexIndex)
736 {
cf806753
PE
737 default:
738 abort ();
44e7ead1
PH
739 case 1:
740 yylloc.first_column = 1;
741 yylloc.last_column = 9;
742 return T_PORT;
743 case 2:
744 yylloc.first_column = 13;
745 yylloc.last_column = 17;
746 return T_PORT;
cf806753 747 case 3:
44e7ead1
PH
748 return 0;
749 }
750}
751
752int
69ce078b 753main (void)
44e7ead1
PH
754{
755 yyparse();
756 return 0;
757}
758]])
759
da730230 760AT_BISON_CHECK([[-o glr-regr8.c glr-regr8.y]], 0, [],
44e7ead1
PH
761[glr-regr8.y: conflicts: 1 reduce/reduce
762])
763AT_COMPILE([glr-regr8])
764
7d2d521f 765AT_PARSER_CHECK([[./glr-regr8]], 0,
44e7ead1
PH
766[empty: 9/9
7671/9 - 9/9 - 13/17
768],
769[])
770
771AT_CLEANUP
69ce078b
PE
772
773
774## ------------------------------------------------------------------------- ##
4158e0a1 775## No users destructors if stack 0 deleted. See ##
69ce078b
PE
776## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>. ##
777## ------------------------------------------------------------------------- ##
778
779AT_SETUP([No users destructors if stack 0 deleted])
780
781AT_DATA_GRAMMAR([glr-regr9.y],
782[[
783%{
affac613
AD
784# include <stdio.h>
785# include <stdlib.h>
69ce078b
PE
786 static void yyerror (char const *);
787 static int yylex (void);
affac613 788# define YYSTACKEXPANDABLE 0
69ce078b
PE
789 static int tokens = 0;
790 static int destructors = 0;
affac613 791# define USE(Var)
69ce078b
PE
792%}
793
794%glr-parser
795%union { int dummy; }
796%type <dummy> 'a'
797
798%destructor {
799 destructors += 1;
800} 'a'
801
802%%
803
804start:
affac613 805 ambig0 'a' { destructors += 2; USE ($2); }
69ce078b
PE
806 | ambig1 start { destructors += 1; }
807 | ambig2 start { destructors += 1; }
808 ;
809
810ambig0: 'a' ;
811ambig1: 'a' ;
812ambig2: 'a' ;
813
814%%
815
816static int
817yylex (void)
818{
819 tokens += 1;
820 return 'a';
821}
822
823static void
824yyerror (char const *msg)
825{
826 fprintf (stderr, "%s\n", msg);
827}
828
829int
830main (void)
831{
832 int exit_status;
833 exit_status = yyparse ();
834 if (tokens != destructors)
835 {
836 fprintf (stderr, "Tokens = %d, Destructors = %d\n", tokens, destructors);
837 return 1;
838 }
839 return !exit_status;
840}
841]])
842
da730230 843AT_BISON_CHECK([[-o glr-regr9.c glr-regr9.y]], 0, [],
69ce078b
PE
844[glr-regr9.y: conflicts: 1 reduce/reduce
845])
846AT_COMPILE([glr-regr9])
847
7d2d521f 848AT_PARSER_CHECK([[./glr-regr9]], 0, [],
69ce078b
PE
849[memory exhausted
850])
851
852AT_CLEANUP
d659304d
JD
853
854
855## ------------------------------------------------------------------------- ##
856## Corrupted semantic options if user action cuts parse. ##
857## ------------------------------------------------------------------------- ##
858
bf70fa87 859AT_SETUP([Corrupted semantic options if user action cuts parse])
d659304d
JD
860
861AT_DATA_GRAMMAR([glr-regr10.y],
862[[
863%{
cf806753 864# include <stdlib.h>
d659304d
JD
865# include <stdio.h>
866 static void yyerror (char const *);
867 static int yylex (void);
868 #define GARBAGE_SIZE 50
869 static char garbage[GARBAGE_SIZE];
870%}
871
872%glr-parser
873%union { char *ptr; }
874%type <ptr> start
875
876%%
877
878start:
879 %dprec 2 { $$ = garbage; YYACCEPT; }
880 | %dprec 1 { $$ = garbage; YYACCEPT; }
881 ;
882
883%%
884
885static void
886yyerror (char const *msg)
887{
888 fprintf (stderr, "%s\n", msg);
889}
890
891static int
892yylex (void)
893{
cf806753
PE
894 static int called;
895 if (called++)
896 abort ();
d659304d
JD
897 return 0;
898}
899
900int
901main (void)
902{
c66dfadd
PE
903 int i;
904 for (i = 0; i < GARBAGE_SIZE; i+=1)
905 garbage[i] = 108;
d659304d
JD
906 return yyparse ();
907}
908]])
909
da730230 910AT_BISON_CHECK([[-o glr-regr10.c glr-regr10.y]], 0, [],
d659304d
JD
911[glr-regr10.y: conflicts: 1 reduce/reduce
912])
913AT_COMPILE([glr-regr10])
914
7d2d521f 915AT_PARSER_CHECK([[./glr-regr10]], 0, [], [])
d659304d
JD
916
917AT_CLEANUP
918
919
920## ------------------------------------------------------------------------- ##
921## Undesirable destructors if user action cuts parse. ##
922## ------------------------------------------------------------------------- ##
923
bf70fa87 924AT_SETUP([Undesirable destructors if user action cuts parse])
d659304d
JD
925
926AT_DATA_GRAMMAR([glr-regr11.y],
927[[
928%{
929# include <stdlib.h>
930 static void yyerror (char const *);
931 static int yylex (void);
932 static int destructors = 0;
933# define USE(val)
934%}
935
936%glr-parser
937%union { int dummy; }
938%type <int> 'a'
939%destructor { destructors += 1; } 'a'
940
941%%
942
943start:
944 'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
945 | 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
946 ;
947
948%%
949
950static void
951yyerror (char const *msg)
952{
953 fprintf (stderr, "%s\n", msg);
954}
955
956static int
957yylex (void)
958{
cf806753
PE
959 static char const input[] = "a";
960 static size_t toknum;
961 if (! (toknum < sizeof input))
962 abort ();
963 return input[toknum++];
d659304d
JD
964}
965
966int
967main (void)
968{
969 int exit_status = yyparse ();
970 if (destructors != 1)
971 {
972 fprintf (stderr, "Destructor calls: %d\n", destructors);
973 return 1;
974 }
975 return exit_status;
976}
977]])
978
da730230 979AT_BISON_CHECK([[-o glr-regr11.c glr-regr11.y]], 0, [],
d659304d
JD
980[glr-regr11.y: conflicts: 1 reduce/reduce
981])
982AT_COMPILE([glr-regr11])
983
7d2d521f 984AT_PARSER_CHECK([[./glr-regr11]], 0, [], [])
d659304d
JD
985
986AT_CLEANUP
987
988
989## ------------------------------------------------------------------------- ##
520181ab 990## Leaked semantic values if user action cuts parse. ##
d659304d
JD
991## ------------------------------------------------------------------------- ##
992
520181ab 993AT_SETUP([Leaked semantic values if user action cuts parse])
d659304d
JD
994
995AT_DATA_GRAMMAR([glr-regr12.y],
996[[
997%glr-parser
998%union { int dummy; }
520181ab
JD
999%token PARENT_RHS_AFTER
1000%type <dummy> parent_rhs_before merged PARENT_RHS_AFTER
1001%destructor { parent_rhs_before_value = 0; } parent_rhs_before
1002%destructor { merged_value = 0; } merged
1003%destructor { parent_rhs_after_value = 0; } PARENT_RHS_AFTER
d659304d
JD
1004
1005%{
1006# include <stdlib.h>
1007 static int merge (YYSTYPE, YYSTYPE);
1008 static void yyerror (char const *);
1009 static int yylex (void);
520181ab
JD
1010 static int parent_rhs_before_value = 0;
1011 static int merged_value = 0;
1012 static int parent_rhs_after_value = 0;
d659304d
JD
1013# define USE(val)
1014%}
1015
1016%%
1017
1018start:
520181ab
JD
1019 alt1 %dprec 1
1020 | alt2 %dprec 2
6d05403d 1021 ;
520181ab
JD
1022
1023alt1:
1024 PARENT_RHS_AFTER {
1025 USE ($1);
1026 parent_rhs_after_value = 0;
1027 }
1028 ;
1029
1030alt2:
1031 parent_rhs_before merged PARENT_RHS_AFTER {
1032 USE (($1, $2, $3));
1033 parent_rhs_before_value = 0;
1034 merged_value = 0;
1035 parent_rhs_after_value = 0;
1036 }
1037 ;
1038
1039parent_rhs_before:
1040 {
1041 USE ($$);
1042 parent_rhs_before_value = 1;
1043 }
1044 ;
1045
1046merged:
1047 %merge<merge> {
1048 USE ($$);
1049 merged_value = 1;
1050 }
1051 | cut %merge<merge> {
1052 USE ($$);
1053 merged_value = 1;
1054 }
d659304d
JD
1055 ;
1056
520181ab
JD
1057cut: { YYACCEPT; } ;
1058
d659304d
JD
1059%%
1060
1061static int
1062merge (YYSTYPE s1, YYSTYPE s2)
1063{
1064 /* Not invoked. */
bf70fa87
JD
1065 char dummy = s1.dummy + s2.dummy;
1066 return dummy;
d659304d
JD
1067}
1068
1069static void
1070yyerror (char const *msg)
1071{
1072 fprintf (stderr, "%s\n", msg);
1073}
1074
1075static int
1076yylex (void)
1077{
520181ab 1078 static int const input[] = { PARENT_RHS_AFTER, 0 };
cf806753
PE
1079 static size_t toknum;
1080 if (! (toknum < sizeof input / sizeof *input))
1081 abort ();
1082 if (input[toknum] == PARENT_RHS_AFTER)
520181ab 1083 parent_rhs_after_value = 1;
cf806753 1084 return input[toknum++];
d659304d
JD
1085}
1086
1087int
1088main (void)
1089{
1090 int exit_status = yyparse ();
520181ab 1091 if (parent_rhs_before_value)
d659304d 1092 {
520181ab
JD
1093 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1094 exit_status = 1;
1095 }
1096 if (merged_value)
1097 {
1098 fprintf (stderr, "`merged' destructor not called.\n");
1099 exit_status = 1;
1100 }
1101 if (parent_rhs_after_value)
1102 {
1103 fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
1104 exit_status = 1;
d659304d
JD
1105 }
1106 return exit_status;
1107}
1108]])
1109
da730230 1110AT_BISON_CHECK([[-o glr-regr12.c glr-regr12.y]], 0, [],
520181ab 1111[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
d659304d
JD
1112])
1113AT_COMPILE([glr-regr12])
1114
7d2d521f 1115AT_PARSER_CHECK([[./glr-regr12]], 0, [], [])
d659304d
JD
1116
1117AT_CLEANUP
bf70fa87
JD
1118
1119
1120## ------------------------------------------------------------------------- ##
1121## Incorrect lookahead during deterministic GLR. See ##
3f001415
JD
1122## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html> and ##
1123## <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00060.html>. ##
bf70fa87
JD
1124## ------------------------------------------------------------------------- ##
1125
1126AT_SETUP([Incorrect lookahead during deterministic GLR])
1127
1128AT_DATA_GRAMMAR([glr-regr13.y],
1129[[
1130/* Tests:
1131 - Defaulted state with initial yychar: yychar == YYEMPTY.
1132 - Nondefaulted state: yychar != YYEMPTY.
1133 - Defaulted state after lookahead: yychar != YYEMPTY.
3f001415
JD
1134 - Defaulted state after shift: yychar == YYEMPTY.
1135 - User action changing the lookahead. */
bf70fa87
JD
1136
1137%{
1138 #include <stdio.h>
1139 static void yyerror (char const *);
1140 static int yylex (void);
742e4900 1141 static void print_lookahead (char const *);
bf70fa87
JD
1142 #define USE(value)
1143%}
1144
1145%union { char value; }
1146%type <value> 'a' 'b'
1147%glr-parser
1148%locations
1149
1150%%
1151
1152start:
3f001415 1153 defstate_init defstate_shift 'b' change_lookahead 'a' {
bf70fa87 1154 USE ($3);
742e4900 1155 print_lookahead ("start <- defstate_init defstate_shift 'b'");
bf70fa87
JD
1156 }
1157 ;
1158defstate_init:
1159 {
742e4900 1160 print_lookahead ("defstate_init <- empty string");
bf70fa87
JD
1161 }
1162 ;
1163defstate_shift:
1164 nondefstate defstate_look 'a' {
1165 USE ($3);
742e4900 1166 print_lookahead ("defstate_shift <- nondefstate defstate_look 'a'");
bf70fa87
JD
1167 }
1168 ;
1169defstate_look:
1170 {
742e4900 1171 print_lookahead ("defstate_look <- empty string");
bf70fa87
JD
1172 }
1173 ;
1174nondefstate:
1175 {
742e4900 1176 print_lookahead ("nondefstate <- empty string");
bf70fa87
JD
1177 }
1178 | 'b' {
1179 USE ($1);
742e4900 1180 print_lookahead ("nondefstate <- 'b'");
bf70fa87
JD
1181 }
1182 ;
3f001415
JD
1183change_lookahead:
1184 {
1185 yychar = 'a';
1186 }
1187 ;
bf70fa87
JD
1188
1189%%
1190
1191static void
1192yyerror (char const *msg)
1193{
1194 fprintf (stderr, "%s\n", msg);
1195}
1196
1197static int
1198yylex (void)
1199{
cf806753
PE
1200 static char const input[] = "ab";
1201 static size_t toknum;
1202 if (! (toknum < sizeof input))
1203 abort ();
bf70fa87 1204 yylloc.first_line = yylloc.last_line = 1;
cf806753
PE
1205 yylloc.first_column = yylloc.last_column = toknum + 1;
1206 yylval.value = input[toknum] + 'A' - 'a';
1207 return input[toknum++];
bf70fa87
JD
1208}
1209
1210static void
742e4900 1211print_lookahead (char const *reduction)
bf70fa87
JD
1212{
1213 printf ("%s:\n yychar=", reduction);
1214 if (yychar == YYEMPTY)
1215 printf ("YYEMPTY");
1216 else if (yychar == YYEOF)
1217 printf ("YYEOF");
1218 else
1219 {
1220 printf ("'%c', yylval='", yychar);
1221 if (yylval.value > ' ')
1222 printf ("%c", yylval.value);
1223 printf ("', yylloc=(%d,%d),(%d,%d)",
1224 yylloc.first_line, yylloc.first_column,
1225 yylloc.last_line, yylloc.last_column);
1226 }
1227 printf ("\n");
1228}
1229
1230int
1231main (void)
1232{
1233 yychar = '#'; /* Not a token in the grammar. */
1234 yylval.value = '!';
1235 return yyparse ();
1236}
1237]])
1238
da730230 1239AT_BISON_CHECK([[-o glr-regr13.c glr-regr13.y]], 0, [], [])
bf70fa87
JD
1240AT_COMPILE([glr-regr13])
1241
7d2d521f 1242AT_PARSER_CHECK([[./glr-regr13]], 0,
bf70fa87
JD
1243[defstate_init <- empty string:
1244 yychar=YYEMPTY
1245nondefstate <- empty string:
1246 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1247defstate_look <- empty string:
1248 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1249defstate_shift <- nondefstate defstate_look 'a':
1250 yychar=YYEMPTY
1251start <- defstate_init defstate_shift 'b':
1252 yychar=YYEMPTY
1253], [])
1254
1255AT_CLEANUP
1256
1257
1258## ------------------------------------------------------------------------- ##
1259## Incorrect lookahead during nondeterministic GLR. ##
1260## ------------------------------------------------------------------------- ##
1261
1262AT_SETUP([Incorrect lookahead during nondeterministic GLR])
1263
1264AT_DATA_GRAMMAR([glr-regr14.y],
1265[[
1266/* Tests:
b7691f15 1267 - Conflicting actions (split-off parse, which copies lookahead need,
bf70fa87
JD
1268 which is necessarily yytrue) and nonconflicting actions (non-split-off
1269 parse) for nondefaulted state: yychar != YYEMPTY.
b7691f15 1270 - Merged deferred actions (lookahead need and RHS from different stack
bf70fa87
JD
1271 than the target state) and nonmerged deferred actions (same stack).
1272 - Defaulted state after lookahead: yychar != YYEMPTY.
1273 - Defaulted state after shift: yychar == YYEMPTY.
b7691f15 1274 - yychar != YYEMPTY but lookahead need is yyfalse (a previous stack has
bf70fa87
JD
1275 seen the lookahead but current stack has not).
1276 - Exceeding stack capacity (stack explosion), and thus reallocating
b7691f15 1277 lookahead need array.
bf70fa87
JD
1278 Note that it does not seem possible to see the initial yychar value during
1279 nondeterministic operation since:
1280 - In order to preserve the initial yychar, only defaulted states may be
1281 entered.
1282 - If only defaulted states are entered, there are no conflicts, so
1283 nondeterministic operation does not start. */
1284
1285%union { char value; }
1286
1287%{
cf806753 1288 #include <stdlib.h>
bf70fa87
JD
1289 #include <stdio.h>
1290 static void yyerror (char const *);
1291 static int yylex (void);
742e4900 1292 static void print_lookahead (char const *);
bf70fa87
JD
1293 static char merge (union YYSTYPE, union YYSTYPE);
1294 #define USE(value)
1295%}
1296
1297%type <value> 'a' 'b' 'c' 'd' stack_explosion
1298%glr-parser
1299%locations
1300
1301%%
1302
1303start:
1304 merge 'c' stack_explosion {
1305 USE ($2); USE ($3);
742e4900 1306 print_lookahead ("start <- merge 'c' stack_explosion");
bf70fa87
JD
1307 }
1308 ;
1309
b7691f15 1310/* When merging the 2 deferred actions, the lookahead needs are different. */
bf70fa87
JD
1311merge:
1312 nonconflict1 'a' 'b' nonconflict2 %dprec 1 {
1313 USE ($2); USE ($3);
742e4900 1314 print_lookahead ("merge <- nonconflict1 'a' 'b' nonconflict2");
bf70fa87
JD
1315 }
1316 | conflict defstate_look 'a' nonconflict2 'b' defstate_shift %dprec 2 {
1317 USE ($3); USE ($5);
742e4900 1318 print_lookahead ("merge <- conflict defstate_look 'a' nonconflict2 'b'"
bf70fa87
JD
1319 " defstate_shift");
1320 }
1321 ;
1322
1323nonconflict1:
1324 {
742e4900 1325 print_lookahead ("nonconflict1 <- empty string");
bf70fa87
JD
1326 }
1327 ;
1328nonconflict2:
1329 {
742e4900 1330 print_lookahead ("nonconflict2 <- empty string");
bf70fa87
JD
1331 }
1332 | 'a' {
1333 USE ($1);
742e4900 1334 print_lookahead ("nonconflict2 <- 'a'");
bf70fa87
JD
1335 }
1336 ;
1337conflict:
1338 {
742e4900 1339 print_lookahead ("conflict <- empty string");
bf70fa87
JD
1340 }
1341 ;
1342defstate_look:
1343 {
742e4900 1344 print_lookahead ("defstate_look <- empty string");
bf70fa87
JD
1345 }
1346 ;
1347
b7691f15 1348/* yychar != YYEMPTY but lookahead need is yyfalse. */
bf70fa87
JD
1349defstate_shift:
1350 {
742e4900 1351 print_lookahead ("defstate_shift <- empty string");
bf70fa87
JD
1352 }
1353 ;
1354
1355stack_explosion:
1356 { $$ = '\0'; }
1357 | alt1 stack_explosion %merge<merge> { $$ = $2; }
1358 | alt2 stack_explosion %merge<merge> { $$ = $2; }
1359 | alt3 stack_explosion %merge<merge> { $$ = $2; }
1360 ;
1361alt1:
1362 'd' no_look {
1363 USE ($1);
1364 if (yychar != 'd' && yychar != YYEOF)
1365 {
1366 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1367 }
1368 }
1369 ;
1370alt2:
1371 'd' no_look {
1372 USE ($1);
1373 if (yychar != 'd' && yychar != YYEOF)
1374 {
1375 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1376 }
1377 }
1378 ;
1379alt3:
1380 'd' no_look {
1381 USE ($1);
1382 if (yychar != 'd' && yychar != YYEOF)
1383 {
1384 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1385 }
1386 }
1387 ;
1388no_look:
1389 {
1390 if (yychar != YYEMPTY)
1391 {
1392 fprintf (stderr,
1393 "Found lookahead where shouldn't during stack explosion.\n");
1394 }
1395 }
1396 ;
1397
1398%%
1399
1400static void
1401yyerror (char const *msg)
1402{
1403 fprintf (stderr, "%s\n", msg);
1404}
1405
1406static int
1407yylex (void)
1408{
cf806753
PE
1409 static char const input[] = "abcdddd";
1410 static size_t toknum;
1411 if (! (toknum < sizeof input))
1412 abort ();
bf70fa87 1413 yylloc.first_line = yylloc.last_line = 1;
cf806753
PE
1414 yylloc.first_column = yylloc.last_column = toknum + 1;
1415 yylval.value = input[toknum] + 'A' - 'a';
1416 return input[toknum++];
bf70fa87
JD
1417}
1418
1419static void
742e4900 1420print_lookahead (char const *reduction)
bf70fa87
JD
1421{
1422 printf ("%s:\n yychar=", reduction);
1423 if (yychar == YYEMPTY)
1424 printf ("YYEMPTY");
1425 else if (yychar == YYEOF)
1426 printf ("YYEOF");
1427 else
1428 {
1429 printf ("'%c', yylval='", yychar);
1430 if (yylval.value > ' ')
1431 printf ("%c", yylval.value);
1432 printf ("', yylloc=(%d,%d),(%d,%d)",
1433 yylloc.first_line, yylloc.first_column,
1434 yylloc.last_line, yylloc.last_column);
1435 }
1436 printf ("\n");
1437}
1438
1439static char
1440merge (union YYSTYPE s1, union YYSTYPE s2)
1441{
1442 char dummy = s1.value + s2.value;
1443 return dummy;
1444}
1445
1446int
1447main (void)
1448{
1449 yychar = '#'; /* Not a token in the grammar. */
1450 yylval.value = '!';
1451 return yyparse ();
1452}
1453]])
1454
da730230 1455AT_BISON_CHECK([[-o glr-regr14.c glr-regr14.y]], 0, [],
bf70fa87
JD
1456[glr-regr14.y: conflicts: 3 reduce/reduce
1457])
1458AT_COMPILE([glr-regr14])
1459
7d2d521f 1460AT_PARSER_CHECK([[./glr-regr14]], 0,
bf70fa87
JD
1461[conflict <- empty string:
1462 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1463defstate_look <- empty string:
1464 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1465nonconflict2 <- empty string:
1466 yychar='b', yylval='B', yylloc=(1,2),(1,2)
1467defstate_shift <- empty string:
1468 yychar=YYEMPTY
1469merge <- conflict defstate_look 'a' nonconflict2 'b' defstate_shift:
1470 yychar=YYEMPTY
1471start <- merge 'c' stack_explosion:
1472 yychar=YYEOF
1473], [])
1474
1475AT_CLEANUP
35ee866a
JD
1476
1477
1478## ------------------------------------------------------------------------- ##
1479## Leaked semantic values when reporting ambiguity. ##
1480## ------------------------------------------------------------------------- ##
1481
1482AT_SETUP([Leaked semantic values when reporting ambiguity])
1483
1484AT_DATA_GRAMMAR([glr-regr15.y],
1485[[
1486%glr-parser
35ee866a
JD
1487%destructor { parent_rhs_before_value = 0; } parent_rhs_before
1488
1489%{
1490# include <stdlib.h>
1491 static void yyerror (char const *);
1492 static int yylex (void);
1493 static int parent_rhs_before_value = 0;
1494# define USE(val)
1495%}
1496
1497%%
1498
1499start:
1500 alt1 %dprec 1
1501 | alt2 %dprec 2
1502 ;
1503
1504/* This stack must be merged into the other stacks *last* (added at the
1505 beginning of the semantic options list) so that yyparse will choose to clean
1506 it up rather than the tree for which some semantic actions have been
1507 performed. Thus, if yyreportAmbiguity longjmp's to yyparse, the values from
1508 those other trees are not cleaned up. */
1509alt1: ;
1510
1511alt2:
1512 parent_rhs_before ambiguity {
1513 USE ($1);
1514 parent_rhs_before_value = 0;
1515 }
1516 ;
1517
1518parent_rhs_before:
1519 {
1520 USE ($$);
1521 parent_rhs_before_value = 1;
1522 }
1523 ;
1524
1525ambiguity: ambiguity1 | ambiguity2 ;
1526ambiguity1: ;
1527ambiguity2: ;
1528
1529%%
1530
1531static void
1532yyerror (char const *msg)
1533{
1534 fprintf (stderr, "%s\n", msg);
1535}
1536
1537static int
1538yylex (void)
1539{
cf806753
PE
1540 static int called;
1541 if (called++)
1542 abort ();
35ee866a
JD
1543 return 0;
1544}
1545
1546int
1547main (void)
1548{
1549 int exit_status = yyparse () != 1;
1550 if (parent_rhs_before_value)
1551 {
1552 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1553 exit_status = 1;
1554 }
1555 return exit_status;
1556}
1557]])
1558
da730230 1559AT_BISON_CHECK([[-o glr-regr15.c glr-regr15.y]], 0, [],
35ee866a
JD
1560[glr-regr15.y: conflicts: 2 reduce/reduce
1561])
1562AT_COMPILE([glr-regr15])
1563
7d2d521f 1564AT_PARSER_CHECK([[./glr-regr15]], 0, [],
35ee866a
JD
1565[syntax is ambiguous
1566])
1567
1568AT_CLEANUP
ae952af2
JD
1569
1570
1571## ------------------------------------------------------------------------- ##
1572## Leaked lookahead after nondeterministic parse syntax error. ##
1573## ------------------------------------------------------------------------- ##
1574
1575AT_SETUP([Leaked lookahead after nondeterministic parse syntax error])
1576AT_DATA_GRAMMAR([glr-regr16.y],
1577[[
1578%glr-parser
1579%destructor { lookahead_value = 0; } 'b'
1580
1581%{
1582# include <stdlib.h>
1583 static void yyerror (char const *);
1584 static int yylex (void);
1585 static int lookahead_value = 0;
1586# define USE(val)
1587%}
1588
1589%%
1590
1591start: alt1 'a' | alt2 'a' ;
1592alt1: ;
1593alt2: ;
1594
1595%%
1596
1597static void
1598yyerror (char const *msg)
1599{
1600 fprintf (stderr, "%s\n", msg);
1601}
1602
1603static int
1604yylex (void)
1605{
cf806753
PE
1606 static char const input[] = "ab";
1607 static size_t toknum;
1608 if (! (toknum < sizeof input))
1609 abort ();
1610 if (input[toknum] == 'b')
ae952af2 1611 lookahead_value = 1;
cf806753 1612 return input[toknum++];
ae952af2
JD
1613}
1614
1615int
1616main (void)
1617{
1618 int exit_status = yyparse () != 1;
1619 if (lookahead_value)
1620 {
1621 fprintf (stderr, "Lookahead destructor not called.\n");
1622 exit_status = 1;
1623 }
1624 return exit_status;
1625}
1626]])
1627
da730230 1628AT_BISON_CHECK([[-o glr-regr16.c glr-regr16.y]], 0, [],
ae952af2
JD
1629[glr-regr16.y: conflicts: 1 reduce/reduce
1630])
1631AT_COMPILE([glr-regr16])
1632
7d2d521f 1633AT_PARSER_CHECK([[./glr-regr16]], 0, [],
ae952af2
JD
1634[syntax error
1635])
1636
1637AT_CLEANUP
8710fc41
JD
1638
1639
1640## ------------------------------------------------------------------------- ##
1641## Uninitialized location when reporting ambiguity. ##
1642## ------------------------------------------------------------------------- ##
1643
1644AT_SETUP([Uninitialized location when reporting ambiguity])
1645AT_DATA_GRAMMAR([glr-regr17.y],
1646[[
1647%glr-parser
1648%locations
d9df47b6 1649%define api.pure
8710fc41
JD
1650%error-verbose
1651
1652%union { int dummy; }
1653
1654%{
1655 static void yyerror (YYLTYPE *, char const *);
1656 static int yylex (YYSTYPE *, YYLTYPE *);
1657%}
1658
1659%initial-action {
1660 @$.first_line = 1;
1661 @$.first_column = 1;
1662 @$.last_line = 1;
1663 @$.last_column = 1;
1664}
1665
1666%%
1667
5ad0a449
JD
1668/* Tests the case of an empty RHS that has inherited the location of the
1669 previous nonterminal, which is unresolved. That location is reported as the
1670 last position of the ambiguity. */
1671start: ambig1 empty1 | ambig2 empty2 ;
1672
8710fc41 1673/* Tests multiple levels of yyresolveLocations recursion. */
8710fc41
JD
1674ambig1: sub_ambig1 | sub_ambig2 ;
1675ambig2: sub_ambig1 | sub_ambig2 ;
1676
5ad0a449
JD
1677/* Tests the case of a non-empty RHS as well as the case of an empty RHS that
1678 has inherited the initial location. The empty RHS's location is reported as
1679 the first position in the ambiguity. */
1680sub_ambig1: empty1 'a' 'b' ;
1681sub_ambig2: empty2 'a' 'b' ;
1682empty1: ;
1683empty2: ;
8710fc41
JD
1684
1685%%
1686
1687static void
1688yyerror (YYLTYPE *locp, char const *msg)
1689{
1690 fprintf (stderr, "Error at %d.%d-%d.%d: %s.\n", locp->first_line,
1691 locp->first_column, locp->last_line, locp->last_column, msg);
1692}
1693
6d05403d 1694static int
8710fc41
JD
1695yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
1696{
6d05403d 1697 static char const input[] = "ab";
cf806753
PE
1698 static size_t toknum;
1699 if (! (toknum < sizeof input))
1700 abort ();
6d05403d 1701 lvalp->dummy = 0;
8710fc41 1702 llocp->first_line = llocp->last_line = 2;
cf806753 1703 llocp->first_column = toknum + 1;
8710fc41 1704 llocp->last_column = llocp->first_column + 1;
cf806753 1705 return input[toknum++];
8710fc41
JD
1706}
1707
1708int
1709main (void)
1710{
1711 return yyparse () != 1;
1712}
1713]])
1714
da730230 1715AT_BISON_CHECK([[-o glr-regr17.c glr-regr17.y]], 0, [],
8710fc41
JD
1716[glr-regr17.y: conflicts: 3 reduce/reduce
1717])
1718AT_COMPILE([glr-regr17])
1719
7d2d521f 1720AT_PARSER_CHECK([[./glr-regr17]], 0, [],
8710fc41
JD
1721[Error at 1.1-2.3: syntax is ambiguous.
1722])
1723
1724AT_CLEANUP
8ee5b538
JD
1725
1726
1727## -------------------------------------------------------------##
1728## Missed %merge type warnings when LHS type is declared later. ##
1729## -------------------------------------------------------------##
1730
1731AT_SETUP([Missed %merge type warnings when LHS type is declared later])
1732AT_DATA_GRAMMAR([glr-regr18.y],
1733[[%glr-parser
1734
1735%{
cf806753 1736 #include <stdlib.h>
8ee5b538
JD
1737 static void yyerror (char const *);
1738 static int yylex ();
1739%}
1740
1741%union {
1742 int type1;
1743 int type2;
dd60572a 1744 int type3;
8ee5b538
JD
1745}
1746
1747%%
1748
1749sym1: sym2 %merge<merge> { $$ = $1; } ;
dd60572a
JD
1750sym2: sym3 %merge<merge> { $$ = $1; } ;
1751sym3: %merge<merge> { $$ = 0; } ;
8ee5b538
JD
1752
1753%type <type1> sym1;
1754%type <type2> sym2;
dd60572a 1755%type <type3> sym3;
8ee5b538
JD
1756
1757%%
1758
1759static void
1760yyerror (char const *msg)
1761{
1762 fprintf (stderr, "%s\n", msg);
1763}
1764
1765static int
1766yylex ()
1767{
cf806753
PE
1768 static int called;
1769 if (called++)
1770 abort ();
8ee5b538
JD
1771 return 0;
1772}
1773
1774int
1775main (void)
1776{
1777 return yyparse ();
1778}
1779]])
1780
da730230 1781AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [],
231ed89a
PE
1782[glr-regr18.y:26.18-24: result type clash on merge function `merge': <type2> != <type1>
1783glr-regr18.y:25.18-24: previous declaration
1784glr-regr18.y:27.13-19: result type clash on merge function `merge': <type3> != <type2>
1785glr-regr18.y:26.18-24: previous declaration
8ee5b538
JD
1786])
1787
1788AT_CLEANUP