on master help sign in
Implement takeWhileP parser
commit8bf2703dafe2a4a43fd26728b002f4864f414d3a authorHarendra Kumar <harendra@composewell.com> dateFri 6 May 2022, 17:31 (4 years ago) parent0409d4b
2 files changed+31−7
core/src/Streamly/Internal/Data/Parser.hs+14−7 core/src/Streamly/Internal/Data/Parser/ParserD.hs+17
core/src/Streamly/Internal/Data/Parser.hs+14−7
@@ -578,6 +578,8 @@ takeGE n = D.toParserK . D.takeGE n
578578-- $takeWhile
579579-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
580580
581+-- XXX We should perhaps use only takeWhileP and rename it to takeWhile.
582+--
581583-- | Like 'takeWhile' but uses a 'Parser' instead of a 'Fold' to collect the
582584-- input. The combinator stops when the condition fails or if the collecting
583585-- parser stops.
@@ -585,19 +587,16 @@ takeGE n = D.toParserK . D.takeGE n
585587-- This is a generalized version of takeWhile, for example 'takeWhile1' can be
586588-- implemented in terms of this:
587589--
588−-- @
589−-- takeWhile1 cond p = takeWhile cond (takeBetween 1 maxBound p)
590−-- @
590+-- >>> takeWhile1 cond p = takeWhile cond (takeBetween 1 maxBound p)
591591--
592592-- Stops: when the condition fails or the collecting parser stops.
593593-- Fails: when the collecting parser fails.
594594--
595−-- /Unimplemented/
595+-- /Pre-release/
596596--
597597{-# INLINE takeWhileP #-}
598−takeWhileP :: -- MonadCatch m =>
599− (a -> Bool) -> Parser m a b -> Parser m a b
600−takeWhileP _cond = undefined -- D.toParserK . D.takeWhileP cond
598+takeWhileP :: MonadCatch m => (a -> Bool) -> Parser m a b -> Parser m a b
599+takeWhileP cond p = D.toParserK $ D.takeWhileP cond (D.fromParserK p)
601600
602601-- | Collect stream elements until an element fails the predicate. The element
603602-- on which the predicate fails is returned back to the input stream.
@@ -608,6 +607,8 @@ takeWhileP _cond = undefined -- D.toParserK . D.takeWhileP cond
608607-- >>> Stream.parse (Parser.takeWhile (== 0) Fold.toList) $ Stream.fromList [0,0,1,0,1]
609608-- [0,0]
610609--
610+-- >>> takeWhile cond f = Parser.takeWhileP cond (Parser.fromFold f)
611+--
611612-- We can implement a @breakOn@ using 'takeWhile':
612613--
613614-- @
@@ -619,20 +620,26 @@ takeWhileP _cond = undefined -- D.toParserK . D.takeWhileP cond
619620{-# INLINE takeWhile #-}
620621takeWhile :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
621622takeWhile cond = D.toParserK . D.takeWhile cond
623+-- takeWhile cond f = takeWhileP cond (fromFold f)
622624
623625-- | Like 'takeWhile' but takes at least one element otherwise fails.
624626--
627+-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
628+--
625629-- /Pre-release/
626630--
627631{-# INLINE takeWhile1 #-}
628632takeWhile1 :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
629633takeWhile1 cond = D.toParserK . D.takeWhile1 cond
634+-- takeWhile1 cond f = takeWhileP cond (takeBetween 1 maxBound f)
630635
631636-- | Drain the input as long as the predicate succeeds, running the effects and
632637-- discarding the results.
633638--
634639-- This is also called @skipWhile@ in some parsing libraries.
635640--
641+-- >>> dropWhile p = Parser.takeWhile p Fold.drain
642+--
636643-- /Pre-release/
637644--
638645{-# INLINE dropWhile #-}
core/src/Streamly/Internal/Data/Parser/ParserD.hs+17
@@ -68,6 +68,7 @@ module Streamly.Internal.Data.Parser.ParserD
6868 -- Grab a sequence of input elements by inspecting them
6969 , lookAhead
7070 , takeWhile
71+ , takeWhileP
7172 , takeWhile1
7273
7374 -- Separators
@@ -580,6 +581,22 @@ takeGE n (Fold fstep finitial fextract) = Parser step initial extract
580581-- Conditional splitting
581582-------------------------------------------------------------------------------
582583
584+-- | See 'Streamly.Internal.Data.Parser.takeWhileP'.
585+--
586+-- /Pre-release/
587+--
588+{-# INLINE takeWhileP #-}
589+takeWhileP :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
590+takeWhileP predicate (Parser pstep pinitial pextract) =
591+ Parser step pinitial pextract
592+
593+ where
594+
595+ step s a =
596+ if predicate a
597+ then pstep s a
598+ else Done 1 <$> pextract s
599+
583600-- | See 'Streamly.Internal.Data.Parser.takeWhile'.
584601--
585602-- /Pre-release/