2010-01-15 35 views
3

我一直在为我的个人娱乐开发类C语法。但是,我已经遇到了转变/减少冲突,我很确定他们可以得到解决。在Bison下移动/减少与类C语法的冲突

现在我expressions这个样子的,一个简单的形式,剥离的动作:

%left '+' '-' 

%% 
expr 
: NUMBER 
| IDENTIFIER 
| expr '+' expr 
| expr '-' expr 
/* other operators like '*', '/', etc. */ 
| expr '(' expr ')' /* function call */ 
%% 

然而,这导致移进/归约冲突:解析器是不知道如何对待括号。从-v告诉我,目前还不清楚像expr '+' expr '('这样的表达式是否应该将expr '+' expr减少为expr或者移动括号。

显然,我想括号被移位。 foo % bar(4)最终不应该是(foo % bar)(4)。但是,我没有成功使用%prec指令。在规则没有变化后添加%left FUNCALL%prec FUNCALL

我知道默认路径Bison的LALR解析器会遇到shift/reduce会移动,并且我可以使用%expect 修复 解决此问题。但是,每个表达式都会产生一个冲突,我需要更改该列表,我还需要更改%expect声明,这对我来说看起来是一个相当难看的解决方案。此外,我相信你们中的一位聪明的孩子能够解决这个问题。

我的目标是制定一个类似于上面的规则,为此,Bison会知道,只要遇到来自函数调用规则的'(',它就会移动括号,而没有可能的移位/减少冲突。为了记录,我使用%prec指令如下,所以如果我只是做错了,你可以纠正我。它确实有转变/减少的冲突。

%left '+' '-' 
%left FUNCALL 

%% 

expr 
    : NUMBER 
    | IDENTIFIER 
    | expr '+' expr 
    | expr '-' expr 
    /* other operators like '*', '/', etc. */ 
    | expr '(' expr ')' %prec FUNCALL /* function call */ 

%% 

回答

4

您需要添加%left '('到您的优先规则(或%nonassoc '('可能会更好)。

是优先工程,以解决移/降低yacc的冲突方式/野牛是它的规则的优先级比较与令牌的优先级要移位减少。在你的榜样,冲突是减少expr: expr '+' expr和移位'('之间,所以要解决这个问题,你需要'('一个优先级(你希望它是不是规则,它来源于'+'更高)

%prec指令只是设置了规则的优先级,覆盖了它的rhs上第一个标记的默认优先级。它不会以任何方式影响规则中出现的标记的优先级。

+0

哦,我明白了。我无法真正负担'%nonassoc'(''因为除非我错过别的东西,否则它会完全破坏嵌套的括号,但是我明白你的意思,谢谢。 – zneak 2010-01-15 00:57:13

+1

嵌套parens不应该涉及任何冲突,所以'%nonassoc '不应该是一个问题 - 优先规则只是为了解决冲突问题 – 2010-01-15 19:25:49