Skip to content

Instantly share code, notes, and snippets.

@ezksd
Created May 14, 2017 09:59
Show Gist options
  • Save ezksd/84c0ea7e010ffaae938e4a0adf022be1 to your computer and use it in GitHub Desktop.
Save ezksd/84c0ea7e010ffaae938e4a0adf022be1 to your computer and use it in GitHub Desktop.
module Parser where
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.State
import Data.Char
type Parser a = StateT String Maybe a
runParse :: Parser a -> String -> Maybe a
runParse p s = do (a,b) <- runStateT p s
guard (null b)
return a
item :: Parser Char
item = do s <- get
guard (not (null s))
put (tail s)
return (head s)
test :: Parser a -> (a -> Bool) -> Parser a
test m p = do a <- m
guard (p a)
return a
sat :: (Char -> Bool) -> Parser Char
sat = test item
char :: Char -> Parser Char
char = sat . (==)
letter :: Parser String
letter = some (sat isAlpha)
int :: Parser Int
int = do sign <- (char '-' >> pure negate) <|> pure id
num <- read <$> some (sat isDigit)
return (sign num)
oneOf :: String -> Parser Char
oneOf = sat . flip elem
notIn :: String -> Parser Char
notIn = sat . flip notElem
token :: Parser a -> Parser a
token = (>>) spaces
where spaces = many $ sat isSpace
type Env = Map.Map String Expr
type Fun = [Expr] -> Expr
data Expr = Symbol String
| String String
| Number Int
| Bool Bool
| List [Expr]
| Closure Env Expr
deriving (Show)
nil :: Expr
nil = List []
symbol :: Parser Expr
symbol = Symbol <$> s
where s = some $ notIn " \r\n\"\'#()"
string :: Parser Expr
string = String <$> (char '"' *> letter <* char '"')
number :: Parser Expr
number = Number <$> int
bool :: Parser Expr
bool = Bool <$> (char '#' *> (t <|> f))
where t = char 't' >> pure True
f = char 'f' >> pure False
list :: Parser Expr
list = List <$> (char '(' *> x <* char ')')
where x = many $ token expr
expr :: Parser Expr
expr = string <|> bool <|> number <|> symbol <|> list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment