]> git.saurik.com Git - bison.git/blame_incremental - tests/conflicts.at
gnulib: update
[bison.git] / tests / conflicts.at
... / ...
CommitLineData
1# Exercising Bison on conflicts. -*- Autotest -*-
2
3# Copyright (C) 2002-2005, 2007-2015 Free Software Foundation, Inc.
4
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18AT_BANNER([[Conflicts.]])
19
20## ------------------------- ##
21## Token declaration order. ##
22## ------------------------- ##
23
24# This test checks that token are declared left to right when in a precedence
25# statement.
26
27AT_SETUP([Token declaration order])
28
29AT_BISON_OPTION_PUSHDEFS
30
31AT_DATA_GRAMMAR([[input.y]],
32[[%code {
33 #include <stdio.h>
34 ]AT_YYERROR_DECLARE[
35 ]AT_YYLEX_DECLARE[
36}
37%token A B C
38%token D
39%right E F G
40%right H I
41%right J
42%left K
43%left L M N
44%nonassoc O P Q
45%precedence R S T U
46%precedence V W
47%%
48exp: A
49%%
50]AT_YYERROR_DEFINE[
51]AT_YYLEX_DEFINE[
52int main (void)
53{
54 assert (A < B);
55 assert (B < C);
56 assert (C < D);
57 assert (D < E);
58 assert (E < F);
59 assert (F < G);
60 assert (G < H);
61 assert (H < I);
62 assert (I < J);
63 assert (J < K);
64 assert (K < L);
65 assert (L < M);
66 assert (M < N);
67 assert (N < O);
68 assert (O < P);
69 assert (P < Q);
70 assert (Q < R);
71 assert (R < S);
72 assert (S < T);
73 assert (T < U);
74 assert (U < V);
75 assert (V < W);
76 return 0;
77}
78]])
79
80AT_BISON_CHECK([-o input.c input.y])
81AT_COMPILE([input])
82
83AT_PARSER_CHECK([./input])
84
85AT_BISON_OPTION_POPDEFS
86
87AT_CLEANUP
88
89
90## --------------------------------------------------- ##
91## Token declaration order: literals vs. identifiers. ##
92## --------------------------------------------------- ##
93
94# This test checks that when several tokens are declared by the same keyword,
95# some of them defined as a character ('a'), others as simple textual reference
96# (A), they are declared correctly left to right.
97# Previously, the following test would declare the states in the order 'o' 'p'
98# M N, instead of M N 'o' 'p'.
99
100AT_SETUP([Token declaration order: literals vs. identifiers])
101
102AT_DATA_GRAMMAR([[input.y]],
103[[%token 'a' 'b' C D
104%token E F 'g' 'h'
105%right 'i' 'j' K L
106%right M N 'o' 'p'
107%%
108exp: 'a'
109 | 'b'
110 | C
111 | D
112 | E
113 | F
114 | 'g'
115 | 'h'
116 | 'i'
117 | 'j'
118 | K
119 | L
120 | M
121 | N
122 | 'o'
123 | 'p'
124;
125%%
126]])
127
128AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
129AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
130[[State 0
131
132 0 $accept: . exp $end
133 1 exp: . 'a'
134 2 | . 'b'
135 3 | . C
136 4 | . D
137 5 | . E
138 6 | . F
139 7 | . 'g'
140 8 | . 'h'
141 9 | . 'i'
142 10 | . 'j'
143 11 | . K
144 12 | . L
145 13 | . M
146 14 | . N
147 15 | . 'o'
148 16 | . 'p'
149
150 'a' shift, and go to state 1
151 'b' shift, and go to state 2
152 C shift, and go to state 3
153 D shift, and go to state 4
154 E shift, and go to state 5
155 F shift, and go to state 6
156 'g' shift, and go to state 7
157 'h' shift, and go to state 8
158 'i' shift, and go to state 9
159 'j' shift, and go to state 10
160 K shift, and go to state 11
161 L shift, and go to state 12
162 M shift, and go to state 13
163 N shift, and go to state 14
164 'o' shift, and go to state 15
165 'p' shift, and go to state 16
166
167 exp go to state 17
168
169
170State 1
171]])
172
173AT_CLEANUP
174
175
176## ------------------------------- ##
177## Useless associativity warning. ##
178## ------------------------------- ##
179
180AT_SETUP([Useless associativity warning])
181
182AT_DATA([[input.y]],
183[[%token EQ "=" PL "+" ST "*" LP "("
184%nonassoc "="
185%left "+"
186%left "*"
187%precedence "("
188%%
189stmt:
190 exp
191| "var" "=" exp
192;
193
194exp:
195 exp "+" exp
196| exp "*" "num"
197| "(" exp ")"
198| "num"
199;
200]])
201
202AT_BISON_CHECK([-Wprecedence input.y], 0, [],
203[[input.y:2.1-9: warning: useless precedence and associativity for "=" [-Wprecedence]
204input.y:4.1-5: warning: useless associativity for "*", use %precedence [-Wprecedence]
205input.y:5.1-11: warning: useless precedence for "(" [-Wprecedence]
206]])
207
208AT_CLEANUP
209
210
211## ---------------------------- ##
212## Useless precedence warning. ##
213## ---------------------------- ##
214
215AT_SETUP([Useless precedence warning])
216
217AT_DATA([[input.y]],
218[[%token A B U V W X Y Z
219%precedence Z
220%left X
221%precedence Y
222%left W
223%right V
224%nonassoc U
225%%
226a: b
227 | a U b
228 | f
229;
230b: c
231 | b V c
232;
233c: d
234 | c W d
235;
236d: A
237 | d X d
238 | d Y A
239;
240f: B
241 | f Z B
242;
243]])
244
245AT_BISON_CHECK([-Wprecedence -fcaret -o input.c input.y], 0, [],
246[[input.y:7.1-9: warning: useless precedence and associativity for U [-Wprecedence]
247 %nonassoc U
248 ^^^^^^^^^
249input.y:6.1-6: warning: useless precedence and associativity for V [-Wprecedence]
250 %right V
251 ^^^^^^
252input.y:5.1-5: warning: useless precedence and associativity for W [-Wprecedence]
253 %left W
254 ^^^^^
255input.y:2.1-11: warning: useless precedence for Z [-Wprecedence]
256 %precedence Z
257 ^^^^^^^^^^^
258]])
259
260AT_CLEANUP
261
262
263## ---------------- ##
264## S/R in initial. ##
265## ---------------- ##
266
267# I once hacked Bison in such a way that it lost its reductions on the
268# initial state (because it was confusing it with the last state). It
269# took me a while to strip down my failures to this simple case. So
270# make sure it finds the s/r conflict below.
271
272AT_SETUP([S/R in initial])
273
274AT_DATA([[input.y]],
275[[%expect 1
276%%
277exp: e 'e';
278e: 'e' | /* Nothing. */;
279]])
280
281AT_BISON_CHECK([-o input.c input.y], 0, [],
282[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
283]])
284
285AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
286[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
287 e: 'e' | /* Nothing. */;
288 ^
289]])
290
291AT_CLEANUP
292
293
294## ------------------- ##
295## %nonassoc and eof. ##
296## ------------------- ##
297
298AT_SETUP([%nonassoc and eof])
299
300AT_BISON_OPTION_PUSHDEFS
301AT_DATA_GRAMMAR([input.y],
302[[
303%{
304#include <stdio.h>
305#include <stdlib.h>
306#include <string.h>
307#include <assert.h>
308
309#define YYERROR_VERBOSE 1
310]AT_YYERROR_DEFINE[
311/* The current argument. */
312static const char *input;
313
314static int
315yylex (void)
316{
317 static size_t toknum;
318 assert (toknum <= strlen (input));
319 return input[toknum++];
320}
321
322%}
323
324%nonassoc '<' '>'
325
326%%
327expr: expr '<' expr
328 | expr '>' expr
329 | '0'
330 ;
331%%
332int
333main (int argc, const char *argv[])
334{
335 input = argc <= 1 ? "" : argv[1];
336 return yyparse ();
337}
338]])
339AT_BISON_OPTION_POPDEFS
340
341m4_pushdef([AT_NONASSOC_AND_EOF_CHECK],
342[AT_BISON_CHECK([$1[ -o input.c input.y]])
343AT_COMPILE([input])
344
345m4_pushdef([AT_EXPECTING], [m4_if($2, [correct], [[, expecting $end]])])
346
347AT_PARSER_CHECK([./input '0<0'])
348AT_PARSER_CHECK([./input '0<0<0'], [1], [],
349 [syntax error, unexpected '<'AT_EXPECTING
350])
351
352AT_PARSER_CHECK([./input '0>0'])
353AT_PARSER_CHECK([./input '0>0>0'], [1], [],
354 [syntax error, unexpected '>'AT_EXPECTING
355])
356
357AT_PARSER_CHECK([./input '0<0>0'], [1], [],
358 [syntax error, unexpected '>'AT_EXPECTING
359])
360
361m4_popdef([AT_EXPECTING])])
362
363# Expected token list is missing.
364AT_NONASSOC_AND_EOF_CHECK([], [[incorrect]])
365
366# We must disable default reductions in inconsistent states in order to
367# have an explicit list of all expected tokens.
368AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reduction=consistent]],
369 [[correct]])
370
371# lr.default-reduction=consistent happens to work for this test case.
372# However, for other grammars, lookahead sets can be merged for
373# different left contexts, so it is still possible to have an incorrect
374# expected list. Canonical LR is almost a general solution (that is, it
375# can fail only when %nonassoc is used), so make sure it gives the same
376# result as above.
377AT_NONASSOC_AND_EOF_CHECK([[-Dlr.type=canonical-lr]], [[correct]])
378
379# parse.lac=full is a completely general solution that does not require
380# any of the above sacrifices. Of course, it does not extend the
381# language-recognition power of LALR to (IE)LR, but it does ensure that
382# the reported list of expected tokens matches what the given parser
383# would have accepted in place of the unexpected token.
384AT_NONASSOC_AND_EOF_CHECK([[-Dparse.lac=full]], [[correct]])
385
386m4_popdef([AT_NONASSOC_AND_EOF_CHECK])
387
388AT_CLEANUP
389
390
391
392## ------------------------------------------- ##
393## parse.error=verbose and consistent errors. ##
394## ------------------------------------------- ##
395
396m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
397
398AT_SETUP([[parse.error=verbose and consistent errors: $1]])
399
400AT_BISON_OPTION_PUSHDEFS([$1])
401
402m4_pushdef([AT_YYLEX_PROTOTYPE],
403[AT_SKEL_CC_IF([[int yylex (yy::parser::semantic_type *lvalp)]],
404 [[int yylex (YYSTYPE *lvalp)]])])
405
406AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y],
407[AT_SKEL_JAVA_IF([[
408
409%code imports {
410 import java.io.IOException;
411}]], [[
412
413%code {]AT_SKEL_CC_IF([[
414 #include <string>]], [[
415 #include <assert.h>
416 #include <stdio.h>
417 ]AT_YYERROR_DECLARE])[
418 ]AT_YYLEX_PROTOTYPE[;
419 #define USE(Var)
420}
421
422]AT_SKEL_CC_IF([[%defines]], [[%define api.pure]])])[
423
424]$1[
425
426%define parse.error verbose
427
428%%
429
430]$2[
431
432]AT_SKEL_JAVA_IF([[%code lexer {]], [[%%]])[
433
434/*--------.
435| yylex. |
436`--------*/]AT_SKEL_JAVA_IF([[
437
438public String input = "]$3[";
439public int index = 0;
440public int yylex ()
441{
442 if (index < input.length ())
443 return input.charAt (index++);
444 else
445 return 0;
446}
447public Object getLVal ()
448{
449 return new Integer(1);
450}]], [[
451
452]AT_YYLEX_PROTOTYPE[
453{
454 static char const *input = "]$3[";
455 *lvalp = 1;
456 return *input++;
457}]])[
458]AT_YYERROR_DEFINE[
459]AT_SKEL_JAVA_IF([[
460};
461
462%%]])[
463
464/*-------.
465| main. |
466`-------*/
467]AT_MAIN_DEFINE
468])
469
470AT_FULL_COMPILE([[input]])
471
472m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']],
473 $5, [a], [[, expecting 'a']],
474 $5, [b], [[, expecting 'b']])])
475
476AT_SKEL_JAVA_IF([AT_JAVA_PARSER_CHECK([[input]], [[0]]],
477 [AT_PARSER_CHECK([[./input]], [[1]]]),
478[[]],
479[[syntax error, unexpected ]$4[]AT_EXPECTING[
480]])
481
482m4_popdef([AT_EXPECTING])
483m4_popdef([AT_YYLEX_PROTOTYPE])
484AT_BISON_OPTION_POPDEFS
485
486AT_CLEANUP
487]) dnl AT_CONSISTENT_ERRORS_CHECK
488
489
490
491
492m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR],
493[[%nonassoc 'a';
494
495start: consistent-error-on-a-a 'a' ;
496
497consistent-error-on-a-a:
498 'a' default-reduction
499 | 'a' default-reduction 'a'
500 | 'a' shift
501 ;
502
503default-reduction: /*empty*/ ;
504shift: 'b' ;
505
506// Provide another context in which all rules are useful so that this
507// test case looks a little more realistic.
508start: 'b' consistent-error-on-a-a 'c' ;
509]])
510
511m4_pushdef([AT_PREVIOUS_STATE_INPUT], [[a]])
512
513# Unfortunately, no expected tokens are reported even though 'b' can be
514# accepted. Nevertheless, the main point of this test is to make sure
515# that at least the unexpected token is reported. In a previous version
516# of Bison, it wasn't reported because the error is detected in a
517# consistent state with an error action, and that case always triggered
518# the simple "syntax error" message.
519#
520# The point isn't to test IELR here, but state merging happens to
521# complicate this example.
522AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr]],
523 [AT_PREVIOUS_STATE_GRAMMAR],
524 [AT_PREVIOUS_STATE_INPUT],
525 [[$end]], [[none]])
526AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
527 %glr-parser]],
528 [AT_PREVIOUS_STATE_GRAMMAR],
529 [AT_PREVIOUS_STATE_INPUT],
530 [[$end]], [[none]])
531AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
532 %language "c++"]],
533 [AT_PREVIOUS_STATE_GRAMMAR],
534 [AT_PREVIOUS_STATE_INPUT],
535 [[$end]], [[none]])
536AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
537 %language "java"]],
538 [AT_PREVIOUS_STATE_GRAMMAR],
539 [AT_PREVIOUS_STATE_INPUT],
540 [[end of input]], [[none]])
541
542# Even canonical LR doesn't foresee the error for 'a'!
543AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
544 %define lr.default-reduction consistent]],
545 [AT_PREVIOUS_STATE_GRAMMAR],
546 [AT_PREVIOUS_STATE_INPUT],
547 [[$end]], [[ab]])
548AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
549 %define lr.default-reduction accepting]],
550 [AT_PREVIOUS_STATE_GRAMMAR],
551 [AT_PREVIOUS_STATE_INPUT],
552 [[$end]], [[ab]])
553AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
554 [AT_PREVIOUS_STATE_GRAMMAR],
555 [AT_PREVIOUS_STATE_INPUT],
556 [[$end]], [[ab]])
557
558# Only LAC gets it right.
559AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr
560 %define parse.lac full]],
561 [AT_PREVIOUS_STATE_GRAMMAR],
562 [AT_PREVIOUS_STATE_INPUT],
563 [[$end]], [[b]])
564AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
565 %define parse.lac full]],
566 [AT_PREVIOUS_STATE_GRAMMAR],
567 [AT_PREVIOUS_STATE_INPUT],
568 [[$end]], [[b]])
569
570m4_popdef([AT_PREVIOUS_STATE_GRAMMAR])
571m4_popdef([AT_PREVIOUS_STATE_INPUT])
572
573m4_pushdef([AT_USER_ACTION_GRAMMAR],
574[[%nonassoc 'a';
575
576// If $$ = 0 here, then we know that the 'a' destructor is being invoked
577// incorrectly for the 'b' set in the semantic action below. All 'a'
578// tokens are returned by yylex, which sets $$ = 1.
579%destructor {
580 if (!$$)
581 fprintf (stderr, "Wrong destructor.\n");
582} 'a';
583
584// Rather than depend on an inconsistent state to induce reading a
585// lookahead as in the previous grammar, just assign the lookahead in a
586// semantic action. That lookahead isn't needed before either error
587// action is encountered. In a previous version of Bison, this was a
588// problem as it meant yychar was not translated into yytoken before
589// either error action. The second error action thus invoked a
590// destructor that it selected according to the incorrect yytoken. The
591// first error action would have reported an incorrect unexpected token
592// except that, due to the bug described in the previous grammar, the
593// unexpected token was not reported at all.
594start: error-reduce consistent-error 'a' { USE ($][3); } ;
595
596error-reduce:
597 'a' 'a' consistent-reduction consistent-error 'a'
598 { USE (($][1, $][2, $][5)); }
599| 'a' error
600 { USE ($][1); }
601;
602
603consistent-reduction: /*empty*/ {
604 assert (yychar == YYEMPTY);
605 yylval = 0;
606 yychar = 'b';
607} ;
608
609consistent-error:
610 'a' { USE ($][1); }
611| /*empty*/ %prec 'a'
612;
613
614// Provide another context in which all rules are useful so that this
615// test case looks a little more realistic.
616start: 'b' consistent-error 'b' ;
617]])
618m4_pushdef([AT_USER_ACTION_INPUT], [[aa]])
619
620AT_CONSISTENT_ERRORS_CHECK([[]],
621 [AT_USER_ACTION_GRAMMAR],
622 [AT_USER_ACTION_INPUT],
623 [['b']], [[none]])
624AT_CONSISTENT_ERRORS_CHECK([[%glr-parser]],
625 [AT_USER_ACTION_GRAMMAR],
626 [AT_USER_ACTION_INPUT],
627 [['b']], [[none]])
628# No C++ or Java test because yychar cannot be manipulated by users.
629
630AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction consistent]],
631 [AT_USER_ACTION_GRAMMAR],
632 [AT_USER_ACTION_INPUT],
633 [['b']], [[none]])
634
635# Canonical LR doesn't foresee the error for 'a'!
636AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction accepting]],
637 [AT_USER_ACTION_GRAMMAR],
638 [AT_USER_ACTION_INPUT],
639 [[$end]], [[a]])
640AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
641 [AT_USER_ACTION_GRAMMAR],
642 [AT_USER_ACTION_INPUT],
643 [[$end]], [[a]])
644
645AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full]],
646 [AT_USER_ACTION_GRAMMAR],
647 [AT_USER_ACTION_INPUT],
648 [['b']], [[none]])
649AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full
650 %define lr.default-reduction accepting]],
651 [AT_USER_ACTION_GRAMMAR],
652 [AT_USER_ACTION_INPUT],
653 [[$end]], [[none]])
654
655m4_popdef([AT_USER_ACTION_GRAMMAR])
656m4_popdef([AT_USER_ACTION_INPUT])
657
658m4_popdef([AT_CONSISTENT_ERRORS_CHECK])
659
660
661
662
663## ------------------------------------------------------- ##
664## LAC: %nonassoc requires splitting canonical LR states. ##
665## ------------------------------------------------------- ##
666
667# This test case demonstrates that, when %nonassoc is used, canonical
668# LR(1) parser table construction followed by conflict resolution
669# without further state splitting is not always sufficient to produce a
670# parser that can detect all syntax errors as soon as possible on one
671# token of lookahead. However, LAC solves the problem completely even
672# with minimal LR parser tables.
673
674AT_SETUP([[LAC: %nonassoc requires splitting canonical LR states]])
675AT_BISON_OPTION_PUSHDEFS
676AT_DATA_GRAMMAR([[input.y]],
677[[%code {
678 #include <stdio.h>
679 ]AT_YYERROR_DECLARE[
680 ]AT_YYLEX_DECLARE[
681}
682
683%error-verbose
684%nonassoc 'a'
685
686%%
687
688start:
689 'a' problem 'a' // First context.
690| 'b' problem 'b' // Second context.
691| 'c' reduce-nonassoc // Just makes reduce-nonassoc useful.
692;
693
694problem:
695 look reduce-nonassoc
696| look 'a'
697| look 'b'
698;
699
700// For the state reached after shifting the 'a' in these productions,
701// lookahead sets are the same in both the first and second contexts.
702// Thus, canonical LR reuses the same state for both contexts. However,
703// the lookahead 'a' for the reduction "look: 'a'" later becomes an
704// error action only in the first context. In order to immediately
705// detect the syntax error on 'a' here for only the first context, this
706// canonical LR state would have to be split into two states, and the
707// 'a' lookahead would have to be removed from only one of the states.
708look:
709 'a' // Reduction lookahead set is always ['a', 'b'].
710| 'a' 'b'
711| 'a' 'c' // 'c' is forgotten as an expected token.
712;
713
714reduce-nonassoc: %prec 'a';
715
716%%
717]AT_YYERROR_DEFINE[
718]AT_YYLEX_DEFINE(["aaa"])[
719]AT_MAIN_DEFINE
720])
721AT_BISON_OPTION_POPDEFS
722
723# Show canonical LR's failure.
724AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]],
725 [[0]], [[]],
726[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
727]])
728AT_COMPILE([[input]])
729AT_PARSER_CHECK([[./input]], [[1]], [[]],
730[[syntax error, unexpected 'a', expecting 'b'
731]])
732
733# It's corrected by LAC.
734AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
735 -o input.c input.y]], [[0]], [[]],
736[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
737]])
738AT_COMPILE([[input]])
739AT_PARSER_CHECK([[./input]], [[1]], [[]],
740[[syntax error, unexpected 'a', expecting 'b' or 'c'
741]])
742
743# IELR is sufficient when LAC is used.
744AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]],
745 [[0]], [[]],
746[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
747]])
748AT_COMPILE([[input]])
749AT_PARSER_CHECK([[./input]], [[1]], [[]],
750[[syntax error, unexpected 'a', expecting 'b' or 'c'
751]])
752
753AT_CLEANUP
754
755## ------------------------- ##
756## Unresolved SR Conflicts. ##
757## ------------------------- ##
758
759AT_SETUP([Unresolved SR Conflicts])
760
761AT_KEYWORDS([report])
762
763AT_DATA([input.y],
764[[%token NUM OP
765%%
766exp: exp OP exp | NUM;
767]])
768
769AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
770[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
771]])
772
773# Check the contents of the report.
774AT_CHECK([cat input.output], [],
775[[State 5 conflicts: 1 shift/reduce
776
777
778Grammar
779
780 0 $accept: exp $end
781
782 1 exp: exp OP exp
783 2 | NUM
784
785
786Terminals, with rules where they appear
787
788$end (0) 0
789error (256)
790NUM (258) 2
791OP (259) 1
792
793
794Nonterminals, with rules where they appear
795
796$accept (5)
797 on left: 0
798exp (6)
799 on left: 1 2, on right: 0 1
800
801
802State 0
803
804 0 $accept: . exp $end
805 1 exp: . exp OP exp
806 2 | . NUM
807
808 NUM shift, and go to state 1
809
810 exp go to state 2
811
812
813State 1
814
815 2 exp: NUM .
816
817 $default reduce using rule 2 (exp)
818
819
820State 2
821
822 0 $accept: exp . $end
823 1 exp: exp . OP exp
824
825 $end shift, and go to state 3
826 OP shift, and go to state 4
827
828
829State 3
830
831 0 $accept: exp $end .
832
833 $default accept
834
835
836State 4
837
838 1 exp: . exp OP exp
839 1 | exp OP . exp
840 2 | . NUM
841
842 NUM shift, and go to state 1
843
844 exp go to state 5
845
846
847State 5
848
849 1 exp: exp . OP exp
850 1 | exp OP exp . [$end, OP]
851
852 OP shift, and go to state 4
853
854 OP [reduce using rule 1 (exp)]
855 $default reduce using rule 1 (exp)
856]])
857
858AT_CLEANUP
859
860
861
862## ----------------------- ##
863## Resolved SR Conflicts. ##
864## ----------------------- ##
865
866AT_SETUP([Resolved SR Conflicts])
867
868AT_KEYWORDS([report])
869
870AT_DATA([input.y],
871[[%token NUM OP
872%left OP
873%%
874exp: exp OP exp | NUM;
875]])
876
877AT_BISON_CHECK([-o input.c --report=all input.y])
878
879# Check the contents of the report.
880AT_CHECK([cat input.output], [],
881[[Grammar
882
883 0 $accept: exp $end
884
885 1 exp: exp OP exp
886 2 | NUM
887
888
889Terminals, with rules where they appear
890
891$end (0) 0
892error (256)
893NUM (258) 2
894OP (259) 1
895
896
897Nonterminals, with rules where they appear
898
899$accept (5)
900 on left: 0
901exp (6)
902 on left: 1 2, on right: 0 1
903
904
905State 0
906
907 0 $accept: . exp $end
908 1 exp: . exp OP exp
909 2 | . NUM
910
911 NUM shift, and go to state 1
912
913 exp go to state 2
914
915
916State 1
917
918 2 exp: NUM .
919
920 $default reduce using rule 2 (exp)
921
922
923State 2
924
925 0 $accept: exp . $end
926 1 exp: exp . OP exp
927
928 $end shift, and go to state 3
929 OP shift, and go to state 4
930
931
932State 3
933
934 0 $accept: exp $end .
935
936 $default accept
937
938
939State 4
940
941 1 exp: . exp OP exp
942 1 | exp OP . exp
943 2 | . NUM
944
945 NUM shift, and go to state 1
946
947 exp go to state 5
948
949
950State 5
951
952 1 exp: exp . OP exp
953 1 | exp OP exp . [$end, OP]
954
955 $default reduce using rule 1 (exp)
956
957 Conflict between rule 1 and token OP resolved as reduce (%left OP).
958]])
959
960AT_CLEANUP
961
962
963## ---------------------- ##
964## %precedence suffices. ##
965## ---------------------- ##
966
967AT_SETUP([%precedence suffices])
968
969AT_DATA([input.y],
970[[%precedence "then"
971%precedence "else"
972%%
973stmt:
974 "if" cond "then" stmt
975| "if" cond "then" stmt "else" stmt
976| "stmt"
977;
978
979cond:
980 "exp"
981;
982]])
983
984AT_BISON_CHECK([-o input.c input.y])
985
986AT_CLEANUP
987
988
989## ------------------------------ ##
990## %precedence does not suffice. ##
991## ------------------------------ ##
992
993AT_SETUP([%precedence does not suffice])
994
995AT_DATA([input.y],
996[[%precedence "then"
997%precedence "else"
998%%
999stmt:
1000 "if" cond "then" stmt
1001| "if" cond "then" stmt "else" stmt
1002| "stmt"
1003;
1004
1005cond:
1006 "exp"
1007| cond "then" cond
1008;
1009]])
1010
1011AT_BISON_CHECK([-o input.c input.y], 0, [],
1012[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
1013input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother]
1014]])
1015
1016AT_CLEANUP
1017
1018
1019## -------------------------------- ##
1020## Defaulted Conflicted Reduction. ##
1021## -------------------------------- ##
1022
1023# When there are RR conflicts, some rules are disabled. Usually it is
1024# simply displayed as:
1025#
1026# $end reduce using rule 3 (num)
1027# $end [reduce using rule 4 (id)]
1028#
1029# But when 'reduce 3' is the default action, we'd produce:
1030#
1031# $end [reduce using rule 4 (id)]
1032# $default reduce using rule 3 (num)
1033#
1034# In this precise case (a reduction is masked by the default
1035# reduction), we make the 'reduce 3' explicit:
1036#
1037# $end reduce using rule 3 (num)
1038# $end [reduce using rule 4 (id)]
1039# $default reduce using rule 3 (num)
1040#
1041# Maybe that's not the best display, but then, please propose something
1042# else.
1043
1044AT_SETUP([Defaulted Conflicted Reduction])
1045AT_KEYWORDS([report])
1046
1047AT_DATA([input.y],
1048[[%%
1049exp: num | id;
1050num: '0';
1051id : '0';
1052%%
1053]])
1054
1055AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
1056[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1057input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother]
1058]])
1059
1060# Check the contents of the report.
1061AT_CHECK([cat input.output], [],
1062[[Rules useless in parser due to conflicts
1063
1064 4 id: '0'
1065
1066
1067State 1 conflicts: 1 reduce/reduce
1068
1069
1070Grammar
1071
1072 0 $accept: exp $end
1073
1074 1 exp: num
1075 2 | id
1076
1077 3 num: '0'
1078
1079 4 id: '0'
1080
1081
1082Terminals, with rules where they appear
1083
1084$end (0) 0
1085'0' (48) 3 4
1086error (256)
1087
1088
1089Nonterminals, with rules where they appear
1090
1091$accept (4)
1092 on left: 0
1093exp (5)
1094 on left: 1 2, on right: 0
1095num (6)
1096 on left: 3, on right: 1
1097id (7)
1098 on left: 4, on right: 2
1099
1100
1101State 0
1102
1103 0 $accept: . exp $end
1104 1 exp: . num
1105 2 | . id
1106 3 num: . '0'
1107 4 id: . '0'
1108
1109 '0' shift, and go to state 1
1110
1111 exp go to state 2
1112 num go to state 3
1113 id go to state 4
1114
1115
1116State 1
1117
1118 3 num: '0' . [$end]
1119 4 id: '0' . [$end]
1120
1121 $end reduce using rule 3 (num)
1122 $end [reduce using rule 4 (id)]
1123 $default reduce using rule 3 (num)
1124
1125
1126State 2
1127
1128 0 $accept: exp . $end
1129
1130 $end shift, and go to state 5
1131
1132
1133State 3
1134
1135 1 exp: num .
1136
1137 $default reduce using rule 1 (exp)
1138
1139
1140State 4
1141
1142 2 exp: id .
1143
1144 $default reduce using rule 2 (exp)
1145
1146
1147State 5
1148
1149 0 $accept: exp $end .
1150
1151 $default accept
1152]])
1153
1154AT_CLEANUP
1155
1156
1157
1158
1159## -------------------- ##
1160## %expect not enough. ##
1161## -------------------- ##
1162
1163AT_SETUP([%expect not enough])
1164
1165AT_DATA([input.y],
1166[[%token NUM OP
1167%expect 0
1168%%
1169exp: exp OP exp | NUM;
1170]])
1171
1172AT_BISON_CHECK([-o input.c input.y], 1, [],
1173[[input.y: error: shift/reduce conflicts: 1 found, 0 expected
1174]])
1175AT_CLEANUP
1176
1177
1178## --------------- ##
1179## %expect right. ##
1180## --------------- ##
1181
1182AT_SETUP([%expect right])
1183
1184AT_DATA([input.y],
1185[[%token NUM OP
1186%expect 1
1187%%
1188exp: exp OP exp | NUM;
1189]])
1190
1191AT_BISON_CHECK([-o input.c input.y])
1192AT_CLEANUP
1193
1194
1195## ------------------ ##
1196## %expect too much. ##
1197## ------------------ ##
1198
1199AT_SETUP([%expect too much])
1200
1201AT_DATA([input.y],
1202[[%token NUM OP
1203%expect 2
1204%%
1205exp: exp OP exp | NUM;
1206]])
1207
1208AT_BISON_CHECK([-o input.c input.y], 1, [],
1209[[input.y: error: shift/reduce conflicts: 1 found, 2 expected
1210]])
1211AT_CLEANUP
1212
1213
1214## ------------------------------- ##
1215## %expect with reduce conflicts. ##
1216## ------------------------------- ##
1217
1218AT_SETUP([%expect with reduce conflicts])
1219
1220AT_DATA([input.y],
1221[[%expect 0
1222%%
1223program: a 'a' | a a;
1224a: 'a';
1225]])
1226
1227AT_BISON_CHECK([-o input.c input.y], 1, [],
1228[[input.y: error: reduce/reduce conflicts: 1 found, 0 expected
1229]])
1230AT_CLEANUP
1231
1232
1233## ------------------------- ##
1234## %prec with user strings. ##
1235## ------------------------- ##
1236
1237AT_SETUP([%prec with user string])
1238
1239AT_DATA([[input.y]],
1240[[%%
1241exp:
1242 "foo" %prec "foo"
1243;
1244]])
1245
1246AT_BISON_CHECK([-o input.c input.y])
1247AT_CLEANUP
1248
1249
1250## -------------------------------- ##
1251## %no-default-prec without %prec. ##
1252## -------------------------------- ##
1253
1254AT_SETUP([%no-default-prec without %prec])
1255
1256AT_DATA([[input.y]],
1257[[%left '+'
1258%left '*'
1259
1260%%
1261
1262%no-default-prec;
1263
1264e: e '+' e
1265 | e '*' e
1266 | '0'
1267 ;
1268]])
1269
1270AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
1271[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
1272input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence]
1273input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence]
1274]])
1275AT_CLEANUP
1276
1277
1278## ----------------------------- ##
1279## %no-default-prec with %prec. ##
1280## ----------------------------- ##
1281
1282AT_SETUP([%no-default-prec with %prec])
1283
1284AT_DATA([[input.y]],
1285[[%left '+'
1286%left '*'
1287
1288%%
1289
1290%no-default-prec;
1291
1292e: e '+' e %prec '+'
1293 | e '*' e %prec '*'
1294 | '0'
1295 ;
1296]])
1297
1298AT_BISON_CHECK([-o input.c input.y])
1299AT_CLEANUP
1300
1301
1302## --------------- ##
1303## %default-prec. ##
1304## --------------- ##
1305
1306AT_SETUP([%default-prec])
1307
1308AT_DATA([[input.y]],
1309[[%left '+'
1310%left '*'
1311
1312%%
1313
1314%default-prec;
1315
1316e: e '+' e
1317 | e '*' e
1318 | '0'
1319 ;
1320]])
1321
1322AT_BISON_CHECK([-o input.c input.y])
1323AT_CLEANUP
1324
1325
1326## ---------------------------------------------- ##
1327## Unreachable States After Conflict Resolution. ##
1328## ---------------------------------------------- ##
1329
1330AT_SETUP([[Unreachable States After Conflict Resolution]])
1331
1332# If conflict resolution makes states unreachable, remove those states, report
1333# rules that are then unused, and don't report conflicts in those states. Test
1334# what happens when a nonterminal becomes useless as a result of state removal
1335# since that causes lalr.o's goto map to be rewritten.
1336
1337AT_DATA([[input.y]],
1338[[%output "input.c"
1339%left 'a'
1340
1341%%
1342
1343start: resolved_conflict 'a' reported_conflicts 'a' ;
1344
1345/* S/R conflict resolved as reduce, so the state with item
1346 * (resolved_conflict: 'a' . unreachable1) and all it transition successors are
1347 * unreachable, and the associated production is useless. */
1348resolved_conflict:
1349 'a' unreachable1
1350 | %prec 'a'
1351 ;
1352
1353/* S/R conflict that need not be reported since it is unreachable because of
1354 * the previous conflict resolution. Nonterminal unreachable1 and all its
1355 * productions are useless. */
1356unreachable1:
1357 'a' unreachable2
1358 |
1359 ;
1360
1361/* Likewise for a R/R conflict and nonterminal unreachable2. */
1362unreachable2: | ;
1363
1364/* Make sure remaining S/R and R/R conflicts are still reported correctly even
1365 * when their states are renumbered due to state removal. */
1366reported_conflicts:
1367 'a'
1368 | 'a'
1369 |
1370 ;
1371
1372]])
1373
1374AT_BISON_CHECK([[--report=all input.y]], 0, [],
1375[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
1376input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1377input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother]
1378input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother]
1379input.y:21.4: warning: rule useless in parser due to conflicts [-Wother]
1380input.y:25.13: warning: rule useless in parser due to conflicts [-Wother]
1381input.y:25.16: warning: rule useless in parser due to conflicts [-Wother]
1382input.y:31.5-7: warning: rule useless in parser due to conflicts [-Wother]
1383input.y:32.4: warning: rule useless in parser due to conflicts [-Wother]
1384]])
1385
1386AT_CHECK([[cat input.output]], 0,
1387[[Rules useless in parser due to conflicts
1388
1389 2 resolved_conflict: 'a' unreachable1
1390
1391 4 unreachable1: 'a' unreachable2
1392 5 | %empty
1393
1394 6 unreachable2: %empty
1395 7 | %empty
1396
1397 9 reported_conflicts: 'a'
1398 10 | %empty
1399
1400
1401State 4 conflicts: 1 shift/reduce
1402State 5 conflicts: 1 reduce/reduce
1403
1404
1405Grammar
1406
1407 0 $accept: start $end
1408
1409 1 start: resolved_conflict 'a' reported_conflicts 'a'
1410
1411 2 resolved_conflict: 'a' unreachable1
1412 3 | %empty
1413
1414 4 unreachable1: 'a' unreachable2
1415 5 | %empty
1416
1417 6 unreachable2: %empty
1418 7 | %empty
1419
1420 8 reported_conflicts: 'a'
1421 9 | 'a'
1422 10 | %empty
1423
1424
1425Terminals, with rules where they appear
1426
1427$end (0) 0
1428'a' (97) 1 2 4 8 9
1429error (256)
1430
1431
1432Nonterminals, with rules where they appear
1433
1434$accept (4)
1435 on left: 0
1436start (5)
1437 on left: 1, on right: 0
1438resolved_conflict (6)
1439 on left: 2 3, on right: 1
1440unreachable1 (7)
1441 on left: 4 5, on right: 2
1442unreachable2 (8)
1443 on left: 6 7, on right: 4
1444reported_conflicts (9)
1445 on left: 8 9 10, on right: 1
1446
1447
1448State 0
1449
1450 0 $accept: . start $end
1451 1 start: . resolved_conflict 'a' reported_conflicts 'a'
1452 2 resolved_conflict: . 'a' unreachable1
1453 3 | . %empty ['a']
1454
1455 $default reduce using rule 3 (resolved_conflict)
1456
1457 start go to state 1
1458 resolved_conflict go to state 2
1459
1460 Conflict between rule 3 and token 'a' resolved as reduce (%left 'a').
1461
1462
1463State 1
1464
1465 0 $accept: start . $end
1466
1467 $end shift, and go to state 3
1468
1469
1470State 2
1471
1472 1 start: resolved_conflict . 'a' reported_conflicts 'a'
1473
1474 'a' shift, and go to state 4
1475
1476
1477State 3
1478
1479 0 $accept: start $end .
1480
1481 $default accept
1482
1483
1484State 4
1485
1486 1 start: resolved_conflict 'a' . reported_conflicts 'a'
1487 8 reported_conflicts: . 'a'
1488 9 | . 'a'
1489 10 | . %empty ['a']
1490
1491 'a' shift, and go to state 5
1492
1493 'a' [reduce using rule 10 (reported_conflicts)]
1494
1495 reported_conflicts go to state 6
1496
1497
1498State 5
1499
1500 8 reported_conflicts: 'a' . ['a']
1501 9 | 'a' . ['a']
1502
1503 'a' reduce using rule 8 (reported_conflicts)
1504 'a' [reduce using rule 9 (reported_conflicts)]
1505 $default reduce using rule 8 (reported_conflicts)
1506
1507
1508State 6
1509
1510 1 start: resolved_conflict 'a' reported_conflicts . 'a'
1511
1512 'a' shift, and go to state 7
1513
1514
1515State 7
1516
1517 1 start: resolved_conflict 'a' reported_conflicts 'a' .
1518
1519 $default reduce using rule 1 (start)
1520]])
1521
1522AT_DATA([[input-keep.y]],
1523[[%define lr.keep-unreachable-state
1524]])
1525AT_CHECK([[cat input.y >> input-keep.y]])
1526
1527AT_BISON_CHECK([[input-keep.y]], 0, [],
1528[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
1529input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
1530input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother]
1531input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother]
1532input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother]
1533input-keep.y:33.4: warning: rule useless in parser due to conflicts [-Wother]
1534]])
1535
1536AT_CLEANUP
1537
1538
1539## ------------------------------------------------------------ ##
1540## Solved conflicts report for multiple reductions in a state. ##
1541## ------------------------------------------------------------ ##
1542
1543AT_SETUP([[Solved conflicts report for multiple reductions in a state]])
1544
1545# Used to lose earlier solved conflict messages even within a single S/R/R.
1546
1547AT_DATA([[input.y]],
1548[[%left 'a'
1549%right 'b'
1550%right 'c'
1551%right 'd'
1552%%
1553start:
1554 'a'
1555 | empty_a 'a'
1556 | 'b'
1557 | empty_b 'b'
1558 | 'c'
1559 | empty_c1 'c'
1560 | empty_c2 'c'
1561 | empty_c3 'c'
1562 ;
1563empty_a: %prec 'a' ;
1564empty_b: %prec 'b' ;
1565empty_c1: %prec 'c' ;
1566empty_c2: %prec 'c' ;
1567empty_c3: %prec 'd' ;
1568]])
1569AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
1570AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
1571[[State 0
1572
1573 0 $accept: . start $end
1574 1 start: . 'a'
1575 2 | . empty_a 'a'
1576 3 | . 'b'
1577 4 | . empty_b 'b'
1578 5 | . 'c'
1579 6 | . empty_c1 'c'
1580 7 | . empty_c2 'c'
1581 8 | . empty_c3 'c'
1582 9 empty_a: . %empty ['a']
1583 10 empty_b: . %empty []
1584 11 empty_c1: . %empty []
1585 12 empty_c2: . %empty []
1586 13 empty_c3: . %empty ['c']
1587
1588 'b' shift, and go to state 1
1589
1590 'c' reduce using rule 13 (empty_c3)
1591 $default reduce using rule 9 (empty_a)
1592
1593 start go to state 2
1594 empty_a go to state 3
1595 empty_b go to state 4
1596 empty_c1 go to state 5
1597 empty_c2 go to state 6
1598 empty_c3 go to state 7
1599
1600 Conflict between rule 9 and token 'a' resolved as reduce (%left 'a').
1601 Conflict between rule 10 and token 'b' resolved as shift (%right 'b').
1602 Conflict between rule 11 and token 'c' resolved as shift (%right 'c').
1603 Conflict between rule 12 and token 'c' resolved as shift (%right 'c').
1604 Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd').
1605
1606
1607State 1
1608]])
1609
1610AT_CLEANUP
1611
1612
1613## ------------------------------------------------------------ ##
1614## %nonassoc error actions for multiple reductions in a state. ##
1615## ------------------------------------------------------------ ##
1616
1617# Used to abort when trying to resolve conflicts as %nonassoc error actions for
1618# multiple reductions in a state.
1619
1620# For a %nonassoc error action token, used to print the first remaining
1621# reduction on that token without brackets.
1622
1623AT_SETUP([[%nonassoc error actions for multiple reductions in a state]])
1624
1625AT_DATA([[input.y]],
1626[[%nonassoc 'a' 'b' 'c'
1627%%
1628start:
1629 'a'
1630 | empty_a 'a'
1631 | 'b'
1632 | empty_b 'b'
1633 | 'c'
1634 | empty_c1 'c'
1635 | empty_c2 'c'
1636 | empty_c3 'c'
1637 ;
1638empty_a: %prec 'a' ;
1639empty_b: %prec 'b' ;
1640empty_c1: %prec 'c' ;
1641empty_c2: %prec 'c' ;
1642empty_c3: %prec 'c' ;
1643]])
1644
1645AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
1646AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
1647[[State 0
1648
1649 0 $accept: . start $end
1650 1 start: . 'a'
1651 2 | . empty_a 'a'
1652 3 | . 'b'
1653 4 | . empty_b 'b'
1654 5 | . 'c'
1655 6 | . empty_c1 'c'
1656 7 | . empty_c2 'c'
1657 8 | . empty_c3 'c'
1658 9 empty_a: . %empty []
1659 10 empty_b: . %empty []
1660 11 empty_c1: . %empty []
1661 12 empty_c2: . %empty ['c']
1662 13 empty_c3: . %empty ['c']
1663
1664 'a' error (nonassociative)
1665 'b' error (nonassociative)
1666 'c' error (nonassociative)
1667
1668 'c' [reduce using rule 12 (empty_c2)]
1669 'c' [reduce using rule 13 (empty_c3)]
1670
1671 start go to state 1
1672 empty_a go to state 2
1673 empty_b go to state 3
1674 empty_c1 go to state 4
1675 empty_c2 go to state 5
1676 empty_c3 go to state 6
1677
1678 Conflict between rule 9 and token 'a' resolved as an error (%nonassoc 'a').
1679 Conflict between rule 10 and token 'b' resolved as an error (%nonassoc 'b').
1680 Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c').
1681
1682
1683State 1
1684]])
1685AT_CLEANUP
1686
1687
1688## -------------------- ##
1689## %expect-rr non GLR. ##
1690## -------------------- ##
1691
1692AT_SETUP([[%expect-rr non GLR]])
1693
1694AT_DATA([[1.y]],
1695[[%expect-rr 0
1696%%
1697exp: 'a'
1698]])
1699
1700AT_BISON_CHECK([[1.y]], [[0]], [],
1701[[1.y: warning: %expect-rr applies only to GLR parsers [-Wother]
1702]])
1703
1704AT_DATA([[2.y]],
1705[[%expect-rr 1
1706%%
1707exp: 'a' | 'a';
1708]])
1709
1710AT_BISON_CHECK([[2.y]], [[0]], [],
1711[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
17122.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
17132.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother]
1714]])
1715
1716AT_CLEANUP
1717
1718
1719## ---------------------------------- ##
1720## -W versus %expect and %expect-rr. ##
1721## ---------------------------------- ##
1722
1723AT_SETUP([[-W versus %expect and %expect-rr]])
1724
1725AT_DATA([[sr-rr.y]],
1726[[%glr-parser
1727%%
1728start: 'a' | A 'a' | B 'a' ;
1729A: ;
1730B: ;
1731]])
1732AT_DATA([[sr.y]],
1733[[%glr-parser
1734%%
1735start: 'a' | A 'a' ;
1736A: ;
1737]])
1738AT_DATA([[rr.y]],
1739[[%glr-parser
1740%%
1741start: A | B ;
1742A: ;
1743B: ;
1744]])
1745
1746AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]],
1747[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
1748sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1749]])
1750AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]],
1751[[sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
1752]])
1753AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
1754[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
1755]])
1756
1757[
1758# This is piece of code is rather complex for a simple task: try every
1759# combinaison of (0 or 1 real SR) x (0 or 1 real RR) x (don't %expect
1760# or %expect 0, 1, or 2 SR) x (don't %expect-rr or %expect-rr 0, 1, or 2
1761# RR).
1762
1763# Number and types of genuine conflicts in the grammar.
1764for gram in sr-rr sr rr; do
1765 # Number of expected s/r conflicts.
1766 for sr_exp_i in '' 0 1 2; do
1767 # Number of expected r/r conflicts.
1768 for rr_exp_i in '' 0 1 2; do
1769 test -z "$sr_exp_i" && test -z "$rr_exp_i" && continue
1770
1771 # Build grammar file.
1772 sr_exp=0
1773 rr_exp=0
1774 file=$gram
1775 directives=
1776 if test -n "$sr_exp_i"; then
1777 sr_exp=$sr_exp_i
1778 file=$file-expect-$sr_exp
1779 directives="%expect $sr_exp"
1780 fi
1781 if test -n "$rr_exp_i"; then
1782 rr_exp=$rr_exp_i
1783 file=$file-expect-rr-$rr_exp
1784 directives="$directives %expect-rr $rr_exp"
1785 fi
1786 file=$file.y
1787 echo "$directives" > $file
1788 cat $gram.y >> $file
1789
1790 # Number of found conflicts.
1791 case $gram in
1792 (sr) sr_count=1; rr_count=0;;
1793 (rr) sr_count=0; rr_count=1;;
1794 (sr-rr) sr_count=1; rr_count=1;;
1795 esac
1796
1797 # Update number of expected conflicts: if %expect is given then
1798 # %expect-rr defaults to 0, and vice-versa. Leave empty if
1799 # nothing expected.
1800 case $sr_exp_i:$rr_exp_i in
1801 ?:) rr_exp_i=0;;
1802 :?) sr_exp_i=0;;
1803 esac
1804
1805 # Run tests.
1806 if test $sr_count -eq $sr_exp && test $rr_count -eq $rr_exp; then
1807 ]AT_BISON_CHECK([[-Wnone $file]])[
1808 ]AT_BISON_CHECK([[-Werror $file]])[
1809 else
1810 {
1811 if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then
1812 echo "warning: $sr_count shift/reduce conflicts"
1813 elif test "$sr_exp_i" -ne "$sr_count"; then
1814 echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
1815 fi
1816 if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then
1817 echo "warning: $rr_count reduce/reduce conflicts"
1818 elif test "$rr_exp_i" -ne "$rr_count"; then
1819 echo "error: reduce/reduce conflicts: $rr_count found, $rr_exp_i expected"
1820 fi
1821 } | sed -e "s/^/$file: /" > experr
1822 ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[
1823 ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[
1824 fi
1825 done
1826 done
1827done]
1828
1829AT_CLEANUP