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