derive consName Token, Value
:: Expression | DelayedParse [Token]
-
:: Token
= IntToken Int | BoolToken Bool | CharToken Char | IdentToken String
| InfixrToken | InfixlToken | SemiColonToken | OpenBraceToken
| CloseBraceToken | EqualsToken | CodeToken | LambdaToken
- | ArrowToken
+ | ArrowToken | LetToken | InToken
+:: ParseState = {tokens :: [Token], infixers :: [Infix]}
+:: Infix = Infix String Fixity Int
+:: Fixity = InfixL | InfixR
+:: Parser a :== StateT ParseState (Either [String]) a
+
+instance < Infix where (<) (Infix _ _ s) (Infix _ _ t) = s < t
+instance zero ParseState where zero = {tokens=[],infixers=[]}
lex :: [Char] -> [Token]
lex cs = lex` cs
where
- lex` [] = []
- lex` ['\n':cs] = lex` cs
- lex` [c:cs]
- | isSpace c = lex` cs
- lex` [';':cs] = [SemiColonToken:lex` cs]
- lex` ['=',c:cs]
- | not (isIdent c) = [EqualsToken:lex` [c:cs]]
- lex` ['(':cs] = [OpenBraceToken:lex` cs]
- lex` [')':cs] = [CloseBraceToken:lex` cs]
- lex` ['-','>':cs] = [ArrowToken:lex` cs]
- lex` ['\\':cs] = [LambdaToken:lex` cs]
- lex` ['\'',c,'\'':cs] = [CharToken c:lex` cs]
- lex` ['T','r','u','e':cs] = [BoolToken True:lex` cs]
- lex` ['c','o','d','e':cs] = [CodeToken:lex` cs]
- lex` ['F','a','l','s','e':cs] = [BoolToken True:lex` cs]
- lex` ['i','n','f','i','x','r':cs] = [InfixrToken:lex` cs]
- lex` ['i','n','f','i','x','l':cs] = [InfixlToken:lex` cs]
+ lex` [] = []
+ lex` ['\n':cs] = lex` cs
+ lex` [c:cs] | isSpace c = lex` cs
+ lex` [';':cs] = [SemiColonToken:lex` cs]
+ lex` ['=',c:cs] | not (isIdent c) = [EqualsToken:lex` [c:cs]]
+ lex` ['(':cs] = [OpenBraceToken:lex` cs]
+ lex` [')':cs] = [CloseBraceToken:lex` cs]
+ lex` ['->':cs] = [ArrowToken:lex` cs]
+ lex` ['\\':cs] = [LambdaToken:lex` cs]
+ lex` ['\'',c,'\'':cs] = [CharToken c:lex` cs]
+ lex` ['let':cs] | whiteOrEnd cs = [LetToken:lex` cs]
+ lex` ['in':cs] | whiteOrEnd cs = [InToken:lex` cs]
+ lex` ['code':cs] | whiteOrEnd cs = [CodeToken:lex` cs]
+ lex` ['False':cs] | whiteOrEnd cs = [BoolToken True:lex` cs]
+ lex` ['True':cs] | whiteOrEnd cs = [BoolToken True:lex` cs]
+ lex` ['infixr':cs] | whiteOrEnd cs = [InfixrToken:lex` cs]
+ lex` ['infixl':cs] | whiteOrEnd cs = [InfixlToken:lex` cs]
lex` ['-',c:cs]
| isDigit c
= case lex` [c:cs] of
= [IdentToken $ toString [c:i]:lex` cs]
= abort $ "Huh lexer failed on: " +++ toString (toInt c)
+whiteOrEnd [] = True
+whiteOrEnd [c:cs] = isSpace c
+
isIdent c = isAlpha c || elem c ['\'`']
isFunny = flip elem ['!@#$%^&*\|+-?/\'<>.:~=']
-:: ParseState =
- { tokens :: [Token]
- , infixers :: [Infix]
- }
-:: Infix = Infix String Fixity Int
-instance < Infix where (<) (Infix _ _ s) (Infix _ _ t) = s < t
-:: Fixity = InfixL | InfixR
-
-:: Parser a :== StateT ParseState (Either [String]) a
-
-instance zero ParseState where zero = {tokens=[],infixers=[]}
-
(<?>) infixl 1 :: a (StateT b (Either (c a)) d) -> StateT b (Either (c a)) d | Semigroup (c a) & Applicative c
(<?>) err p = StateT $ first (flip mappend (pure err)) o runStateT p
parseBasic
//Bracketed
= token OpenBraceToken *> parseBracketed <* token CloseBraceToken
+ <|> Let <$> (token LetToken *> parseIdent <* token EqualsToken) <*> (parseExpr <* token InToken) <*> parseExpr
<|> Literal <$> Int <$> parseInt
<|> Code <$> (token CodeToken *> parseIdent)
<|> flip (foldr Lambda) <$> (token LambdaToken *> some parseIdent <* token ArrowToken) <*> parseExpr
parseBracketed :: Parser Expression
parseBracketed
//Curried prefix infix
- = (\e op->Apply (Apply fpflip op) e) <$> parseIfx <*> parseExpr
+ = (\op->Lambda "_v" o Apply (Apply op (Variable "v"))) <$> parseIfx <*> parseExpr
//Regular Prefix infix
<|> parseIfx
//Curried flipped prefix infix
- <|> Apply <$> parseExpr <*> parseIfx
+ <|> (\e op->Lambda "_v" (Apply (Apply op e) (Variable "v"))) <$> parseExpr <*> parseIfx
//Parse regular expression
<|> parseExpr
- fpflip :: Expression
- fpflip = Lambda "x" $ Lambda "y" $ Lambda "z" $ Apply (Apply (Variable "x") (Variable "z")) (Variable "y")
-
parseWithIfx :: ([String] String -> Bool) -> Parser String
parseWithIfx f = gets (\s->[i\\Infix i _ _<-s.infixers]) >>= flip parseIf parseIdent o f
['id x = x;'] ++
['const x y = x;'] ++
['flip x y z = x z y;'] ++
+ ['twice f = f . f;'] ++
+ ['fix f x = let x = f x in x;'] ++
['. infixr 9 f g x = f $ g x;'] ++
['$ infixr 0 = id;'] ++
['& infixr 0 = flip $;'] ++
['/ infixr 7 = code div;'] ++
['&& infixl 3 = code and;'] ++
['|| infixl 2 = code or;'] ++
- ['ap = f . g $ x;']
+ ['ap = (1 +);'] ++
+ ['ap = (+ 1);']
) zero