0

私は bison を使用して C でパーサーを作成しています。これまでに試したすべての状況で正しく動作するように見えますが、2 項演算子 (単項 NOT 演算子の場合は 1 つ) で多数のシフト/リデュース警告が表示されます。良い)。

binary_op :
      PLUS { }
      | MINUS { }
      | TIMES { }
      | SLASH { }
      | POWER { }
      | AND { }
      | OR { }
      | LE { }
      | LT { }
      | GE { }
      | GT { }
      | EQ { }
      | NE { }
      | MOD { }
    ;

unary_op :
    NOT { }
    ;

expr :
    ...
    | unary_op expr { }
    | expr binary_op expr { }

bison --verbose を使用して .y ファイルを実行すると、次のように表示されます。

state 51
   11 set_existence: expr . IN set
   12              | expr . NOT IN set
   34 expr: expr . binary_op expr
   34     | expr binary_op expr .

   ...
   NOT    shift, and go to state 26
   AND    shift, and go to state 27
   OR     shift, and go to state 28
   ....
   NOT     [reduce using rule 34 (expr)]
   AND     [reduce using rule 34 (expr)]
   OR      [reduce using rule 34 (expr)]

二項演算子を実際に解析する問題は見られませんが、とにかくシフト/削減の問題を解決する必要があるようです。競合がどこにあるのかわかりません - set_existence プロダクションは完全に無関係のようです。私の最善の推測 (暗闇でのショット) は、EQ が二項演算子 (等価比較) および代入 (たとえば、"foo = bar = baz;" が設定される) として使用されるという事実と関係がある可能性があるということです。 bar と baz が等しいかどうかに基づいて、foo を true/false に変換します)。等価比較を == ("foo = bar==baz;") に変更すると、パーサーは期待どおりに動作しますが、同じシフト/削減の競合が発生します。

編集:結合性が指定されています:

%left OR
%left AND
%left NOT
%left LT LE GT GE NE EQ
%left PLUS MINUS
%left TIMES MOD SLASH
%left POWER
4

1 に答える 1

2

これを回避するには、いくつかの方法があります。%left1 つ目は、、%rightおよび%nonassocコマンドを使用して優先レベルを指定する方法です (マニュアルを参照)。

私が個人的に好むもう 1 つのオプションは、優先順位を文法に直接エンコードすることです。たとえば、単純な算術式の BNF は次のとおりです。

expr ::= term | expr + term
term ::= factor | term * factor
factor ::= number | ( expr )

これにより、文法レベルでのあいまいな解析が排除されます。

于 2010-10-05T00:36:01.020 に答える