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