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