import Control.Applicative
import Control.Lens.SemiIso
import Control.Lens.TH
import qualified Data.Attoparsec.Text as AP
import Data.Char
import Data.SemiIsoFunctor
import Data.Syntax (Syntax)
import qualified Data.Syntax as S
import qualified Data.Syntax.Attoparsec.Text as S
import qualified Data.Syntax.Char as S
import qualified Data.Syntax.Combinator as S
import qualified Data.Syntax.Pretty as S
import Data.Text (Text)
import qualified Data.Text.IO as T
import qualified Text.PrettyPrint as P
data AST = Var Text
| App AST AST
| Abs Text AST
deriving (Show)
$(makePrisms ''AST)
name :: Syntax syn Text => syn Text
name = S.takeWhile1 isAlphaNum
parens :: Syntax syn Text => syn a -> syn a
parens m = S.char '(' */ S.spaces_ */ m /* S.spaces_ /* S.char ')'
atom :: Syntax syn Text => syn AST
atom = _Var /$/ name
/|/ parens expr
apps :: Syntax syn Text => syn AST
apps = bifoldl1 (attemptAp_ _App) /$/ S.sepBy1 atom S.spaces1
expr :: Syntax syn Text => syn AST
expr = _Abs /$/ S.char '\\' /* S.spaces_
*/ name /* S.spaces
/* S.string "->" /* S.spaces
/*/ expr
/|/ apps
main :: IO ()
main = do
t <- T.getContents
case AP.parseOnly (S.getParser expr <* AP.skipSpace <* AP.endOfInput) t of
Left err -> putStrLn err
Right ast -> do
print ast
case S.runPrinter expr ast of
Left err -> putStrLn err
Right doc -> putStrLn (P.render doc)
return ()