implementation module parse import Control.Applicative import Control.Monad import Control.Monad.State import Control.Monad.Trans import Data.Either import Data.GenEq import Data.Functor import Data.Func import Data.List import Data.Tuple import StdEnv import ast (<:>) infixl 0 :: a (m [a]) -> m [a] | Functor m (<:>) l r = (\xs->[l:xs]) <$> r :: Token = TTEq | TTSemiColon | TTLambda | TTDot | TTBrackOpen | TTBrackClose | TTBool Bool | TTInt Int | TTIdent [Char] derive gEq Token lex :: [Char] -> Either [String] [Token] lex [] = pure [] lex [';':ts] = TTSemiColon <:> lex ts lex [')':ts] = TTBrackClose <:> lex ts lex ['(':ts] = TTBrackOpen <:> lex ts lex ['True':ts] = TTBool True <:> lex ts lex ['False':ts] = TTBool False <:> lex ts lex ['-',t:ts] | isDigit t = lex [t:ts] >>= \v->case v of [TTInt i:rest] = Right [TTInt (~i):rest] x = pure x lex [t:ts] | isSpace t = lex ts | isDigit t # (i, ts) = span isDigit [t:ts] = TTInt (toInt (toString i)) <:> lex ts | isIdent t # (i, ts) = span isIdent [t:ts] | i =: ['='] = TTEq <:> lex ts | i =: ['.'] = TTDot <:> lex ts | i =: ['\\'] = TTLambda <:> lex ts = TTIdent i <:> lex ts = Left ["Unexpected: " +++ toString t +++ " ord: " +++ toString (toInt t)] where isIdent c = isAlpha c || isMember c ['!@#$%^&*=+/?-_|\\\'",<>.:'] :: Parser a :== StateT ParseState (Either [String]) a :: ParseState = { tokens :: [Token] , ifxs :: [((Parser Expression) -> Parser Expression, Int)] } instance zero ParseState where zero = {tokens=[],ifxs=[]} pTop :: Parser Token pTop = getState >>= \s->case s.tokens of [t:ts] = put {s & tokens=ts} >>| pure t [] = liftT (Left ["Fully consumed input"]) pEof :: Parser () pEof = getState >>= \s->case s.tokens of [] = pure () [t:ts] = liftT (Left ["Expected EOF"]) pSatisfy :: (Token -> Bool) -> Parser Token pSatisfy f = pTop >>= \t->if (f t) (pure t) empty pToken :: (Token -> Parser Token) pToken = pSatisfy o (===) pChainl :: (Parser (a a -> a)) (Parser a) -> Parser a pChainl op p = foldl (flip ($)) <$> p <*> many (flip <$> op <*> p) pChainr :: (Parser (a a -> a)) (Parser a) -> Parser a pChainr op p = flip ($) <$> p <*> (flip <$> op <*> pChainr op p) <|> p parse :: [Token] -> Either [String] [Function] parse ts = case runStateT (pAST <* pEof) {zero & tokens=ts} of Right (a, _) = Right a Left e = Left e where pAST :: Parser [Function] pAST = many pFunction >>= mapM \(id, args, body)->Function id args <$ modify (\t->{t&tokens=body}) <*> pExpression <* pEof pId = (\(TTIdent i)->i) <$> pSatisfy (\t->t=:(TTIdent _)) pCId a = pId >>= \b->if (a == b) (pure a) empty pFunction :: Parser ([Char], [[Char]], [Token]) pFunction = tuple3 <$> (pFunId <|> pId) <*> many pId <* pToken TTEq <*> many (pSatisfy ((=!=)TTSemiColon)) <* pToken TTSemiColon pFunId :: Parser [Char] pFunId = pId >>= \i->pChainr <$ pCId ['ifxr'] <|> pChainl <$ pCId ['ifxl'] >>= \p->(\(TTInt i)->i) <$> pSatisfy (\t->t=:(TTInt _)) >>= \s->modify (\t->{t & ifxs=[(p (App o App (Var i) <$ pCId i), s):t.ifxs]}) >>| pure i pExpression :: Parser Expression pExpression = getState >>= \{ifxs}->flip (foldr ($)) [pChainl (pure App):map fst $ sortBy (on (<) snd) ifxs] $ Lambda <$ pToken TTLambda <*> pId <* pToken TTDot <*> pExpression <|> pToken TTBrackOpen *> pExpression <* pToken TTBrackClose <|> Lit o Int <$> (\(TTInt i)->i) <$> pSatisfy (\t->t=:(TTInt _)) <|> (\(TTBool i)->Lit (Bool i)) <$> pSatisfy (\t->t=:(TTBool _)) <|> Var <$> pId