packages feed

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:)