@@ -1,121 +1,131 @@
1−module Parser where
1+module Parser (toDefs) where
4−import Binop (binops)
4+import Control.Applicative ((<$>), (<*>))
6−import Control.Monad (liftM)
5+import Control.Monad
6+import Data.Char (isSymbol, isDigit)
7import Data.List (foldl')
7import Data.List (foldl')
8+import Text.Parsec hiding (newline,spaces)
8import Guid
15import Guid
11−import ParseTypes (datatype)
14import Types (Type (VarT))
16import Types (Type (VarT))
16-------- Basic Terms --------
18-------- Basic Terms --------
18−numTerm = do { whitespace; t <- item
20+numTerm :: (Monad m) => ParsecT [Char] u m Expr
19− ; case t of { NUMBER n -> return $ Number n; _ -> zero } }
21+numTerm = liftM (Number . read) (many1 digit) <?> "number"
20−strTerm = do { whitespace; t <- item
22+
21− ; case t of { STRING cs -> return $ Str cs
23+strTerm :: (Monad m) => ParsecT [Char] u m Expr
22− ; _ -> zero } }
24+strTerm = liftM Str . expecting "string" . betwixt '"' '"' . many $
25+ backslashed <|> satisfy (/='"')
27+varTerm :: (Monad m) => ParsecT [Char] u m Expr
28+varTerm = toVar <$> var <?> "variable"
24−varTerm = Var `liftM` var
30+toVar v = case v of "True" -> Boolean True
25−chrTerm = Chr `liftM` chr
31+ "False" -> Boolean False
27−trueTerm = do { t TRUE; return $ Boolean True }
34+chrTerm :: (Monad m) => ParsecT [Char] u m Expr
28−falseTerm = do { t FALSE; return $ Boolean False }
35+chrTerm = Chr <$> betwixt '\'' '\'' (backslashed <|> satisfy (/='\''))
31-------- Complex Terms --------
39-------- Complex Terms --------
33−listTerm = (do { t LBRACKET; start <- expr; t DOT2; end <- expr; t RBRACKET
41+listTerm = braces $ choice
34− ; return $ Range start end }) +|+
42+ [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
35− (do { t LBRACKET; es <- sepBy (t COMMA) expr; t RBRACKET
43+ ; Range lo <$> expr }
36− ; return $ list es })
44+ , list <$> commaSep expr
38−parensTerm = (do { t LPAREN; op <- anyOp; t RPAREN
47+parensTerm = parens $ choice
39− ; return . Lambda "x" . Lambda "y" $
49+ return . Lambda "x" . Lambda "y" $ Binop op (Var "x") (Var "y")
40− Binop op (Var "x") (Var "y") }) +|+
50+ , do es <- commaSep expr
41− (do { t LPAREN; es <- sepBy (t COMMA) expr; t RPAREN
42− ; return $ case es of { [e] -> e; _ -> tuple es } })
51+ return $ case es of { [e] -> e; _ -> tuple es }
44−term = select [ numTerm
54+term = choice [ numTerm, strTerm, chrTerm
46 , accessible varTerm
55 , accessible varTerm
50− , listTerm
56+ , listTerm, parensTerm ]
51− , accessible parensTerm
57+ <?> "basic term (number, variable, etc.)"
54-------- Applications --------
59-------- Applications --------
56appExpr = do
61appExpr = do
57− tlist <- plus term
62+ tlist <- spaceSep1 term
58 return $ case tlist of
63 return $ case tlist of
60 t:ts -> foldl' App t ts
65 t:ts -> foldl' App t ts
63−-------- Expressions with infix operators --------
65−binaryExpr = binops appExpr anyOp
68-------- Normal Expressions --------
67-------- Normal Expressions --------
70−ifExpr = do { t IF; e1 <- expr; t THEN; e2 <- expr; t ELSE; e3 <- expr
69+binaryExpr = binops appExpr anyOp
71− ; return $ If e1 e2 e3 }
73−lambdaExpr = do { t LAMBDA; vs <- plus var; t ARROW; e <- expr
74− ; return $ foldr Lambda e vs }
71+ifExpr = do reserved "if" ; whitespace ; e1 <- expr ; whitespace
72+ reserved "then" ; whitespace ; e2 <- expr ; (whitespace <?> "an 'else' branch")
73+ reserved "else" <?> "an 'else' branch" ; whitespace ; If e1 e2 <$> expr
75+lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
77+ args <- spaceSep1 patternTerm
78+ whitespace ; arrow ; whitespace
80+ return $ makeFunction args e
76−assignExpr = whitespace >> assignExprNospace
82+assignExpr = do
77−assignExprNospace = do
83+ patterns <- spaceSep1 (patternTerm <?> "the definition of a variable (x = ...)")
78− p:ps <- plus patternTerm; assign; e <- expr
84+ whitespace; string "="; whitespace; exp <- expr
79− case p:ps of
85+ case patterns of
80− PVar x : _ -> return (x, foldr func e ps)
86+ PVar f : args -> return (f, makeFunction args exp)
81− where func PAnything e' = Lambda "_" e'
87+ [PData x ps] -> if "Tuple" == take 5 x && all isDigit (drop 5 x) then
82− func (PVar x) e' = Lambda x e'
88+ fail "matching tuples is not yet supported in this context"
83− func p' e' = Lambda "_temp" (Case (Var "_temp") [(p', e')])
89+ else fail $ "Only tuples can be matched in this context, " ++
84−-- _ : [] -> return $ \hole -> Case e [(p,hole)]
90+ "not other abstract data types such as lists."
85− _ -> zero
91+ _ -> fail $ "Left-hand side of assign statement is not acceptable: " ++
92+ "only named variables, named functions, and tuples are okay."
87letExpr = do
94letExpr = do
88− t LET; brace <- optional $ t LBRACE
95+ reserved "let"
96+ brace <- optionMaybe . try $ do
98+ char '{' <?> "a set of definitions { x = ... ; y = ... }"
89 case brace of
99 case brace of
90− Nothing -> do f <- assignExpr; t IN; e <- expr; return (Let [f] e)
100+ Nothing -> do whitespace; f <- assignExpr; whitespace; reserved "in"; whitespace
91− Just LBRACE -> do fs <- sepBy1 (t SEMI) assignExpr; t RBRACE; t IN;
101+ Let [f] <$> expr
102+ Just '{' -> do whitespace ; fs <- semiSep1 assignExpr ; whitespace
103+ string "}" <?> "closing bracket '}'"
104+ whitespace; reserved "in"; whitespace; e <- expr
92− e <- expr; return (Let fs e)
105+ return (Let fs e)
94caseExpr = do
107caseExpr = do
95− t CASE; e <- expr; t OF; t LBRACE
108+ reserved "case"; whitespace; e <- expr; whitespace; reserved "of"; whitespace
96− cases <- sepBy1 (t SEMI)
109+ Case e <$> brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
97− (do { p <- patternExpr; t ARROW; e <- expr; return (p,e) })
110+ where case_ = do p <- patternExpr; whitespace; arrow; whitespace
98− t RBRACE
111+ (,) p <$> expr
99− return $ Case e cases
112+
101−-------- All Expressions --------
114+expr = choice [ ifExpr, letExpr, caseExpr, lambdaExpr, binaryExpr ] <?> "expression"
103−expr = select [ letExpr
116+def = do (f,e) <- assignExpr
110−def = do (f,e) <- assignExprNospace
111 return ([f], [e], guid >>= \x -> return [VarT x])
117 return ([f], [e], guid >>= \x -> return [VarT x])
119+defs1 = do optional freshLine
120+ d <- datatype <|> def
121+ (d:) <$> many (try (try freshLine >> (datatype <|> def)))
114− (fss,ess,tss) <- unzip3 `liftM` plus (whitespace >> plus (sat (==NEWLINE)) >> def +|+ datatype)
124+ (fss,ess,tss) <- unzip3 <$> defs1
115 let (fs,es,ts) = (concat fss, concat ess, concat `liftM` sequence tss)
125 let (fs,es,ts) = (concat fss, concat ess, concat `liftM` sequence tss)
116− star $ sat (==NEWLINE) +|+ sat (==SPACES)
126+ optional freshLine ; optional spaces ; eof
117 return (Let (zip fs es) (Var "main"), liftM (zip fs) ts)
127 return (Let (zip fs es) (Var "main"), liftM (zip fs) ts)
119−err = "Parse Error: Better error messages to come!"
120−toExpr = extractResult err . parse expr
121−toDefs = extractResult err . parse defs . (NEWLINE:)
129+toDefs source = case parse defs "" source of
130+ Right result -> Right result
131+ Left err -> Left $ "Parse error at " ++ show err