@@ -18,24 +18,29 @@ module Streamly.Internal.Data.Parser
1818 (
1919 Parser (..)
2020
21− -- * Parsers
21+ -- * Folds
2222 , any
2323 , all
2424
25− , takeWhile
26− , takeExact
27− , takeAtLeast
25+ , sepBy
26+ , sepByMax
27+ , sepWithSuffix
28+ , wordBy
2829
29− , endOn
30− , endAfter
31− , endBefore
30+ -- * Parsers
31+ , takeWhile
32+ , takeEQ
33+ , takeGE
3234
33− , finishBy
35+ , sepWithPrefix
36+ -- , sepWithInfix
37+ , groupBy
3438 )
3539where
3640
3741import Prelude
3842 hiding (any, all, takeWhile)
43+
3944import Streamly.Internal.Data.Parser.Types (Parser(..), Step(..))
4045import Streamly.Internal.Data.Fold.Types (Fold(..))
4146
@@ -45,9 +50,6 @@ import Streamly.Internal.Data.Strict
4550-- Terminating folds
4651-------------------------------------------------------------------------------
4752--
48−-- XXX any/all should be terminating folds when we have a terminating fold
49−-- type.
50−--
5153-- |
5254-- >>> S.parse (PR.any (== 0)) $ S.fromList [1,0,1]
5355-- > Right True
@@ -92,13 +94,13 @@ all predicate = Parser step initial (return . Right)
9294-- * Fails - if the stream ends before it can collect @n@ elements.
9395--
9496-- >>> 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"
9698--
9799-- /Internal/
98100--
99−{-# INLINABLE takeExact #-}
100−takeExact :: Monad m => Int -> Fold m a b -> Parser m a b
101−takeExact n (Fold fstep finitial fextract) = Parser step initial extract
101+{-# INLINABLE takeEQ #-}
102+takeEQ :: Monad m => Int -> Fold m a b -> Parser m a b
103+takeEQ n (Fold fstep finitial fextract) = Parser step initial extract
102104
103105 where
104106
@@ -115,7 +117,7 @@ takeExact n (Fold fstep finitial fextract) = Parser step initial extract
115117 where
116118
117119 err =
118− "takeExact: Expecting exactly " ++ show n
120+ "takeEQ: Expecting exactly " ++ show n
119121 ++ " elements, got " ++ show i
120122
121123 f x =
@@ -128,17 +130,17 @@ takeExact n (Fold fstep finitial fextract) = Parser step initial extract
128130-- * Stops - never.
129131-- * Fails - if the stream end before producing @n@ elements.
130132--
131−-- >>> S.parse (PR.takeAtLeast 4 FL.toList) $ S.fromList [1,0,1]
132−-- > Left "takeAtLeast: Expecting at least 4 elements, got only 3"
133+-- >>> S.parse (PR.takeGE 4 FL.toList) $ S.fromList [1,0,1]
134+-- > Left "takeGE: Expecting at least 4 elements, got only 3"
133135--
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]
135137-- > Right [1,0,1,0,1]
136138--
137139-- /Internal/
138140--
139−{-# INLINABLE takeAtLeast #-}
140−takeAtLeast :: Monad m => Int -> Fold m a b -> Parser m a b
141−takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
141+{-# INLINABLE takeGE #-}
142+takeGE :: Monad m => Int -> Fold m a b -> Parser m a b
143+takeGE n (Fold fstep finitial fextract) = Parser step initial extract
142144
143145 where
144146
@@ -157,7 +159,7 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
157159 where
158160
159161 err =
160− "takeAtLeast: Expecting at least " ++ show n
162+ "takeGE: Expecting at least " ++ show n
161163 ++ " elements, got only " ++ show i
162164
163165 f x =
@@ -165,7 +167,8 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
165167 then Right x
166168 else Left err
167169
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.
169172--
170173-- * Stops - when the predicate fails.
171174-- * Fails - never.
@@ -173,6 +176,10 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
173176-- >>> S.parse (PR.takeWhile (== 0) FL.toList) $ S.fromList [0,0,1,0,1]
174177-- > Right [0,0]
175178--
179+-- @
180+-- breakOn p = takeWhile (not p)
181+-- @
182+--
176183-- /Internal/
177184--
178185{-# INLINABLE takeWhile #-}
@@ -197,17 +204,19 @@ takeWhile predicate (Fold fstep finitial fextract) =
197204-- * Stops - when the predicate succeeds.
198205-- * Fails - never.
199206--
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]
201208-- > Right [0,0]
202209--
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]
204211-- > [[0,0],[0],[]]
205212--
213+-- S.splitOn pred f = S.parseChunks (PR.sepBy pred f)
214+--
206215-- /Internal/
207216--
208−{-# INLINABLE endOn #-}
209−endOn :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
210−endOn predicate (Fold fstep finitial fextract) =
217+{-# INLINABLE sepBy #-}
218+sepBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
219+sepBy predicate (Fold fstep finitial fextract) =
211220 Parser step initial extract
212221
213222 where
@@ -227,13 +236,15 @@ endOn predicate (Fold fstep finitial fextract) =
227236-- * Stops - when the predicate succeeds.
228237-- * Fails - never.
229238--
239+-- S.splitWithSuffix pred f = S.parseChunks (PR.sepWithSuffix pred f)
240+--
230241-- /Unimplemented/
231242--
232−{-# INLINABLE endAfter #-}
233−endAfter ::
243+{-# INLINABLE sepWithSuffix #-}
244+sepWithSuffix ::
234245 -- Monad m =>
235246 (a -> Bool) -> Fold m a b -> Parser m a b
236−endAfter = undefined
247+sepWithSuffix = undefined
237248
238249-- | Keep taking elements until the predicate succeeds. Return the succeeding
239250-- element back to the input.
@@ -241,18 +252,76 @@ endAfter = undefined
241252-- * Stops - when the predicate succeeds.
242253-- * Fails - never.
243254--
255+-- S.splitWithPrefix pred f = S.parseChunks (PR.sepWithPrefix pred f)
256+--
257+-- /Unimplemented/
258+--
259+{-# INLINABLE sepWithPrefix #-}
260+sepWithPrefix ::
261+ -- Monad m =>
262+ (a -> Bool) -> Fold m a b -> Parser m a b
263+sepWithPrefix = undefined
264+
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
267+-- is dropped.
268+--
269+-- /Internal/
270+--
271+{-# INLINABLE sepByMax #-}
272+sepByMax :: Monad m
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
276+
277+ where
278+
279+ initial = Tuple' 0 <$> finitial
280+ step (Tuple' i r) a = do
281+ res <- fstep r a
282+ let i1 = i + 1
283+ s1 = Tuple' i1 res
284+ if not (predicate a) && i1 < count
285+ then return $ Yield 0 s1
286+ else return $ Stop 0 s1
287+ extract (Tuple' _ r) = do
288+ b <- fextract r
289+ return $ Right b
290+
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
294+-- separated text.
295+--
296+-- * Stops - when it finds a word separator after a non-word element
297+-- * Fails - never.
298+--
299+-- S.wordsBy pred f = S.parseChunks (PR.wordBy pred f)
300+--
244301-- /Unimplemented/
245302--
246−{-# INLINABLE endBefore #-}
247−endBefore ::
303+{-# INLINABLE wordBy #-}
304+wordBy ::
248305 -- Monad m =>
249306 (a -> Bool) -> Fold m a b -> Parser m a b
250−endBefore = undefined
307+wordBy = undefined
251308
252−-- | Distribute the input to a parse and a fold until the parse succeeds or
253−-- fails. The parse can be used to decide the termination of the fold.
309+-- | @group cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
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.
315+--
316+-- * Stops - when the group ends.
317+-- * Fails - never.
318+--
319+-- S.groupsBy cmp f = S.parseChunks (PR.groupBy cmp f)
254320--
255321-- /Unimplemented/
256322--
257−finishBy :: Parser m a x -> Fold m a y -> Parser m a (x, y)
258−finishBy = undefined
323+{-# INLINABLE groupBy #-}
324+groupBy ::
325+ -- Monad m =>
326+ (a -> a -> Bool) -> Fold m a b -> Parser m a b
327+groupBy = undefined