# Exercising Bison on conflicts. -*- Autotest -*-
-# Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc.
+# Copyright (C) 2002-2005, 2007-2015 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
AT_BANNER([[Conflicts.]])
+## ------------------------- ##
+## Token declaration order. ##
+## ------------------------- ##
+
+# This test checks that token are declared left to right when in a precedence
+# statement.
+
+AT_SETUP([Token declaration order])
+
+AT_BISON_OPTION_PUSHDEFS
+
+AT_DATA_GRAMMAR([[input.y]],
+[[%code {
+ #include <stdio.h>
+ ]AT_YYERROR_DECLARE[
+ ]AT_YYLEX_DECLARE[
+}
+%token A B C
+%token D
+%right E F G
+%right H I
+%right J
+%left K
+%left L M N
+%nonassoc O P Q
+%precedence R S T U
+%precedence V W
+%%
+exp: A
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE[
+int main (void)
+{
+ assert (A < B);
+ assert (B < C);
+ assert (C < D);
+ assert (D < E);
+ assert (E < F);
+ assert (F < G);
+ assert (G < H);
+ assert (H < I);
+ assert (I < J);
+ assert (J < K);
+ assert (K < L);
+ assert (L < M);
+ assert (M < N);
+ assert (N < O);
+ assert (O < P);
+ assert (P < Q);
+ assert (Q < R);
+ assert (R < S);
+ assert (S < T);
+ assert (T < U);
+ assert (U < V);
+ assert (V < W);
+ return 0;
+}
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+AT_COMPILE([input])
+
+AT_PARSER_CHECK([./input])
+
+AT_BISON_OPTION_POPDEFS
+
+AT_CLEANUP
+
+
+## --------------------------------------------------- ##
+## Token declaration order: literals vs. identifiers. ##
+## --------------------------------------------------- ##
+
+# This test checks that when several tokens are declared by the same keyword,
+# some of them defined as a character ('a'), others as simple textual reference
+# (A), they are declared correctly left to right.
+# Previously, the following test would declare the states in the order 'o' 'p'
+# M N, instead of M N 'o' 'p'.
+
+AT_SETUP([Token declaration order: literals vs. identifiers])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[%token 'a' 'b' C D
+%token E F 'g' 'h'
+%right 'i' 'j' K L
+%right M N 'o' 'p'
+%%
+exp: 'a'
+ | 'b'
+ | C
+ | D
+ | E
+ | F
+ | 'g'
+ | 'h'
+ | 'i'
+ | 'j'
+ | K
+ | L
+ | M
+ | N
+ | 'o'
+ | 'p'
+;
+%%
+]])
+
+AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
+
+ 0 $accept: . exp $end
+ 1 exp: . 'a'
+ 2 | . 'b'
+ 3 | . C
+ 4 | . D
+ 5 | . E
+ 6 | . F
+ 7 | . 'g'
+ 8 | . 'h'
+ 9 | . 'i'
+ 10 | . 'j'
+ 11 | . K
+ 12 | . L
+ 13 | . M
+ 14 | . N
+ 15 | . 'o'
+ 16 | . 'p'
+
+ 'a' shift, and go to state 1
+ 'b' shift, and go to state 2
+ C shift, and go to state 3
+ D shift, and go to state 4
+ E shift, and go to state 5
+ F shift, and go to state 6
+ 'g' shift, and go to state 7
+ 'h' shift, and go to state 8
+ 'i' shift, and go to state 9
+ 'j' shift, and go to state 10
+ K shift, and go to state 11
+ L shift, and go to state 12
+ M shift, and go to state 13
+ N shift, and go to state 14
+ 'o' shift, and go to state 15
+ 'p' shift, and go to state 16
+
+ exp go to state 17
+
+
+State 1
+]])
+
+AT_CLEANUP
+
+
+## ------------------------------- ##
+## Useless associativity warning. ##
+## ------------------------------- ##
+
+AT_SETUP([Useless associativity warning])
+
+AT_DATA([[input.y]],
+[[%token EQ "=" PL "+" ST "*" LP "("
+%nonassoc "="
+%left "+"
+%left "*"
+%precedence "("
+%%
+stmt:
+ exp
+| "var" "=" exp
+;
+
+exp:
+ exp "+" exp
+| exp "*" "num"
+| "(" exp ")"
+| "num"
+;
+]])
+
+AT_BISON_CHECK([-Wprecedence input.y], 0, [],
+[[input.y:2.1-9: warning: useless precedence and associativity for "=" [-Wprecedence]
+input.y:4.1-5: warning: useless associativity for "*", use %precedence [-Wprecedence]
+input.y:5.1-11: warning: useless precedence for "(" [-Wprecedence]
+]])
+
+AT_CLEANUP
+
+
+## ---------------------------- ##
+## Useless precedence warning. ##
+## ---------------------------- ##
+
+AT_SETUP([Useless precedence warning])
+
+AT_DATA([[input.y]],
+[[%token A B U V W X Y Z
+%precedence Z
+%left X
+%precedence Y
+%left W
+%right V
+%nonassoc U
+%%
+a: b
+ | a U b
+ | f
+;
+b: c
+ | b V c
+;
+c: d
+ | c W d
+;
+d: A
+ | d X d
+ | d Y A
+;
+f: B
+ | f Z B
+;
+]])
+
+AT_BISON_CHECK([-Wprecedence -fcaret -o input.c input.y], 0, [],
+[[input.y:7.1-9: warning: useless precedence and associativity for U [-Wprecedence]
+ %nonassoc U
+ ^^^^^^^^^
+input.y:6.1-6: warning: useless precedence and associativity for V [-Wprecedence]
+ %right V
+ ^^^^^^
+input.y:5.1-5: warning: useless precedence and associativity for W [-Wprecedence]
+ %left W
+ ^^^^^
+input.y:2.1-11: warning: useless precedence for Z [-Wprecedence]
+ %precedence Z
+ ^^^^^^^^^^^
+]])
+
+AT_CLEANUP
+
## ---------------- ##
## S/R in initial. ##
]])
AT_BISON_CHECK([-o input.c input.y], 0, [],
-[[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ [-Wother]
+[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
+]])
+
+AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
+[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
+ e: 'e' | /* Nothing. */;
+ ^
]])
AT_CLEANUP
# We must disable default reductions in inconsistent states in order to
# have an explicit list of all expected tokens.
-AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reductions=consistent]],
+AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reduction=consistent]],
[[correct]])
-# lr.default-reductions=consistent happens to work for this test case.
+# lr.default-reduction=consistent happens to work for this test case.
# However, for other grammars, lookahead sets can be merged for
# different left contexts, so it is still possible to have an incorrect
# expected list. Canonical LR is almost a general solution (that is, it
## parse.error=verbose and consistent errors. ##
## ------------------------------------------- ##
-AT_SETUP([[parse.error=verbose and consistent errors]])
-
m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
+AT_SETUP([[parse.error=verbose and consistent errors: $1]])
+
AT_BISON_OPTION_PUSHDEFS([$1])
m4_pushdef([AT_YYLEX_PROTOTYPE],
/*-------.
| main. |
-`-------*/]AT_SKEL_JAVA_IF([[
-
-class input
-{
- public static void main (String args[]) throws IOException
- {
- YYParser p = new YYParser ();
- p.parse ();
- }
-}]], [AT_SKEL_CC_IF([[
-
-int
-main (void)
-{
- yy::parser parser;
- return parser.parse ();
-}]], [[
-
-int
-main (void)
-{
- return yyparse ();
-}]])])[
-]])
+`-------*/
+]AT_MAIN_DEFINE
+])
AT_FULL_COMPILE([[input]])
m4_popdef([AT_YYLEX_PROTOTYPE])
AT_BISON_OPTION_POPDEFS
-])
+AT_CLEANUP
+]) dnl AT_CONSISTENT_ERRORS_CHECK
+
+
+
m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR],
[[%nonassoc 'a';
# Even canonical LR doesn't foresee the error for 'a'!
AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
- %define lr.default-reductions consistent]],
+ %define lr.default-reduction consistent]],
[AT_PREVIOUS_STATE_GRAMMAR],
[AT_PREVIOUS_STATE_INPUT],
[[$end]], [[ab]])
AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
- %define lr.default-reductions accepting]],
+ %define lr.default-reduction accepting]],
[AT_PREVIOUS_STATE_GRAMMAR],
[AT_PREVIOUS_STATE_INPUT],
[[$end]], [[ab]])
[['b']], [[none]])
# No C++ or Java test because yychar cannot be manipulated by users.
-AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]],
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction consistent]],
[AT_USER_ACTION_GRAMMAR],
[AT_USER_ACTION_INPUT],
[['b']], [[none]])
# Canonical LR doesn't foresee the error for 'a'!
-AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions accepting]],
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction accepting]],
[AT_USER_ACTION_GRAMMAR],
[AT_USER_ACTION_INPUT],
[[$end]], [[a]])
[AT_USER_ACTION_INPUT],
[['b']], [[none]])
AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full
- %define lr.default-reductions accepting]],
+ %define lr.default-reduction accepting]],
[AT_USER_ACTION_GRAMMAR],
[AT_USER_ACTION_INPUT],
[[$end]], [[none]])
m4_popdef([AT_CONSISTENT_ERRORS_CHECK])
-AT_CLEANUP
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["aaa"])[
-
-int
-main (void)
-{
- return yyparse ();
-}
-]])
+]AT_MAIN_DEFINE
+])
AT_BISON_OPTION_POPDEFS
# Show canonical LR's failure.
on left: 1 2, on right: 0 1
-state 0
+State 0
0 $accept: . exp $end
1 exp: . exp OP exp
exp go to state 2
-state 1
+State 1
2 exp: NUM .
$default reduce using rule 2 (exp)
-state 2
+State 2
0 $accept: exp . $end
1 exp: exp . OP exp
OP shift, and go to state 4
-state 3
+State 3
0 $accept: exp $end .
$default accept
-state 4
+State 4
1 exp: . exp OP exp
1 | exp OP . exp
exp go to state 5
-state 5
+State 5
1 exp: exp . OP exp
1 | exp OP exp . [$end, OP]
on left: 1 2, on right: 0 1
-state 0
+State 0
0 $accept: . exp $end
1 exp: . exp OP exp
exp go to state 2
-state 1
+State 1
2 exp: NUM .
$default reduce using rule 2 (exp)
-state 2
+State 2
0 $accept: exp . $end
1 exp: exp . OP exp
OP shift, and go to state 4
-state 3
+State 3
0 $accept: exp $end .
$default accept
-state 4
+State 4
1 exp: . exp OP exp
1 | exp OP . exp
exp go to state 5
-state 5
+State 5
1 exp: exp . OP exp
1 | exp OP exp . [$end, OP]
AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
-input.y:12.3-18: warning: rule useless in parser due to conflicts: cond: cond "then" cond [-Wother]
+input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother]
]])
AT_CLEANUP
# $end reduce using rule 3 (num)
# $end [reduce using rule 4 (id)]
#
-# But when `reduce 3' is the default action, we'd produce:
+# But when 'reduce 3' is the default action, we'd produce:
#
# $end [reduce using rule 4 (id)]
# $default reduce using rule 3 (num)
#
# In this precise case (a reduction is masked by the default
-# reduction), we make the `reduce 3' explicit:
+# reduction), we make the 'reduce 3' explicit:
#
# $end reduce using rule 3 (num)
# $end [reduce using rule 4 (id)]
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
-input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' [-Wother]
+input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother]
]])
# Check the contents of the report.
on left: 4, on right: 2
-state 0
+State 0
0 $accept: . exp $end
1 exp: . num
id go to state 4
-state 1
+State 1
3 num: '0' . [$end]
4 id: '0' . [$end]
$default reduce using rule 3 (num)
-state 2
+State 2
0 $accept: exp . $end
$end shift, and go to state 5
-state 3
+State 3
1 exp: num .
$default reduce using rule 1 (exp)
-state 4
+State 4
2 exp: id .
$default reduce using rule 2 (exp)
-state 5
+State 5
0 $accept: exp $end .
;
]])
-AT_BISON_CHECK([-o input.c input.y], 0, [],
+AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
+input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence]
+input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence]
]])
AT_CLEANUP
AT_BISON_CHECK([[--report=all input.y]], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
-input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 [-Wother]
-input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 [-Wother]
-input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
-input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
-input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
-input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
-input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
+input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother]
+input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother]
+input.y:21.4: warning: rule useless in parser due to conflicts [-Wother]
+input.y:25.13: warning: rule useless in parser due to conflicts [-Wother]
+input.y:25.16: warning: rule useless in parser due to conflicts [-Wother]
+input.y:31.5-7: warning: rule useless in parser due to conflicts [-Wother]
+input.y:32.4: warning: rule useless in parser due to conflicts [-Wother]
]])
AT_CHECK([[cat input.output]], 0,
2 resolved_conflict: 'a' unreachable1
4 unreachable1: 'a' unreachable2
- 5 | /* empty */
+ 5 | %empty
- 6 unreachable2: /* empty */
- 7 | /* empty */
+ 6 unreachable2: %empty
+ 7 | %empty
9 reported_conflicts: 'a'
- 10 | /* empty */
+ 10 | %empty
State 4 conflicts: 1 shift/reduce
1 start: resolved_conflict 'a' reported_conflicts 'a'
2 resolved_conflict: 'a' unreachable1
- 3 | /* empty */
+ 3 | %empty
4 unreachable1: 'a' unreachable2
- 5 | /* empty */
+ 5 | %empty
- 6 unreachable2: /* empty */
- 7 | /* empty */
+ 6 unreachable2: %empty
+ 7 | %empty
8 reported_conflicts: 'a'
9 | 'a'
- 10 | /* empty */
+ 10 | %empty
Terminals, with rules where they appear
on left: 8 9 10, on right: 1
-state 0
+State 0
0 $accept: . start $end
1 start: . resolved_conflict 'a' reported_conflicts 'a'
2 resolved_conflict: . 'a' unreachable1
- 3 | . ['a']
+ 3 | . %empty ['a']
$default reduce using rule 3 (resolved_conflict)
Conflict between rule 3 and token 'a' resolved as reduce (%left 'a').
-state 1
+State 1
0 $accept: start . $end
$end shift, and go to state 3
-state 2
+State 2
1 start: resolved_conflict . 'a' reported_conflicts 'a'
'a' shift, and go to state 4
-state 3
+State 3
0 $accept: start $end .
$default accept
-state 4
+State 4
1 start: resolved_conflict 'a' . reported_conflicts 'a'
8 reported_conflicts: . 'a'
9 | . 'a'
- 10 | . ['a']
+ 10 | . %empty ['a']
'a' shift, and go to state 5
reported_conflicts go to state 6
-state 5
+State 5
8 reported_conflicts: 'a' . ['a']
9 | 'a' . ['a']
$default reduce using rule 8 (reported_conflicts)
-state 6
+State 6
1 start: resolved_conflict 'a' reported_conflicts . 'a'
'a' shift, and go to state 7
-state 7
+State 7
1 start: resolved_conflict 'a' reported_conflicts 'a' .
]])
AT_DATA([[input-keep.y]],
-[[%define lr.keep-unreachable-states
+[[%define lr.keep-unreachable-state
]])
AT_CHECK([[cat input.y >> input-keep.y]])
AT_BISON_CHECK([[input-keep.y]], 0, [],
[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
-input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
-input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
-input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
-input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
+input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:33.4: warning: rule useless in parser due to conflicts [-Wother]
]])
AT_CLEANUP
empty_c3: %prec 'd' ;
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
-AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
-[[state 0
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
0 $accept: . start $end
1 start: . 'a'
6 | . empty_c1 'c'
7 | . empty_c2 'c'
8 | . empty_c3 'c'
- 9 empty_a: . ['a']
- 10 empty_b: . []
- 11 empty_c1: . []
- 12 empty_c2: . []
- 13 empty_c3: . ['c']
+ 9 empty_a: . %empty ['a']
+ 10 empty_b: . %empty []
+ 11 empty_c1: . %empty []
+ 12 empty_c2: . %empty []
+ 13 empty_c3: . %empty ['c']
'b' shift, and go to state 1
Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd').
-state 1
+State 1
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
-AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0,
-[[state 0
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
0 $accept: . start $end
1 start: . 'a'
6 | . empty_c1 'c'
7 | . empty_c2 'c'
8 | . empty_c3 'c'
- 9 empty_a: . []
- 10 empty_b: . []
- 11 empty_c1: . []
- 12 empty_c2: . ['c']
- 13 empty_c3: . ['c']
+ 9 empty_a: . %empty []
+ 10 empty_b: . %empty []
+ 11 empty_c1: . %empty []
+ 12 empty_c2: . %empty ['c']
+ 13 empty_c3: . %empty ['c']
'a' error (nonassociative)
'b' error (nonassociative)
Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c').
-state 1
+State 1
]])
AT_CLEANUP
AT_BISON_CHECK([[2.y]], [[0]], [],
[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
-2.y:3.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
+2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother]
]])
AT_CLEANUP