@@ -30,6 +30,7 @@ module Data.Attoparsec.Combinator
31import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
31import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
32 (<|>), (*>), (<$>))
32 (<|>), (*>), (<$>))
33+import Control.Monad (MonadPlus(..))
33#if !MIN_VERSION_base(4,2,0)
34#if !MIN_VERSION_base(4,2,0)
34import Control.Applicative (many)
35import Control.Applicative (many)
@@ -65,18 +66,24 @@ option x p = p <|> pure x
65{-# SPECIALIZE option :: a -> Z.Parser a -> Z.Parser a #-}
66{-# SPECIALIZE option :: a -> Z.Parser a -> Z.Parser a #-}
69+-- | A version of 'liftM2' that is strict in the result of its first
71+liftM2' :: (Monad m) => (a -> b -> c) -> m a -> m b -> m c
76+{-# INLINE liftM2' #-}
68-- | @many' p@ applies the action @p@ /zero/ or more times. Returns a
78-- | @many' p@ applies the action @p@ /zero/ or more times. Returns a
69-- list of the returned values of @p@. The value returned by @p@ is
79-- list of the returned values of @p@. The value returned by @p@ is
70-- forced to WHNF.
80-- forced to WHNF.
72-- > word = many' letter
82-- > word = many' letter
73−many' :: (Alternative f, Monad f) => f a -> f [a]
83+many' :: (MonadPlus m) => m a -> m [a]
74many' p = many_p
84many' p = many_p
75− where many_p = some_p <|> pure []
85+ where many_p = some_p `mplus` return []
76− some_p = do
86+ some_p = liftM2' (:) p many_p
80{-# INLINE many' #-}
87{-# INLINE many' #-}
82-- | @many1 p@ applies the action @p@ /one/ or more times. Returns a
89-- | @many1 p@ applies the action @p@ /one/ or more times. Returns a
@@ -92,11 +99,8 @@ many1 p = liftA2 (:) p (many p)
92-- forced to WHNF.
99-- forced to WHNF.
94-- > word = many1' letter
101-- > word = many1' letter
95−many1' :: (Alternative f, Monad f) => f a -> f [a]
102+many1' :: (MonadPlus m) => m a -> m [a]
96−many1' p = do
103+many1' p = liftM2' (:) p (many' p)
100{-# INLINE many1' #-}
104{-# INLINE many1' #-}
102-- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
106-- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
@@ -117,13 +121,9 @@ sepBy p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure []) <|> pure []
117-- returned by @p@ is forced to WHNF.
121-- returned by @p@ is forced to WHNF.
119-- > commaSep p = p `sepBy'` (symbol ",")
123-- > commaSep p = p `sepBy'` (symbol ",")
120−sepBy' :: (Alternative f, Monad f) => f a -> f s -> f [a]
124+sepBy' :: (MonadPlus m) => m a -> m s -> m [a]
121−sepBy' p s = scan <|> pure []
125+sepBy' p s = scan `mplus` return []
122− where
126+ where scan = liftM2' (:) p ((s >> sepBy1' p s) `mplus` return [])
125− as <- (s *> sepBy1' p s) <|> pure []
127#if __GLASGOW_HASKELL__ >= 700
127#if __GLASGOW_HASKELL__ >= 700
128{-# SPECIALIZE sepBy' :: Parser ByteString a -> Parser ByteString s
128{-# SPECIALIZE sepBy' :: Parser ByteString a -> Parser ByteString s
129 -> Parser ByteString [a] #-}
129 -> Parser ByteString [a] #-}
@@ -150,11 +150,9 @@ sepBy1 p s = scan
150-- returned by @p@ is forced to WHNF.
150-- returned by @p@ is forced to WHNF.
152-- > commaSep p = p `sepBy1'` (symbol ",")
152-- > commaSep p = p `sepBy1'` (symbol ",")
153−sepBy1' :: (Alternative f, Monad f) => f a -> f s -> f [a]
153+sepBy1' :: (MonadPlus m) => m a -> m s -> m [a]
154sepBy1' p s = scan
154sepBy1' p s = scan
155− where scan = do !a <- p
155+ where scan = liftM2' (:) p ((s >> scan) `mplus` return [])
156− as <- (s *> scan) <|> pure []
158#if __GLASGOW_HASKELL__ >= 700
156#if __GLASGOW_HASKELL__ >= 700
159{-# SPECIALIZE sepBy1' :: Parser ByteString a -> Parser ByteString s
157{-# SPECIALIZE sepBy1' :: Parser ByteString a -> Parser ByteString s
160 -> Parser ByteString [a] #-}
158 -> Parser ByteString [a] #-}
@@ -189,13 +187,9 @@ manyTill p end = scan
189-- Note the overlapping parsers @anyChar@ and @string \"<!--\"@, and
187-- Note the overlapping parsers @anyChar@ and @string \"<!--\"@, and
190-- therefore the use of the 'try' combinator. The value returned by @p@
188-- therefore the use of the 'try' combinator. The value returned by @p@
191-- is forced to WHNF.
189-- is forced to WHNF.
192−manyTill' :: (Alternative f, Monad f) => f a -> f b -> f [a]
190+manyTill' :: (MonadPlus m) => m a -> m b -> m [a]
193manyTill' p end = scan
191manyTill' p end = scan
194− where scan = (end *> pure []) <|> scan'
192+ where scan = (end >> return []) `mplus` liftM2' (:) p scan
199#if __GLASGOW_HASKELL__ >= 700
193#if __GLASGOW_HASKELL__ >= 700
200{-# SPECIALIZE manyTill' :: Parser ByteString a -> Parser ByteString b
194{-# SPECIALIZE manyTill' :: Parser ByteString a -> Parser ByteString b
201 -> Parser ByteString [a] #-}
195 -> Parser ByteString [a] #-}