module Distribution.Compat.ReadP
(
ReadP,
get,
look,
(+++),
(<++),
gather,
pfail,
satisfy,
char,
string,
munch,
munch1,
skipSpaces,
choice,
count,
between,
option,
optional,
many,
many1,
skipMany,
skipMany1,
sepBy,
sepBy1,
endBy,
endBy1,
chainr,
chainl,
chainl1,
chainr1,
manyTill,
ReadS,
readP_to_S,
readS_to_P
)
where
import Control.Monad( MonadPlus(..), liftM, liftM2, ap )
import Data.Char (isSpace)
import Control.Applicative (Applicative(..), Alternative(empty, (<|>)))
infixr 5 +++, <++
data P s a
= Get (s -> P s a)
| Look ([s] -> P s a)
| Fail
| Result a (P s a)
| Final [(a,[s])]
instance Functor (P s) where
fmap = liftM
instance Applicative (P s) where
pure = return
(<*>) = ap
instance Monad (P s) where
return x = Result x Fail
(Get f) >>= k = Get (\c -> f c >>= k)
(Look f) >>= k = Look (\s -> f s >>= k)
Fail >>= _ = Fail
(Result x p) >>= k = k x `mplus` (p >>= k)
(Final r) >>= k = final [ys' | (x,s) <- r, ys' <- run (k x) s]
fail _ = Fail
instance Alternative (P s) where
empty = mzero
(<|>) = mplus
instance MonadPlus (P s) where
mzero = Fail
Get f1 `mplus` Get f2 = Get (\c -> f1 c `mplus` f2 c)
Result x p `mplus` q = Result x (p `mplus` q)
p `mplus` Result x q = Result x (p `mplus` q)
Fail `mplus` p = p
p `mplus` Fail = p
Final r `mplus` Final t = Final (r ++ t)
Final r `mplus` Look f = Look (\s -> Final (r ++ run (f s) s))
Final r `mplus` p = Look (\s -> Final (r ++ run p s))
Look f `mplus` Final r = Look (\s -> Final (run (f s) s ++ r))
p `mplus` Final r = Look (\s -> Final (run p s ++ r))
Look f `mplus` Look g = Look (\s -> f s `mplus` g s)
Look f `mplus` p = Look (\s -> f s `mplus` p)
p `mplus` Look f = Look (\s -> p `mplus` f s)
newtype Parser r s a = R ((a -> P s r) -> P s r)
type ReadP r a = Parser r Char a
instance Functor (Parser r s) where
fmap h (R f) = R (\k -> f (k . h))
instance Applicative (Parser r s) where
pure = return
(<*>) = ap
instance Monad (Parser r s) where
return x = R (\k -> k x)
fail _ = R (\_ -> Fail)
R m >>= f = R (\k -> m (\a -> let R m' = f a in m' k))
final :: [(a,[s])] -> P s a
final [] = Fail
final r = Final r
run :: P c a -> ([c] -> [(a, [c])])
run (Get f) (c:s) = run (f c) s
run (Look f) s = run (f s) s
run (Result x p) s = (x,s) : run p s
run (Final r) _ = r
run _ _ = []
get :: ReadP r Char
get = R Get
look :: ReadP r String
look = R Look
pfail :: ReadP r a
pfail = R (\_ -> Fail)
(+++) :: ReadP r a -> ReadP r a -> ReadP r a
R f1 +++ R f2 = R (\k -> f1 k `mplus` f2 k)
(<++) :: ReadP a a -> ReadP r a -> ReadP r a
R f <++ q =
do s <- look
probe (f return) s 0
where
probe (Get f') (c:s) n = probe (f' c) s (n+1 :: Int)
probe (Look f') s n = probe (f' s) s n
probe p@(Result _ _) _ n = discard n >> R (p >>=)
probe (Final r) _ _ = R (Final r >>=)
probe _ _ _ = q
discard 0 = return ()
discard n = get >> discard (n-1 :: Int)
gather :: ReadP (String -> P Char r) a -> ReadP r (String, a)
gather (R m) =
R (\k -> gath id (m (\a -> return (\s -> k (s,a)))))
where
gath l (Get f) = Get (\c -> gath (l.(c:)) (f c))
gath _ Fail = Fail
gath l (Look f) = Look (\s -> gath l (f s))
gath l (Result k p) = k (l []) `mplus` gath l p
gath _ (Final _) = error "do not use readS_to_P in gather!"
satisfy :: (Char -> Bool) -> ReadP r Char
satisfy p = do c <- get; if p c then return c else pfail
char :: Char -> ReadP r Char
char c = satisfy (c ==)
string :: String -> ReadP r String
string this = do s <- look; scan this s
where
scan [] _ = do return this
scan (x:xs) (y:ys) | x == y = do get >> scan xs ys
scan _ _ = do pfail
munch :: (Char -> Bool) -> ReadP r String
munch p =
do s <- look
scan s
where
scan (c:cs) | p c = do _ <- get; s <- scan cs; return (c:s)
scan _ = do return ""
munch1 :: (Char -> Bool) -> ReadP r String
munch1 p =
do c <- get
if p c then do s <- munch p; return (c:s)
else pfail
choice :: [ReadP r a] -> ReadP r a
choice [] = pfail
choice [p] = p
choice (p:ps) = p +++ choice ps
skipSpaces :: ReadP r ()
skipSpaces =
do s <- look
skip s
where
skip (c:s) | isSpace c = do _ <- get; skip s
skip _ = do return ()
count :: Int -> ReadP r a -> ReadP r [a]
count n p = sequence (replicate n p)
between :: ReadP r open -> ReadP r close -> ReadP r a -> ReadP r a
between open close p = do _ <- open
x <- p
_ <- close
return x
option :: a -> ReadP r a -> ReadP r a
option x p = p +++ return x
optional :: ReadP r a -> ReadP r ()
optional p = (p >> return ()) +++ return ()
many :: ReadP r a -> ReadP r [a]
many p = return [] +++ many1 p
many1 :: ReadP r a -> ReadP r [a]
many1 p = liftM2 (:) p (many p)
skipMany :: ReadP r a -> ReadP r ()
skipMany p = many p >> return ()
skipMany1 :: ReadP r a -> ReadP r ()
skipMany1 p = p >> skipMany p
sepBy :: ReadP r a -> ReadP r sep -> ReadP r [a]
sepBy p sep = sepBy1 p sep +++ return []
sepBy1 :: ReadP r a -> ReadP r sep -> ReadP r [a]
sepBy1 p sep = liftM2 (:) p (many (sep >> p))
endBy :: ReadP r a -> ReadP r sep -> ReadP r [a]
endBy p sep = many (do x <- p ; _ <- sep ; return x)
endBy1 :: ReadP r a -> ReadP r sep -> ReadP r [a]
endBy1 p sep = many1 (do x <- p ; _ <- sep ; return x)
chainr :: ReadP r a -> ReadP r (a -> a -> a) -> a -> ReadP r a
chainr p op x = chainr1 p op +++ return x
chainl :: ReadP r a -> ReadP r (a -> a -> a) -> a -> ReadP r a
chainl p op x = chainl1 p op +++ return x
chainr1 :: ReadP r a -> ReadP r (a -> a -> a) -> ReadP r a
chainr1 p op = scan
where scan = p >>= rest
rest x = do f <- op
y <- scan
return (f x y)
+++ return x
chainl1 :: ReadP r a -> ReadP r (a -> a -> a) -> ReadP r a
chainl1 p op = p >>= rest
where rest x = do f <- op
y <- p
rest (f x y)
+++ return x
manyTill :: ReadP r a -> ReadP [a] end -> ReadP r [a]
manyTill p end = scan
where scan = (end >> return []) <++ (liftM2 (:) p scan)
readP_to_S :: ReadP a a -> ReadS a
readP_to_S (R f) = run (f return)
readS_to_P :: ReadS a -> ReadP r a
readS_to_P r =
R (\k -> Look (\s -> final [bs'' | (a,s') <- r s, bs'' <- run (k a) s']))