2

(削減された) Pascal から ARM asm にコンパイラを作成しています。私はプロセスの 2 番目のステップにいます。語彙アナライザーを作成した後、Java cupを使用した構文解析に取り組んでいます。

私は自分の文法を書きましたが、5 つの S/R 競合が発生しました。これらはすべて非常に似ています。例:

   Warning : *** Shift/Reduce conflict found in state #150
between assign_stmt ::= val_expr ASSIGN val_expr (*) 
  and     val_expr ::= val_expr (*) LBRACKET val_expr RBRACKET 
  under symbol LBRACKET
  Resolved in favor of shifting

このセクションの文法:

assign_stmt ::=
 val_expr ASSIGN val_expr;

val_expr ::=
     NIL | BOOL_CONST | INT_CONST | CHAR_CONST | PTR val_expr %prec MEM | ADD val_expr %prec UADD |
     SUB val_expr %prec USUB | NOT val_expr | val_expr PTR %prec VAL | val_expr MUL val_expr |
     val_expr DIV val_expr | val_expr ADD val_expr | val_expr SUB val_expr | val_expr EQU val_expr |
     val_expr NEQ val_expr | val_expr LTH val_expr | val_expr GTH val_expr | val_expr LEQ val_expr |
     val_expr GEQ val_expr | val_expr AND val_expr | val_expr OR val_expr | IDENTIFIER | 
     val_expr LBRACKET val_expr RBRACKET | val_expr DOT IDENTIFIER | IDENTIFIER LPARENTHESIS params_list RPARENTHESIS |
     LBRACKET type_desc RBRACKET | LPARENTHESIS val_expr RPARENTHESIS
    ;

どうすればこの競合を解消できますか?

ありがとう。

4

1 に答える 1

5

あなたの文法はあいまいで、右再帰と左再帰の両方があります。パーサーに関する私の (限られた) 知識から、これはほとんどのパーサー ジェネレーターでは解析できないことがわかっています。

val_expr ADD val_expr SUB val_expr次のように解析できるため、あいまいです。

       ADD
      /   \
val_expr  SUB
         /   \
   val_expr  val_expr

        SUB
       /   \
     ADD  val_expr
    /   \
val_expr  val_expr

Java CUP を使用したことはありませんが、別のパーサー ジェネレーターを使用して同様のことを行った方法を次に示します。

val_expr ::=
    expr1 (SUB | ADD | <add all your operators here>) val_expr
    | expr1 ;

expr1 ::=
    NIL | BOOL_CONST | INT_CONST | CHAR_CONST | <etc> ;

これにより、文法が明確になり、右再帰のみになります。これは、私が知っているすべてのパーサー ジェネレーターで処理できます。

この文法のマイナス面は、優先順位がないことですが、Java CUP にはおそらく優先順位を指定する別の方法があります。

編集: 最初の文法規則を修正しました。

于 2010-10-16T15:10:16.857 に答える