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