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