aboutsummaryrefslogtreecommitdiff
path: root/parser/CC/Parser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'parser/CC/Parser.hs')
-rw-r--r--parser/CC/Parser.hs42
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