parsing - Happy 运算符优先级错误

标签 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

但不是快乐/亚历克斯:
$ 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]

最佳答案

这似乎是 haskell-parser-examples 使用 token 优先级的一个错误。 Happy 的运算符优先级仅影响直接使用 token 的规则。在解析器中,我们希望对 Expr 应用优先级。规则,但唯一适用的规则,

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

不使用 token 本身,而是依赖 opEnc扩展它们。如果 opEnc内联到 Expr ,
| Expr '*' Expr { Op Mul $1 $3 }
| Expr '+' Expr { Op Add $1 $3 }
| Expr '-' Expr { Op Sub $1 $3 }

它应该可以正常工作。

关于parsing - Happy 运算符优先级错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25302418/

相关文章:

python - 如何编写 Python 调试器/编辑器

ruby - nokogiri + 通过文本 Mechanize css 选择器

haskell - 使用 Uniplate 简化 GADT

lisp - 内外还原,结果一样吗?

java - 在递归中使用 += 在 Java 和 C++ 中产生不同的结果

operator-keyword - 反引号运算符的固定性?

c# - HTML Agility Pack 找不到带有尾随空格的类

haskell - 使用 QuickCheck 仅生成正整数

algorithm - 我如何从单个种子廉价地产生无限可拆分的非冲突数字流?

javascript - 使用 JavaScript 读取 *.csv 文件