问题
This grammar has given me conflict despite specifying precedence of operators. Even in the Dragon book it's been resolved in such a way(the way implemented as first 7 lines below) but it still gets conflict! Below is the code implemented in yacc
%right THEN_KW
%right ELSE_KW
%left XOR_KW OR_KW
%right '='
%left AND_KW ALSO_KW
%left EQ_KW LT_KW GT_KW LE_KW GE_KW
%left PLUS_KW MINUS_KW
%left MULT_KW DIV_KW MOD_KW
%right NOT_KW
arthlogicexpr -> operand | arthlogicexpr arthop arthlogicexpr
arthop -> '+' | '-' | '*' | '/' |'%'
operand -> variable
variable -> IDENTIFIER
erro in parser.output is :
state 141
78 arthlogicexpr: arthlogicexpr . arthop arthlogicexpr
78 | arthlogicexpr arthop arthlogicexpr .
'+' shift, and go to state 103
'-' shift, and go to state 104
'*' shift, and go to state 105
'/' shift, and go to state 106
'%' shift, and go to state 107
'+' [reduce using rule 78 (arthlogicexpr)]
'-' [reduce using rule 78 (arthlogicexpr)]
'*' [reduce using rule 78 (arthlogicexpr)]
'/' [reduce using rule 78 (arthlogicexpr)]
'%' [reduce using rule 78 (arthlogicexpr)]
$default reduce using rule 78 (arthlogicexpr)
arthop go to state 109
more info about other states :
state 103
79 arthop: '+' .
$default reduce using rule 79 (arthop)
state 104
80 arthop: '-' .
$default reduce using rule 80 (arthop)
state 105
81 arthop: '*' .
$default reduce using rule 81 (arthop)
state 106
82 arthop: '/' .
$default reduce using rule 82 (arthop)
state 107
83 arthop: '%' .
$default reduce using rule 83 (arthop)
回答1:
Because of the way the conflict resolution is performed, you cannot factor the operators as you just did. Because you are going to specify precedences between rules and tokens, you need to tell the difference between rules that must not be treated the same way. And you do not want to treat exp: exp "+" exp
as equivalent to exp: exp "*" exp
.
So keep four rules, one for each operator.
If you really want to factor something you could define one rule per precedence level, but that's going to be more complex for no real added value IMHO.
A proper tool should tell you that your precedence directives (%right
, etc.) are useless here. That's an hint the conflict resolution cannot use them (because of the way you wrote the grammar). I venture Bison would warn.
You should also have a look there:
- Why doesn't %prec have an effect in this bison grammar?
- Bison Shift/reduce error for C-like language
回答2:
If you want to avoid the warning you need to either specify operator associativity or you need to structure the grammar so that "arthlogicexpr" is not on both sides of the operator.
Given the input
a + b - c
your grammar is ambiguous as to whether that means
arthlogicexpr (arthlogicexpr (a, +, b), -, c)
or arthlogicexpr (a, +, arthlogicexpr (b, -, c))
来源:https://stackoverflow.com/questions/47433547/shift-reduce-conflict-for-arithmetic-expressions-in-yacc