Elm-0.1.0: src/Parse/Parser.hs
module Parser where
import Ast
import Binop (binops)
import Combinators
import Data.List (foldl')
import Lexer
import ParserLib
import ParseTypes (datatype)
import ParsePatterns
import Tokens
-------- Basic Terms --------
num_term = do { whitespace; t <- item
; case t of { NUMBER n -> return $ Number n; _ -> zero } }
str_term = do { whitespace; t <- item
; case t of { STRING cs -> return . list $ map Chr cs
; _ -> zero } }
var_term = do var >>= return . Var
chr_term = do chr >>= return . Chr
true_term = do { t TRUE; return $ Boolean True }
false_term = do { t FALSE; return $ Boolean False }
-------- Complex Terms --------
list_term = (do { t LBRACKET; start <- expr; t DOT2; end <- expr; t RBRACKET
; return $ Range start end }) +|+
(do { t LBRACKET; es <- sepBy (t COMMA) expr; t RBRACKET
; return $ list es })
parens_term = (do { t LPAREN; op <- anyOp; t RPAREN
; return . Lambda "x" . Lambda "y" $
Binop op (Var "x") (Var "y") }) +|+
(do { t LPAREN; es <- sepBy (t COMMA) expr; t RPAREN
; return $ case es of { [e] -> e; _ -> tuple es } })
term = select [ num_term
, str_term
, accessible var_term
, chr_term
, true_term
, false_term
, list_term
, accessible parens_term
]
-------- Applications --------
app_expr = do
tlist <- plus term
return $ case tlist of
t:[] -> t
t:ts -> foldl' App t ts
-------- Expressions with infix operators --------
binary_expr = binops app_expr anyOp
-------- Normal Expressions --------
if_expr = do { t IF; e1 <- expr; t THEN; e2 <- expr; t ELSE; e3 <- expr
; return $ If e1 e2 e3 }
lambda_expr = do { t LAMBDA; vs <- plus var; t ARROW; e <- expr
; return $ foldr (\x e -> Lambda x e) e vs }
assign_expr = whitespace >> assign_expr_nospace
assign_expr_nospace = do
p:ps <- plus pattern_term; assign; e <- expr
case p:ps of
PVar x : _ -> return (x, foldr func e ps)
where func PAnything e' = Lambda "_" e'
func (PVar x) e' = Lambda x e'
func p' e' = Lambda "_temp" (Case (Var "_temp") [(p', e')])
-- _ : [] -> return $ \hole -> Case e [(p,hole)]
_ -> zero
let_expr = do
t LET; brace <- optional $ t LBRACE
case brace of
Nothing -> do f <- assign_expr; t IN; e <- expr; return (Let [f] e)
Just LBRACE -> do fs <- sepBy1 (t SEMI) assign_expr; t RBRACE; t IN;
e <- expr; return (Let fs e)
case_expr = do
t CASE; e <- expr; t OF; t LBRACE
cases <- sepBy1 (t SEMI)
(do { p <- pattern_expr; t ARROW; e <- expr; return (p,e) })
t RBRACE
return $ Case e cases
-------- All Expressions --------
expr = select [ let_expr
, binary_expr
, if_expr
, case_expr
, lambda_expr
]
def = assign_expr_nospace >>= return . (:[])
defs = do
ds <- plus (whitespace >> plus (sat (==NEWLINE)) >> def +|+ datatype)
star $ sat (==NEWLINE) +|+ sat (==SPACES)
return $ Let (concat ds) (Var "main")
err = "Parse Error: Better error messages to come!"
toExpr = extractResult err . parse expr
toDefs = extractResult err . parse defs . (NEWLINE:)