ML-Yacc Tiger Parser减少/减少错误

时间:2017-02-16 03:02:33

标签: parsing compiler-construction sml tiger ml-yacc

我正在进行Ch3编程练习,在Appel"现代编译器实现ML"中生成Tiger Parser。书。我的tiger.grm文件是here。我试图诊断的错误是由一元和二元减运算符的规则引起的减少 - 减少冲突。这是yacc错误:

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定义为优先于MINUS,并使用%prec在我的规则中明确设置。当然,当我删除任一规则时,冲突消失,但语法将错误地解析MINUS标志。

我无法诊断此错误 - 有任何想法吗?

2 个答案:

答案 0 :(得分:3)

狂野猜测:您的某个规则是否允许exp为空?如果是这样,则会在exp可选的任何地方产生歧义 - 例如在- exp之前。

答案 1 :(得分: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*)