diff options
Diffstat (limited to 'parser/CC')
-rw-r--r-- | parser/CC/Parser.hs | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/parser/CC/Parser.hs b/parser/CC/Parser.hs index bbabe3c..2d2c4b7 100644 --- a/parser/CC/Parser.hs +++ b/parser/CC/Parser.hs @@ -64,7 +64,7 @@ pParenType = do _ -> return (TTup tys) pExpr :: Parser Expr -pExpr = label (pCall <|> pLam) "expression" +pExpr = label (pLam <|> pLet <|> pCall) "expression" where pCall = do atoms <- many1 pExprAtom @@ -90,6 +90,31 @@ pExpr = label (pCall <|> pLam) "expression" p2 <- getPosition return (Lam (SourceRange p1 p2) names body) + pLet = do + p1 <- try $ do + whitespace + p <- getPosition + void (string "let") + return p + afterKeyword p1 + where + afterKeyword p1 = do + whitespace1 + lhs <- pName0 + symbol "=" + rhs <- pExpr + let fullRange rest = mergeRange (SourceRange p1 p1) (range rest) + choice [ do p1' <- try $ do + whitespace + p1' <- getPosition + void (string "let") + return p1' + rest <- afterKeyword p1' + return (Let (fullRange rest) lhs rhs rest) + , do symbol "in" + body <- pExpr + return (Let (fullRange body) lhs rhs body) ] + pExprAtom :: Parser Expr pExprAtom = choice [ uncurry (flip Int) <$> pInt @@ -119,11 +144,15 @@ pInt = try (whitespace >> pInt0) pName0 :: Parser (Name, SourceRange) pName0 = do p1 <- getPosition - c <- pWordFirstChar - cs <- many pWordMidChar + s <- try $ do + c <- pWordFirstChar + cs <- many pWordMidChar + let s = c : cs + guard (s `notElem` ["let", "in"]) + return s p2 <- getPosition notFollowedBy pWordMidChar - return (c : cs, SourceRange p1 p2) + return (s, SourceRange p1 p2) pWordFirstChar :: Parser Char pWordFirstChar = letter <|> oneOf "_$#!" @@ -146,8 +175,9 @@ token s = try (whitespace >> void (string s)) emptyLines :: Parser () emptyLines = (try (whitespace >> newline) >> emptyLines) <|> try (whitespace >> eof) <|> return () -whitespace :: Parser () -whitespace = void (many (void (char ' ') <|> void (try (string "\n ")))) +whitespace, whitespace1 :: Parser () +whitespace = void (many (void (char ' ') <|> void (try (string "\n ")))) +whitespace1 = void (many1 (void (char ' ') <|> void (try (string "\n ")))) getPosition :: Parser SourcePos getPosition = do |