git @ Cat's Eye Technologies Lanthorn / master src / Language / Lanthorn / Parser.hs
master

Tree @master (Download .tar.gz)

Parser.hs @masterraw · history · blame

{-# LANGUAGE FlexibleContexts #-}
module Language.Lanthorn.Parser where

import Text.ParserCombinators.Parsec

import Language.Lanthorn.AST


--
-- Expr        ::= LetExpr | CaseExpr | IfExpr | Primitive | Application.
-- LetExpr     ::= "let" Name "=" Expr {"," Name "=" Expr} "in" Expr.
-- IfExpr      ::= "if" Expr "then" Expr "else" Expr.
-- Primitive   ::= NumLit | FunLit.
-- FunLit      ::= "fun" "(" Name {"," Name} ")" "->" Expr.
-- Reference   ::= Name [Application].
-- Application ::= "(" [Expr {"," Expr}] ")".
-- NumLit      ::= <<0-9+>> .
-- Name        ::= <<letters>> .
--

--
-- High level: Expressions
--

expr = letRecExpr <|> letExpr <|> ifExpr <|> primExpr <|> reference

letRecExpr = do
    keyword "letrec"
    b <- manyTill (binding) (keyword "in")
    e <- expr
    return (LetRec b e)

letExpr = do
    keyword "let"
    b <- manyTill (binding) (keyword "in")
    e <- expr
    return (LetStar b e)

binding = do
    n <- name
    keyword "="
    e <- expr
    return (n, e)

ifExpr = do
    keyword "if"
    c <- expr
    keyword "then"
    t <- expr
    keyword "else"
    f <- expr
    return (If c t f)

--
-- Primitives
---

primExpr = funLit <|> numLit

funLit = do
    keyword "fun"
    keyword "("
    formals <- sepBy (name) (keyword ",")
    keyword ")"
    keyword "->"
    body <- expr
    return (Fun formals body)

reference = do
    n <- name
    application n <|> return (ValueOf n)

application n = do
    keyword "("
    actuals <- sepBy (expr) (keyword ",")
    keyword ")"
    return (Apply n actuals)

--
-- Low level: Concrete things
--

keyword s = do
    try (string s)
    spaces

name :: Parser String
name = do
    c <- letter
    cs <- many (alphaNum <|> char '_')
    spaces
    return (c:cs)

numLit = do
    ds <- many1 digit
    spaces
    return (NumLit (read ds))

--
-- Driver
--

parseExpr text = parse expr "" text