2016-02-14 25 views
3

是否有任何常用的方法,甚至是用於使用分配關聯性和優先級的(二元)運算符打印(和解析)語法樹的庫結果儘可能少地使用括號?Haskell中具有運算符優先級和關聯性的漂亮打印語法樹


取命題演算式爲例:

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

假定優先級爲Imp < Or < And < Not(所以Not結合最),並且AndOrImp應該與權利相關聯;所以例如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). 

它生成一個解析器和一個漂亮的打印機。

+3

在Haskell中沒有這樣的語言功能,因爲有Coq - 你可能會自己寫一個解析器。標準的[parsec](https://hackage.haskell.org/package/parsec-3.1.9/docs/Text-Parsec-Expr.html)可以很容易地處理這個用例。 [一些](https://hackage.haskell.org/package/boomerang-1.4.5.1)[庫](https://hackage.haskell.org/package/invertible-syntax)允許你定義一個解析器和漂亮的打印機從一些規範的語法。 – user2407038

回答

2

一個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 

,這將使任何Formulashow n,其中合適的括號:

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

打印(printputStrLn . show):

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