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