on master help sign in
Add takeFramedByGeneric parser
ef2ea11Harendra Kumar
core/src/Streamly/Internal/Data/Parser.hs+31−6
@@ -127,6 +127,7 @@ module Streamly.Internal.Data.Parser
127 -- , takeFramedBy
127 -- , takeFramedBy
128 , takeFramedBy_
128 , takeFramedBy_
129 , takeFramedByEsc_
129 , takeFramedByEsc_
130+ , takeFramedByGeneric
130 -- , wordByQuoted
131 -- , wordByQuoted
131 -- , wordByQuotedEsc
132 -- , wordByQuotedEsc
132
133
@@ -660,7 +661,17 @@ dropWhile p = takeWhile p FL.drain
660-- Separators
661-- Separators
661-------------------------------------------------------------------------------
662-------------------------------------------------------------------------------
662
663
664+{-# INLINE takeFramedByGeneric #-}
665+takeFramedByGeneric :: MonadCatch m =>
666+ Maybe (a -> Bool)
667+ -> Maybe (a -> Bool)
668+ -> Maybe (a -> Bool)
669+ -> Fold m a b
670+ -> Parser m a b
671+takeFramedByGeneric esc begin end f =
672+ D.toParserK $ D.takeFramedByGeneric esc begin end f
673+
663−-- | @takeEndBy_ cond parser@ parses a token that ends by a separator chosen by
674+-- | @takeEndBy cond parser@ parses a token that ends by a separator chosen by
664-- the supplied predicate. The separator is also taken with the token.
675-- the supplied predicate. The separator is also taken with the token.
665--
676--
666-- This can be combined with other parsers to implement other interesting
677-- This can be combined with other parsers to implement other interesting
@@ -669,6 +680,8 @@ dropWhile p = takeWhile p FL.drain
669-- >>> takeEndByLE cond n p = Parser.takeEndBy cond (Parser.fromFold $ Fold.take n p)
680-- >>> takeEndByLE cond n p = Parser.takeEndBy cond (Parser.fromFold $ Fold.take n p)
670-- >>> takeEndByBetween cond m n p = Parser.takeEndBy cond (Parser.takeBetween m n p)
681-- >>> takeEndByBetween cond m n p = Parser.takeEndBy cond (Parser.takeBetween m n p)
671--
682--
683+-- >>> takeEndBy = Parser.takeEndByEsc (const False)
684+--
672-- See also "Streamly.Data.Fold.takeEndBy".
685-- See also "Streamly.Data.Fold.takeEndBy".
673--
686--
674-- /Pre-release/
687-- /Pre-release/
@@ -676,6 +689,7 @@ dropWhile p = takeWhile p FL.drain
676{-# INLINE takeEndBy #-}
689{-# INLINE takeEndBy #-}
677takeEndBy :: MonadCatch m => (a -> Bool) -> Parser m a b -> Parser m a b
690takeEndBy :: MonadCatch m => (a -> Bool) -> Parser m a b -> Parser m a b
678takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
691takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
692+-- takeEndBy = takeEndByEsc (const False)
679
693
680-- | Like 'takeEndBy' but the separator is dropped.
694-- | Like 'takeEndBy' but the separator is dropped.
681--
695--
@@ -686,6 +700,10 @@ takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
686{-# INLINE takeEndBy_ #-}
700{-# INLINE takeEndBy_ #-}
687takeEndBy_ :: MonadCatch m => (a -> Bool) -> Parser m a b -> Parser m a b
701takeEndBy_ :: MonadCatch m => (a -> Bool) -> Parser m a b -> Parser m a b
688takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
702takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
703+{-
704+takeEndBy_ isEnd p =
705+ takeFramedByGeneric Nothing Nothing (Just isEnd) (toFold p)
706+-}
689
707
690-- | Take either the separator or the token. Separator is a Left value and
708-- | Take either the separator or the token. Separator is a Left value and
691-- token is Right value.
709-- token is Right value.
@@ -724,6 +742,12 @@ takeEitherSepBy _cond = undefined -- D.toParserK . D.takeEitherSepBy cond
724takeStartBy :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
742takeStartBy :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
725takeStartBy cond = D.toParserK . D.takeStartBy cond
743takeStartBy cond = D.toParserK . D.takeStartBy cond
726
744
745+{-
746+{-# INLINE takeStartBy_ #-}
747+takeStartBy_ :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
748+takeStartBy_ isBegin = takeFramedByGeneric Nothing (Just isBegin) Nothing
749+-}
750+
727-------------------------------------------------------------------------------
751-------------------------------------------------------------------------------
728-- Quoting and Escaping
752-- Quoting and Escaping
729-------------------------------------------------------------------------------
753-------------------------------------------------------------------------------
@@ -732,14 +756,12 @@ takeStartBy cond = D.toParserK . D.takeStartBy cond
732-- escape char determined by the first predicate. The escape characters are
756-- escape char determined by the first predicate. The escape characters are
733-- removed.
757-- removed.
734--
758--
735−-- >>> takeEndBy = Parser.takeEndByEsc (const False)
736−--
737-- /pre-release/
759-- /pre-release/
738{-# INLINE takeEndByEsc #-}
760{-# INLINE takeEndByEsc #-}
739takeEndByEsc :: MonadCatch m =>
761takeEndByEsc :: MonadCatch m =>
740 (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
762 (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
741−takeEndByEsc isEsc isSep p =
763+takeEndByEsc isEsc isEnd p =
742− D.toParserK $ D.takeEndByEsc isEsc isSep (D.fromParserK p)
764+ D.toParserK $ D.takeEndByEsc isEsc isEnd (D.fromParserK p)
743
765
744-- | @takeFramedByEsc_ isEsc isBegin isEnd fold@ parses a token framed using a
766-- | @takeFramedByEsc_ isEsc isBegin isEnd fold@ parses a token framed using a
745-- begin and end predicate, and an escape character. The frame begin and end
767-- begin and end predicate, and an escape character. The frame begin and end
@@ -767,6 +789,8 @@ takeFramedByEsc_ :: MonadCatch m =>
767 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
789 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
768takeFramedByEsc_ isEsc isBegin isEnd f =
790takeFramedByEsc_ isEsc isBegin isEnd f =
769 D.toParserK $ D.takeFramedByEsc_ isEsc isBegin isEnd f
791 D.toParserK $ D.takeFramedByEsc_ isEsc isBegin isEnd f
792+-- takeEndByEsc_ isEsc isEnd p =
793+-- takeFramedByGeneric (Just isEsc) Nothing (Just isEnd) (toFold p)
770
794
771-- | @takeFramedBy_ isBegin isEnd fold@ parses a token framed by a begin and an
795-- | @takeFramedBy_ isBegin isEnd fold@ parses a token framed by a begin and an
772-- end predicate.
796-- end predicate.
@@ -777,7 +801,8 @@ takeFramedByEsc_ isEsc isBegin isEnd f =
777takeFramedBy_ :: MonadCatch m =>
801takeFramedBy_ :: MonadCatch m =>
778 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
802 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
779takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
803takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
780−-- takeFramedBy_ = takeFramedByEsc_ (const False)
804+-- takeFramedBy_ isBegin isEnd =
805+-- takeFramedByGeneric (Just (const False)) (Just isBegin) (Just isEnd)
781
806
782-------------------------------------------------------------------------------
807-------------------------------------------------------------------------------
783-- Grouping and words
808-- Grouping and words
core/src/Streamly/Internal/Data/Parser/ParserD.hs+98
@@ -78,6 +78,7 @@ module Streamly.Internal.Data.Parser.ParserD
78 , takeStartBy
78 , takeStartBy
79 , takeFramedBy_
79 , takeFramedBy_
80 , takeFramedByEsc_
80 , takeFramedByEsc_
81+ , takeFramedByGeneric
81
82
82 -- Words and grouping
83 -- Words and grouping
83 , wordBy
84 , wordBy
@@ -676,6 +677,103 @@ takeWhile1 predicate (Fold fstep finitial fextract) =
676-- Separators
677-- Separators
677-------------------------------------------------------------------------------
678-------------------------------------------------------------------------------
678
679
680+{-# INLINE takeFramedByGeneric #-}
681+takeFramedByGeneric :: MonadThrow m =>
682+ Maybe (a -> Bool)
683+ -> Maybe (a -> Bool)
684+ -> Maybe (a -> Bool)
685+ -> Fold m a b
686+ -> Parser m a b
687+takeFramedByGeneric esc begin end (Fold fstep finitial fextract) =
688+
689+ Parser step initial extract
690+
691+ where
692+
693+ initial = do
694+ res <- finitial
695+ return $
696+ case res of
697+ FL.Partial s -> IPartial (FrameEscInit s)
698+ FL.Done _ ->
699+ error "takeFramedByGeneric: fold done without input"
700+
701+ {-# INLINE process #-}
702+ process s a n = do
703+ res <- fstep s a
704+ return
705+ $ case res of
706+ FL.Partial s1 -> Continue 0 (FrameEscGo s1 n)
707+ FL.Done b -> Done 0 b
708+
709+ {-# INLINE processNoEsc #-}
710+ processNoEsc s a n =
711+ case end of
712+ Just isEnd ->
713+ case begin of
714+ Just isBegin ->
715+ -- takeFramedBy case
716+ if isEnd a
717+ then
718+ if n == 0
719+ then Done 0 <$> fextract s
720+ else process s a (n - 1)
721+ else
722+ let n1 = if isBegin a then n + 1 else n
723+ in process s a n1
724+ Nothing -> -- takeEndBy case
725+ if isEnd a
726+ then Done 0 <$> fextract s
727+ else process s a n
728+ Nothing -> -- takeStartBy case
729+ case begin of
730+ Just isBegin ->
731+ if isBegin a
732+ then Done 0 <$> fextract s
733+ else process s a n
734+ Nothing ->
735+ error $ "takeFramedByGeneric: "
736+ ++ "Both begin and end frame predicate missing"
737+
738+ {-# INLINE processCheckEsc #-}
739+ processCheckEsc s a n =
740+ case esc of
741+ Just isEsc ->
742+ if isEsc a
743+ then return $ Partial 0 $ FrameEscEsc s n
744+ else processNoEsc s a n
745+ Nothing -> processNoEsc s a n
746+
747+ step (FrameEscInit s) a =
748+ case begin of
749+ Just isBegin ->
750+ if isBegin a
751+ then return $ Partial 0 (FrameEscGo s 0)
752+ else return $ Error "takeFramedByGeneric: missing frame start"
753+ Nothing ->
754+ case end of
755+ Just isEnd ->
756+ if isEnd a
757+ then Done 0 <$> fextract s
758+ else processCheckEsc s a 0
759+ Nothing ->
760+ error "Both begin and end frame predicate missing"
761+ step (FrameEscGo s n) a = processCheckEsc s a n
762+ step (FrameEscEsc s n) a = process s a n
763+
764+ err = throwM . ParseError
765+
766+ extract (FrameEscInit _) =
767+ err "takeFramedByGeneric: empty token"
768+ extract (FrameEscGo s _) =
769+ case begin of
770+ Just _ ->
771+ case end of
772+ Nothing -> fextract s
773+ Just _ -> err "takeFramedByGeneric: missing frame end"
774+ Nothing -> err "takeFramedByGeneric: missing closing frame"
775+ extract (FrameEscEsc _ _) = err "takeFramedByGeneric: trailing escape"
776+
679-- | See 'Streamly.Internal.Data.Parser.takeEndBy'.
777-- | See 'Streamly.Internal.Data.Parser.takeEndBy'.
680--
778--
681-- /Pre-release/
779-- /Pre-release/