@@ -140,11 +140,13 @@ module Streamly.Internal.Data.Parser
140140 -- ** Sequential Repetition
141141 , count
142142 , countBetween
143− -- , countBetweenTill
144143
144+ , manyP
145145 , many
146146 , some
147+ , manyTillP
147148 , manyTill
149+ , manyThen
148150
149151 -- ** Special cases
150152 -- | TODO: traditional implmentations of these may be of limited use. For
@@ -177,10 +179,7 @@ module Streamly.Internal.Data.Parser
177179 --
178180 -- 1. Round robin
179181 -- 2. Priority based
180−
181− -- ** Interleaved repetition
182− -- | repeat one parser and when it fails run an error recovery parser
183− -- e.g. to find a key frame in the stream after an error
182+ , roundRobin
184183
185184 -- ** Collection of Alternatives
186185 -- | Unimplemented
@@ -194,13 +193,9 @@ module Streamly.Internal.Data.Parser
194193 , choice -- first successful in position
195194
196195 -- ** Repeated Alternatives
197− -- |
198− --
199− -- @
200− -- , retryMax -- try N times
201− -- , retryUntil -- try until successful
202− -- , retryUntilN -- try until successful n times
203− -- @
196+ , retryMaxTotal
197+ , retryMaxSuccessive
198+ , retry
204199 )
205200where
206201
@@ -898,6 +893,8 @@ deintercalate = undefined
898893-- | @sequence f t@ collects sequential parses of parsers in the container @t@
899894-- using the fold @f@. Fails if the input ends or any of the parsers fail.
900895--
896+-- This is same as 'Data.Traversable.sequence' but more efficient.
897+--
901898-- /Unimplemented/
902899--
903900{-# INLINE sequence #-}
@@ -927,6 +924,10 @@ concatMap f p = D.toParserK $ D.concatMap (D.fromParserK . f) (D.fromParserK p)
927924-- | @choice parsers@ applies the @parsers@ in order and returns the first
928925-- successful parse.
929926--
927+-- This is same as 'asum' but more efficient.
928+--
929+-- /Unimplemented/
930+--
930931{-# INLINE choice #-}
931932choice ::
932933 -- Foldable t =>
@@ -942,6 +943,16 @@ choice _ps = undefined
942943-- downgraded to a Fold. Or we can make the return type a Fold instead and
943944-- upgrade that to a parser when needed.
944945
946+-- | Like 'many' but uses a 'Parser' instead of a 'Fold' to collect the
947+-- results. Parsing stops or fails if the collecting parser stops or fails.
948+--
949+-- /Unimplemented/
950+--
951+{-# INLINE manyP #-}
952+manyP :: -- MonadCatch m =>
953+ Parser m b c -> Parser m a b -> Parser m a c
954+manyP _f _p = undefined -- D.toParserK $ D.manyP f (D.fromParserK p)
955+
945956-- | Collect zero or more parses. Apply the parser repeatedly on the input
946957-- stream, stop when the parser fails, accumulate zero or more parse results
947958-- using the supplied 'Fold'. This parser never fails, in case the first
@@ -968,7 +979,7 @@ many f p = D.toParserK $ D.many f (D.fromParserK p)
968979{-# INLINE some #-}
969980some :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
970981some f p = D.toParserK $ D.some f (D.fromParserK p)
971−-- some f p = many (takeGE 1 f) p
982+-- some f p = manyP (takeGE 1 f) p
972983-- many = countBetween 1 maxBound
973984
974985-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
@@ -982,7 +993,7 @@ countBetween ::
982993 -- MonadCatch m =>
983994 Int -> Int -> Fold m b c -> Parser m a b -> Parser m a c
984995countBetween _m _n _f = undefined
985−-- countBetween m n f p = many (takeBetween m n f) p
996+-- countBetween m n f p = manyP (takeBetween m n f) p
986997
987998-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
988999-- the fold @f@. Fails if the input ends or the parser fails before @n@
@@ -995,7 +1006,24 @@ count ::
9951006 -- MonadCatch m =>
9961007 Int -> Fold m b c -> Parser m a b -> Parser m a c
9971008count n = countBetween n n
998−-- count n f p = many (takeEQ n f) p
1009+-- count n f p = manyP (takeEQ n f) p
1010+
1011+-- | Like 'manyTill' but uses a 'Parser' to collect the results instead of a
1012+-- 'Fold'. Parsing stops or fails if the collecting parser stops or fails.
1013+--
1014+-- We can implemnent parsers like the following using 'manyTillP':
1015+--
1016+-- @
1017+-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
1018+-- @
1019+--
1020+-- /Unimplemented/
1021+--
1022+{-# INLINE manyTillP #-}
1023+manyTillP :: -- MonadCatch m =>
1024+ Parser m b c -> Parser m a b -> Parser m a x -> Parser m a c
1025+manyTillP _f _p1 _p2 = undefined
1026+ -- D.toParserK $ D.manyTillP f (D.fromParserK p1) (D.fromParserK p2)
9991027
10001028-- | @manyTill f collect test@ tries the parser @test@ on the input, if @test@
10011029-- fails it backtracks and tries @collect@, after @collect@ succeeds @test@ is
@@ -1010,3 +1038,68 @@ manyTill :: MonadCatch m
10101038 => Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
10111039manyTill f p1 p2 =
10121040 D.toParserK $ D.manyTill f (D.fromParserK p1) (D.fromParserK p2)
1041+
1042+-- | @manyThen f collect recover@ repeats the parser @collect@ on the input and
1043+-- collects the output in the supplied fold. If the the parser @collect@ fails,
1044+-- parser @recover@ is run until it stops and then we start repeating the
1045+-- parser @collect@ again. The parser fails if the recovery parser fails.
1046+--
1047+-- For example, this can be used to find a key frame in a video stream after an
1048+-- error.
1049+--
1050+-- /Unimplemented/
1051+--
1052+{-# INLINE manyThen #-}
1053+manyThen :: -- (Foldable t, MonadCatch m) =>
1054+ Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1055+manyThen _f _parser _recover = undefined
1056+
1057+-------------------------------------------------------------------------------
1058+-- Interleaving a collection of parsers
1059+-------------------------------------------------------------------------------
1060+--
1061+-- | Apply a collection of parsers to an input stream in a round robin fashion.
1062+-- Each parser is applied until it stops and then we repeat starting with the
1063+-- the first parser again.
1064+--
1065+-- /Unimplemented/
1066+--
1067+{-# INLINE roundRobin #-}
1068+roundRobin :: -- (Foldable t, MonadCatch m) =>
1069+ Fold m b c -> t (Parser m a b) -> Parser m a c
1070+roundRobin _f _ps = undefined
1071+
1072+-------------------------------------------------------------------------------
1073+-- Repeated Alternatives
1074+-------------------------------------------------------------------------------
1075+
1076+-- | Keep trying a parser up to a maximum of @n@ failures. When the parser
1077+-- fails the input consumed till now is dropped and the new instance is tried
1078+-- on the fresh input.
1079+--
1080+-- /Unimplemented/
1081+--
1082+{-# INLINE retryMaxTotal #-}
1083+retryMaxTotal :: -- (MonadCatch m) =>
1084+ Int -> Fold m b c -> Parser m a b -> Parser m a c
1085+retryMaxTotal _n _f _p = undefined
1086+
1087+-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
1088+--
1089+-- /Unimplemented/
1090+--
1091+{-# INLINE retryMaxSuccessive #-}
1092+retryMaxSuccessive :: -- (MonadCatch m) =>
1093+ Int -> Fold m b c -> Parser m a b -> Parser m a c
1094+retryMaxSuccessive _n _f _p = undefined
1095+
1096+-- | Keep trying a parser until it succeeds. When the parser fails the input
1097+-- consumed till now is dropped and the new instance is tried on the fresh
1098+-- input.
1099+--
1100+-- /Unimplemented/
1101+--
1102+{-# INLINE retry #-}
1103+retry :: -- (MonadCatch m) =>
1104+ Parser m a b -> Parser m a b
1105+retry _p = undefined