-- | -- Module : SExpPP -- Description : A simple S-expression type with a pretty printable 'Doc' type -- at the leaves -- Copyright : Benjamin F Jones 2016 -- License : ISC -- -- Maintainer : bjones@galois.com -- Stability : experimental -- Portability : unknown -- -- This module gives a uniform way to pretty print S-expressions through a -- typeclass 'ToSExp'. -- {-# LANGUAGE OverloadedStrings #-} module Language.Sally.SExpPP ( -- * S-expression pretty printing SExp(..) , ToSExp(..) , bareText -- * misc , sallyCom ) where import Data.Text (Text) import qualified Data.Text as T import Text.PrettyPrint.ANSI.Leijen -- | A simple S-expression datatype with 'Doc' values at the leaves. data SExp = SXBare Doc -- ^ bare symbol or literal represented by a 'Doc' | SXList [SExp] -- ^ list of 'SExp', e.g. (foo a b) -- | Typeclass for values that can be converted to a 'SExp'. These values can -- then be pretty printed using the default layout scheme given by 'sxPretty'. class ToSExp a where toSExp :: a -> SExp sxPretty :: a -> Doc sxPretty = sxPrettyDefault . toSExp sxPrettyCompact :: a -> Doc sxPrettyCompact = sxPrettyCompactDefault . toSExp -- | Trivial 'ToSExp' instance for 'SExp'. instance ToSExp SExp where toSExp = id -- | Pretty print an 'SExp' using the default layout scheme. sxPrettyDefault :: SExp -> Doc sxPrettyDefault (SXBare x) = x sxPrettyDefault (SXList []) = lparen <> rparen sxPrettyDefault (SXList xs) = parens . group . align . vsep . fmap sxPretty $ xs -- sxPrettyDefault (SXList ll@(x:_)) = case x of -- SXBare _ -> parens (hang' (fillSep (map sxPretty ll))) -- SXList _ -> parens (fillSep (map sxPretty ll)) -- | Pretty print an 'SExp' using the default *compact* layout scheme. sxPrettyCompactDefault :: SExp -> Doc sxPrettyCompactDefault (SXBare x) = x sxPrettyCompactDefault (SXList []) = lparen <> rparen sxPrettyCompactDefault (SXList xs) = parens . hsep . fmap sxPretty $ xs -- | Inject a text literal as a 'SExp'. bareText :: Text -> SExp bareText = SXBare . text . T.unpack -- Misc Sally Specific Items --------------------------------------------------- -- | A Sally comment. sallyCom :: Doc sallyCom = text ";;"