@@ -125,6 +125,7 @@ module Streamly.Internal.Data.Parser.ParserD.Type
126 , splitSome -- parseSome?
126 , splitSome -- parseSome?
127 , splitMany -- parseMany?
127 , splitMany -- parseMany?
129 , concatMap
130 , concatMap
@@ -656,6 +657,67 @@ splitMany (Parser step1 initial1 extract1) (Fold fstep finitial fextract) =
656 FL.Partial s1 -> fextract s1
657 FL.Partial s1 -> fextract s1
657 FL.Done b1 -> return b1
658 FL.Done b1 -> return b1
660+-- | Like splitMany, but inner fold emits an output at the end even if no input
665+{-# INLINE splitManyPost #-}
666+splitManyPost :: MonadCatch m => Parser m a b -> Fold m b c -> Parser m a c
667+splitManyPost (Parser step1 initial1 extract1) (Fold fstep finitial fextract) =
668+ Parser step initial extract
672+ -- Caution! There is mutual recursion here, inlining the right functions is
675+ {-# INLINE handleCollect #-}
676+ handleCollect partial done fres =
681+ IPartial ps -> return $ partial $ Tuple3' ps 0 fs
683+ runCollectorWith (handleCollect partial done) fs pb
684+ IError _ -> done <$> fextract fs
685+ FL.Done fb -> return $ done fb
687+ -- Do not inline this
688+ runCollectorWith cont fs pb = fstep fs pb >>= cont
690+ initial = finitial >>= handleCollect IPartial IDone
693+ step (Tuple3' st cnt fs) a = do
698+ assert (cnt1 - n >= 0) (return ())
699+ return $ Continue n (Tuple3' s (cnt1 - n) fs)
701+ assert (cnt1 - n >= 0) (return ())
702+ return $ Continue n (Tuple3' s (cnt1 - n) fs)
704+ assert (cnt1 - n >= 0) (return ())
705+ fstep fs b >>= handleCollect (Partial n) (Done n)
708+ return $ Done cnt1 xs
710+ -- XXX The "try" may impact performance if this parser is used as a scan
711+ extract (Tuple3' s _ fs) = do
712+ r <- try $ extract1 s
714+ Left (_ :: ParseError) -> fextract fs
718+ FL.Partial s1 -> fextract s1
719+ FL.Done b1 -> return b1
659-- | See documentation of 'Streamly.Internal.Data.Parser.some'.
721-- | See documentation of 'Streamly.Internal.Data.Parser.some'.
661-- /Pre-release/
723-- /Pre-release/