1 {-# OPTIONS -fglasgow-exts -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
4 -- Module : Text.ParserCombinators.ReadP
5 -- Copyright : (c) The University of Glasgow 2002
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
9 -- Stability : provisional
10 -- Portability : non-portable (local universal quantification)
12 -- This is a library of parser combinators, originally written by Koen Claessen.
13 -- It parses all alternatives in parallel, so it never keeps hold of
14 -- the beginning of the input string, a common source of space leaks with
15 -- other parsers. The '(+++)' choice combinator is genuinely commutative;
16 -- it makes no difference which branch is \"shorter\".
18 -----------------------------------------------------------------------------
20 module Text.ParserCombinators.ReadP
23 ReadP, -- :: * -> *; instance Functor, Monad, MonadPlus
25 -- * Primitive operations
27 look, -- :: ReadP String
28 (+++), -- :: ReadP a -> ReadP a -> ReadP a
29 (<++), -- :: ReadP a -> ReadP a -> ReadP a
30 gather, -- :: ReadP a -> ReadP (String, a)
34 satisfy, -- :: (Char -> Bool) -> ReadP Char
35 char, -- :: Char -> ReadP Char
36 string, -- :: String -> ReadP String
37 munch, -- :: (Char -> Bool) -> ReadP String
38 munch1, -- :: (Char -> Bool) -> ReadP String
39 skipSpaces, -- :: ReadP ()
40 choice, -- :: [ReadP a] -> ReadP a
43 ReadS, -- :: *; = String -> [(a,String)]
44 readP_to_S, -- :: ReadP a -> ReadS a
45 readS_to_P, -- :: ReadS a -> ReadP a
52 import Control.Monad( MonadPlus(..) )
53 #ifdef __GLASGOW_HASKELL__
55 import {-# SOURCE #-} GHC.Unicode ( isSpace )
59 import Data.Char( isSpace )
64 #ifdef __GLASGOW_HASKELL__
65 ------------------------------------------------------------------------
68 -- | A parser for a type @a@, represented as a function that takes a
69 -- 'String' and returns a list of possible parses as @(a,'String')@ pairs.
71 -- Note that this kind of backtracking parser is very inefficient;
72 -- reading a large structure may be quite slow (cf 'ReadP').
73 type ReadS a = String -> [(a,String)]
76 -- ---------------------------------------------------------------------------
78 -- is representation type -- should be kept abstract
82 | Look (String -> P a)
85 | Final [(a,String)] -- invariant: list is non-empty!
89 instance Monad P where
90 return x = Result x Fail
92 (Get f) >>= k = Get (\c -> f c >>= k)
93 (Look f) >>= k = Look (\s -> f s >>= k)
95 (Result x p) >>= k = k x `mplus` (p >>= k)
96 (Final r) >>= k = final [ys' | (x,s) <- r, ys' <- run (k x) s]
100 instance MonadPlus P where
103 -- most common case: two gets are combined
104 Get f1 `mplus` Get f2 = Get (\c -> f1 c `mplus` f2 c)
106 -- results are delivered as soon as possible
107 Result x p `mplus` q = Result x (p `mplus` q)
108 p `mplus` Result x q = Result x (p `mplus` q)
114 -- two finals are combined
115 -- final + look becomes one look and one final (=optimization)
116 -- final + sthg else becomes one look and one final
117 Final r `mplus` Final t = Final (r ++ t)
118 Final r `mplus` Look f = Look (\s -> Final (r ++ run (f s) s))
119 Final r `mplus` p = Look (\s -> Final (r ++ run p s))
120 Look f `mplus` Final r = Look (\s -> Final (run (f s) s ++ r))
121 p `mplus` Final r = Look (\s -> Final (run p s ++ r))
123 -- two looks are combined (=optimization)
124 -- look + sthg else floats upwards
125 Look f `mplus` Look g = Look (\s -> f s `mplus` g s)
126 Look f `mplus` p = Look (\s -> f s `mplus` p)
127 p `mplus` Look f = Look (\s -> p `mplus` f s)
129 -- ---------------------------------------------------------------------------
132 newtype ReadP a = R (forall b . (a -> P b) -> P b)
134 -- Functor, Monad, MonadPlus
136 instance Functor ReadP where
137 fmap h (R f) = R (\k -> f (k . h))
139 instance Monad ReadP where
140 return x = R (\k -> k x)
141 fail _ = R (\_ -> Fail)
142 R m >>= f = R (\k -> m (\a -> let R m' = f a in m' k))
144 instance MonadPlus ReadP where
148 -- ---------------------------------------------------------------------------
151 final :: [(a,String)] -> P a
152 -- Maintains invariant for Final constructor
156 run :: P a -> ReadS a
157 run (Get f) (c:s) = run (f c) s
158 run (Look f) s = run (f s) s
159 run (Result x p) s = (x,s) : run p s
163 -- ---------------------------------------------------------------------------
164 -- Operations over ReadP
167 -- ^ Consumes and returns the next character.
168 -- Fails if there is no input left.
172 -- ^ Look-ahead: returns the part of the input that is left, without
178 pfail = R (\_ -> Fail)
180 (+++) :: ReadP a -> ReadP a -> ReadP a
181 -- ^ Symmetric choice.
182 R f1 +++ R f2 = R (\k -> f1 k `mplus` f2 k)
184 (<++) :: ReadP a -> ReadP a -> ReadP a
185 -- ^ Local, exclusive, left-biased choice: If left parser
186 -- locally produces any result at all, then right parser is
188 #ifdef __GLASGOW_HASKELL__
191 probe (f return) s 0#
193 probe (Get f) (c:s) n = probe (f c) s (n+#1#)
194 probe (Look f) s n = probe (f s) s n
195 probe p@(Result _ _) _ n = discard n >> R (p >>=)
196 probe (Final r) _ _ = R (Final r >>=)
199 discard 0# = return ()
200 discard n = get >> discard (n-#1#)
206 probe (Get f) (c:s) n = probe (f c) s (n+1)
207 probe (Look f) s n = probe (f s) s n
208 probe p@(Result _ _) _ n = discard n >> R (p >>=)
209 probe (Final r) _ _ = R (Final r >>=)
212 discard 0 = return ()
213 discard n = get >> discard (n-1)
216 gather :: ReadP a -> ReadP (String, a)
217 -- ^ Transforms a parser into one that does the same, but
218 -- in addition returns the exact characters read.
219 -- IMPORTANT NOTE: 'gather' gives a runtime error if its first argument
220 -- is built using any occurrences of readS_to_P.
222 R (\k -> gath id (m (\a -> return (\s -> k (s,a)))))
224 gath l (Get f) = Get (\c -> gath (l.(c:)) (f c))
226 gath l (Look f) = Look (\s -> gath l (f s))
227 gath l (Result k p) = k (l []) `mplus` gath l p
228 gath l (Final r) = error "do not use readS_to_P in gather!"
230 -- ---------------------------------------------------------------------------
231 -- Derived operations
233 satisfy :: (Char -> Bool) -> ReadP Char
234 -- ^ Consumes and returns the next character, if it satisfies the
235 -- specified predicate.
236 satisfy p = do c <- get; if p c then return c else pfail
238 char :: Char -> ReadP Char
239 -- ^ Parses and returns the specified character.
240 char c = satisfy (c ==)
242 string :: String -> ReadP String
243 -- ^ Parses and returns the specified string.
244 string this = do s <- look; scan this s
246 scan [] _ = do return this
247 scan (x:xs) (y:ys) | x == y = do get; scan xs ys
250 munch :: (Char -> Bool) -> ReadP String
251 -- ^ Parses the first zero or more characters satisfying the predicate.
256 scan (c:cs) | p c = do get; s <- scan cs; return (c:s)
257 scan _ = do return ""
259 munch1 :: (Char -> Bool) -> ReadP String
260 -- ^ Parses the first one or more characters satisfying the predicate.
263 if p c then do s <- munch p; return (c:s) else pfail
265 choice :: [ReadP a] -> ReadP a
266 -- ^ Combines all parsers in the specified list.
269 choice (p:ps) = p +++ choice ps
271 skipSpaces :: ReadP ()
272 -- ^ Skips all whitespace.
277 skip (c:s) | isSpace c = do get; skip s
278 skip _ = do return ()
280 -- ---------------------------------------------------------------------------
281 -- Converting between ReadP and Read
283 readP_to_S :: ReadP a -> ReadS a
284 -- ^ Converts a parser into a Haskell ReadS-style function.
285 -- This is the main way in which you can \"run\" a 'ReadP' parser:
286 -- the expanded type is
287 -- @ readP_to_S :: ReadP a -> String -> [(a,String)] @
288 readP_to_S (R f) = run (f return)
290 readS_to_P :: ReadS a -> ReadP a
291 -- ^ Converts a Haskell ReadS-style function into a parser.
292 -- Warning: This introduces local backtracking in the resulting
293 -- parser, and therefore a possible inefficiency.
295 R (\k -> Look (\s -> final [bs'' | (a,s') <- r s, bs'' <- run (k a) s']))
297 -- ---------------------------------------------------------------------------
298 -- QuickCheck properties that hold for the combinators
301 The following are QuickCheck specifications of what the combinators do.
302 These can be seen as formal specifications of the behavior of the
305 We use bags to give semantics to the combinators.
309 Equality on bags does not care about the order of elements.
311 > (=~) :: Ord a => Bag a -> Bag a -> Bool
312 > xs =~ ys = sort xs == sort ys
314 A special equality operator to avoid unresolved overloading
315 when testing the properties.
317 > (=~.) :: Bag (Int,String) -> Bag (Int,String) -> Bool
320 Here follow the properties:
323 > readP_to_S get [] =~ []
325 > prop_Get_Cons c s =
326 > readP_to_S get (c:s) =~ [(c,s)]
329 > readP_to_S look s =~ [(s,s)]
332 > readP_to_S pfail s =~. []
335 > readP_to_S (return x) s =~. [(x,s)]
338 > readP_to_S (p >>= k) s =~.
340 > | (x,s') <- readP_to_S p s
341 > , ys'' <- readP_to_S (k (x::Int)) s'
345 > readP_to_S (p +++ q) s =~.
346 > (readP_to_S p s ++ readP_to_S q s)
348 > prop_LeftPlus p q s =
349 > readP_to_S (p <++ q) s =~.
350 > (readP_to_S p s +<+ readP_to_S q s)
356 > forAll readPWithoutReadS $ \p ->
357 > readP_to_S (gather p) s =~
358 > [ ((pre,x::Int),s')
359 > | (x,s') <- readP_to_S p s
360 > , let pre = take (length s - length s') s
363 > prop_String_Yes this s =
364 > readP_to_S (string this) (this ++ s) =~
367 > prop_String_Maybe this s =
368 > readP_to_S (string this) s =~
369 > [(this, drop (length this) s) | this `isPrefixOf` s]
372 > readP_to_S (munch p) s =~
373 > [(takeWhile p s, dropWhile p s)]
376 > readP_to_S (munch1 p) s =~
377 > [(res,s') | let (res,s') = (takeWhile p s, dropWhile p s), not (null res)]
380 > readP_to_S (choice ps) s =~.
381 > readP_to_S (foldr (+++) pfail ps) s
384 > readP_to_S (readS_to_P r) s =~. r s