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