4

Haskell で解析ライブラリを調べていると、このプロジェクトに出くわしました: haskell-parser-examples。いくつかの例を実行すると、演算子の優先順位に問題があることがわかりました。Parsec を使用すると問題なく動作します。

$ echo "3*2+1" | dist/build/lambda-parsec/lambda-parsec
Op Add (Op Mul (Num 3) (Num 2)) (Num 1)
Num 7

しかし、ハッピー/アレックスではそうではありません:

$ echo "3*2+1" | dist/build/lambda-happy-alex/lambda-happy-alex
Op Mul (Num 3) (Op Add (Num 2) (Num 1))
Num 9

演算子の優先順位は明確に定義されているように見えますが。パーサーからの抜粋:

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

%%

Exprs : Expr                             { $1 }
      | Exprs Expr                       { App $1 $2 }

Expr : Exprs                             { $1 }
     | let var '=' Expr in Expr end      { App (Abs $2 $6) $4 }
     | '\\' var '->' Expr                { Abs $2 $4 }
     | Expr op Expr                      { Op (opEnc $2) $1 $3 }
     | '(' Expr ')'                      { $2 }
     | int                               { Num $1 }

ヒントはありますか?(しばらく前にバグレポートを開きましたが、応答がありません)。

[gch 7.6.3、alex 3.1.3、happy 1.19.4 を使用]

4

1 に答える 1

2

これは、haskell-parser-examples のトークンの優先順位の使用におけるバグのようです。Happy の演算子の優先順位は、トークンを直接使用するルールにのみ影響します。パーサーでは、ルールに優先順位を適用したいのですExprが、適用可能な唯一のルールは、

| Expr op Expr { Op (opEnc $2) $1 $3 }

トークン自体を使用せず、代わりにそれらを展開することに依存しopEncます。opEncにインライン化されている場合Expr

| Expr '*' Expr { Op Mul $1 $3 }
| Expr '+' Expr { Op Add $1 $3 }
| Expr '-' Expr { Op Sub $1 $3 }

それは正しく動作するはずです。

于 2014-08-20T00:43:53.703 に答える