1

C の文法を書こうとしていますが、よくわからない問題が発生しています。文法の関連部分:

stmt :
  types decl SEMI                { marks (A.Declare ($1, $2)) (1, 2) }
 | simp SEMI                     { marks $1 (1, 1) }
 | RETURN exp SEMI               { marks (A.Return $2) (1, 2) }
 | control                       { $1 } 
 | block                         { marks $1 (1, 1) }
 ;

 control :
   if                                                    { $1 }
  | WHILE RPAREN exp LPAREN stmt                         { marks (A.While ($3, $5)) (1, 5) }
  | FOR LPAREN simpopt SEMI exp SEMI simpopt RPAREN stmt { marks (A.For ($3, $5, $7, $9)) (1, 9) }
  ;

  if :
    IF RPAREN exp LPAREN stmt                                { marks (A.If ($3, $5, None)) (1, 5) }
  | IF RPAREN exp LPAREN stmt ELSE stmt                      { marks (A.If ($3, $5, $7)) (1, 7) }
  ;

これはうまくいきません。ocamlyacc -v を実行したところ、次のレポートが得られました。

83: shift/reduce conflict (shift 86, reduce 14) on ELSE
state 83
    if : IF RPAREN exp LPAREN stmt .  (14)
    if : IF RPAREN exp LPAREN stmt . ELSE stmt  (15)

    ELSE  shift 86
    IF  reduce 14
    WHILE  reduce 14
    FOR  reduce 14
    BOOL  reduce 14
    IDENT  reduce 14
    RETURN  reduce 14
    INT  reduce 14
    MAIN  reduce 14
    LBRACE  reduce 14
    RBRACE  reduce 14
    LPAREN  reduce 14

シフト/リデュースの競合は文法の仕様のあいまいさが原因であると読みましたが、あいまいではない方法でこれを指定する方法がわかりませんか?

4

1 に答える 1