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