解决减少 - 减少冲突

时间:2017-04-21 10:00:49

标签: parsing bison yacc 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是非关联的。

我该如何解决这个冲突?

1 个答案:

答案 0 :(得分:1)

这里的问题是:

中的含糊不清
new foo(1)(2)

这可以通过两种方式解析:

(new foo(1))(2) // call the new object
new (foo(1))(2) // function returns class to construct

这些(如果有的话)在语义上可行取决于您的语言。当然可以想象两者都是有意义的。语法没有提供任何关于语义的提示。

因此,您有必要决定哪些(如果有的话)是预期的解析,并相应地制定语法。

优先级声明无济于事,因为优先级仅用于解决shift / reduce冲突:优先级关系始终位于生产和前瞻标记之间,绝不会在两个生产之间。

Bison将解决缩减/减少冲突,支持第一次制作,就像在这种情况下所做的那样。因此,如果语法合法且明确,那么您可以通过在必要时重新排序产品来选择所需的解析。这会给你留下警告,但你可以用%expect-rr声明来压制它。

您还可以通过显式修改语法来禁止一个或另一个解析(或两者),以排除new表达式作为调用中的第一个参数和/或排除调用作为{的第一个参数{1}},通过new的明确子集。