LambdaPrettyQuote-0.0.0.2: src/Language/Lambda/Parser.hs
{-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-}
{-- | Parser for the lambda AST built of parsec. Converts to an intermediate format for antiexpressions -}
module Language.Lambda.Parser where
import Text.Parsec
import Text.Parsec.Language
import Text.Parsec.Token
import Language.Lambda.AST
import Data.Functor.Identity
import Data.List
import Data.Data
type M = Identity
data MetaExpr = MVar Sym
| MApp MetaExpr MetaExpr
| MLam Sym MetaExpr
| AntiExpr String
deriving(Show, Eq, Data, Typeable)
type Output = MetaExpr
top_expr :: ParsecT String u M Output
top_expr = do
spaces
e <- parse_expr
spaces
eof
return e
parse_expr :: ParsecT String u M Output
parse_expr = try parse_aexpr
<|> try parse_lambda
<|> try parse_anti_expr
parse_aexpr :: ParsecT String u M Output
parse_aexpr = try parse_app
<|> try parse_atom
parse_anti_expr :: ParsecT String u M Output
parse_anti_expr = do
_ <- string "$"
i <- (identifier haskell)
return $ AntiExpr i
parse_lambda :: ParsecT String u M Output
parse_lambda = do
_ <- char '\\'
spaces
sym <- parse_sym <?> "lambda argument"
_ <- char '.'
spaces
expr <- parse_expr <?> "lambda expression"
return $ MLam sym expr
parse_app :: ParsecT String u M Output
parse_app = do
expr_0 <- parse_atom <?> "first apply argument"
spaces
as <- sepBy1 parse_atom spaces <?> "other apply arguments"
return $ foldl' MApp expr_0 as
parse_atom :: ParsecT String u M Output
parse_atom = try (parens' parse_expr)
<|> try parse_var
<|> try parse_anti_expr
parse_var :: ParsecT String u M Output
parse_var = do
spaces
sym <- parse_sym <?> "Var symbol"
return $ MVar sym
parse_sym :: ParsecT String u M Sym
parse_sym = many1 (alphaNum <|> char '_') <?> "symbol"
parens' :: Stream s m Char => ParsecT s u m b -> ParsecT s u m b
parens' p = do
_ <- char '('
e <- p
_ <- char ')'
return e
meta_to_expr :: MetaExpr -> Expr
meta_to_expr (MVar x) = Var x
meta_to_expr (MApp x y) = App (meta_to_expr x) (meta_to_expr y)
meta_to_expr (MLam x y) = Lam x (meta_to_expr y)
meta_to_expr (AntiExpr _) = error "meta_to_expr should not be used if the MetaExpr tree has AntiExpr"
to_meta :: Expr -> MetaExpr
to_meta (Var x) = MVar x
to_meta (App x y) = MApp (to_meta x) (to_meta y)
to_meta (Lam x y) = MLam x (to_meta y)