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