@@ -74,6 +74,7 @@ module Streamly.Internal.Data.Parser.ParserD
7474 -- Separators
7575 , takeEndBy
7676 , takeEndBy_
77+ , takeEndByEsc
7778 , takeStartBy
7879
7980 -- Words and grouping
@@ -190,6 +191,7 @@ where
190191import Control.Exception (assert, Exception)
191192import Control.Monad (when)
192193import Control.Monad.Catch (MonadCatch, MonadThrow(..))
194+import Data.Bifunctor (first)
193195import Fusion.Plugin.Types (Fuse(..))
194196import Streamly.Internal.Data.Fold.Type (Fold(..))
195197import Streamly.Internal.Data.SVar.Type (defState)
@@ -687,12 +689,39 @@ takeEndBy cond (Parser pstep pinitial pextract) =
687689 res <- pstep s a
688690 if not (cond a)
689691 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
690712 else do
691− case res of
692− Partial n s1 -> Done n <$> pextract s1
693− Done n b -> return $ Done n b
694− Continue n s1 -> Done n <$> pextract s1
695− Error _ -> return res
713+ res <- pstep s a
714+ if not (isSep a)
715+ then return $ mapStateStep Left res
716+ else extractStep pextract 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"
696725
697726-- | See 'Streamly.Internal.Data.Parser.takeEndBy_'.
698727--