on master help sign in
Implement slicesepby, add tests and benchmarks
5ccf51dAnurag Hooda
benchmark/Streamly/Benchmark/Data/Parser.hs+7
@@ -161,6 +161,12 @@ split_ value =
161 (PR.drainWhile (<= value))
161 (PR.drainWhile (<= value))
162 )
162 )
163
163
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+
164{-# INLINE teeAllAny #-}
170{-# INLINE teeAllAny #-}
165teeAllAny :: MonadCatch m
171teeAllAny :: MonadCatch m
166 => Int -> SerialT m Int -> m ((), ())
172 => Int -> SerialT m Int -> m ((), ())
@@ -281,6 +287,7 @@ o_1_space_serial value =
281 , benchIOSink value "splitApBefore" $ splitApBefore value
287 , benchIOSink value "splitApBefore" $ splitApBefore value
282 , benchIOSink value "splitApAfter" $ splitApAfter value
288 , benchIOSink value "splitApAfter" $ splitApAfter value
283 , benchIOSink value "splitWith" $ splitWith value
289 , benchIOSink value "splitWith" $ splitWith value
290+ , benchIOSink value "sliceSepBy" $ sliceSepBy value
284 , benchIOSink value "many" many
291 , benchIOSink value "many" many
285 , benchIOSink value "many (wordBy even)" $ manyWordByEven
292 , benchIOSink value "many (wordBy even)" $ manyWordByEven
286 , benchIOSink value "some" some
293 , benchIOSink value "some" some
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+5
@@ -100,6 +100,10 @@ someAlt xs = do
100 x <- IP.parseD (AP.some (PR.satisfy (> 0))) xs
100 x <- IP.parseD (AP.some (PR.satisfy (> 0))) xs
101 return $ Prelude.length x
101 return $ Prelude.length x
102
102
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))))
103{-# INLINE manyTill #-}
107{-# INLINE manyTill #-}
104manyTill :: MonadCatch m => Int -> SerialT m Int -> m Int
108manyTill :: MonadCatch m => Int -> SerialT m Int -> m Int
105manyTill value =
109manyTill value =
@@ -214,6 +218,7 @@ o_1_space_serial value =
214 , benchIOSink value "many" many
218 , benchIOSink value "many" many
215 , benchIOSink value "many (wordBy even)" $ manyWordByEven
219 , benchIOSink value "many (wordBy even)" $ manyWordByEven
216 , benchIOSink value "some" some
220 , benchIOSink value "some" some
221+ , benchIOSink value "sliceSepBy" $ sliceSepBy value
217 , benchIOSink value "manyTill" $ manyTill value
222 , benchIOSink value "manyTill" $ manyTill value
218 , benchIOSink value "tee (all,any)" $ teeAllAny value
223 , benchIOSink value "tee (all,any)" $ teeAllAny value
219 , benchIOSink value "teeFst (all,any)" $ teeFstAllAny value
224 , 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
487-- sliceSepByBetween cond m n p = sliceBy cond (takeBetween m n p)
487-- sliceSepByBetween cond m n p = sliceBy cond (takeBetween m n p)
488-- @
488-- @
489--
489--
490−-- /Unimplemented/
490+-- /Internal/
491--
491--
492{-# INLINABLE sliceSepBy #-}
492{-# INLINABLE sliceSepBy #-}
493+sliceSepBy ::
493−sliceSepBy :: -- MonadCatch m =>
494+ MonadCatch m =>
494 (a -> Bool) -> Parser m a b -> Parser m a b
495 (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
496
497
497-- | Like 'sliceSepBy' but does not drop the separator element, instead
498-- | Like 'sliceSepBy' but does not drop the separator element, instead
498-- separator is emitted as a separate element in the output.
499-- 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) =
487--
487--
488-- /Internal/
488-- /Internal/
489--
489--
490−sliceSepBy :: -- MonadCatch m =>
490+sliceSepBy :: MonadCatch m =>
491 (a -> Bool) -> Parser m a b -> Parser m a b
491 (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
493
506
494-- | See 'Streamly.Internal.Data.Parser.sliceBeginWith'.
507-- | See 'Streamly.Internal.Data.Parser.sliceBeginWith'.
495--
508--
test/Streamly/Test/Data/Parser.hs+12
@@ -311,6 +311,17 @@ takeProperties =
311-- where
311-- where
312-- list_length = Prelude.length ls
312-- list_length = Prelude.length ls
313
313
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+
314takeWhile :: Property
325takeWhile :: Property
315takeWhile =
326takeWhile =
316 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
327 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
@@ -693,6 +704,7 @@ main =
693 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
704 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
694 -- prop "Fail when stream length exceeded" lookAheadFail
705 -- prop "Fail when stream length exceeded" lookAheadFail
695 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
706 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
707+ prop "P.sliceSepBy test" Main.sliceSepBy
696 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
708 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
697 prop ("P.takeWhile1 = Prelude.takeWhile if taken something,"
709 prop ("P.takeWhile1 = Prelude.takeWhile if taken something,"
698 ++ " else check why failed") takeWhile1
710 ++ " else check why failed") takeWhile1
test/Streamly/Test/Data/Parser/ParserD.hs+8−4
@@ -292,6 +292,7 @@ lookAhead =
292 where
292 where
293 list_length = Prelude.length ls
293 list_length = Prelude.length ls
294
294
295+
295takeWhile :: Property
296takeWhile :: Property
296takeWhile =
297takeWhile =
297 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
298 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
@@ -336,12 +337,15 @@ groupBy =
336
337
337sliceSepBy :: Property
338sliceSepBy :: Property
338sliceSepBy =
339sliceSepBy =
339− forAll (listOf (chooseInt (0, 1))) $ \ls ->
340+ forAll (listOf (chooseInt (min_value, max_value ))) $ \ls ->
340− case S.parseD (P.fromFold $ FL.sliceSepBy predicate FL.toList) (S.fromList ls) of
341+ case S.parseD (P.sliceSepBy predicate prsr) (S.fromList ls) of
341− Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
342+ Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile
343+ (not. predicate) ls)
342 Left _ -> property False
344 Left _ -> property False
343 where
345 where
344− predicate = (== 1)
346+ predicate = (>= 100)
347+ prsr = P.many FL.toList (P.satisfy (const True))
348+
345
349
346sliceSepByMax :: Property
350sliceSepByMax :: Property
347sliceSepByMax =
351sliceSepByMax =