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