11module Text.Parsing.StringParser where
22
3+ import Data.Maybe (Maybe (..))
34import Data.String (charAt , length , take )
45import Data.Either (Either (..))
56
@@ -64,15 +65,13 @@ instance alternativeParser :: Alternative Parser where
6465 unParser p1 s (\_ ->
6566 unParser p2 s fc sc) sc)
6667
67- --
68- -- Error handling combinator
69- --
70- (<?>) :: forall a . Parser a -> String -> Parser a
71- (<?>) p msg = Parser (\s fc sc -> unParser p s (\_ -> fc (ParseError msg)) sc)
72-
7368--
7469-- Some elementary parsers
7570--
71+
72+ fail :: forall a . String -> Parser a
73+ fail msg = Parser (\_ fc _ -> fc (ParseError msg))
74+
7675eof :: Parser { }
7776eof = Parser (\s fc sc -> case s of
7877 { str = str, pos = i } | i < length str -> fc (ParseError " Expected EOF" )
@@ -94,6 +93,104 @@ foreign import indexOf'
9493
9594string :: String -> Parser String
9695string nt = Parser (\s fc sc -> case s of
97- { str = str, pos = i } | indexOf' nt i str == 0 -> sc nt { str: str, pos: i + length nt }
98- _ -> fc (ParseError $ " Expected '" ++ nt ++ " '" ))
96+ { str = str, pos = i } | indexOf' nt i str == i -> sc nt { str: str, pos: i + length nt }
97+ { pos = i } -> fc (ParseError $ " Expected '" ++ nt ++ " ' at position " ++ show i ++ " . " ))
9998
99+ --
100+ -- Parsing Combinators
101+ --
102+
103+ many :: forall a . Parser a -> Parser [a ]
104+ many p = many1 p <|> return []
105+
106+ many1 :: forall a . Parser a -> Parser [a ]
107+ many1 p = do
108+ a <- p
109+ as <- many p
110+ return (a : as)
111+
112+ (<?>) :: forall a . Parser a -> String -> Parser a
113+ (<?>) p msg = p <|> fail msg
114+
115+ fix :: forall a . (Parser a -> Parser a ) -> Parser a
116+ fix f = Parser (\s fc sc -> unParser (f (fix f)) s fc sc)
117+
118+ between :: forall a open close . Parser open -> Parser close -> Parser a -> Parser a
119+ between open close p = do
120+ open
121+ a <- p
122+ close
123+ return a
124+
125+ option :: forall a . a -> Parser a -> Parser a
126+ option a p = p <|> return a
127+
128+ optional :: forall a . Parser a -> Parser { }
129+ optional p = (p >>= \_ -> return {}) <|> return {}
130+
131+ optionMaybe :: forall a . Parser a -> Parser (Maybe a )
132+ optionMaybe p = option Nothing (Just <$> p)
133+
134+ sepBy :: forall a sep . Parser a -> Parser sep -> Parser [a ]
135+ sepBy p sep = sepBy1 p sep <|> return []
136+
137+ sepBy1 :: forall a sep . Parser a -> Parser sep -> Parser [a ]
138+ sepBy1 p sep = do
139+ a <- p
140+ as <- many $ do
141+ sep
142+ p
143+ return (a : as)
144+
145+ sepEndBy :: forall a sep . Parser a -> Parser sep -> Parser [a ]
146+ sepEndBy p sep = sepEndBy1 p sep <|> return []
147+
148+ sepEndBy1 :: forall a sep . Parser a -> Parser sep -> Parser [a ]
149+ sepEndBy1 p sep = do
150+ a <- p
151+ (do sep
152+ as <- sepEndBy p sep
153+ return (a : as)) <|> return [a]
154+
155+ endBy1 :: forall a sep . Parser a -> Parser sep -> Parser [a ]
156+ endBy1 p sep = many1 $ do
157+ a <- p
158+ sep
159+ return a
160+
161+ endBy :: forall a sep . Parser a -> Parser sep -> Parser [a ]
162+ endBy p sep = many $ do
163+ a <- p
164+ sep
165+ return a
166+
167+ chainr :: forall a . Parser a -> Parser (a -> a -> a ) -> a -> Parser a
168+ chainr p f a = chainr1 p f <|> return a
169+
170+ chainl :: forall a . Parser a -> Parser (a -> a -> a ) -> a -> Parser a
171+ chainl p f a = chainl1 p f <|> return a
172+
173+ chainl1 :: forall a . Parser a -> Parser (a -> a -> a ) -> Parser a
174+ chainl1 p f = do
175+ a <- p
176+ chainl1' p f a
177+
178+ chainl1' :: forall a . Parser a -> Parser (a -> a -> a ) -> a -> Parser a
179+ chainl1' p f a = (do f' <- f
180+ a' <- p
181+ chainl1' p f (f' a a')) <|> return a
182+
183+ chainr1 :: forall a . Parser a -> Parser (a -> a -> a ) -> Parser a
184+ chainr1 p f = do
185+ a <- p
186+ chainr1' p f a
187+
188+ chainr1' :: forall a . Parser a -> Parser (a -> a -> a ) -> a -> Parser a
189+ chainr1' p f a = (do f' <- f
190+ a' <- chainr1 p f
191+ return $ f' a a') <|> return a
192+
193+ choice :: forall a . [Parser a ] -> Parser a
194+ choice [] = fail " Nothing to parse"
195+ choice [x] = x
196+ choice (x:xs) = x <|> choice xs
0 commit comments