on master help sign in
Implement takeEndByEsc
424765dHarendra Kumar
core/src/Streamly/Internal/Data/Parser.hs+9−6
@@ -729,14 +729,17 @@ takeStartBy cond = D.toParserK . D.takeStartBy cond
729-------------------------------------------------------------------------------
729-------------------------------------------------------------------------------
730
730
731-- | Like 'takeEndBy' but the separator elements can be escaped using an
731-- | Like 'takeEndBy' but the separator elements can be escaped using an
732−-- escape char determined by the second predicate.
732+-- escape char determined by the first predicate. The escape characters are
733+-- removed.
733--
734--
734−-- /Unimplemented/
735+-- >>> takeEndBy = Parser.takeEndByEsc (const False)
736+--
737+-- /pre-release/
735{-# INLINE takeEndByEsc #-}
738{-# INLINE takeEndByEsc #-}
736−takeEndByEsc :: -- MonadCatch m =>
739+takeEndByEsc :: MonadCatch m =>
737− (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
740+ (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
738−takeEndByEsc _cond _esc = undefined
741+takeEndByEsc isEsc isSep p =
739− -- D.toParserK . D.takeEndByEsc cond esc
742+ D.toParserK $ D.takeEndByEsc isEsc isSep (D.fromParserK p)
740
743
741-- | @takeFramedByEsc begin end escape@ parses a string framed using @begin@ and
744-- | @takeFramedByEsc begin end escape@ parses a string framed using @begin@ and
742-- @end@ as the frame begin and end marker elements and @escape@ as an escaping
745-- @end@ as the frame begin and end marker elements and @escape@ as an escaping
core/src/Streamly/Internal/Data/Parser/ParserD.hs+34−5
@@ -74,6 +74,7 @@ module Streamly.Internal.Data.Parser.ParserD
74 -- Separators
74 -- Separators
75 , takeEndBy
75 , takeEndBy
76 , takeEndBy_
76 , takeEndBy_
77+ , takeEndByEsc
77 , takeStartBy
78 , takeStartBy
78
79
79 -- Words and grouping
80 -- Words and grouping
@@ -190,6 +191,7 @@ where
190import Control.Exception (assert, Exception)
191import Control.Exception (assert, Exception)
191import Control.Monad (when)
192import Control.Monad (when)
192import Control.Monad.Catch (MonadCatch, MonadThrow(..))
193import Control.Monad.Catch (MonadCatch, MonadThrow(..))
194+import Data.Bifunctor (first)
193import Fusion.Plugin.Types (Fuse(..))
195import Fusion.Plugin.Types (Fuse(..))
194import Streamly.Internal.Data.Fold.Type (Fold(..))
196import Streamly.Internal.Data.Fold.Type (Fold(..))
195import Streamly.Internal.Data.SVar.Type (defState)
197import Streamly.Internal.Data.SVar.Type (defState)
@@ -687,12 +689,39 @@ takeEndBy cond (Parser pstep pinitial pextract) =
687 res <- pstep s a
689 res <- pstep s a
688 if not (cond a)
690 if not (cond a)
689 then return res
691 then return res
692+ else extractStep pextract res
693+
694+-- | See 'Streamly.Internal.Data.Parser.takeEndByEsc'.
695+--
696+-- /Pre-release/
697+--
698+{-# INLINE takeEndByEsc #-}
699+takeEndByEsc :: MonadCatch m =>
700+ (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
701+takeEndByEsc isEsc isSep (Parser pstep pinitial pextract) =
702+
703+ Parser step initial extract
704+
705+ where
706+
707+ initial = first Left <$> pinitial
708+
709+ step (Left s) a = do
710+ if isEsc a
711+ then return $ Partial 0 $ Right s
690 else do
712 else do
691− case res of
713+ res <- pstep s a
692− Partial n s1 -> Done n <$> pextract s1
714+ if not (isSep a)
693− Done n b -> return $ Done n b
715+ then return $ mapStateStep Left res
694− Continue n s1 -> Done n <$> pextract s1
716+ else extractStep pextract res
695− Error _ -> return res
717+
718+ step (Right s) a = do
719+ res <- pstep s a
720+ return $ mapStateStep Left res
721+
722+ extract (Left s) = pextract s
723+ extract (Right _) =
724+ throwM $ ParseError "takeEndByEsc: trailing escape, end of input"
696
725
697-- | See 'Streamly.Internal.Data.Parser.takeEndBy_'.
726-- | See 'Streamly.Internal.Data.Parser.takeEndBy_'.
698--
727--
core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs+22
@@ -169,6 +169,8 @@ module Streamly.Internal.Data.Parser.ParserD.Type
169 -- * Types
169 -- * Types
170 Initial (..)
170 Initial (..)
171 , Step (..)
171 , Step (..)
172+ , mapStateStep
173+ , extractStep
172 , Parser (..)
174 , Parser (..)
173 , ParseError (..)
175 , ParseError (..)
174 , rmapM
176 , rmapM
@@ -367,6 +369,26 @@ instance Functor (Step s) where
367 fmap f (Done n b) = Done n (f b)
369 fmap f (Done n b) = Done n (f b)
368 fmap _ (Error err) = Error err
370 fmap _ (Error err) = Error err
369
371
372+-- | Map an extract function over the state of Step
373+--
374+{-# INLINE extractStep #-}
375+extractStep :: Monad m => (s -> m b) -> Step s b -> m (Step s1 b)
376+extractStep f res =
377+ case res of
378+ Partial n s1 -> Done n <$> f s1
379+ Done n b -> return $ Done n b
380+ Continue n s1 -> Done n <$> f s1
381+ Error err -> return $ Error err
382+
383+{-# INLINE mapStateStep #-}
384+mapStateStep :: (s -> s1) -> Step s b -> (Step s1 b)
385+mapStateStep f res =
386+ case res of
387+ Partial n s1 -> Partial n $ f s1
388+ Done n b -> Done n b
389+ Continue n s1 -> Continue n $ f s1
390+ Error err -> Error err
391+
370-- | Map a monadic function over the result @b@ in @Step s b@.
392-- | Map a monadic function over the result @b@ in @Step s b@.
371--
393--
372-- /Internal/
394-- /Internal/