2010-01-15 86 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