on master help sign in
Implement slicesepby, add tests and benchmarks
commit5ccf51dcae090266fcafadca558bda0a6b5646d4 authorAnurag Hooda <anuraghooda@composewell.com> dateMon 11 Jan 2021, 18:41 (6 years ago) parent6e51373
6 files changed+51−9
benchmark/Streamly/Benchmark/Data/Parser.hs+7 benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+5 src/Streamly/Internal/Data/Parser.hs+4−3 src/Streamly/Internal/Data/Parser/ParserD.hs+15−2 test/Streamly/Test/Data/Parser.hs+12 test/Streamly/Test/Data/Parser/ParserD.hs+8−4
benchmark/Streamly/Benchmark/Data/Parser.hs+7
@@ -161,6 +161,12 @@ split_ value =
161161 (PR.drainWhile (<= value))
162162 )
163163
164+{-# INLINE sliceSepBy #-}
165+sliceSepBy :: MonadCatch m
166+ => Int -> SerialT m Int -> m()
167+sliceSepBy value = IP.parse (PR.sliceSepBy (>= value) (PR.many FL.drain
168+ (PR.satisfy (const True))))
169+
164170{-# INLINE teeAllAny #-}
165171teeAllAny :: MonadCatch m
166172 => Int -> SerialT m Int -> m ((), ())
@@ -281,6 +287,7 @@ o_1_space_serial value =
281287 , benchIOSink value "splitApBefore" $ splitApBefore value
282288 , benchIOSink value "splitApAfter" $ splitApAfter value
283289 , benchIOSink value "splitWith" $ splitWith value
290+ , benchIOSink value "sliceSepBy" $ sliceSepBy value
284291 , benchIOSink value "many" many
285292 , benchIOSink value "many (wordBy even)" $ manyWordByEven
286293 , benchIOSink value "some" some
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+5
@@ -100,6 +100,10 @@ someAlt xs = do
100100 x <- IP.parseD (AP.some (PR.satisfy (> 0))) xs
101101 return $ Prelude.length x
102102
103+{-#INLINE sliceSepBy #-}
104+sliceSepBy :: MonadCatch m => Int -> SerialT m Int -> m ()
105+sliceSepBy value = IP.parseD (PR.sliceSepBy (>= value) (PR.many FL.drain
106+ (PR.satisfy (const True))))
103107{-# INLINE manyTill #-}
104108manyTill :: MonadCatch m => Int -> SerialT m Int -> m Int
105109manyTill value =
@@ -214,6 +218,7 @@ o_1_space_serial value =
214218 , benchIOSink value "many" many
215219 , benchIOSink value "many (wordBy even)" $ manyWordByEven
216220 , benchIOSink value "some" some
221+ , benchIOSink value "sliceSepBy" $ sliceSepBy value
217222 , benchIOSink value "manyTill" $ manyTill value
218223 , benchIOSink value "tee (all,any)" $ teeAllAny value
219224 , benchIOSink value "teeFst (all,any)" $ teeFstAllAny value
src/Streamly/Internal/Data/Parser.hs+4−3
@@ -487,12 +487,13 @@ drainWhile p = takeWhile p FL.drain
487487-- sliceSepByBetween cond m n p = sliceBy cond (takeBetween m n p)
488488-- @
489489--
490−-- /Unimplemented/
490+-- /Internal/
491491--
492492{-# INLINABLE sliceSepBy #-}
493−sliceSepBy :: -- MonadCatch m =>
493+sliceSepBy ::
494+ MonadCatch m =>
494495 (a -> Bool) -> Parser m a b -> Parser m a b
495−sliceSepBy _cond = undefined -- K.toParserK . D.sliceSepBy cond
496+sliceSepBy cond = K.toParserK . D.sliceSepBy cond . K.fromParserK
496497
497498-- | Like 'sliceSepBy' but does not drop the separator element, instead
498499-- separator is emitted as a separate element in the output.
src/Streamly/Internal/Data/Parser/ParserD.hs+15−2
@@ -487,9 +487,22 @@ takeWhile1 predicate (Fold fstep finitial fextract) =
487487--
488488-- /Internal/
489489--
490−sliceSepBy :: -- MonadCatch m =>
490+sliceSepBy :: MonadCatch m =>
491491 (a -> Bool) -> Parser m a b -> Parser m a b
492−sliceSepBy _cond = undefined
492+sliceSepBy cond (Parser pstep pinitial pextract) =
493+
494+ Parser step initial pextract
495+
496+ where
497+
498+ initial = pinitial
499+
500+ step s a =
501+ if cond a
502+ then do
503+ res <- pextract s
504+ return $ Done 0 res
505+ else pstep s a
493506
494507-- | See 'Streamly.Internal.Data.Parser.sliceBeginWith'.
495508--
test/Streamly/Test/Data/Parser.hs+12
@@ -311,6 +311,17 @@ takeProperties =
311311-- where
312312-- list_length = Prelude.length ls
313313
314+sliceSepBy :: Property
315+sliceSepBy =
316+ forAll (listOf (chooseInt (min_value, max_value ))) $ \ls ->
317+ case S.parse (P.sliceSepBy predicate prsr) (S.fromList ls) of
318+ Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile
319+ (not. predicate) ls)
320+ Left _ -> property False
321+ where
322+ predicate = (>= 100)
323+ prsr = P.many FL.toList (P.satisfy (const True))
324+
314325takeWhile :: Property
315326takeWhile =
316327 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
@@ -693,6 +704,7 @@ main =
693704 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
694705 -- prop "Fail when stream length exceeded" lookAheadFail
695706 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
707+ prop "P.sliceSepBy test" Main.sliceSepBy
696708 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
697709 prop ("P.takeWhile1 = Prelude.takeWhile if taken something,"
698710 ++ " else check why failed") takeWhile1
test/Streamly/Test/Data/Parser/ParserD.hs+8−4
@@ -292,6 +292,7 @@ lookAhead =
292292 where
293293 list_length = Prelude.length ls
294294
295+
295296takeWhile :: Property
296297takeWhile =
297298 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
@@ -336,12 +337,15 @@ groupBy =
336337
337338sliceSepBy :: Property
338339sliceSepBy =
339− forAll (listOf (chooseInt (0, 1))) $ \ls ->
340− case S.parseD (P.fromFold $ FL.sliceSepBy predicate FL.toList) (S.fromList ls) of
341− Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
340+ forAll (listOf (chooseInt (min_value, max_value ))) $ \ls ->
341+ case S.parseD (P.sliceSepBy predicate prsr) (S.fromList ls) of
342+ Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile
343+ (not. predicate) ls)
342344 Left _ -> property False
343345 where
344− predicate = (== 1)
346+ predicate = (>= 100)
347+ prsr = P.many FL.toList (P.satisfy (const True))
348+
345349
346350sliceSepByMax :: Property
347351sliceSepByMax =