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