【发布时间】:2019-05-04 05:41:34
【问题描述】:
我在 Haskell 中编写了一个解析器,它以字符串输入的形式解析公式,并生成由下面的 BNF 定义的 Haskell data 类型。
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
现在我想创建一个Show 的实例,以便我可以很好地打印由我的类型定义的公式(我不想使用deriving (Show))。我的问题是:如何定义我的函数,以便它可以判断何时需要括号?我不想要太多的括号,也不要太少的括号。
例如,给定公式∀ X . (X & Y) & (∀ Y . Y) & false,解析时会生成数据结构
And (And (Forall "X" (And (Var "X") (Var "Y"))) (Forall "Y" (Var "Y"))) False
我们有
Too little parentheses: ∀ X . X & Y & ∀ Y . Y & false
Too much parentheses: (∀ X . (((X) & (Y)))) & (∀ Y . (Y)) & (false)
Just right: ∀ X . (X & Y) & (∀ Y . Y) & false
有没有办法衡量需要多少括号以使语义永远不会模棱两可?我很感激任何反馈。
【问题讨论】:
-
查看
showsPrec,其中shows与给定运算符Precedence 相关。 -
@AJFarmar 你能推荐一些关于如何使用
showsPrec的教程吗?我在上面找到的文档非常少。 -
@AJFarmar 或者提供一个答案:)
-
这也是品味问题。在我自己的首选约定中,
∀ X的优先级最低,因此∀ X . A & B表示∀ X . (A & B),而不是(∀ X . A) & B。 (有时会使用其他优先级。)Haskell 还使\ x ->尽可能向右扩展。您必须选择优先级。 -
@chi 通常我会同意你的观点,但考虑到我使用这个语法的目的,事实证明给连词赋予较低的优先级更方便。我的问题不是关于选择优先级,而是关于如何实际实现
show函数,以便最少地打印括号。
标签: parsing haskell pretty-print