Regen.
[bison/ericb.git] / tests / glr-regression.at
blob2f71926020f79f8da5ed381f4f86f2aa2bebfbb6
1 # Checking GLR Parsing: Regression Tests           -*- Autotest -*-
2 # Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
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.
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.
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/>.
17 AT_BANNER([[GLR Regression Tests]])
19 ## --------------------------- ##
20 ## Badly Collapsed GLR States. ##
21 ## --------------------------- ##
23 AT_SETUP([Badly Collapsed GLR States])
25 AT_DATA_GRAMMAR([glr-regr1.y],
26 [[/* Regression Test: Improper state compression */
27 /* Reported by Scott McPeak */
30 #include <stdio.h>
31 #include <stdlib.h>
33 #define YYSTYPE int
34 static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1);
35 int yylex (void);
36 void yyerror (char const *msg);
40 %glr-parser
43 /* -------- productions ------ */
46 StartSymbol: E  { $$=0; }                   %merge <exprMerge>
47            ;
49 E: E 'P' E { $$=1; printf("E -> E 'P' E\n"); }  %merge <exprMerge>
50  | 'B'     { $$=2; printf("E -> 'B'\n"); }      %merge <exprMerge>
51  ;
55 /* ---------- C code ----------- */
58 static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1)
60   (void) x0;
61   (void) x1;
62   printf ("<OR>\n");
63   return 0;
66 int
67 main (void)
69   return yyparse ();
72 void
73 yyerror (char const *msg)
75   fprintf (stderr, "%s\n", msg);
79 int
80 yylex (void)
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     }
94 ]])
96 AT_BISON_CHECK([[-o glr-regr1.c glr-regr1.y]], 0, [],
97 [glr-regr1.y: conflicts: 1 shift/reduce
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 ]], [])
112 AT_CLEANUP
114 ## ------------------------------------------------------------ ##
115 ## Improper handling of embedded actions and $-N in GLR parsers ##
116 ## ------------------------------------------------------------ ##
118 AT_SETUP([Improper handling of embedded actions and dollar(-N) in GLR parsers])
120 AT_DATA_GRAMMAR([glr-regr2a.y],
121 [[/* Regression Test: Improper handling of embedded actions and $-N  */
122 /* Reported by S. Eken */
125   #define YYSTYPE char *
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 *);
135 %glr-parser
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   ;
150 var:
151   'V'
152      { $$ = $1; }
153   ;
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   ;
168 var_printer: 'v'
169    { printf ("Variable: '%s'\n", $-1); }
173 FILE *input;
176 yylex (void)
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';
200 void
201 yyerror (char const *s)
202 { printf ("%s\n", s);
206 main (int argc, char **argv)
208   input = stdin;
209   if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
210   return yyparse ();
214 AT_BISON_CHECK([[-o glr-regr2a.c glr-regr2a.y]], 0, [],
215 [glr-regr2a.y: conflicts: 2 shift/reduce
217 AT_COMPILE([glr-regr2a])
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]],
224 [[Varlist: 'VARIABLE_1,ANOTHER_VARIABLE_2'
226 AT_PARSER_CHECK([[echo s VARIABLE_3 t v x | ./glr-regr2a]], 0,
227 [[Variable: 'VARIABLE_3'
228 ]], [])
231 AT_CLEANUP
233 ## ------------------------------------------------------------ ##
234 ## Improper merging of GLR delayed action sets                  ##
235 ## ------------------------------------------------------------ ##
237 AT_SETUP([Improper merging of GLR delayed action sets])
239 AT_DATA_GRAMMAR([glr-regr3.y],
240 [[/* Regression Test: Improper merging of GLR delayed action sets.  */
241 /* Reported by M. Rosien */
244 #include <stdio.h>
245 #include <stdlib.h>
246 #include <stdarg.h>
248 static int MergeRule (int x0, int x1);
249 static void yyerror (char const * s);
250 int yylex (void);
252 #define RULE(x) (1 << (x))
256 %glr-parser
258 %token BAD_CHAR
259 %token P1 P2 T1 T2 T3 T4 O1 O2
263 S : P1 T4 O2 NT6 P2  { printf ("Result: %x\n", $4); }
266 NT1 : P1 T1 O1 T2 P2 { $$ = RULE(2); }  %merge<MergeRule>
269 NT2 : NT1             { $$ = RULE(3); } %merge<MergeRule>
270     | P1 NT1 O1 T3 P2 { $$ = RULE(4); } %merge<MergeRule>
273 NT3 : T3              { $$ = RULE(5); } %merge<MergeRule>
274     | P1 NT1 O1 T3 P2 { $$ = RULE(6); } %merge<MergeRule>
277 NT4 : NT3              { $$ = RULE(7); } %merge<MergeRule>
278     | NT2              { $$ = RULE(8); } %merge<MergeRule>
279     | P1 NT2 O1 NT3 P2 { $$ = RULE(9); } %merge<MergeRule>
282 NT5 : NT4              { $$ = RULE(10); } %merge<MergeRule>
285 NT6 : P1 NT1 O1 T3 P2  { $$ = RULE(11) | $2; } %merge<MergeRule>
286     | NT5              { $$ = RULE(12) | $1; } %merge<MergeRule>
291 static int MergeRule (int x0, int x1) {
292   return x0 | x1;
295 static void yyerror(char const * s) {
296   fprintf(stderr,"error: %s\n",s);
299 FILE *input = NULL;
301 int P[] = { P1, P2 };
302 int O[] = { O1, O2 };
303 int T[] = { T1, T2, T3, T4 };
305 int yylex (void)
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;
321 int main(int argc, char* argv[]) {
322   input = stdin;
323   if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
324   return yyparse ();
328 AT_BISON_CHECK([[-o glr-regr3.c glr-regr3.y]], 0, [],
329 [glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
331 AT_COMPILE([glr-regr3])
333 AT_PARSER_CHECK([[echo p1 t4 o2 p1 p1 t1 o1 t2 p2 o1 t3 p2 p2 | ./glr-regr3]],
335 [[Result: 1c04
336 ]], [])
338 AT_CLEANUP
341 ## ------------------------------------------------------------------------- ##
342 ## Duplicate representation of merged trees.  See                            ##
343 ## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00013.html>.     ##
344 ## ------------------------------------------------------------------------- ##
346 AT_SETUP([Duplicate representation of merged trees])
348 AT_DATA_GRAMMAR([glr-regr4.y],
350 %union { char *ptr; }
351 %type <ptr> S A A1 A2 B
352 %glr-parser
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;
368 tree: S { printf ("%s\n", $1); } ;
371   A   %merge<merge> { $$ = make_value ("S", $1); }
372   | B %merge<merge> { $$ = make_value ("S", $1); }
373   ;
376   A1   %merge<merge> { $$ = make_value ("A", $1); }
377   | A2 %merge<merge> { $$ = make_value ("A", $1); }
378   ;
380 A1: 'a' { $$ = make_value ("A1", "'a'"); } ;
381 A2: 'a' { $$ = make_value ("A2", "'a'"); } ;
382 B:  'a' { $$ = make_value ("B", "'a'");  } ;
386 static int
387 yylex (void)
389   static char const input[] = "a";
390   static size_t toknum;
391   if (! (toknum < sizeof input))
392     abort ();
393   return input[toknum++];
397 main (void)
399   int status = yyparse ();
400   while (ptrs_next != ptrs)
401     free (*--ptrs_next);
402   return status;
405 static char *
406 make_value (char const *parent, char const *child)
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;
415 static char *
416 merge (YYSTYPE s1, YYSTYPE s2)
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;
425 static void
426 yyerror (char const *msg)
428   fprintf (stderr, "%s\n", msg);
432 AT_BISON_CHECK([[-o glr-regr4.c glr-regr4.y]], 0, [],
433 [glr-regr4.y: conflicts: 1 reduce/reduce
435 AT_COMPILE([glr-regr4])
437 AT_PARSER_CHECK([[./glr-regr4]], 0,
438 [[merge{ S <- merge{ A <- A1 <- 'a' and A <- A2 <- 'a' } and S <- B <- 'a' }
439 ]], [])
441 AT_CLEANUP
444 ## -------------------------------------------------------------------------- ##
445 ## User destructor for unresolved GLR semantic value.  See                    ##
446 ## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00016.html>.   ##
447 ## -------------------------------------------------------------------------- ##
449 AT_SETUP([User destructor for unresolved GLR semantic value])
451 AT_DATA_GRAMMAR([glr-regr5.y],
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 */
461 %glr-parser
462 %union { int value; }
463 %type <value> start
465 %destructor {
466   if ($$ != MAGIC_VALUE)
467     {
468       fprintf (stderr, "Bad destructor call.\n");
469       exit (EXIT_FAILURE);
470     }
471 } start
475 start:
476    'a' { $$ = MAGIC_VALUE; }
477    | 'a' { $$ = MAGIC_VALUE; }
478    ;
482 static int
483 yylex (void)
485   static char const input[] = "a";
486   static size_t toknum;
487   if (! (toknum < sizeof input))
488     abort ();
489   return input[toknum++];
492 static void
493 yyerror (char const *msg)
495   fprintf (stderr, "%s\n", msg);
499 main (void)
501   return yyparse () != 1;
505 AT_BISON_CHECK([[-o glr-regr5.c glr-regr5.y]], 0, [],
506 [glr-regr5.y: conflicts: 1 reduce/reduce
508 AT_COMPILE([glr-regr5])
510 AT_PARSER_CHECK([[./glr-regr5]], 0, [],
511 [syntax is ambiguous
514 AT_CLEANUP
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 ## -------------------------------------------------------------------------- ##
522 AT_SETUP([User destructor after an error during a split parse])
524 AT_DATA_GRAMMAR([glr-regr6.y],
527   #include <stdio.h>
528   #include <stdlib.h>
529   static void yyerror (char const *);
530   static int yylex (void);
533 %glr-parser
534 %union { int value; }
535 %type <value> 'a'
537 %destructor {
538   printf ("Destructor called.\n");
539 } 'a'
543 start: 'a' | 'a' ;
547 static int
548 yylex (void)
550   static char const input[] = "a";
551   static size_t toknum;
552   if (! (toknum < sizeof input))
553     abort ();
554   return input[toknum++];
557 static void
558 yyerror (char const *msg)
560   fprintf (stderr, "%s\n", msg);
564 main (void)
566   return yyparse () != 1;
570 AT_BISON_CHECK([[-o glr-regr6.c glr-regr6.y]], 0, [],
571 [glr-regr6.y: conflicts: 1 reduce/reduce
573 AT_COMPILE([glr-regr6])
575 AT_PARSER_CHECK([[./glr-regr6]], 0,
576 [Destructor called.
578 [syntax is ambiguous
581 AT_CLEANUP
584 ## ------------------------------------------------------------------------- ##
585 ## Duplicated user destructor for lookahead.  See                            ##
586 ## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00035.html>.  ##
587 ## ------------------------------------------------------------------------- ##
589 AT_SETUP([Duplicated user destructor for lookahead])
591 AT_DATA_GRAMMAR([glr-regr7.y],
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;
606 %glr-parser
607 %union { count_node *node; }
608 %type <node> 'a'
610 %destructor {
611   if ($$->count++)
612     fprintf (stderr, "Destructor called on same value twice.\n");
613 } 'a'
617 start:
618     stack1 start
619   | stack2 start
620   | /* empty */
621   ;
622 stack1: 'a' ;
623 stack2: 'a' ;
627 static int
628 yylex (void)
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';
642 static void
643 yyerror (char const *msg)
645   fprintf (stderr, "%s\n", msg);
649 main (void)
651   int status = yyparse ();
652   while (tail)
653     {
654       count_node *prev = tail->prev;
655       free (tail);
656       tail = prev;
657     }
658   return status;
662 AT_BISON_CHECK([[-o glr-regr7.c glr-regr7.y]], 0, [],
663 [glr-regr7.y: conflicts: 2 reduce/reduce
665 AT_COMPILE([glr-regr7])
667 AT_PARSER_CHECK([[./glr-regr7]], 2, [],
668 [memory exhausted
671 AT_CLEANUP
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 ## ------------------------------------------------------------------------- ##
681 AT_SETUP([Incorrectly initialized location for empty right-hand side in GLR])
683 AT_DATA_GRAMMAR([glr-regr8.y],
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);
693 %token T_CONSTANT
694 %token T_PORT
695 %token T_SIGNAL
697 %glr-parser
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         ;
709 InterfaceDeclaration    : OptConstantWord       %dprec 1
710         | OptSignalWord %dprec 2
711         ;
713 OptConstantWord : /* empty */
714         | T_CONSTANT
715         ;
717 OptSignalWord   : /* empty */
718                 { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
719         | T_SIGNAL
720         ;
724 void
725 yyerror (char const *msg)
727   fprintf (stderr, "%s\n", msg);
730 static int lexIndex;
732 int yylex (void)
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     }
753 main (void)
755   yyparse();
756   return 0;
760 AT_BISON_CHECK([[-o glr-regr8.c glr-regr8.y]], 0, [],
761 [glr-regr8.y: conflicts: 1 reduce/reduce
763 AT_COMPILE([glr-regr8])
765 AT_PARSER_CHECK([[./glr-regr8]], 0,
766 [empty: 9/9
767 1/9 - 9/9 - 13/17
771 AT_CLEANUP
774 ## ------------------------------------------------------------------------- ##
775 ## No users destructors if stack 0 deleted.  See                             ##
776 ## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>.  ##
777 ## ------------------------------------------------------------------------- ##
779 AT_SETUP([No users destructors if stack 0 deleted])
781 AT_DATA_GRAMMAR([glr-regr9.y],
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)
794 %glr-parser
795 %union { int dummy; }
796 %type <dummy> 'a'
798 %destructor {
799   destructors += 1;
800 } 'a'
804 start:
805     ambig0 'a'   { destructors += 2; USE ($2); }
806   | ambig1 start { destructors += 1; }
807   | ambig2 start { destructors += 1; }
808   ;
810 ambig0: 'a' ;
811 ambig1: 'a' ;
812 ambig2: 'a' ;
816 static int
817 yylex (void)
819   tokens += 1;
820   return 'a';
823 static void
824 yyerror (char const *msg)
826   fprintf (stderr, "%s\n", msg);
830 main (void)
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;
843 AT_BISON_CHECK([[-o glr-regr9.c glr-regr9.y]], 0, [],
844 [glr-regr9.y: conflicts: 1 reduce/reduce
846 AT_COMPILE([glr-regr9])
848 AT_PARSER_CHECK([[./glr-regr9]], 0, [],
849 [memory exhausted
852 AT_CLEANUP
855 ## ------------------------------------------------------------------------- ##
856 ## Corrupted semantic options if user action cuts parse.                     ##
857 ## ------------------------------------------------------------------------- ##
859 AT_SETUP([Corrupted semantic options if user action cuts parse])
861 AT_DATA_GRAMMAR([glr-regr10.y],
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];
872 %glr-parser
873 %union { char *ptr; }
874 %type <ptr> start
878 start:
879     %dprec 2 { $$ = garbage; YYACCEPT; }
880   | %dprec 1 { $$ = garbage; YYACCEPT; }
881   ;
885 static void
886 yyerror (char const *msg)
888   fprintf (stderr, "%s\n", msg);
891 static int
892 yylex (void)
894   static int called;
895   if (called++)
896     abort ();
897   return 0;
901 main (void)
903   int i;
904   for (i = 0; i < GARBAGE_SIZE; i+=1)
905     garbage[i] = 108;
906   return yyparse ();
910 AT_BISON_CHECK([[-o glr-regr10.c glr-regr10.y]], 0, [],
911 [glr-regr10.y: conflicts: 1 reduce/reduce
913 AT_COMPILE([glr-regr10])
915 AT_PARSER_CHECK([[./glr-regr10]], 0, [], [])
917 AT_CLEANUP
920 ## ------------------------------------------------------------------------- ##
921 ## Undesirable destructors if user action cuts parse.                        ##
922 ## ------------------------------------------------------------------------- ##
924 AT_SETUP([Undesirable destructors if user action cuts parse])
926 AT_DATA_GRAMMAR([glr-regr11.y],
929 # include <stdlib.h>
930   static void yyerror (char const *);
931   static int yylex (void);
932   static int destructors = 0;
933 # define USE(val)
936 %glr-parser
937 %union { int dummy; }
938 %type <int> 'a'
939 %destructor { destructors += 1; } 'a'
943 start:
944     'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
945   | 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
946   ;
950 static void
951 yyerror (char const *msg)
953   fprintf (stderr, "%s\n", msg);
956 static int
957 yylex (void)
959   static char const input[] = "a";
960   static size_t toknum;
961   if (! (toknum < sizeof input))
962     abort ();
963   return input[toknum++];
967 main (void)
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;
979 AT_BISON_CHECK([[-o glr-regr11.c glr-regr11.y]], 0, [],
980 [glr-regr11.y: conflicts: 1 reduce/reduce
982 AT_COMPILE([glr-regr11])
984 AT_PARSER_CHECK([[./glr-regr11]], 0, [], [])
986 AT_CLEANUP
989 ## ------------------------------------------------------------------------- ##
990 ## Leaked semantic values if user action cuts parse.                         ##
991 ## ------------------------------------------------------------------------- ##
993 AT_SETUP([Leaked semantic values if user action cuts parse])
995 AT_DATA_GRAMMAR([glr-regr12.y],
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
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)
1018 start:
1019   alt1 %dprec 1
1020   | alt2 %dprec 2
1021   ;
1023 alt1:
1024   PARENT_RHS_AFTER {
1025     USE ($1);
1026     parent_rhs_after_value = 0;
1027   }
1028   ;
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   ;
1039 parent_rhs_before:
1040   {
1041     USE ($$);
1042     parent_rhs_before_value = 1;
1043   }
1044   ;
1046 merged:
1047   %merge<merge> {
1048     USE ($$);
1049     merged_value = 1;
1050   }
1051   | cut %merge<merge> {
1052     USE ($$);
1053     merged_value = 1;
1054   }
1055   ;
1057 cut: { YYACCEPT; } ;
1061 static int
1062 merge (YYSTYPE s1, YYSTYPE s2)
1064   /* Not invoked. */
1065   char dummy = s1.dummy + s2.dummy;
1066   return dummy;
1069 static void
1070 yyerror (char const *msg)
1072   fprintf (stderr, "%s\n", msg);
1075 static int
1076 yylex (void)
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++];
1088 main (void)
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;
1110 AT_BISON_CHECK([[-o glr-regr12.c glr-regr12.y]], 0, [],
1111 [glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
1113 AT_COMPILE([glr-regr12])
1115 AT_PARSER_CHECK([[./glr-regr12]], 0, [], [])
1117 AT_CLEANUP
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 ## ------------------------------------------------------------------------- ##
1126 AT_SETUP([Incorrect lookahead during deterministic GLR])
1128 AT_DATA_GRAMMAR([glr-regr13.y],
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.  */
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)
1145 %union { char value; }
1146 %type <value> 'a' 'b'
1147 %glr-parser
1148 %locations
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   ;
1191 static void
1192 yyerror (char const *msg)
1194   fprintf (stderr, "%s\n", msg);
1197 static int
1198 yylex (void)
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++];
1210 static void
1211 print_lookahead (char const *reduction)
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");
1231 main (void)
1233   yychar = '#'; /* Not a token in the grammar.  */
1234   yylval.value = '!';
1235   return yyparse ();
1239 AT_BISON_CHECK([[-o glr-regr13.c glr-regr13.y]], 0, [], [])
1240 AT_COMPILE([glr-regr13])
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 ], [])
1255 AT_CLEANUP
1258 ## ------------------------------------------------------------------------- ##
1259 ## Incorrect lookahead during nondeterministic GLR.                          ##
1260 ## ------------------------------------------------------------------------- ##
1262 AT_SETUP([Incorrect lookahead during nondeterministic GLR])
1264 AT_DATA_GRAMMAR([glr-regr14.y],
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.  */
1285 %union { char value; }
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)
1297 %type <value> 'a' 'b' 'c' 'd' stack_explosion
1298 %glr-parser
1299 %locations
1303 start:
1304   merge 'c' stack_explosion {
1305     USE ($2); USE ($3);
1306     print_lookahead ("start <- merge 'c' stack_explosion");
1307   }
1308   ;
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   ;
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   ;
1348 /* yychar != YYEMPTY but lookahead need is yyfalse.  */
1349 defstate_shift:
1350   {
1351     print_lookahead ("defstate_shift <- empty string");
1352   }
1353   ;
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   ;
1400 static void
1401 yyerror (char const *msg)
1403   fprintf (stderr, "%s\n", msg);
1406 static int
1407 yylex (void)
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++];
1419 static void
1420 print_lookahead (char const *reduction)
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");
1439 static char
1440 merge (union YYSTYPE s1, union YYSTYPE s2)
1442   char dummy = s1.value + s2.value;
1443   return dummy;
1447 main (void)
1449   yychar = '#'; /* Not a token in the grammar.  */
1450   yylval.value = '!';
1451   return yyparse ();
1455 AT_BISON_CHECK([[-o glr-regr14.c glr-regr14.y]], 0, [],
1456 [glr-regr14.y: conflicts: 3 reduce/reduce
1458 AT_COMPILE([glr-regr14])
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 ], [])
1475 AT_CLEANUP
1478 ## ------------------------------------------------------------------------- ##
1479 ## Leaked semantic values when reporting ambiguity.                          ##
1480 ## ------------------------------------------------------------------------- ##
1482 AT_SETUP([Leaked semantic values when reporting ambiguity])
1484 AT_DATA_GRAMMAR([glr-regr15.y],
1486 %glr-parser
1487 %destructor { parent_rhs_before_value = 0; } parent_rhs_before
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)
1499 start:
1500   alt1 %dprec 1
1501   | alt2 %dprec 2
1502   ;
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: ;
1511 alt2:
1512   parent_rhs_before ambiguity {
1513     USE ($1);
1514     parent_rhs_before_value = 0;
1515   }
1516   ;
1518 parent_rhs_before:
1519   {
1520     USE ($$);
1521     parent_rhs_before_value = 1;
1522   }
1523   ;
1525 ambiguity: ambiguity1 | ambiguity2 ;
1526 ambiguity1: ;
1527 ambiguity2: ;
1531 static void
1532 yyerror (char const *msg)
1534   fprintf (stderr, "%s\n", msg);
1537 static int
1538 yylex (void)
1540   static int called;
1541   if (called++)
1542     abort ();
1543   return 0;
1547 main (void)
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;
1559 AT_BISON_CHECK([[-o glr-regr15.c glr-regr15.y]], 0, [],
1560 [glr-regr15.y: conflicts: 2 reduce/reduce
1562 AT_COMPILE([glr-regr15])
1564 AT_PARSER_CHECK([[./glr-regr15]], 0, [],
1565 [syntax is ambiguous
1568 AT_CLEANUP
1571 ## ------------------------------------------------------------------------- ##
1572 ## Leaked lookahead after nondeterministic parse syntax error.               ##
1573 ## ------------------------------------------------------------------------- ##
1575 AT_SETUP([Leaked lookahead after nondeterministic parse syntax error])
1576 AT_DATA_GRAMMAR([glr-regr16.y],
1578 %glr-parser
1579 %destructor { lookahead_value = 0; } 'b'
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)
1591 start: alt1 'a' | alt2 'a' ;
1592 alt1: ;
1593 alt2: ;
1597 static void
1598 yyerror (char const *msg)
1600   fprintf (stderr, "%s\n", msg);
1603 static int
1604 yylex (void)
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++];
1616 main (void)
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;
1628 AT_BISON_CHECK([[-o glr-regr16.c glr-regr16.y]], 0, [],
1629 [glr-regr16.y: conflicts: 1 reduce/reduce
1631 AT_COMPILE([glr-regr16])
1633 AT_PARSER_CHECK([[./glr-regr16]], 0, [],
1634 [syntax error
1637 AT_CLEANUP
1640 ## ------------------------------------------------------------------------- ##
1641 ## Uninitialized location when reporting ambiguity.                          ##
1642 ## ------------------------------------------------------------------------- ##
1644 AT_SETUP([Uninitialized location when reporting ambiguity])
1645 AT_DATA_GRAMMAR([glr-regr17.y],
1647 %glr-parser
1648 %locations
1649 %define api.pure
1650 %error-verbose
1652 %union { int dummy; }
1655   static void yyerror (YYLTYPE *, char const *);
1656   static int yylex (YYSTYPE *, YYLTYPE *);
1659 %initial-action {
1660   @$.first_line = 1;
1661   @$.first_column = 1;
1662   @$.last_line = 1;
1663   @$.last_column = 1;
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 ;
1673 /* Tests multiple levels of yyresolveLocations recursion.  */
1674 ambig1: sub_ambig1 | sub_ambig2 ;
1675 ambig2: sub_ambig1 | sub_ambig2 ;
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: ;
1687 static void
1688 yyerror (YYLTYPE *locp, char const *msg)
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);
1694 static int
1695 yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
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++];
1709 main (void)
1711   return yyparse () != 1;
1715 AT_BISON_CHECK([[-o glr-regr17.c glr-regr17.y]], 0, [],
1716 [glr-regr17.y: conflicts: 3 reduce/reduce
1718 AT_COMPILE([glr-regr17])
1720 AT_PARSER_CHECK([[./glr-regr17]], 0, [],
1721 [Error at 1.1-2.3: syntax is ambiguous.
1724 AT_CLEANUP
1727 ## -------------------------------------------------------------##
1728 ## Missed %merge type warnings when LHS type is declared later. ##
1729 ## -------------------------------------------------------------##
1731 AT_SETUP([Missed %merge type warnings when LHS type is declared later])
1732 AT_DATA_GRAMMAR([glr-regr18.y],
1733 [[%glr-parser
1736   #include <stdlib.h>
1737   static void yyerror (char const *);
1738   static int yylex ();
1741 %union {
1742   int type1;
1743   int type2;
1744   int type3;
1749 sym1: sym2 %merge<merge> { $$ = $1; } ;
1750 sym2: sym3 %merge<merge> { $$ = $1; } ;
1751 sym3: %merge<merge> { $$ = 0; } ;
1753 %type <type1> sym1;
1754 %type <type2> sym2;
1755 %type <type3> sym3;
1759 static void
1760 yyerror (char const *msg)
1762   fprintf (stderr, "%s\n", msg);
1765 static int
1766 yylex ()
1768   static int called;
1769   if (called++)
1770     abort ();
1771   return 0;
1775 main (void)
1777   return yyparse ();
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
1788 AT_CLEANUP