Pretty Printing Syntax Tree with Operator Precedence and Associativity in Haskell

青春壹個敷衍的年華 提交于 2019-12-03 14:47:05

问题


Is there any commonly used method or even a library for pretty printing (and parsing) a syntax tree with (binary) operators that have an associativity and a precedence level assigned, so that the result uses as few brackets as possible?


Take the formulas of propositional calculus as an example:

data Formula
    = Atom String
    | Not (Formula)
    | And (Formula) (Formula)
    | Or (Formula) (Formula)
    | Imp (Formula) (Formula) 

Assume that the precedence is Imp < Or < And < Not (so Not binds the most) and that And, Or and Imp should associate to the right; so for example Imp (And (Imp (Atom "A") (Atom "B")) (Atom "A")) (Atom "B") should print something like (A -> B) /\ A -> B.


Of course this could be achieved by pattern matching but this is tedious and very unpleasant; I'm looking for something similarly simple to this notation from the Coq proof assistant:

Notation "A /\ B" := (and A B) (at level 80, right associativity).

which generates a parser and a pretty printer.


回答1:


A Show instance for Formula might look like this:

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

Which will allow any Formula to be shown with appropriate parens:

main = print $ Imp (And (Imp (Atom "A") (Atom "B")) (Atom "A")) (Atom "B")

Prints (print is putStrLn . show):

(A -> B) /\ A -> B


来源:https://stackoverflow.com/questions/35398355/pretty-printing-syntax-tree-with-operator-precedence-and-associativity-in-haskel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!