jul*_*les 5 haskell pretty-print abstract-syntax-tree
是否有任何常用的方法甚至库来漂亮地打印(和解析)带有(二进制)运算符的语法树,并为其分配了关联性和优先级,以便结果使用尽可能少的括号?
以命题演算的公式为例:
data Formula
= Atom String
| Not (Formula)
| And (Formula) (Formula)
| Or (Formula) (Formula)
| Imp (Formula) (Formula)
Run Code Online (Sandbox Code Playgroud)
假定优先级为Imp< Or< And< Not(所以Not结合最),并且And,Or和Imp应关联到的权利; 所以例如Imp (And (Imp (Atom "A") (Atom "B")) (Atom "A")) (Atom "B")应该打印像(A -> B) /\ A -> B。
当然,这可以通过模式匹配来实现,但这很繁琐而且非常不愉快。我正在从Coq证明助理中寻找与此符号类似的简单内容:
Notation "A /\ B" := (and A B) (at level 80, right associativity).
Run Code Online (Sandbox Code Playgroud)
生成一个解析器和一个漂亮的打印机。
的Show实例Formula可能如下所示:
instance Show Formula where
showsPrec _ (Atom name) = showString name
showsPrec p (Not formula) = showParen (p > 3) $
showString "\\+ " . showsPrec 3 formula
showsPrec p (And lhs rhs) = showParen (p > 2) $
showsPrec 3 lhs . showString " /\\ " . showsPrec 2 rhs
showsPrec p (Or lhs rhs) = showParen (p > 1) $
showsPrec 2 lhs . showString " \\/ " . showsPrec 1 rhs
showsPrec p (Imp lhs rhs) = showParen (p > 0) $
showsPrec 1 lhs . showString " -> " . showsPrec 0 rhs
Run Code Online (Sandbox Code Playgroud)
这将允许 anyFormula成为shown 并带有适当的括号:
main = print $ Imp (And (Imp (Atom "A") (Atom "B")) (Atom "A")) (Atom "B")
Run Code Online (Sandbox Code Playgroud)
打印(print是putStrLn . show):
(A -> B) /\ A -> B
Run Code Online (Sandbox Code Playgroud)