错误的运算符优先级与Happy

时间:2014-08-14 07:32:12

标签: parsing haskell operator-precedence happy

在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

但与Happy / Alex不一样:

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

即使运算符优先级看起来很明确。摘录自parser

%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 }

任何提示? (我前段时间开了bug report,但没有回复。)

[使用gch 7.6.3,alex 3.1.3,happy 1.19.4]

1 个答案:

答案 0 :(得分: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 }

它应该正常工作。