解析器 - Shift/reduce 冲突

Parser - Shift/reduce conflict

我的解析器有问题,这让我发疯,想知道你们是否能帮助我。

我有这套规则:

exp:        exp OP exp
    |       exp OSQUAREPAR exp CSQUAREPAR
    |       exp DOT LENGTH
    |       exp DOT ID OPAR expList CPAR
    |       READERS DOT INTREADER DOT READINT OPAR CPAR
    |       DIGIT
    |       TRUE
    |       FALSE
    |       ID
    |       THIS
    |       NEW INT OSQUAREPAR exp CSQUAREPAR 
    |       NEW ID OPAR CPAR
    |       EXCL exp    
    |       OPAR exp CPAR   
    ;

与以下冲突:

rule 28 exp -> exp OP exp

rule 29 exp -> exp OSQUAREPAR exp CSQUAREPAR

rule 30 exp -> exp DOT LENGTH

rule 31 exp -> exp DOT ID OPAR expList CPAR

rule 32 exp -> READERS DOT INTREADER DOT READINT OPAR CPAR

rule 33 exp -> DIGIT

rule 34 exp -> TRUE

rule 35 exp -> FALSE

rule 36 exp -> ID

rule 37 exp -> THIS

rule 38 exp -> NEW INT OSQUAREPAR exp CSQUAREPAR

rule 39 exp -> NEW ID OPAR CPAR

rule 40 exp -> EXCL exp

rule 41 exp -> OPAR exp CPAR

state 94

exp  ->  EXCL exp .   (rule 37)
exp2  ->  exp . OP exp   (rule 39)
exp2  ->  exp . OSQUAREPAR exp CSQUAREPAR   (rule 40)
exp2  ->  exp . DOT LENGTH   (rule 41)
exp2  ->  exp . DOT ID OPAR expList CPAR   (rule 42)

OSQUAREPAR    shift, and go to state 97
DOT   shift, and go to state 98
OP    shift, and go to state 99

OSQUAREPAR    [reduce using rule 37 (exp)]
DOT   [reduce using rule 37 (exp)]
OP    [reduce using rule 37 (exp)]
$default  reduce using rule 37 (exp)

关于如何解决这个问题的任何想法?我已经检查了其他类似的问题,甚至尝试像其中一个答案所示那样向 EXCL 添加优先级,但无法解决这个问题。

谢谢。

一个可能的方法示例(无冲突):

%token DIGIT FALSE ID INT INTREADER LENGTH NEW READERS READINT THIS TRUE

%left  '+' '-'
%left  '*' '/'
%left  UNARY

%%

exp:       unary
   |       exp '+' exp
   |       exp '-' exp
   |       exp '*' exp
   |       exp '/' exp
   ;

expList:    exp
       |    expList ',' exp
       ;

operand:    '(' exp ')'
       |    DIGIT
       |    TRUE
       |    FALSE
       |    ID
       |    THIS
       |    READERS '.' INTREADER '.' READINT '(' ')'
       |    NEW INT '[' exp ']' 
       |    NEW ID '(' ')'
       ;

primary:    operand
       |    primary '[' exp ']'
       |    primary '.' LENGTH
       |    primary '.' ID '(' expList ')'
       ;

unary:      primary
     |      '!' unary
     |      '+' unary
     |      '-' unary %prec UNARY
     ;