@@ -76,9 +76,12 @@ module Streamly.Internal.Data.Parser.ParserD
7676 , takeEndBy_
7777 , takeEndByEsc
7878 , takeStartBy
79+ , takeFramedBy_
80+ , takeFramedByEsc_
7981
8082 -- Words and grouping
8183 , wordBy
84+ -- wordFramedBy
8285 , groupBy
8386 , groupByRolling
8487 , groupByRollingEither
@@ -787,6 +790,101 @@ takeStartBy cond (Fold fstep finitial fextract) =
787790 extract (Left' s) = fextract s
788791 extract (Right' s) = fextract s
789792
793+data FramedEscState s =
794+ FrameEscInit !s | FrameEscGo !s !Int | FrameEscEsc !s !Int
795+
796+{-# INLINE takeFramedByEsc_ #-}
797+takeFramedByEsc_ :: MonadThrow m =>
798+ (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
799+takeFramedByEsc_ isEsc isBegin isEnd (Fold fstep finitial fextract) =
800+
801+ Parser step initial extract
802+
803+ where
804+
805+ initial = do
806+ res <- finitial
807+ return $
808+ case res of
809+ FL.Partial s -> IPartial (FrameEscInit s)
810+ FL.Done _ ->
811+ error "takeFramedByEsc_: fold done without input"
812+
813+ {-# INLINE process #-}
814+ process s a n = do
815+ res <- fstep s a
816+ return
817+ $ case res of
818+ FL.Partial s1 -> Continue 0 (FrameEscGo s1 n)
819+ FL.Done b -> Done 0 b
820+
821+ step (FrameEscInit s) a =
822+ if isBegin a
823+ then return $ Partial 0 (FrameEscGo s 0)
824+ else return $ Error "takeFramedByEsc_: missing frame start"
825+ step (FrameEscGo s n) a =
826+ if isEsc a
827+ then return $ Partial 0 $ FrameEscEsc s n
828+ else do
829+ if not (isEnd a)
830+ then
831+ let n1 = if isBegin a then n + 1 else n
832+ in process s a n1
833+ else
834+ if n == 0
835+ then Done 0 <$> fextract s
836+ else process s a (n - 1)
837+ step (FrameEscEsc s n) a = process s a n
838+
839+ err = throwM . ParseError
840+
841+ extract (FrameEscInit _) = err "takeFramedByEsc_: empty token"
842+ extract (FrameEscGo _ _) = err "takeFramedByEsc_: missing frame end"
843+ extract (FrameEscEsc _ _) = err "takeFramedByEsc_: trailing escape"
844+
845+data FramedState s = FrameInit !s | FrameGo !s Int
846+
847+{-# INLINE takeFramedBy_ #-}
848+takeFramedBy_ :: MonadThrow m =>
849+ (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
850+takeFramedBy_ isBegin isEnd (Fold fstep finitial fextract) =
851+
852+ Parser step initial extract
853+
854+ where
855+
856+ initial = do
857+ res <- finitial
858+ return $
859+ case res of
860+ FL.Partial s -> IPartial (FrameInit s)
861+ FL.Done _ ->
862+ error "takeFramedBy_: fold done without input"
863+
864+ {-# INLINE process #-}
865+ process s a n = do
866+ res <- fstep s a
867+ return
868+ $ case res of
869+ FL.Partial s1 -> Continue 0 (FrameGo s1 n)
870+ FL.Done b -> Done 0 b
871+
872+ step (FrameInit s) a =
873+ if isBegin a
874+ then return $ Continue 0 (FrameGo s 0)
875+ else return $ Error "takeFramedBy_: missing frame start"
876+ step (FrameGo s n) a
877+ | not (isEnd a) =
878+ let n1 = if isBegin a then n + 1 else n
879+ in process s a n1
880+ | n == 0 = Done 0 <$> fextract s
881+ | otherwise = process s a (n - 1)
882+
883+ err = throwM . ParseError
884+
885+ extract (FrameInit _) = err "takeFramedBy_: empty token"
886+ extract (FrameGo _ _) = err "takeFramedBy_: missing frame end"
887+
790888-------------------------------------------------------------------------------
791889-- Grouping and words
792890-------------------------------------------------------------------------------