@@ -18,24 +18,29 @@ module Streamly.Internal.Data.Parser
19 Parser (..)
19 Parser (..)
21− -- * Parsers
21+ -- * Folds
25− , takeWhile
25+ , sepBy
26− , takeExact
26+ , sepByMax
27− , takeAtLeast
27+ , sepWithSuffix
29− , endOn
30+ -- * Parsers
30− , endAfter
31+ , takeWhile
31− , endBefore
32+ , takeEQ
33− , finishBy
35+ , sepWithPrefix
37import Prelude
41import Prelude
38 hiding (any, all, takeWhile)
42 hiding (any, all, takeWhile)
39import Streamly.Internal.Data.Parser.Types (Parser(..), Step(..))
44import Streamly.Internal.Data.Parser.Types (Parser(..), Step(..))
40import Streamly.Internal.Data.Fold.Types (Fold(..))
45import Streamly.Internal.Data.Fold.Types (Fold(..))
@@ -45,9 +50,6 @@ import Streamly.Internal.Data.Strict
45-- Terminating folds
50-- Terminating folds
46-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
48−-- XXX any/all should be terminating folds when we have a terminating fold
52-- >>> S.parse (PR.any (== 0)) $ S.fromList [1,0,1]
54-- >>> S.parse (PR.any (== 0)) $ S.fromList [1,0,1]
53-- > Right True
55-- > Right True
@@ -92,13 +94,13 @@ all predicate = Parser step initial (return . Right)
92-- * Fails - if the stream ends before it can collect @n@ elements.
94-- * Fails - if the stream ends before it can collect @n@ elements.
94-- >>> S.parse (PR.takeExact 4 FL.toList) $ S.fromList [1,0,1]
96-- >>> S.parse (PR.takeExact 4 FL.toList) $ S.fromList [1,0,1]
95−-- > Left "takeExact: Expecting exactly 4 elements, got 3"
97+-- > Left "takeEQ: Expecting exactly 4 elements, got 3"
97-- /Internal/
99-- /Internal/
99−{-# INLINABLE takeExact #-}
101+{-# INLINABLE takeEQ #-}
100−takeExact :: Monad m => Int -> Fold m a b -> Parser m a b
102+takeEQ :: Monad m => Int -> Fold m a b -> Parser m a b
101−takeExact n (Fold fstep finitial fextract) = Parser step initial extract
103+takeEQ n (Fold fstep finitial fextract) = Parser step initial extract
@@ -115,7 +117,7 @@ takeExact n (Fold fstep finitial fextract) = Parser step initial extract
118− "takeExact: Expecting exactly " ++ show n
120+ "takeEQ: Expecting exactly " ++ show n
119 ++ " elements, got " ++ show i
121 ++ " elements, got " ++ show i
@@ -128,17 +130,17 @@ takeExact n (Fold fstep finitial fextract) = Parser step initial extract
128-- * Stops - never.
130-- * Stops - never.
129-- * Fails - if the stream end before producing @n@ elements.
131-- * Fails - if the stream end before producing @n@ elements.
131−-- >>> S.parse (PR.takeAtLeast 4 FL.toList) $ S.fromList [1,0,1]
133+-- >>> S.parse (PR.takeGE 4 FL.toList) $ S.fromList [1,0,1]
132−-- > Left "takeAtLeast: Expecting at least 4 elements, got only 3"
134+-- > Left "takeGE: Expecting at least 4 elements, got only 3"
134−-- >>> S.parse (PR.takeAtLeast 4 FL.toList) $ S.fromList [1,0,1,0,1]
136+-- >>> S.parse (PR.takeGE 4 FL.toList) $ S.fromList [1,0,1,0,1]
135-- > Right [1,0,1,0,1]
137-- > Right [1,0,1,0,1]
137-- /Internal/
139-- /Internal/
139−{-# INLINABLE takeAtLeast #-}
141+{-# INLINABLE takeGE #-}
140−takeAtLeast :: Monad m => Int -> Fold m a b -> Parser m a b
142+takeGE :: Monad m => Int -> Fold m a b -> Parser m a b
141−takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
143+takeGE n (Fold fstep finitial fextract) = Parser step initial extract
@@ -157,7 +159,7 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
160− "takeAtLeast: Expecting at least " ++ show n
162+ "takeGE: Expecting at least " ++ show n
161 ++ " elements, got only " ++ show i
163 ++ " elements, got only " ++ show i
@@ -165,7 +167,8 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
165 then Right x
167 then Right x
166 else Left err
168 else Left err
168−-- | Take until the predicate fails. Does not take the failing element.
170+-- | Take until the predicate fails. The element on which the predicate fails
171+-- is returned back to the input stream.
170-- * Stops - when the predicate fails.
173-- * Stops - when the predicate fails.
171-- * Fails - never.
174-- * Fails - never.
@@ -173,6 +176,10 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
173-- >>> S.parse (PR.takeWhile (== 0) FL.toList) $ S.fromList [0,0,1,0,1]
176-- >>> S.parse (PR.takeWhile (== 0) FL.toList) $ S.fromList [0,0,1,0,1]
174-- > Right [0,0]
177-- > Right [0,0]
180+-- breakOn p = takeWhile (not p)
176-- /Internal/
183-- /Internal/
178{-# INLINABLE takeWhile #-}
185{-# INLINABLE takeWhile #-}
@@ -197,17 +204,19 @@ takeWhile predicate (Fold fstep finitial fextract) =
197-- * Stops - when the predicate succeeds.
204-- * Stops - when the predicate succeeds.
198-- * Fails - never.
205-- * Fails - never.
200−-- >>> S.parse (PR.endOn (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
207+-- >>> S.parse (PR.sepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
201-- > Right [0,0]
208-- > Right [0,0]
203−-- >>> S.toList $ S.parseChunks (PR.endOn (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
210+-- >>> S.toList $ S.parseChunks (PR.sepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
204-- > [[0,0],[0],[]]
211-- > [[0,0],[0],[]]
213+-- S.splitOn pred f = S.parseChunks (PR.sepBy pred f)
206-- /Internal/
215-- /Internal/
208−{-# INLINABLE endOn #-}
217+{-# INLINABLE sepBy #-}
209−endOn :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
218+sepBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
210−endOn predicate (Fold fstep finitial fextract) =
219+sepBy predicate (Fold fstep finitial fextract) =
211 Parser step initial extract
220 Parser step initial extract
@@ -227,13 +236,15 @@ endOn predicate (Fold fstep finitial fextract) =
227-- * Stops - when the predicate succeeds.
236-- * Stops - when the predicate succeeds.
228-- * Fails - never.
237-- * Fails - never.
239+-- S.splitWithSuffix pred f = S.parseChunks (PR.sepWithSuffix pred f)
230-- /Unimplemented/
241-- /Unimplemented/
232−{-# INLINABLE endAfter #-}
243+{-# INLINABLE sepWithSuffix #-}
233−endAfter ::
244+sepWithSuffix ::
234 -- Monad m =>
245 -- Monad m =>
235 (a -> Bool) -> Fold m a b -> Parser m a b
246 (a -> Bool) -> Fold m a b -> Parser m a b
236−endAfter = undefined
247+sepWithSuffix = undefined
238-- | Keep taking elements until the predicate succeeds. Return the succeeding
249-- | Keep taking elements until the predicate succeeds. Return the succeeding
239-- element back to the input.
250-- element back to the input.
@@ -241,18 +252,76 @@ endAfter = undefined
241-- * Stops - when the predicate succeeds.
252-- * Stops - when the predicate succeeds.
242-- * Fails - never.
253-- * Fails - never.
255+-- S.splitWithPrefix pred f = S.parseChunks (PR.sepWithPrefix pred f)
259+{-# INLINABLE sepWithPrefix #-}
262+ (a -> Bool) -> Fold m a b -> Parser m a b
263+sepWithPrefix = undefined
265+-- | Split using a condition or a count whichever occurs first. This is a
266+-- hybrid of 'splitOn' and 'take'. The element on which the condition succeeds
271+{-# INLINABLE sepByMax #-}
273+ => (a -> Bool) -> Int -> Fold m a b -> Parser m a b
274+sepByMax predicate count (Fold fstep finitial fextract) =
275+ Parser step initial extract
279+ initial = Tuple' 0 <$> finitial
280+ step (Tuple' i r) a = do
284+ if not (predicate a) && i1 < count
285+ then return $ Yield 0 s1
286+ else return $ Stop 0 s1
287+ extract (Tuple' _ r) = do
291+-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
292+-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
293+-- @["a","b"]@. In other words, its like parsing words from whitespace
296+-- * Stops - when it finds a word separator after a non-word element
299+-- S.wordsBy pred f = S.parseChunks (PR.wordBy pred f)
244-- /Unimplemented/
301-- /Unimplemented/
246−{-# INLINABLE endBefore #-}
303+{-# INLINABLE wordBy #-}
247−endBefore ::
304+wordBy ::
248 -- Monad m =>
305 -- Monad m =>
249 (a -> Bool) -> Fold m a b -> Parser m a b
306 (a -> Bool) -> Fold m a b -> Parser m a b
250−endBefore = undefined
307+wordBy = undefined
252−-- | Distribute the input to a parse and a fold until the parse succeeds or
309+-- | @group cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
253−-- fails. The parse can be used to decide the termination of the fold.
310+-- first group, if @a \`cmp` b@ is 'True' then @b@ is also assigned to the same
311+-- group. If @a \`cmp` c@ is 'True' then @c@ is also assigned to the same
312+-- group and so on. When the comparison fails a new group is started. Each
313+-- group is folded using the fold @f@ and the result of the fold is emitted in
314+-- the output stream.
316+-- * Stops - when the group ends.
319+-- S.groupsBy cmp f = S.parseChunks (PR.groupBy cmp f)
255-- /Unimplemented/
321-- /Unimplemented/
257−finishBy :: Parser m a x -> Fold m a y -> Parser m a (x, y)
323+{-# INLINABLE groupBy #-}
326+ (a -> a -> Bool) -> Fold m a b -> Parser m a b
258−finishBy = undefined
327+groupBy = undefined