]> git.saurik.com Git - bison.git/blob - tests/glr-regression.at
gnulib: update
[bison.git] / tests / glr-regression.at
1 # Checking GLR Parsing: Regression Tests -*- Autotest -*-
2
3 # Copyright (C) 2002-2003, 2005-2007, 2009-2012 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 int
492 main (void)
493 {
494 return yyparse () != 1;
495 }
496 ]])
497 AT_BISON_OPTION_POPDEFS
498
499 AT_BISON_CHECK([[-o glr-regr5.c glr-regr5.y]], 0, [],
500 [[glr-regr5.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
501 ]])
502 AT_COMPILE([glr-regr5])
503
504 AT_PARSER_CHECK([[./glr-regr5]], 0, [],
505 [syntax is ambiguous
506 ])
507
508 AT_CLEANUP
509
510
511 ## ------------------------------------------------------------------------- ##
512 ## User destructor after an error during a split parse. See ##
513 ## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00029.html>. ##
514 ## ------------------------------------------------------------------------- ##
515
516 AT_SETUP([User destructor after an error during a split parse])
517
518 AT_BISON_OPTION_PUSHDEFS
519 AT_DATA_GRAMMAR([glr-regr6.y],
520 [[
521 %{
522 #include <stdio.h>
523 #include <stdlib.h>
524 ]AT_YYERROR_DECLARE[
525 ]AT_YYLEX_DECLARE[
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 ]AT_YYERROR_DEFINE[
542 ]AT_YYLEX_DEFINE(["a"])[
543 int
544 main (void)
545 {
546 return yyparse () != 1;
547 }
548 ]])
549 AT_BISON_OPTION_POPDEFS
550
551 AT_BISON_CHECK([[-o glr-regr6.c glr-regr6.y]], 0, [],
552 [[glr-regr6.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
553 ]])
554 AT_COMPILE([glr-regr6])
555
556 AT_PARSER_CHECK([[./glr-regr6]], 0,
557 [Destructor called.
558 ],
559 [syntax is ambiguous
560 ])
561
562 AT_CLEANUP
563
564
565 ## ------------------------------------------------------------------------- ##
566 ## Duplicated user destructor for lookahead. See ##
567 ## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00035.html>. ##
568 ## ------------------------------------------------------------------------- ##
569
570 AT_SETUP([Duplicated user destructor for lookahead])
571
572 AT_BISON_OPTION_PUSHDEFS
573 AT_DATA_GRAMMAR([glr-regr7.y],
574 [[
575 %{
576 #include <stdio.h>
577 #include <stdlib.h>
578 ]AT_YYERROR_DECLARE[
579 ]AT_YYLEX_DECLARE[
580 #define YYSTACKEXPANDABLE 0
581 typedef struct count_node {
582 int count;
583 struct count_node *prev;
584 } count_node;
585 static count_node *tail;
586 %}
587
588 %glr-parser
589 %union { count_node *node; }
590 %type <node> 'a'
591
592 %destructor {
593 if ($$->count++)
594 fprintf (stderr, "Destructor called on same value twice.\n");
595 } 'a'
596
597 %%
598
599 start:
600 stack1 start
601 | stack2 start
602 | /* empty */
603 ;
604 stack1: 'a' ;
605 stack2: 'a' ;
606
607 %%
608
609 static int
610 yylex (void)
611 {
612 yylval.node = (count_node*) malloc (sizeof *yylval.node);
613 if (!yylval.node)
614 {
615 fprintf (stderr, "Test inconclusive.\n");
616 exit (EXIT_FAILURE);
617 }
618 yylval.node->count = 0;
619 yylval.node->prev = tail;
620 tail = yylval.node;
621 return 'a';
622 }
623
624 ]AT_YYERROR_DEFINE[
625 int
626 main (void)
627 {
628 int status = yyparse ();
629 while (tail)
630 {
631 count_node *prev = tail->prev;
632 free (tail);
633 tail = prev;
634 }
635 return status;
636 }
637 ]])
638 AT_BISON_OPTION_POPDEFS
639
640 AT_BISON_CHECK([[-o glr-regr7.c glr-regr7.y]], 0, [],
641 [[glr-regr7.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
642 ]])
643 AT_COMPILE([glr-regr7])
644
645 AT_PARSER_CHECK([[./glr-regr7]], 2, [],
646 [memory exhausted
647 ])
648
649 AT_CLEANUP
650
651
652 ## ------------------------------------------------------------------------- ##
653 ## Incorrect default location for empty right-hand sides. Adapted from bug ##
654 ## report by Claudia Hermann. ##
655 ## See http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00069.html and ##
656 ## http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00072.html ##
657 ## ------------------------------------------------------------------------- ##
658
659 AT_SETUP([Incorrectly initialized location for empty right-hand side in GLR])
660
661 AT_BISON_OPTION_PUSHDEFS
662 AT_DATA_GRAMMAR([glr-regr8.y],
663 [[
664 %{
665 #include <stdio.h>
666 #include <stdlib.h>
667 ]AT_YYERROR_DECLARE[
668 ]AT_YYLEX_DECLARE[
669 %}
670
671 %token T_CONSTANT
672 %token T_PORT
673 %token T_SIGNAL
674
675 %glr-parser
676
677 %%
678
679
680 PortClause : T_PORT InterfaceDeclaration T_PORT
681 { printf("%d/%d - %d/%d - %d/%d\n",
682 @1.first_column, @1.last_column,
683 @2.first_column, @2.last_column,
684 @3.first_column, @3.last_column); }
685 ;
686
687 InterfaceDeclaration : OptConstantWord %dprec 1
688 | OptSignalWord %dprec 2
689 ;
690
691 OptConstantWord : /* empty */
692 | T_CONSTANT
693 ;
694
695 OptSignalWord : /* empty */
696 { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
697 | T_SIGNAL
698 ;
699
700 %%
701
702 ]AT_YYERROR_DEFINE[
703 static int lexIndex;
704
705 int yylex (void)
706 {
707 lexIndex += 1;
708 switch (lexIndex)
709 {
710 default:
711 abort ();
712 case 1:
713 yylloc.first_column = 1;
714 yylloc.last_column = 9;
715 return T_PORT;
716 case 2:
717 yylloc.first_column = 13;
718 yylloc.last_column = 17;
719 return T_PORT;
720 case 3:
721 return 0;
722 }
723 }
724
725 int
726 main (void)
727 {
728 yyparse();
729 return 0;
730 }
731 ]])
732 AT_BISON_OPTION_POPDEFS
733
734 AT_BISON_CHECK([[-o glr-regr8.c glr-regr8.y]], 0, [],
735 [[glr-regr8.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
736 ]])
737 AT_COMPILE([glr-regr8])
738
739 AT_PARSER_CHECK([[./glr-regr8]], 0,
740 [empty: 9/9
741 1/9 - 9/9 - 13/17
742 ],
743 [])
744
745 AT_CLEANUP
746
747
748 ## ------------------------------------------------------------------------- ##
749 ## No users destructors if stack 0 deleted. See ##
750 ## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>. ##
751 ## ------------------------------------------------------------------------- ##
752
753 AT_SETUP([No users destructors if stack 0 deleted])
754
755 AT_BISON_OPTION_PUSHDEFS
756 AT_DATA_GRAMMAR([glr-regr9.y],
757 [[
758 %{
759 # include <stdio.h>
760 # include <stdlib.h>
761 ]AT_YYERROR_DECLARE[
762 ]AT_YYLEX_DECLARE[
763 # define YYSTACKEXPANDABLE 0
764 static int tokens = 0;
765 static int destructors = 0;
766 # define USE(Var)
767 %}
768
769 %glr-parser
770 %union { int dummy; }
771 %type <dummy> 'a'
772
773 %destructor {
774 destructors += 1;
775 } 'a'
776
777 %%
778
779 start:
780 ambig0 'a' { destructors += 2; USE ($2); }
781 | ambig1 start { destructors += 1; }
782 | ambig2 start { destructors += 1; }
783 ;
784
785 ambig0: 'a' ;
786 ambig1: 'a' ;
787 ambig2: 'a' ;
788
789 %%
790
791 static int
792 yylex (void)
793 {
794 tokens += 1;
795 return 'a';
796 }
797
798 ]AT_YYERROR_DEFINE[
799 int
800 main (void)
801 {
802 int exit_status;
803 exit_status = yyparse ();
804 if (tokens != destructors)
805 {
806 fprintf (stderr, "Tokens = %d, Destructors = %d\n", tokens, destructors);
807 return 1;
808 }
809 return !exit_status;
810 }
811 ]])
812 AT_BISON_OPTION_POPDEFS
813
814 AT_BISON_CHECK([[-o glr-regr9.c glr-regr9.y]], 0, [],
815 [[glr-regr9.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
816 ]])
817 AT_COMPILE([glr-regr9])
818
819 AT_PARSER_CHECK([[./glr-regr9]], 0, [],
820 [memory exhausted
821 ])
822
823 AT_CLEANUP
824
825
826 ## ------------------------------------------------------ ##
827 ## Corrupted semantic options if user action cuts parse. ##
828 ## ------------------------------------------------------ ##
829
830 AT_SETUP([Corrupted semantic options if user action cuts parse])
831
832 AT_BISON_OPTION_PUSHDEFS
833 AT_DATA_GRAMMAR([glr-regr10.y],
834 [[
835 %{
836 # include <stdlib.h>
837 # include <stdio.h>
838 ]AT_YYERROR_DECLARE[
839 ]AT_YYLEX_DECLARE[
840 #define GARBAGE_SIZE 50
841 static char garbage[GARBAGE_SIZE];
842 %}
843
844 %glr-parser
845 %union { char *ptr; }
846 %type <ptr> start
847
848 %%
849
850 start:
851 %dprec 2 { $$ = garbage; YYACCEPT; }
852 | %dprec 1 { $$ = garbage; YYACCEPT; }
853 ;
854
855 %%
856 ]AT_YYERROR_DEFINE[
857 ]AT_YYLEX_DEFINE[
858
859 int
860 main (void)
861 {
862 int i;
863 for (i = 0; i < GARBAGE_SIZE; i+=1)
864 garbage[i] = 108;
865 return yyparse ();
866 }
867 ]])
868 AT_BISON_OPTION_POPDEFS
869
870 AT_BISON_CHECK([[-o glr-regr10.c glr-regr10.y]], 0, [],
871 [[glr-regr10.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
872 ]])
873 AT_COMPILE([glr-regr10])
874
875 AT_PARSER_CHECK([[./glr-regr10]], 0, [], [])
876
877 AT_CLEANUP
878
879
880 ## --------------------------------------------------- ##
881 ## Undesirable destructors if user action cuts parse. ##
882 ## --------------------------------------------------- ##
883
884 AT_SETUP([Undesirable destructors if user action cuts parse])
885
886 AT_BISON_OPTION_PUSHDEFS
887 AT_DATA_GRAMMAR([glr-regr11.y],
888 [[
889 %{
890 # include <stdlib.h>
891 ]AT_YYERROR_DECLARE[
892 ]AT_YYLEX_DECLARE[
893 static int destructors = 0;
894 # define USE(val)
895 %}
896
897 %glr-parser
898 %union { int dummy; }
899 %type <int> 'a'
900 %destructor { destructors += 1; } 'a'
901
902 %%
903
904 start:
905 'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
906 | 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
907 ;
908
909 %%
910
911 ]AT_YYERROR_DEFINE[
912 ]AT_YYLEX_DEFINE(["a"])[
913
914 int
915 main (void)
916 {
917 int exit_status = yyparse ();
918 if (destructors != 1)
919 {
920 fprintf (stderr, "Destructor calls: %d\n", destructors);
921 return 1;
922 }
923 return exit_status;
924 }
925 ]])
926 AT_BISON_OPTION_POPDEFS
927
928 AT_BISON_CHECK([[-o glr-regr11.c glr-regr11.y]], 0, [],
929 [[glr-regr11.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
930 ]])
931 AT_COMPILE([glr-regr11])
932
933 AT_PARSER_CHECK([[./glr-regr11]], 0, [], [])
934
935 AT_CLEANUP
936
937
938 ## -------------------------------------------------- ##
939 ## Leaked semantic values if user action cuts parse. ##
940 ## -------------------------------------------------- ##
941
942 AT_SETUP([Leaked semantic values if user action cuts parse])
943
944 AT_BISON_OPTION_PUSHDEFS
945 AT_DATA_GRAMMAR([glr-regr12.y],
946 [[
947 %glr-parser
948 %union { int dummy; }
949 %token PARENT_RHS_AFTER
950 %type <dummy> parent_rhs_before merged PARENT_RHS_AFTER
951 %destructor { parent_rhs_before_value = 0; } parent_rhs_before
952 %destructor { merged_value = 0; } merged
953 %destructor { parent_rhs_after_value = 0; } PARENT_RHS_AFTER
954
955 %{
956 # include <stdlib.h>
957 # include <assert.h>
958 static int merge (YYSTYPE, YYSTYPE);
959 ]AT_YYERROR_DECLARE[
960 ]AT_YYLEX_DECLARE[
961 static int parent_rhs_before_value = 0;
962 static int merged_value = 0;
963 static int parent_rhs_after_value = 0;
964 # define USE(val)
965 %}
966
967 %%
968
969 start:
970 alt1 %dprec 1
971 | alt2 %dprec 2
972 ;
973
974 alt1:
975 PARENT_RHS_AFTER {
976 USE ($1);
977 parent_rhs_after_value = 0;
978 }
979 ;
980
981 alt2:
982 parent_rhs_before merged PARENT_RHS_AFTER {
983 USE (($1, $2, $3));
984 parent_rhs_before_value = 0;
985 merged_value = 0;
986 parent_rhs_after_value = 0;
987 }
988 ;
989
990 parent_rhs_before:
991 {
992 USE ($$);
993 parent_rhs_before_value = 1;
994 }
995 ;
996
997 merged:
998 %merge<merge> {
999 USE ($$);
1000 merged_value = 1;
1001 }
1002 | cut %merge<merge> {
1003 USE ($$);
1004 merged_value = 1;
1005 }
1006 ;
1007
1008 cut: { YYACCEPT; } ;
1009
1010 %%
1011
1012 static int
1013 merge (YYSTYPE s1, YYSTYPE s2)
1014 {
1015 /* Not invoked. */
1016 char dummy = s1.dummy + s2.dummy;
1017 return dummy;
1018 }
1019
1020 ]AT_YYERROR_DEFINE[
1021 ]AT_YYLEX_DEFINE([{ PARENT_RHS_AFTER, 0 }],
1022 [if (res == PARENT_RHS_AFTER)
1023 parent_rhs_after_value = 1;])[
1024
1025 int
1026 main (void)
1027 {
1028 int exit_status = yyparse ();
1029 if (parent_rhs_before_value)
1030 {
1031 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1032 exit_status = 1;
1033 }
1034 if (merged_value)
1035 {
1036 fprintf (stderr, "`merged' destructor not called.\n");
1037 exit_status = 1;
1038 }
1039 if (parent_rhs_after_value)
1040 {
1041 fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
1042 exit_status = 1;
1043 }
1044 return exit_status;
1045 }
1046 ]])
1047 AT_BISON_OPTION_POPDEFS
1048
1049 AT_BISON_CHECK([[-o glr-regr12.c glr-regr12.y]], 0, [],
1050 [[glr-regr12.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
1051 glr-regr12.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1052 ]])
1053 AT_COMPILE([glr-regr12])
1054
1055 AT_PARSER_CHECK([[./glr-regr12]], 0, [], [])
1056
1057 AT_CLEANUP
1058
1059
1060 ## ------------------------------------------------------------------------- ##
1061 ## Incorrect lookahead during deterministic GLR. See ##
1062 ## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html> and ##
1063 ## <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00060.html>. ##
1064 ## ------------------------------------------------------------------------- ##
1065
1066 AT_SETUP([Incorrect lookahead during deterministic GLR])
1067
1068 AT_BISON_OPTION_PUSHDEFS
1069 AT_DATA_GRAMMAR([glr-regr13.y],
1070 [[
1071 /* Tests:
1072 - Defaulted state with initial yychar: yychar == YYEMPTY.
1073 - Nondefaulted state: yychar != YYEMPTY.
1074 - Defaulted state after lookahead: yychar != YYEMPTY.
1075 - Defaulted state after shift: yychar == YYEMPTY.
1076 - User action changing the lookahead. */
1077
1078 %{
1079 #include <stdio.h>
1080 #include <assert.h>
1081 ]AT_YYERROR_DECLARE[
1082 ]AT_YYLEX_DECLARE[
1083 static void print_lookahead (char const *);
1084 #define USE(value)
1085 %}
1086
1087 %union { char value; }
1088 %type <value> 'a' 'b'
1089 %glr-parser
1090 %locations
1091
1092 %%
1093
1094 start:
1095 defstate_init defstate_shift 'b' change_lookahead 'a' {
1096 USE ($3);
1097 print_lookahead ("start <- defstate_init defstate_shift 'b'");
1098 }
1099 ;
1100 defstate_init:
1101 {
1102 print_lookahead ("defstate_init <- empty string");
1103 }
1104 ;
1105 defstate_shift:
1106 nondefstate defstate_look 'a' {
1107 USE ($3);
1108 print_lookahead ("defstate_shift <- nondefstate defstate_look 'a'");
1109 }
1110 ;
1111 defstate_look:
1112 {
1113 print_lookahead ("defstate_look <- empty string");
1114 }
1115 ;
1116 nondefstate:
1117 {
1118 print_lookahead ("nondefstate <- empty string");
1119 }
1120 | 'b' {
1121 USE ($1);
1122 print_lookahead ("nondefstate <- 'b'");
1123 }
1124 ;
1125 change_lookahead:
1126 {
1127 yychar = 'a';
1128 }
1129 ;
1130
1131 %%
1132
1133 ]AT_YYERROR_DEFINE[
1134 ]AT_YYLEX_DEFINE(["ab"],
1135 [yylval.value = res + 'A' - 'a'])[
1136
1137 static void
1138 print_lookahead (char const *reduction)
1139 {
1140 printf ("%s:\n yychar=", reduction);
1141 if (yychar == YYEMPTY)
1142 printf ("YYEMPTY");
1143 else if (yychar == YYEOF)
1144 printf ("YYEOF");
1145 else
1146 {
1147 printf ("'%c', yylval='", yychar);
1148 if (yylval.value > ' ')
1149 printf ("%c", yylval.value);
1150 printf ("', yylloc=(%d,%d),(%d,%d)",
1151 yylloc.first_line, yylloc.first_column,
1152 yylloc.last_line, yylloc.last_column);
1153 }
1154 printf ("\n");
1155 }
1156
1157 int
1158 main (void)
1159 {
1160 yychar = '#'; /* Not a token in the grammar. */
1161 yylval.value = '!';
1162 return yyparse ();
1163 }
1164 ]])
1165 AT_BISON_OPTION_POPDEFS
1166
1167 AT_BISON_CHECK([[-o glr-regr13.c glr-regr13.y]], 0, [], [])
1168 AT_COMPILE([glr-regr13])
1169
1170 AT_PARSER_CHECK([[./glr-regr13]], 0,
1171 [defstate_init <- empty string:
1172 yychar=YYEMPTY
1173 nondefstate <- empty string:
1174 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1175 defstate_look <- empty string:
1176 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1177 defstate_shift <- nondefstate defstate_look 'a':
1178 yychar=YYEMPTY
1179 start <- defstate_init defstate_shift 'b':
1180 yychar=YYEMPTY
1181 ], [])
1182
1183 AT_CLEANUP
1184
1185
1186 ## ------------------------------------------------- ##
1187 ## Incorrect lookahead during nondeterministic GLR. ##
1188 ## ------------------------------------------------- ##
1189
1190 AT_SETUP([Incorrect lookahead during nondeterministic GLR])
1191
1192 AT_BISON_OPTION_PUSHDEFS
1193 AT_DATA_GRAMMAR([glr-regr14.y],
1194 [[
1195 /* Tests:
1196 - Conflicting actions (split-off parse, which copies lookahead need,
1197 which is necessarily yytrue) and nonconflicting actions (non-split-off
1198 parse) for nondefaulted state: yychar != YYEMPTY.
1199 - Merged deferred actions (lookahead need and RHS from different stack
1200 than the target state) and nonmerged deferred actions (same stack).
1201 - Defaulted state after lookahead: yychar != YYEMPTY.
1202 - Defaulted state after shift: yychar == YYEMPTY.
1203 - yychar != YYEMPTY but lookahead need is yyfalse (a previous stack has
1204 seen the lookahead but current stack has not).
1205 - Exceeding stack capacity (stack explosion), and thus reallocating
1206 lookahead need array.
1207 Note that it does not seem possible to see the initial yychar value during
1208 nondeterministic operation since:
1209 - In order to preserve the initial yychar, only defaulted states may be
1210 entered.
1211 - If only defaulted states are entered, there are no conflicts, so
1212 nondeterministic operation does not start. */
1213
1214 %union { char value; }
1215
1216 %{
1217 #include <stdlib.h>
1218 #include <stdio.h>
1219 #include <assert.h>
1220 ]AT_YYERROR_DECLARE[
1221 ]AT_YYLEX_DECLARE[
1222 static void print_lookahead (char const *);
1223 static char merge (union YYSTYPE, union YYSTYPE);
1224 #define USE(value)
1225 %}
1226
1227 %type <value> 'a' 'b' 'c' 'd' stack_explosion
1228 %glr-parser
1229 %locations
1230
1231 %%
1232
1233 start:
1234 merge 'c' stack_explosion {
1235 USE ($2); USE ($3);
1236 print_lookahead ("start <- merge 'c' stack_explosion");
1237 }
1238 ;
1239
1240 /* When merging the 2 deferred actions, the lookahead needs are different. */
1241 merge:
1242 nonconflict1 'a' 'b' nonconflict2 %dprec 1 {
1243 USE ($2); USE ($3);
1244 print_lookahead ("merge <- nonconflict1 'a' 'b' nonconflict2");
1245 }
1246 | conflict defstate_look 'a' nonconflict2 'b' defstate_shift %dprec 2 {
1247 USE ($3); USE ($5);
1248 print_lookahead ("merge <- conflict defstate_look 'a' nonconflict2 'b'"
1249 " defstate_shift");
1250 }
1251 ;
1252
1253 nonconflict1:
1254 {
1255 print_lookahead ("nonconflict1 <- empty string");
1256 }
1257 ;
1258 nonconflict2:
1259 {
1260 print_lookahead ("nonconflict2 <- empty string");
1261 }
1262 | 'a' {
1263 USE ($1);
1264 print_lookahead ("nonconflict2 <- 'a'");
1265 }
1266 ;
1267 conflict:
1268 {
1269 print_lookahead ("conflict <- empty string");
1270 }
1271 ;
1272 defstate_look:
1273 {
1274 print_lookahead ("defstate_look <- empty string");
1275 }
1276 ;
1277
1278 /* yychar != YYEMPTY but lookahead need is yyfalse. */
1279 defstate_shift:
1280 {
1281 print_lookahead ("defstate_shift <- empty string");
1282 }
1283 ;
1284
1285 stack_explosion:
1286 { $$ = '\0'; }
1287 | alt1 stack_explosion %merge<merge> { $$ = $2; }
1288 | alt2 stack_explosion %merge<merge> { $$ = $2; }
1289 | alt3 stack_explosion %merge<merge> { $$ = $2; }
1290 ;
1291 alt1:
1292 'd' no_look {
1293 USE ($1);
1294 if (yychar != 'd' && yychar != YYEOF)
1295 {
1296 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1297 }
1298 }
1299 ;
1300 alt2:
1301 'd' no_look {
1302 USE ($1);
1303 if (yychar != 'd' && yychar != YYEOF)
1304 {
1305 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1306 }
1307 }
1308 ;
1309 alt3:
1310 'd' no_look {
1311 USE ($1);
1312 if (yychar != 'd' && yychar != YYEOF)
1313 {
1314 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1315 }
1316 }
1317 ;
1318 no_look:
1319 {
1320 if (yychar != YYEMPTY)
1321 {
1322 fprintf (stderr,
1323 "Found lookahead where shouldn't during stack explosion.\n");
1324 }
1325 }
1326 ;
1327
1328 %%
1329
1330 ]AT_YYERROR_DEFINE[
1331 static int
1332 yylex (void)
1333 {
1334 static char const input[] = "abcdddd";
1335 static size_t toknum;
1336 assert (toknum < sizeof input);
1337 yylloc.first_line = yylloc.last_line = 1;
1338 yylloc.first_column = yylloc.last_column = toknum + 1;
1339 yylval.value = input[toknum] + 'A' - 'a';
1340 return input[toknum++];
1341 }
1342
1343 static void
1344 print_lookahead (char const *reduction)
1345 {
1346 printf ("%s:\n yychar=", reduction);
1347 if (yychar == YYEMPTY)
1348 printf ("YYEMPTY");
1349 else if (yychar == YYEOF)
1350 printf ("YYEOF");
1351 else
1352 {
1353 printf ("'%c', yylval='", yychar);
1354 if (yylval.value > ' ')
1355 printf ("%c", yylval.value);
1356 printf ("', yylloc=(%d,%d),(%d,%d)",
1357 yylloc.first_line, yylloc.first_column,
1358 yylloc.last_line, yylloc.last_column);
1359 }
1360 printf ("\n");
1361 }
1362
1363 static char
1364 merge (union YYSTYPE s1, union YYSTYPE s2)
1365 {
1366 char dummy = s1.value + s2.value;
1367 return dummy;
1368 }
1369
1370 int
1371 main (void)
1372 {
1373 yychar = '#'; /* Not a token in the grammar. */
1374 yylval.value = '!';
1375 return yyparse ();
1376 }
1377 ]])
1378 AT_BISON_OPTION_POPDEFS
1379
1380 AT_BISON_CHECK([[-o glr-regr14.c glr-regr14.y]], 0, [],
1381 [[glr-regr14.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
1382 ]])
1383 AT_COMPILE([glr-regr14])
1384
1385 AT_PARSER_CHECK([[./glr-regr14]], 0,
1386 [conflict <- empty string:
1387 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1388 defstate_look <- empty string:
1389 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1390 nonconflict2 <- empty string:
1391 yychar='b', yylval='B', yylloc=(1,2),(1,2)
1392 defstate_shift <- empty string:
1393 yychar=YYEMPTY
1394 merge <- conflict defstate_look 'a' nonconflict2 'b' defstate_shift:
1395 yychar=YYEMPTY
1396 start <- merge 'c' stack_explosion:
1397 yychar=YYEOF
1398 ], [])
1399
1400 AT_CLEANUP
1401
1402
1403 ## ------------------------------------------------- ##
1404 ## Leaked semantic values when reporting ambiguity. ##
1405 ## ------------------------------------------------- ##
1406
1407 AT_SETUP([Leaked semantic values when reporting ambiguity])
1408
1409 AT_BISON_OPTION_PUSHDEFS
1410 AT_DATA_GRAMMAR([glr-regr15.y],
1411 [[
1412 %glr-parser
1413 %destructor { parent_rhs_before_value = 0; } parent_rhs_before
1414
1415 %{
1416 # include <stdlib.h>
1417 ]AT_YYERROR_DECLARE[
1418 ]AT_YYLEX_DECLARE[
1419 static int parent_rhs_before_value = 0;
1420 # define USE(val)
1421 %}
1422
1423 %%
1424
1425 start:
1426 alt1 %dprec 1
1427 | alt2 %dprec 2
1428 ;
1429
1430 /* This stack must be merged into the other stacks *last* (added at the
1431 beginning of the semantic options list) so that yyparse will choose to clean
1432 it up rather than the tree for which some semantic actions have been
1433 performed. Thus, if yyreportAmbiguity longjmp's to yyparse, the values from
1434 those other trees are not cleaned up. */
1435 alt1: ;
1436
1437 alt2:
1438 parent_rhs_before ambiguity {
1439 USE ($1);
1440 parent_rhs_before_value = 0;
1441 }
1442 ;
1443
1444 parent_rhs_before:
1445 {
1446 USE ($$);
1447 parent_rhs_before_value = 1;
1448 }
1449 ;
1450
1451 ambiguity: ambiguity1 | ambiguity2 ;
1452 ambiguity1: ;
1453 ambiguity2: ;
1454
1455 %%
1456 ]AT_YYERROR_DEFINE[
1457 ]AT_YYLEX_DEFINE[
1458
1459 int
1460 main (void)
1461 {
1462 int exit_status = yyparse () != 1;
1463 if (parent_rhs_before_value)
1464 {
1465 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1466 exit_status = 1;
1467 }
1468 return exit_status;
1469 }
1470 ]])
1471 AT_BISON_OPTION_POPDEFS
1472
1473 AT_BISON_CHECK([[-o glr-regr15.c glr-regr15.y]], 0, [],
1474 [[glr-regr15.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
1475 ]])
1476 AT_COMPILE([glr-regr15])
1477
1478 AT_PARSER_CHECK([[./glr-regr15]], 0, [],
1479 [syntax is ambiguous
1480 ])
1481
1482 AT_CLEANUP
1483
1484
1485 ## ------------------------------------------------------------ ##
1486 ## Leaked lookahead after nondeterministic parse syntax error. ##
1487 ## ------------------------------------------------------------ ##
1488
1489 AT_SETUP([Leaked lookahead after nondeterministic parse syntax error])
1490
1491 AT_BISON_OPTION_PUSHDEFS
1492 AT_DATA_GRAMMAR([glr-regr16.y],
1493 [[
1494 %glr-parser
1495 %destructor { lookahead_value = 0; } 'b'
1496
1497 %{
1498 # include <stdlib.h>
1499 # include <assert.h>
1500 ]AT_YYERROR_DECLARE[
1501 ]AT_YYLEX_DECLARE[
1502 static int lookahead_value = 0;
1503 # define USE(val)
1504 %}
1505
1506 %%
1507
1508 start: alt1 'a' | alt2 'a' ;
1509 alt1: ;
1510 alt2: ;
1511
1512 %%
1513
1514 ]AT_YYERROR_DEFINE[
1515 ]AT_YYLEX_DEFINE(["ab"],
1516 [if (res == 'b')
1517 lookahead_value = 1])[
1518
1519 int
1520 main (void)
1521 {
1522 int exit_status = yyparse () != 1;
1523 if (lookahead_value)
1524 {
1525 fprintf (stderr, "Lookahead destructor not called.\n");
1526 exit_status = 1;
1527 }
1528 return exit_status;
1529 }
1530 ]])
1531 AT_BISON_OPTION_POPDEFS
1532
1533 AT_BISON_CHECK([[-o glr-regr16.c glr-regr16.y]], 0, [],
1534 [[glr-regr16.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1535 ]])
1536 AT_COMPILE([glr-regr16])
1537
1538 AT_PARSER_CHECK([[./glr-regr16]], 0, [],
1539 [syntax error
1540 ])
1541
1542 AT_CLEANUP
1543
1544
1545 ## ------------------------------------------------- ##
1546 ## Uninitialized location when reporting ambiguity. ##
1547 ## ------------------------------------------------- ##
1548
1549 AT_SETUP([Uninitialized location when reporting ambiguity])
1550
1551 AT_BISON_OPTION_PUSHDEFS([%glr-parser %locations %define api.pure])
1552
1553 AT_DATA_GRAMMAR([glr-regr17.y],
1554 [[
1555 %glr-parser
1556 %locations
1557 %define api.pure
1558 %error-verbose
1559
1560 %union { int dummy; }
1561
1562 %{
1563 ]AT_YYERROR_DECLARE[
1564 ]AT_YYLEX_DECLARE[
1565 %}
1566
1567 %%
1568
1569 /* Tests the case of an empty RHS that has inherited the location of the
1570 previous nonterminal, which is unresolved. That location is reported as the
1571 last position of the ambiguity. */
1572 start: ambig1 empty1 | ambig2 empty2 ;
1573
1574 /* Tests multiple levels of yyresolveLocations recursion. */
1575 ambig1: sub_ambig1 | sub_ambig2 ;
1576 ambig2: sub_ambig1 | sub_ambig2 ;
1577
1578 /* Tests the case of a non-empty RHS as well as the case of an empty RHS that
1579 has inherited the initial location. The empty RHS's location is reported as
1580 the first position in the ambiguity. */
1581 sub_ambig1: empty1 'a' 'b' ;
1582 sub_ambig2: empty2 'a' 'b' ;
1583 empty1: ;
1584 empty2: ;
1585
1586 %%
1587 # include <assert.h>
1588
1589 ]AT_YYERROR_DEFINE[
1590 static int
1591 yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
1592 {
1593 static char const input[] = "ab";
1594 static size_t toknum;
1595 assert (toknum < sizeof input);
1596 lvalp->dummy = 0;
1597 llocp->first_line = llocp->last_line = 2;
1598 llocp->first_column = toknum + 1;
1599 llocp->last_column = llocp->first_column + 1;
1600 return input[toknum++];
1601 }
1602
1603 int
1604 main (void)
1605 {
1606 return yyparse () != 1;
1607 }
1608 ]])
1609 AT_BISON_OPTION_POPDEFS
1610
1611 AT_BISON_CHECK([[-o glr-regr17.c glr-regr17.y]], 0, [],
1612 [[glr-regr17.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
1613 ]])
1614 AT_COMPILE([glr-regr17])
1615
1616 AT_PARSER_CHECK([[./glr-regr17]], 0, [],
1617 [1.1-2.2: syntax is ambiguous
1618 ])
1619
1620 AT_CLEANUP
1621
1622
1623 ## ------------------------------------------------------------- ##
1624 ## Missed %merge type warnings when LHS type is declared later. ##
1625 ## ------------------------------------------------------------- ##
1626
1627 AT_SETUP([Missed %merge type warnings when LHS type is declared later])
1628
1629 AT_BISON_OPTION_PUSHDEFS
1630 AT_DATA_GRAMMAR([glr-regr18.y],
1631 [[%glr-parser
1632
1633 %{
1634 #include <stdlib.h>
1635 ]AT_YYERROR_DECLARE[
1636 ]AT_YYLEX_DECLARE[
1637 %}
1638
1639 %union {
1640 int type1;
1641 int type2;
1642 int type3;
1643 }
1644
1645 %%
1646
1647 sym1: sym2 %merge<merge> { $$ = $1; } ;
1648 sym2: sym3 %merge<merge> { $$ = $1; } ;
1649 sym3: %merge<merge> { $$ = 0; } ;
1650
1651 %type <type1> sym1;
1652 %type <type2> sym2;
1653 %type <type3> sym3;
1654
1655 %%
1656 ]AT_YYERROR_DEFINE[
1657 ]AT_YYLEX_DEFINE[
1658 int
1659 main (void)
1660 {
1661 return yyparse ();
1662 }
1663 ]])
1664 AT_BISON_OPTION_POPDEFS
1665
1666 AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [],
1667 [[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
1668 glr-regr18.y:25.18-24: previous declaration
1669 glr-regr18.y:27.13-19: error: result type clash on merge function 'merge': <type3> != <type2>
1670 glr-regr18.y:26.18-24: previous declaration
1671 ]])
1672
1673 AT_CLEANUP
1674
1675
1676 ## ------------------- ##
1677 ## Ambiguity reports. ##
1678 ## ------------------- ##
1679
1680 AT_SETUP([Ambiguity reports])
1681
1682 AT_BISON_OPTION_PUSHDEFS
1683 AT_DATA_GRAMMAR([input.y],
1684 [[
1685 %{
1686 #include <stdio.h>
1687 #include <stdlib.h>
1688 ]AT_YYERROR_DECLARE[
1689 ]AT_YYLEX_DECLARE[
1690 %}
1691
1692 %debug
1693 %glr-parser
1694
1695 %%
1696 start:
1697 'a' b 'c' d
1698 | 'a' b 'c' d
1699 ;
1700 b: 'b';
1701 d: /* nada. */;
1702 %%
1703 ]AT_YYLEX_DEFINE(["abc"])[
1704 ]AT_YYERROR_DEFINE[
1705 int
1706 main (void)
1707 {
1708 yydebug = 1;
1709 return !!yyparse ();
1710 }
1711 ]])
1712 AT_BISON_OPTION_POPDEFS
1713
1714 AT_BISON_CHECK([[-o input.c input.y]], 0, [],
1715 [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1716 ]])
1717 AT_COMPILE([input])
1718
1719 AT_PARSER_CHECK([[./input]], 1, [],
1720 [Starting parse
1721 Entering state 0
1722 Reading a token: Next token is token 'a' ()
1723 Shifting token 'a' ()
1724 Entering state 1
1725 Reading a token: Next token is token 'b' ()
1726 Shifting token 'b' ()
1727 Entering state 3
1728 Reducing stack 0 by rule 3 (line 25):
1729 $1 = token 'b' ()
1730 -> $$ = nterm b ()
1731 Entering state 4
1732 Reading a token: Next token is token 'c' ()
1733 Shifting token 'c' ()
1734 Entering state 6
1735 Reducing stack 0 by rule 4 (line 26):
1736 -> $$ = nterm d ()
1737 Entering state 7
1738 Reading a token: Now at end of input.
1739 Stack 0 Entering state 7
1740 Now at end of input.
1741 Splitting off stack 1 from 0.
1742 Reduced stack 1 by rule #2; action deferred. Now in state 2.
1743 Stack 1 Entering state 2
1744 Now at end of input.
1745 Reduced stack 0 by rule #1; action deferred. Now in state 2.
1746 Merging stack 0 into stack 1.
1747 Stack 1 Entering state 2
1748 Now at end of input.
1749 Removing dead stacks.
1750 Rename stack 1 -> 0.
1751 On stack 0, shifting token $end ()
1752 Stack 0 now in state #5
1753 Ambiguity detected.
1754 Option 1,
1755 start -> <Rule 1, tokens 1 .. 3>
1756 'a' <tokens 1 .. 1>
1757 b <tokens 2 .. 2>
1758 'c' <tokens 3 .. 3>
1759 d <empty>
1760
1761 Option 2,
1762 start -> <Rule 2, tokens 1 .. 3>
1763 'a' <tokens 1 .. 1>
1764 b <tokens 2 .. 2>
1765 'c' <tokens 3 .. 3>
1766 d <empty>
1767
1768 syntax is ambiguous
1769 Cleanup: popping token $end ()
1770 Cleanup: popping unresolved nterm start ()
1771 Cleanup: popping nterm d ()
1772 Cleanup: popping token 'c' ()
1773 Cleanup: popping nterm b ()
1774 Cleanup: popping token 'a' ()
1775 ])
1776
1777 AT_CLEANUP