@@ -4,8 +4,10 @@ module Parse.Library where
5import Control.Applicative ((<$>),(<*>))
5import Control.Applicative ((<$>),(<*>))
6import Control.Monad
6import Control.Monad
7+import Control.Monad.State
7import Data.Char (isSymbol)
8import Data.Char (isSymbol)
8−import Text.Parsec hiding (newline,spaces)
9+import Text.Parsec hiding (newline,spaces,State)
10+import Text.Parsec.Indent
10reserveds = [ "if", "then", "else"
12reserveds = [ "if", "then", "else"
11 , "case", "of", "data"
13 , "case", "of", "data"
@@ -16,74 +18,82 @@ reserveds = [ "if", "then", "else"
17expecting = flip (<?>)
19expecting = flip (<?>)
19−backslashed :: (Monad m) => ParsecT [Char] u m Char
21+type IParser a = ParsecT String () (State SourcePos) a
23+iParse :: IParser a -> SourceName -> String -> Either ParseError a
24+iParse aParser source_name input =
25+ runIndent source_name $ runParserT aParser () source_name input
27+backslashed :: IParser Char
20backslashed = do { char '\\'; c <- anyChar
28backslashed = do { char '\\'; c <- anyChar
21 ; return . read $ ['\'','\\',c,'\''] }
29 ; return . read $ ['\'','\\',c,'\''] }
23−var :: (Monad m) => ParsecT [Char] u m String
31+var :: IParser String
24var = makeVar (letter <|> char '_' <?> "variable")
32var = makeVar (letter <|> char '_' <?> "variable")
26−lowVar :: (Monad m) => ParsecT [Char] u m String
34+lowVar :: IParser String
27lowVar = makeVar (lower <?> "lower case variable")
35lowVar = makeVar (lower <?> "lower case variable")
28−capVar :: (Monad m) => ParsecT [Char] u m String
36+capVar :: IParser String
29capVar = makeVar (upper <?> "upper case variable")
37capVar = makeVar (upper <?> "upper case variable")
31−innerVarChar :: (Monad m) => ParsecT [Char] u m Char
39+innerVarChar :: IParser Char
32innerVarChar = alphaNum <|> char '_' <|> char '\'' <?> ""
40innerVarChar = alphaNum <|> char '_' <|> char '\'' <?> ""
42+makeVar :: IParser Char -> IParser String
34makeVar p = do v <- (:) <$> p <*> many innerVarChar
43makeVar p = do v <- (:) <$> p <*> many innerVarChar
35 guard (v `notElem` reserveds)
44 guard (v `notElem` reserveds)
47+reserved :: String -> IParser String
38reserved word =
48reserved word =
39 try (string word >> notFollowedBy innerVarChar) >> return word
49 try (string word >> notFollowedBy innerVarChar) >> return word
40 <?> "reserved word '" ++ word ++ "'"
50 <?> "reserved word '" ++ word ++ "'"
42−anyOp :: (Monad m) => ParsecT [Char] u m String
52+anyOp :: IParser String
43anyOp = betwixt '`' '`' var <|> symOp <?> "infix operator (e.g. +, *, ||)"
53anyOp = betwixt '`' '`' var <|> symOp <?> "infix operator (e.g. +, *, ||)"
45isOp c = isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
55isOp c = isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
47−symOp :: (Monad m) => ParsecT [Char] u m String
57+symOp :: IParser String
48symOp = do op <- many1 (satisfy isOp)
58symOp = do op <- many1 (satisfy isOp)
49 guard (op `notElem` [ "=", "..", "->", "--", "|", "\8594" ])
59 guard (op `notElem` [ "=", "..", "->", "--", "|", "\8594" ])
52−arrow :: (Monad m) => ParsecT [Char] u m String
62+arrow :: IParser String
53arrow = string "->" <|> string "\8594" <?> "arrow (->)"
63arrow = string "->" <|> string "\8594" <?> "arrow (->)"
56commitIf check p = commit <|> try p
66commitIf check p = commit <|> try p
57 where commit = do (try $ lookAhead check) >> p
67 where commit = do (try $ lookAhead check) >> p
59−spaceySepBy1 :: (Monad m) => ParsecT [Char] u m b -> ParsecT [Char] u m a -> ParsecT [Char] u m [a]
69+spaceySepBy1 :: IParser b -> IParser a -> IParser [a]
60spaceySepBy1 sep p = do
70spaceySepBy1 sep p = do
62 (a:) <$> many (commitIf (whitespace >> sep) (whitespace >> sep >> whitespace >> p))
72 (a:) <$> many (commitIf (whitespace >> sep) (whitespace >> sep >> whitespace >> p))
65−commaSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
75+commaSep1 :: IParser a -> IParser [a]
66commaSep1 = spaceySepBy1 (char ',' <?> "comma ','")
76commaSep1 = spaceySepBy1 (char ',' <?> "comma ','")
68−commaSep :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
78+commaSep :: IParser a -> IParser [a]
69commaSep = option [] . commaSep1
79commaSep = option [] . commaSep1
71−semiSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
81+semiSep1 :: IParser a -> IParser [a]
72semiSep1 = spaceySepBy1 (char ';' <?> "semicolon ';'")
82semiSep1 = spaceySepBy1 (char ';' <?> "semicolon ';'")
74−pipeSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
84+pipeSep1 :: IParser a -> IParser [a]
75pipeSep1 = spaceySepBy1 (char '|' <?> "type divider '|'")
85pipeSep1 = spaceySepBy1 (char '|' <?> "type divider '|'")
77−consSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
87+consSep1 :: IParser a -> IParser [a]
78consSep1 = spaceySepBy1 (char ':' <?> "cons operator ':'")
88consSep1 = spaceySepBy1 (char ':' <?> "cons operator ':'")
80−dotSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
90+dotSep1 :: IParser a -> IParser [a]
81dotSep1 p = (:) <$> p <*> many (try (char '.') >> p)
91dotSep1 p = (:) <$> p <*> many (try (char '.') >> p)
83−spaceSep1 :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m [a]
93+spaceSep1 :: IParser a -> IParser [a]
84spaceSep1 p = (:) <$> p <*> spacePrefix p
94spaceSep1 p = (:) <$> p <*> spacePrefix p
86−spacePrefix p = many (commitIf (whitespace >> (char '[' <|> char '(')) (whitespace >> p))
96+spacePrefix p = many (try (whitespace >> indented >> p))
88followedBy a b = do x <- a ; b ; return x
98followedBy a b = do x <- a ; b ; return x
@@ -95,15 +105,16 @@ surround a z name p = do
95 char z <?> unwords ["closing", name, show z]
105 char z <?> unwords ["closing", name, show z]
98−braces :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
108+braces :: IParser a -> IParser a
99braces = surround '[' ']' "brace"
109braces = surround '[' ']' "brace"
101−parens :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
111+parens :: IParser a -> IParser a
102parens = surround '(' ')' "paren"
112parens = surround '(' ')' "paren"
104−brackets :: (Monad m) => ParsecT [Char] u m a -> ParsecT [Char] u m a
114+brackets :: IParser a -> IParser a
105brackets = surround '{' '}' "bracket"
115brackets = surround '{' '}' "bracket"
117+accessible :: IParser Expr -> IParser Expr
107accessible expr = do
118accessible expr = do
108 e <- expr
119 e <- expr
109 access <- optionMaybe . try $
120 access <- optionMaybe . try $
@@ -113,34 +124,34 @@ accessible expr = do
113 Nothing -> return e
124 Nothing -> return e
116−spaces :: (Monad m) => ParsecT [Char] u m String
127+spaces :: IParser String
117spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
128spaces = many1 ((multiComment <|> string " " <?> "") >> return ' ') <?> "spaces"
119−forcedWS :: (Monad m) => ParsecT [Char] u m [String]
130+forcedWS :: IParser [String]
120forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
131forcedWS = try (do { spaces; many nl_space }) <|> try (many1 nl_space)
121 where nl_space = try $ many1 newline >> spaces
132 where nl_space = try $ many1 newline >> spaces
123−whitespace :: (Monad m) => ParsecT [Char] u m ()
134+whitespace :: IParser ()
124whitespace = optional forcedWS <?> ""
135whitespace = optional forcedWS <?> ""
126−freshLine :: (Monad m) => ParsecT [Char] u m [[String]]
137+freshLine :: IParser [[String]]
127freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> ""
138freshLine = try (do { many1 newline; many space_nl }) <|> try (many1 space_nl) <?> ""
128 where space_nl = try $ spaces >> many1 newline
139 where space_nl = try $ spaces >> many1 newline
130−newline :: (Monad m) => ParsecT [Char] u m String
141+newline :: IParser String
131newline = simpleNewline <|> lineComment <?> ""
142newline = simpleNewline <|> lineComment <?> ""
133−simpleNewline :: (Monad m) => ParsecT [Char] u m String
144+simpleNewline :: IParser String
134simpleNewline = try (string "\r\n") <|> string "\n"
145simpleNewline = try (string "\r\n") <|> string "\n"
136−lineComment :: (Monad m) => ParsecT [Char] u m String
147+lineComment :: IParser String
137lineComment = do try (string "--")
148lineComment = do try (string "--")
138 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
149 manyTill anyChar $ simpleNewline <|> (eof >> return "\n")
140−multiComment :: (Monad m) => ParsecT [Char] u m String
151+multiComment :: IParser String
141multiComment = do { try (string "{-"); closeComment }
152multiComment = do { try (string "{-"); closeComment }
143−closeComment :: (Monad m) => ParsecT [Char] u m String
154+closeComment :: IParser String
144closeComment = manyTill anyChar . choice $
155closeComment = manyTill anyChar . choice $
145 [ try (string "-}") <?> "close comment"
156 [ try (string "-}") <?> "close comment"
146 , do { try $ string "{-"; closeComment; closeComment }
157 , do { try $ string "{-"; closeComment; closeComment }