@@ -2,6 +2,7 @@
2module ParseLib where
2module ParseLib where
5+import Control.Applicative ((<$>))
5import Control.Monad
6import Control.Monad
6import Data.Char (isSymbol)
7import Data.Char (isSymbol)
7import Text.Parsec hiding (newline,spaces)
8import Text.Parsec hiding (newline,spaces)
@@ -17,7 +18,7 @@ backslashed = do { char '\\'; c <- anyChar
17 ; return . read $ ['\'','\\',c,'\''] }
18 ; return . read $ ['\'','\\',c,'\''] }
19var :: (Monad m) => ParsecT [Char] u m String
20var :: (Monad m) => ParsecT [Char] u m String
20−var = makeVar $ letter <|> char '_'
21+var = makeVar (letter <|> char '_' <?> "variable")
22lowVar :: (Monad m) => ParsecT [Char] u m String
23lowVar :: (Monad m) => ParsecT [Char] u m String
23lowVar = makeVar (lower <?> "lower case variable")
24lowVar = makeVar (lower <?> "lower case variable")
@@ -26,7 +27,7 @@ capVar = makeVar (upper <?> "upper case variable")
27makeVar p = do
28makeVar p = do
29− cs <- many $ alphaNum <|> char '_' <|> char '\''
30+ cs <- many (alphaNum <|> char '_' <|> char '\'' <?> "")
30 guard $ c:cs `notElem` reserved
31 guard $ c:cs `notElem` reserved
31 return $ c:cs
32 return $ c:cs
@@ -34,64 +35,86 @@ makeVar p = do
34anyOp :: (Monad m) => ParsecT [Char] u m String
35anyOp :: (Monad m) => ParsecT [Char] u m String
35anyOp = betwixt '`' '`' var <|>
36anyOp = betwixt '`' '`' var <|>
36 (do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
37 (do op <- many1 (satisfy isSymbol <|> oneOf "+-/*=.$<>:&|^?%#@~!")
37− guard (op `notElem` [ "=", "..", "->" ])
38+ guard (op `notElem` [ "=", "..", "->", "--" ])
38 return op) <?> "infix operator"
39 return op) <?> "infix operator"
40−lexeme p = do whitespace ; p
41+arrow :: (Monad m) => ParsecT [Char] u m String
42+arrow = string "->" <|> string "\8594" <?> "arrow (->)"
42−symbol :: (Monad m) => String -> ParsecT [Char] u m String
44+commaSep :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
43−symbol s = whitespace >> string s
45+commaSep p = do
48+ Just a -> (a:) <$> many (try (whitespace >> char ',' >> whitespace >> p))
45−arrow :: (Monad m) => ParsecT [Char] u m String
51+semiSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
46−arrow = symbol "->" <|> symbol "\8594"
52+semiSep1 p = do a <- p
53+ (a:) <$> many (try (whitespace >> char ';' >> whitespace >> p))
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))
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))
51betwixt a b c = do char a ; out <- c
63betwixt a b c = do char a ; out <- c
52 char b <?> "closing '" ++ [b] ++ "'" ; return out
64 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
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]
71+braces :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
72+braces = surround '[' ']' "brace"
74+parens :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
75+parens = surround '(' ')' "paren"
77+brackets :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
78+brackets = surround '{' '}' "bracket"
58accessible expr = do
80accessible expr = do
60− access <- optionMaybe (char '.')
82+ access <- optionMaybe . try $
83+ (do { char '.' ; notFollowedBy (char '.') } <?> "field access (e.g. List.map)")
61 case access of
84 case access of
62− Just '.' -> accessible (Access e `liftM` var)
85+ Just _ -> accessible (Access e `liftM` var <?> "field access (e.g. List.map)")
63 Nothing -> return e
86 Nothing -> return e
66spaces :: (Monad m) => ParsecT [Char] u m String
89spaces :: (Monad m) => ParsecT [Char] u m String
67−spaces = many1 ((multiComment <|> string " ") >> return ' ') <?> "spaces"
90+spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
69forcedWS :: (Monad m) => ParsecT [Char] u m [String]
92forcedWS :: (Monad m) => ParsecT [Char] u m [String]
70forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
93forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
71 where nl_space = try $ many1 newline >> spaces
94 where nl_space = try $ many1 newline >> spaces
73whitespace :: (Monad m) => ParsecT [Char] u m ()
96whitespace :: (Monad m) => ParsecT [Char] u m ()
74−whitespace = optional forcedWS <?> "whitespace"
97+whitespace = optional forcedWS <?> ""
76freshLine :: (Monad m) => ParsecT [Char] u m [[String]]
99freshLine :: (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) <?> ""
78 where space_nl = try $ spaces >> many1 newline
101 where space_nl = try $ spaces >> many1 newline
80newline :: (Monad m) => ParsecT [Char] u m String
103newline :: (Monad m) => ParsecT [Char] u m String
81−newline = simpleNewline <|> lineComment <?> "newline"
104+newline = simpleNewline <|> lineComment <?> ""
83simpleNewline :: (Monad m) => ParsecT [Char] u m String
106simpleNewline :: (Monad m) => ParsecT [Char] u m String
84simpleNewline = try (string "\r\n") <|> string "\n"
107simpleNewline = try (string "\r\n") <|> string "\n"
86lineComment :: (Monad m) => ParsecT [Char] u m String
109lineComment :: (Monad m) => ParsecT [Char] u m String
87−lineComment = do try $ string "--"
110+lineComment = do try (string "--")
88 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
111 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
90multiComment :: (Monad m) => ParsecT [Char] u m String
113multiComment :: (Monad m) => ParsecT [Char] u m String
91−multiComment = do { try $ string "{-"; closeComment }
114+multiComment = do { try (string "{-"); closeComment }
93closeComment :: (Monad m) => ParsecT [Char] u m String
116closeComment :: (Monad m) => ParsecT [Char] u m String
94closeComment = manyTill anyChar . choice $
117closeComment = manyTill anyChar . choice $
95− [ try $ string "-}"
118+ [ try (string "-}") <?> "close comment"
96 , do { try $ string "{-"; closeComment; closeComment }
119 , do { try $ string "{-"; closeComment; closeComment }