1

fsyaccは、すべてのバイナリ操作に対してshift/reduceエラーを発行しています。

私はこの再帰的なプロダクションを持っています:

scalar_expr:
    | scalar_expr binary_op scalar_expr { Binary($2, $1, $3) }

に変更する

scalar_expr:
    | constant binary_op constant { Binary($2, Constant($1), Constant($3)) }

エラーを排除します(しかし、私が望むものではありません)。優先順位と結合性は次のように定義されます。

%left BITAND BITOR BITXOR
%left ADD SUB
%left MUL DIV MOD

これは、エラーを生成する状態を示すリストファイルからの抜粋です(他の1つの状態にも同じエラーがあります)。

state 42:
  items:
    scalar_expr -> scalar_expr . binary_op scalar_expr
    scalar_expr -> scalar_expr binary_op scalar_expr . 

  actions:
    action 'EOF' (noprec):   reduce scalar_expr --> scalar_expr binary_op scalar_expr
    action 'MUL' (explicit left 9999):   shift 8
    action 'DIV' (explicit left 9999):   shift 9
    action 'MOD' (explicit left 9999):   shift 10
    action 'ADD' (explicit left 9998):   shift 6
    action 'SUB' (explicit left 9998):   shift 7
    action 'BITAND' (explicit left 9997):   shift 11
    action 'BITOR' (explicit left 9997):   shift 12
    action 'BITXOR' (explicit left 9997):   shift 13

すべての場合でパーサーのシフトを確認できますが、これは正しいと思います。少なくとも、動作が正しくないケースは見つかりませんでした。

これらのエラーを排除するために文法を言い換えるにはどうすればよいですか?

4

2 に答える 2

1

Stephen が彼の回答で指摘したように、オペレーターを別のプロダクションに移動すると、オペレーターの優先ルールは適用されません。あなたが投稿した州はそれらを正しく尊重しているように見えるので、これは奇妙です。

ただし、明示的な優先ルールを宣言して適用できる必要があります。たとえば、次のように定義できます。

%left ADD_SUB_OP
%left MUL_DIV_OP

次のように適用します。

scalar_expr:
    | scalar_expr add_sub_ops scalar_expr %prec ADD_SUB_OP { Binary($2, $1, $3) }
    | scalar_expr mul_div_ops scalar_expr %prec MUL_DIV_OP { Binary($2, $1, $3) }

この方法でも複数のルールを定義する必要がありますが、グループ内で同じ優先順位を持つすべての演算子をグループ化できます (ここで選択した名前は貧弱な例であることに注意してください。優先順位を反映した名前を使用するか、演算子を説明する名前を使用することをお勧めします。したがって、それらが何を示しているかは明らかです)。

このソリューションが価値があるかどうかは、私が推測するグループごとのオペレーターの数に依存します。

于 2012-11-16T13:55:13.537 に答える
1

実際にはbinary_opプロダクションです。つまり、次のようなものがあります。

binary_op:
   | ADD { OpDU.Add }
   | SUB { OpDU.Sub }
   ...

もしそうなら、私はそれが問題だと思います.あなたが定義した優先順位規則は では尊重されないと思いますconstant binary_op constant. scalar_expr各パターンを明示的に列挙する必要があります。

scalar_expr:
    | scalar_expr ADD scalar_expr { Binary(OpDU.Add, $1, $3) }
    | scalar_expr SUB scalar_expr { Binary(OpDU.Sub, $1, $3) }
    ...

(FsYacc でこの反復性を抽象化する方法はないと思います)

于 2011-11-23T19:34:12.613 に答える