2017-02-16 180 views
1

我正在經歷在Appel的「ML中的現代編譯器實現」一書中生成Tiger Parser的Ch3編程練習。我的tiger.grm文件是here。我試圖診斷的錯誤是由一元和二元減算子的規則引起的減少 - 減少衝突。這裏是YACC錯誤:ML-Yacc Tiger Parser減少/減少錯誤

error: state 128: reduce/reduce conflict between rule 48 and rule 46 on OR 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on AND 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on GE 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on GT 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on LE 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on LT 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on NEQ 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on EQ 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on DIVIDE 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on TIMES 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on MINUS 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on PLUS 
error: state 128: reduce/reduce conflict between rule 48 and rule 46 on RPAREN 

state 128: 

    boolean : exp . AND exp 
    boolean : exp . OR exp 
    arithmetic : MINUS exp . (reduce by rule 46) 
    arithmetic : exp . PLUS exp 
    arithmetic : exp . MINUS exp 
    arithmetic : exp MINUS exp . (reduce by rule 48) 
    arithmetic : exp . DIVIDE exp 
    arithmetic : exp . TIMES exp 
    comparison : exp . EQ exp 
    comparison : exp . NEQ exp 
    comparison : exp . GT exp 
    comparison : exp . LT exp 
    comparison : exp . LE exp 
    comparison : exp . GE exp 

我已經定義與UNARY低於零下更高的優先級,並且在使用%prec我的規則明確設置它。當然,當我刪除任一規則時,衝突消失,但語法會錯誤地解析MINUS標誌。

我無法診斷此錯誤 - 任何想法?

回答

3

瘋狂的猜測:你的規則之一可能允許exp爲空嗎?如果是這樣,那麼這會在exp是可選的任何地方產生歧義 - 例如在- exp之前。

2

作爲接受的答案(他/她是對的)的後續 - 在序列的生產中出現了一個錯誤,允許exp轉到epsilon

這裏是問題的代碼位(見最後一行):

sequence : LPAREN exp_sequence RPAREN() 
exp_sequence : (*epsilon*)() 
     | exp seq () 

seq : (*epsilon*)    () (*an exp sequence can be empty*) 
    | SEMICOLON exp exp_sequence() (*exps separated by semicolon*) 

這裏是校正後的代碼:

sequence : LPAREN exp_sequence RPAREN() 
exp_sequence : (*epsilon*)() 
      | exp seq () 

seq : (*epsilon*)    () (*an exp sequence can be empty*) 
    | SEMICOLON exp seq() (*exps separated by semicolon*)