on master help sign in
Many bug fixes for new parser. Mainly dealing with spacing issues which cause botched parses.
commitc6a5ef4a4d8de6050ed26928dc5ec22c0b7938c0 authorevancz <info@elm-lang.org> dateSat 9 Jun 2012, 11:47 (14 years ago) parent42b364d
5 files changed+103−71
elm/src/Parse/Binops.hs+8−5 elm/src/Parse/ParseLib.hs+45−22 elm/src/Parse/ParseTypes.hs+12−11 elm/src/Parse/Parser.hs+35−30 elm/src/Parse/Patterns.hs+3−3
elm/src/Parse/Binops.hs+8−5
@@ -27,10 +27,14 @@ sortOps = sortBy (\(i,_,_) (j,_,_) -> compare i j)
2727
2828binops term anyOp = do
2929 e <- term
30− (ops,es) <- liftM unzip $ many (do { op <- lexeme anyOp; e <- term; return (op,e) })
30+ (ops,es) <- liftM unzip $
31+ many (try $ do { whitespace
32+ ; op <- anyOp
33+ ; whitespace
34+ ; e <- term; return (op,e) })
3135 case binopOf Map.empty (sortOps table) ops (e:es) of
3236 Right e -> return e
33− Left msg -> mzero
37+ Left msg -> fail msg
3438
3539binopSplit seen opTable i ops es =
3640 case (splitAt i ops, splitAt (i+1) es) of
@@ -40,8 +44,7 @@ binopSplit seen opTable i ops es =
4044 return $ Binop op e1 e2
4145
4246binopOf _ _ _ [e] = return e
43−binopOf _ [] ops es =
44− return $ foldl' (flip ($)) (head es) $ zipWith Binop ops (tail es)
47+binopOf seen [] ops es = binopOf seen [(9,L,head ops)] ops es
4548
4649binopOf seen (tbl@((lvl, L, op):rest)) ops es =
4750 case elemIndices op ops of
@@ -54,7 +57,7 @@ binopOf seen (tbl@((lvl, assoc, op):rest)) ops es =
5457 case elemIndices op ops of
5558 [] -> binopOf seen rest ops es
5659 i:_ -> case Map.lookup lvl seen of
57− Nothing -> binopSplit (Map.insert lvl (R,op) seen) tbl i ops es
60+ Nothing -> binopSplit (Map.insert lvl (assoc,op) seen) tbl i ops es
5861 Just (assoc',op') ->
5962 if assoc == assoc' && assoc /= N then
6063 binopSplit seen tbl i ops es
elm/src/Parse/ParseLib.hs+45−22
@@ -2,6 +2,7 @@
22module ParseLib where
33
44import Ast
5+import Control.Applicative ((<$>))
56import Control.Monad
67import Data.Char (isSymbol)
78import Text.Parsec hiding (newline,spaces)
@@ -17,7 +18,7 @@ backslashed = do { char '\\'; c <- anyChar
1718 ; return . read $ ['\'','\\',c,'\''] }
1819
1920var :: (Monad m) => ParsecT [Char] u m String
20−var = makeVar $ letter <|> char '_'
21+var = makeVar (letter <|> char '_' <?> "variable")
2122
2223lowVar :: (Monad m) => ParsecT [Char] u m String
2324lowVar = makeVar (lower <?> "lower case variable")
@@ -26,7 +27,7 @@ capVar = makeVar (upper <?> "upper case variable")
2627
2728makeVar p = do
2829 c <- p
29− cs <- many $ alphaNum <|> char '_' <|> char '\''
30+ cs <- many (alphaNum <|> char '_' <|> char '\'' <?> "")
3031 guard $ c:cs `notElem` reserved
3132 return $ c:cs
3233
@@ -34,64 +35,86 @@ makeVar p = do
3435anyOp :: (Monad m) => ParsecT [Char] u m String
3536anyOp = betwixt '`' '`' var <|>
3637 (do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
37− guard (op `notElem` [ "=", "..", "->" ])
38+ guard (op `notElem` [ "=", "..", "->", "--" ])
3839 return op) <?> "infix operator"
3940
40−lexeme p = do whitespace ; p
41+arrow :: (Monad m) => ParsecT [Char] u m String
42+arrow = string "->" <|> string "\8594" <?> "arrow (->)"
4143
42−symbol :: (Monad m) => String -> ParsecT [Char] u m String
43−symbol s = whitespace >> string s
44+commaSep :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
45+commaSep p = do
46+ x <- optionMaybe p
47+ case x of
48+ Just a -> (a:) <$> many (try (whitespace >> char ',' >> whitespace >> p))
49+ Nothing -> return []
4450
45−arrow :: (Monad m) => ParsecT [Char] u m String
46−arrow = symbol "->" <|> symbol "\8594"
51+semiSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
52+semiSep1 p = do a <- p
53+ (a:) <$> many (try (whitespace >> char ';' >> whitespace >> p))
54+
55+pipeSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
56+pipeSep1 p = do a <- p
57+ (a:) <$> many (try (whitespace >> char '|' >> whitespace >> p))
4758
48−commaSep p = p `sepBy` lexeme (char ',')
59+spaceSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
60+spaceSep1 p = do a <- p
61+ (a:) <$> many (try (forcedWS >> p))
4962
50−
5163betwixt a b c = do char a ; out <- c
5264 char b <?> "closing '" ++ [b] ++ "'" ; return out
53−betwixtSpcs a b c = do char a ; whitespace ; out <- c ; whitespace
54− char b <?> "closing '" ++ [b] ++ "'" ; return out
5565
56−listOf p = betwixtSpcs '[' ']' $ p `sepBy` lexeme (char ',')
66+surround a z name p = do
67+ char a ; whitespace ; a <- p ; whitespace
68+ char z <?> unwords ["closing", name, show z]
69+ return a
70+
71+braces :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
72+braces = surround '[' ']' "brace"
73+
74+parens :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
75+parens = surround '(' ')' "paren"
76+
77+brackets :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
78+brackets = surround '{' '}' "bracket"
5779
5880accessible expr = do
5981 e <- expr
60− access <- optionMaybe (char '.')
82+ access <- optionMaybe . try $
83+ (do { char '.' ; notFollowedBy (char '.') } <?> "field access (e.g. List.map)")
6184 case access of
62− Just '.' -> accessible (Access e `liftM` var)
85+ Just _ -> accessible (Access e `liftM` var <?> "field access (e.g. List.map)")
6386 Nothing -> return e
6487
6588
6689spaces :: (Monad m) => ParsecT [Char] u m String
67−spaces = many1 ((multiComment <|> string " ") >> return ' ') <?> "spaces"
90+spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
6891
6992forcedWS :: (Monad m) => ParsecT [Char] u m [String]
7093forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
7194 where nl_space = try $ many1 newline >> spaces
7295
7396whitespace :: (Monad m) => ParsecT [Char] u m ()
74−whitespace = optional forcedWS <?> "whitespace"
97+whitespace = optional forcedWS <?> ""
7598
7699freshLine :: (Monad m) => ParsecT [Char] u m [[String]]
77−freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> "fresh line"
100+freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> ""
78101 where space_nl = try $ spaces >> many1 newline
79102
80103newline :: (Monad m) => ParsecT [Char] u m String
81−newline = simpleNewline <|> lineComment <?> "newline"
104+newline = simpleNewline <|> lineComment <?> ""
82105
83106simpleNewline :: (Monad m) => ParsecT [Char] u m String
84107simpleNewline = try (string "\r\n") <|> string "\n"
85108
86109lineComment :: (Monad m) => ParsecT [Char] u m String
87−lineComment = do try $ string "--"
110+lineComment = do try (string "--")
88111 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
89112
90113multiComment :: (Monad m) => ParsecT [Char] u m String
91−multiComment = do { try $ string "{-"; closeComment }
114+multiComment = do { try (string "{-"); closeComment }
92115
93116closeComment :: (Monad m) => ParsecT [Char] u m String
94117closeComment = manyTill anyChar . choice $
95− [ try $ string "-}"
118+ [ try (string "-}") <?> "close comment"
96119 , do { try $ string "{-"; closeComment; closeComment }
97120 ]
elm/src/Parse/ParseTypes.hs+12−11
@@ -9,7 +9,7 @@ import Data.List (lookup)
99import Text.Parsec
1010
1111import ParseLib
12−import Types
12+import Types hiding (string,parens)
1313import Guid
1414
1515data ParseType = VarPT String
@@ -23,10 +23,10 @@ typeVar :: (Monad m) => ParsecT [Char] u m ParseType
2323typeVar = VarPT <$> lowVar <?> "type variable"
2424
2525typeList :: (Monad m) => ParsecT [Char] u m ParseType
26−typeList = listPT <$> betwixtSpcs '[' ']' typeExpr
26+typeList = listPT <$> braces typeExpr
2727
2828typeTuple :: (Monad m) => ParsecT [Char] u m ParseType
29−typeTuple = do ts <- betwixtSpcs '(' ')' (commaSep typeExpr)
29+typeTuple = do ts <- parens (commaSep typeExpr)
3030 return $ case ts of { [t] -> t ; _ -> tuplePT ts }
3131
3232typeUnambiguous :: (Monad m) => ParsecT [Char] u m ParseType
@@ -44,22 +44,23 @@ typeApp = do name <- capVar
4444
4545typeExpr :: (Monad m) => ParsecT [Char] u m ParseType
4646typeExpr = do
47− whitespace
4847 t1 <- typeVar <|> typeApp <|> typeUnambiguous
49− arrow <- optionMaybe arrow
48+ whitespace ; arrow <- optionMaybe arrow ; whitespace
5049 case arrow of Just _ -> LambdaPT t1 <$> typeExpr
5150 Nothing -> return t1
5251
5352typeConstructor :: (Monad m) => ParsecT [Char] u m (String, [ParseType])
54−typeConstructor = do name <- capVar
55− args <- many (typeSimple <|> typeUnambiguous)
56− return $ (,) name args
53+typeConstructor = do
54+ name <- capVar
55+ args <- many (try (forcedWS >> (typeSimple <|> typeUnambiguous)))
56+ return $ (,) name args
5757
5858datatype :: (Monad m) => ParsecT [Char] u m ([String], [Expr], GuidCounter [Type])
5959datatype = do
60− symbol "data" <?> "datatype definition"
61− name <- capVar ; args <- many lowVar ; symbol "="
62− tcs <- typeConstructor `sepBy1` symbol "|"
60+ string "data" <?> "datatype definition (data T = A | B | ...)"
61+ forcedWS ; name <- capVar ; args <- many (try (forcedWS >> lowVar))
62+ whitespace ; string "=" ; whitespace
63+ tcs <- pipeSep1 typeConstructor
6364 return $ (map fst tcs , map toFunc tcs , toTypes name args tcs)
6465
6566beta = liftM VarT guid
elm/src/Parse/Parser.hs+35−30
@@ -37,27 +37,28 @@ chrTerm = Chr <$> betwixt '\'' '\'' (backslashed <|> satisfy (/='\'')) <?> "char
3737
3838-------- Complex Terms --------
3939
40−listTerm = expecting "list" . betwixtSpcs '[' ']' $ choice
41− [ try $ do { lo <- expr; symbol ".." ; Range lo <$> expr }
40+listTerm = braces $ choice
41+ [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
42+ ; Range lo <$> expr }
4243 , list <$> commaSep expr
4344 ]
4445
45−parensTerm = expecting "parenthesized expression" . betwixtSpcs '(' ')' $ choice
46+parensTerm = parens $ choice
4647 [ do op <- anyOp
4748 return . Lambda "x" . Lambda "y" $ Binop op (Var "x") (Var "y")
4849 , do es <- commaSep expr
4950 return $ case es of { [e] -> e; _ -> tuple es }
5051 ]
5152
52−term = lexeme (choice [ numTerm, strTerm, chrTerm
53− , accessible varTerm
54− , listTerm, parensTerm ])
53+term = choice [ numTerm, strTerm, chrTerm
54+ , accessible varTerm
55+ , listTerm, parensTerm ]
5556 <?> "basic term (number, variable, etc.)"
5657
5758-------- Applications --------
5859
5960appExpr = do
60− tlist <- many1 (try term)
61+ tlist <- spaceSep1 term
6162 return $ case tlist of
6263 t:[] -> t
6364 t:ts -> foldl' App t ts
@@ -66,20 +67,20 @@ appExpr = do
6667
6768binaryExpr = binops appExpr anyOp
6869
69−ifExpr = expecting "if expression" $
70− do symbol "if" ; e1 <- expr
71− symbol "then" ; e2 <- expr
72− expecting "else branch" $ do
73− symbol "else" ; If e1 e2 <$> expr
70+ifExpr = do string "if" ; forcedWS ; e1 <- expr ; forcedWS
71+ string "then" ; forcedWS ; e2 <- expr ; (forcedWS <?> "an 'else' branch")
72+ string "else" <?> "an 'else' branch" ; forcedWS ; If e1 e2 <$> expr
7473
75−lambdaExpr = do lexeme $ oneOf "\\\x03BB"
76− args <- patternTerm `endBy1` whitespace
77− arrow
74+lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
75+ whitespace
76+ args <- spaceSep1 patternTerm
77+ whitespace ; arrow ; whitespace
7878 e <- expr
7979 return $ makeFunction args e
8080
8181assignExpr = do
82− patterns <- (patternTerm <?> "definition") `endBy1` whitespace; symbol "="; exp <- expr
82+ patterns <- spaceSep1 (patternTerm <?> "the definition of a variable (x = ...)")
83+ whitespace; string "="; whitespace; exp <- expr
8384 case patterns of
8485 PVar f : args -> return (f, makeFunction args exp)
8586 [PData x ps] -> if "Tuple" == take 5 x && all isDigit (drop 5 x) then
@@ -90,32 +91,36 @@ assignExpr = do
9091 "only named variables, named functions, and tuples are okay."
9192
9293letExpr = do
93− symbol "let"; brace <- optionMaybe . lexeme $ char '{'
94+ string "let"
95+ brace <- optionMaybe . try $ do
96+ whitespace
97+ char '{' <?> "a set of definitions { x = ... ; y = ... }"
9498 case brace of
95− Nothing -> do f <- assignExpr; symbol "in"; e <- expr; return (Let [f] e)
96− Just '{' -> do fs <- assignExpr `sepBy1` symbol ";"
97− symbol "}" ; symbol "in"; e <- expr
99+ Nothing -> do forcedWS; f <- assignExpr; forcedWS; string "in"; forcedWS;
100+ Let [f] <$> expr
101+ Just '{' -> do whitespace ; fs <- semiSep1 assignExpr ; whitespace
102+ string "}" <?> "closing bracket '}'"
103+ whitespace; string "in"; forcedWS; e <- expr
98104 return (Let fs e)
99105
100106caseExpr = do
101− symbol "case"; e <- expr; symbol "of"
102− betwixtSpcs '{' '}' $ Case e <$> case_ `sepBy1` symbol ";"
103− where case_ = do p <- patternExpr; whitespace; arrow; e <- expr; return (p,e)
107+ string "case"; forcedWS; e <- expr; forcedWS; string "of"; whitespace
108+ Case e <$> brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
109+ where case_ = do p <- patternExpr; whitespace; arrow; whitespace
110+ (,) p <$> expr
104111
105112
106−expr = choice [ ifExpr, letExpr, caseExpr, lambdaExpr, binaryExpr ]
113+expr = choice [ ifExpr, letExpr, caseExpr, lambdaExpr, binaryExpr ] <?> "expression"
107114
108115def = do (f,e) <- assignExpr
109116 return ([f], [e], guid >>= \x -> return [VarT x])
110117
111−manyDefs = try (do { d <- anyDef ; ds <- many freshDef ; return (d:ds) })
112− <|> try (many1 freshDef)
113− where freshDef = try $ many1 freshLine >> anyDef
114− anyDef = def <|> datatype
118+defs1 = do optional freshLine
119+ d <- datatype <|> def
120+ (d:) <$> many (try (freshLine >> (datatype <|> def)))
115121
116122defs = do
117− ds <- manyDefs
118− let (fss,ess,tss) = unzip3 ds
123+ (fss,ess,tss) <- unzip3 <$> defs1
119124 let (fs,es,ts) = (concat fss, concat ess, concat `liftM` sequence tss)
120125 optional freshLine ; optional whitespace ; eof
121126 return (Let (zip fs es) (Var "main"), liftM (zip fs) ts)
elm/src/Parse/Patterns.hs+3−3
@@ -21,19 +21,19 @@ patternBasic =
2121 ]
2222
2323patternTuple :: Monad m => ParsecT [Char] u m Pattern
24−patternTuple = do ps <- betwixtSpcs '(' ')' $ patternExpr `sepBy` lexeme (char ',')
24+patternTuple = do ps <- parens (commaSep patternExpr)
2525 return $ case ps of { [p] -> p; _ -> ptuple ps }
2626
2727patternCons :: Monad m => ParsecT [Char] u m Pattern
2828patternCons = do
2929 p <- patternTerm
30− colon <- optionMaybe (char ':')
30+ colon <- optionMaybe (char ':' <?> "more complicated pattern")
3131 case colon of
3232 Just ':' -> pcons p <$> patternExpr
3333 Nothing -> return p
3434
3535patternList :: Monad m => ParsecT [Char] u m Pattern
36−patternList = plist <$> listOf patternExpr
36+patternList = plist <$> braces (commaSep patternExpr)
3737
3838patternTerm :: Monad m => ParsecT [Char] u m Pattern
3939patternTerm = patternTuple <|> patternList <|> patternBasic <?> "pattern"