on master help sign in
Add splitManyPost (duplicate of splitMany at this point)
commitdc1731784df5d2eb1c84b964b620669fcfb0f334 authorAdithya Kumar <adithya@composewell.com> dateFri 12 Mar 2021, 02:12 (6 years ago) parent0ac0aaf
1 file changed+62
src/Streamly/Internal/Data/Parser/ParserD/Type.hs+62
src/Streamly/Internal/Data/Parser/ParserD/Type.hs+62
@@ -125,6 +125,7 @@ module Streamly.Internal.Data.Parser.ParserD.Type
125125 , dieM
126126 , splitSome -- parseSome?
127127 , splitMany -- parseMany?
128+ , splitManyPost
128129 , alt
129130 , concatMap
130131
@@ -656,6 +657,67 @@ splitMany (Parser step1 initial1 extract1) (Fold fstep finitial fextract) =
656657 FL.Partial s1 -> fextract s1
657658 FL.Done b1 -> return b1
658659
660+-- | Like splitMany, but inner fold emits an output at the end even if no input
661+-- is received.
662+--
663+-- /Internal/
664+--
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
669+
670+ where
671+
672+ -- Caution! There is mutual recursion here, inlining the right functions is
673+ -- important.
674+
675+ {-# INLINE handleCollect #-}
676+ handleCollect partial done fres =
677+ case fres of
678+ FL.Partial fs -> do
679+ pres <- initial1
680+ case pres of
681+ IPartial ps -> return $ partial $ Tuple3' ps 0 fs
682+ IDone pb ->
683+ runCollectorWith (handleCollect partial done) fs pb
684+ IError _ -> done <$> fextract fs
685+ FL.Done fb -> return $ done fb
686+
687+ -- Do not inline this
688+ runCollectorWith cont fs pb = fstep fs pb >>= cont
689+
690+ initial = finitial >>= handleCollect IPartial IDone
691+
692+ {-# INLINE step #-}
693+ step (Tuple3' st cnt fs) a = do
694+ r <- step1 st a
695+ let cnt1 = cnt + 1
696+ case r of
697+ Partial n s -> do
698+ assert (cnt1 - n >= 0) (return ())
699+ return $ Continue n (Tuple3' s (cnt1 - n) fs)
700+ Continue n s -> do
701+ assert (cnt1 - n >= 0) (return ())
702+ return $ Continue n (Tuple3' s (cnt1 - n) fs)
703+ Done n b -> do
704+ assert (cnt1 - n >= 0) (return ())
705+ fstep fs b >>= handleCollect (Partial n) (Done n)
706+ Error _ -> do
707+ xs <- fextract fs
708+ return $ Done cnt1 xs
709+
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
713+ case r of
714+ Left (_ :: ParseError) -> fextract fs
715+ Right b -> do
716+ fs1 <- fstep fs b
717+ case fs1 of
718+ FL.Partial s1 -> fextract s1
719+ FL.Done b1 -> return b1
720+
659721-- | See documentation of 'Streamly.Internal.Data.Parser.some'.
660722--
661723-- /Pre-release/