解决减少-减少冲突
Resolving reduce-reduce conflict
语法问题部分:
expr_var: var_or_ID
| expr_var '[' expr ']'
| NEW expr_var '(' expr_listE ')'
| expr_var '(' expr_listE ')'
| expr_var ARROW expr_var
| expr_var ARROW '{' expr_var '}'
| expr_var DCOLON expr_var
| expr_var DCOLON '{' expr_var '}'
| '(' expr_var ')'
;
问题描述:
expr_var -> NEW expr_var '(' expr_listE ')' . (rule 87)
expr_var -> expr_var '(' expr_listE ')' . (rule 88)
DCOLON reduce using rule 87 (expr_var)
DCOLON [reduce using rule 88 (expr_var)]
ARROW reduce using rule 87 (expr_var)
ARROW [reduce using rule 88 (expr_var)]
'[' reduce using rule 87 (expr_var)
'[' [reduce using rule 88 (expr_var)]
'(' reduce using rule 87 (expr_var)
'(' [reduce using rule 88 (expr_var)]
$default reduce using rule 87 (expr_var)
每个运算符(ARROW、DCOLON...)都是左结合的。运算符 NEW 是非关联的。
我该如何解决这个冲突?
这里的问题是:
new foo(1)(2)
这可以用两种方式解析:
(new foo(1))(2) // call the new object
new (foo(1))(2) // function returns class to construct
其中哪些(如果有的话)在语义上是可行的取决于您的语言。当然可以想象,两者都是有意义的。语法不提供任何有关语义的提示。
因此您有必要决定其中哪一个(如果有的话)是预期的解析,并相应地设计语法。
优先级声明无济于事,因为优先级仅用于解决 shift/reduce 冲突:优先级关系始终存在于产生式和先行标记之间,永远不会存在于两个产生式之间。
Bison 将解决 reduced/reduce 有利于第一个产品的冲突,就像在本例中所做的那样。因此,如果语法是合法且明确的,那么您可以 select 通过在必要时重新排序产生式来进行所需的解析。这会给你留下警告,但你可以用 %expect-rr
声明来抑制它。
您还可以通过显式修改语法以排除 new
表达式作为调用中的第一个参数来抑制一个或另一个解析(或两者) and/or 排除调用作为第一个参数new
的参数,通过 expr_var
.
的显式子集
语法问题部分:
expr_var: var_or_ID
| expr_var '[' expr ']'
| NEW expr_var '(' expr_listE ')'
| expr_var '(' expr_listE ')'
| expr_var ARROW expr_var
| expr_var ARROW '{' expr_var '}'
| expr_var DCOLON expr_var
| expr_var DCOLON '{' expr_var '}'
| '(' expr_var ')'
;
问题描述:
expr_var -> NEW expr_var '(' expr_listE ')' . (rule 87)
expr_var -> expr_var '(' expr_listE ')' . (rule 88)
DCOLON reduce using rule 87 (expr_var)
DCOLON [reduce using rule 88 (expr_var)]
ARROW reduce using rule 87 (expr_var)
ARROW [reduce using rule 88 (expr_var)]
'[' reduce using rule 87 (expr_var)
'[' [reduce using rule 88 (expr_var)]
'(' reduce using rule 87 (expr_var)
'(' [reduce using rule 88 (expr_var)]
$default reduce using rule 87 (expr_var)
每个运算符(ARROW、DCOLON...)都是左结合的。运算符 NEW 是非关联的。
我该如何解决这个冲突?
这里的问题是:
new foo(1)(2)
这可以用两种方式解析:
(new foo(1))(2) // call the new object
new (foo(1))(2) // function returns class to construct
其中哪些(如果有的话)在语义上是可行的取决于您的语言。当然可以想象,两者都是有意义的。语法不提供任何有关语义的提示。
因此您有必要决定其中哪一个(如果有的话)是预期的解析,并相应地设计语法。
优先级声明无济于事,因为优先级仅用于解决 shift/reduce 冲突:优先级关系始终存在于产生式和先行标记之间,永远不会存在于两个产生式之间。
Bison 将解决 reduced/reduce 有利于第一个产品的冲突,就像在本例中所做的那样。因此,如果语法是合法且明确的,那么您可以 select 通过在必要时重新排序产生式来进行所需的解析。这会给你留下警告,但你可以用 %expect-rr
声明来抑制它。
您还可以通过显式修改语法以排除 new
表达式作为调用中的第一个参数来抑制一个或另一个解析(或两者) and/or 排除调用作为第一个参数new
的参数,通过 expr_var
.