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 StdEnv
-import Text.Parsers.Simple.ParserCombinators => qualified parse
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 | TTChar Char | TTInt Int | TTIdent [Char]
-
+:: 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] = TTEq <:> lex ts
lex ['(':ts] = TTBrackOpen <:> lex ts
lex ['True':ts] = TTBool True <:> lex ts
lex ['False':ts] = TTBool False <:> lex ts
-lex ['\'',c,'\'':ts] = TTChar c <:> lex ts
lex ['-',t:ts]
| isDigit t = lex [t:ts] >>= \v->case v of
[TTInt i:rest] = Right [TTInt (~i):rest]
| isDigit t
# (i, ts) = span isDigit [t:ts]
= TTInt (toInt (toString i)) <:> lex ts
- | isAlpha t
- # (i, ts) = span isAlpha [t:ts]
+ | isIdent t
+ # (i, ts) = span isIdent [t: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]
+ , infixs :: [(Bool, [Char], Int)]
+ }
+instance zero ParseState where zero = {tokens=[],infixs=[]}
+
+pTop :: Parser Token
+pTop = getState >>= \s->case s.tokens of
+ [t:ts] = put {s & tokens=ts} >>| pure t
+ [] = liftT (Left ["Fully consumed input"])
+
+pSatisfy :: (Token -> Bool) -> Parser Token
+pSatisfy f = pTop >>= \t->if (f t) (pure t) empty
-parse :: ([Token] -> Either [String] AST)
-parse = 'Text.Parsers.Simple.ParserCombinators'.parse (AST <$> many pFunction)
+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] AST
+parse ts = case runStateT pAST {zero & tokens=ts} of
+ Right (a, {tokens=[]}) = Right a
+ Right (a, _) = Left ["No complete parse result"]
+ Left e = Left e
where
+ pAST :: Parser AST
+ pAST = AST <$> many pFunction
+
pId = (\(TTIdent i)->i) <$> pSatisfy (\t->t=:(TTIdent _))
+ pOp t` = pId >>= \t->if (t == t`) (pure t) empty
- pFunction :: Parser Token Function
+ pFunction :: Parser Function
pFunction
= Function
<$> pId
<*> many pId
- <* pSatisfy (\t->t=:TTEq)
+ <* pToken TTEq
<*> pExpression
- <* pSatisfy (\t->t=:TTSemiColon)
+ <* pToken TTSemiColon
+
+ pExpression :: Parser Expression
+ pExpression = getState >>= \{infixs}->foldr ($) pBasic
+ [ pChainl (pure App)
+ : [ if ifxr pChainr pChainl $ App o App (Var op) <$ pOp op
+ \\(ifxr, op, _)<-infixs]]
- pExpression :: Parser Token Expression
- pExpression = flip pChainl1 (pure App) $
- (Lambda <$ pSatisfy (\t->t=:TTLambda) <*> pId <* pSatisfy (\t->t=:TTDot) <*> pExpression)
- <<|> (pSatisfy (\t->t=:TTBrackOpen) *> pExpression <* pSatisfy (\t->t=:TTBrackClose))
- <<|> ((\(TTInt i)->Lit (Int i)) <$> pSatisfy (\t->t=:(TTInt _)))
- <<|> ((\(TTChar i)->Lit (Char i)) <$> pSatisfy (\t->t=:(TTChar _)))
- <<|> ((\(TTBool i)->Lit (Bool i)) <$> pSatisfy (\t->t=:(TTBool _)))
- <<|> (Var <$> pId)
+ pBasic :: Parser Expression
+ pBasic
+ = Lambda <$ pToken TTLambda <*> pId <* pToken TTDot <*> pExpression
+ <|> pToken TTBrackOpen *> pExpression <* pToken TTBrackClose
+ <|> (\(TTInt i)->Lit (Int i)) <$> pSatisfy (\t->t=:(TTInt _))
+ <|> (\(TTInt i)->Lit (Int i)) <$> pSatisfy (\t->t=:(TTInt _))
+ <|> (\(TTBool i)->Lit (Bool i)) <$> pSatisfy (\t->t=:(TTBool _))
+ <|> Var <$> pId