为什么我的三元运算符导致转换减少冲突?

时间:2013-07-28 03:28:16

标签: parsing compiler-construction grammar shift-reduce-conflict

以下是我的语法:

arithmetic_expression : expression + expression
                      | expression - expression

expression            : constant
                      | ID
                      | arithmetic_expression
                      | ternary

ternary               : expression ? expression : expression

我在这种状态下收到shift-reduce错误:

state 126

    (19) ternary -> expression QUESTION_MARK expression COLON expression .
    (27) arithmetic_exp -> expression . PLUS expression
    (28) arithmetic_exp -> expression . MINUS expression
    (19) ternary -> expression . QUESTION_MARK expression COLON expression

  ! shift/reduce conflict for PLUS resolved as shift
  ! shift/reduce conflict for MINUS resolved as shift
  ! shift/reduce conflict for QUESTION_MARK resolved as shift

    PLUS            shift and go to state 86
    MINUS           shift and go to state 88
    QUESTION_MARK   shift and go to state 85

  ! PLUS            [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]
  ! MINUS           [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]
  ! QUESTION_MARK   [ reduce using rule 19 (ternary -> expression QUESTION_MARK expression COLON expression .) ]

我认为冲突就是那个

true ? 1 : false ? 3 : 2

可以解释为true ? 1 : (false ? 3 : 2)(true ? 1 : false) ? 3 : 2

我已将+的优先级设置为-,将?设置为左关联,并将{{1}}设置为更高级别(我设置为右关联)。

我做错了什么?

2 个答案:

答案 0 :(得分:3)

如果我理解正确,您会执行以下操作:

%left '+' '-'
%right '?'

%%

arithmetic_expression : expression + expression
                      | expression - expression
                      ;
ternary               : expression ? expression : expression
                      ;

那是行不通的,因为你没有告诉野牛ternary制作的优先顺序是什么。

为了解决shift-reduce冲突,bison将可能减少的生产优先级与可能被移位的终端的优先级进行比较。您已声明终端'+',' - '和'?'的优先级,以及arithmetic_expression中两个产品的优先级,但不是ternary中产品的优先级。

引用野牛手册,重点补充:

  

每个规则都优先于组件中提到的 last 终端符号。

这非常微妙,你不会是第一个没有注意到的人。

解决方案:要么声明终端:的优先级,要么将%prec '?'添加到ternary中的作品中。

答案 1 :(得分:1)

Exaclty - 您没有指定关联性。

在C语言中,语法说:

conditional_expression = logical_or_expression [ '?' expression ':' conditional_expression ];

所以我相信你想要像

这样的东西
conditional_expression = arithmetic_expression [ '?' expression ':' conditional_expression ];

如果你想要一个类似C的行为(以及正确的关联性,以及其他属性)。