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