on master help sign in
rename some parsers, add some parsers
b9c461fHarendra Kumar
benchmark/Streamly/Benchmark/FileIO/Stream.hs+1−1
@@ -612,7 +612,7 @@ inspect $ 'splitOnSuffix `hasNoType` ''D.ConcatMapUState
612{-# INLINE parseChunksSplitOn #-}
612{-# INLINE parseChunksSplitOn #-}
613parseChunksSplitOn :: Handle -> IO Int
613parseChunksSplitOn :: Handle -> IO Int
614parseChunksSplitOn inh =
614parseChunksSplitOn inh =
615− (S.length $ IP.parseChunks (PR.endOn (== lf) FL.drain)
615+ (S.length $ IP.parseChunks (PR.sepBy (== lf) FL.drain)
616 (S.unfold FH.read inh)) -- >>= print
616 (S.unfold FH.read inh)) -- >>= print
617
617
618-- | Words by space
618-- | Words by space
src/Streamly/Internal/Data/Fold.hs+2
@@ -838,6 +838,8 @@ or = Fold (\x a -> return $ x || a) (return False) return
838-- Stops after @n@ elements.
838-- Stops after @n@ elements.
839-- Never fails.
839-- Never fails.
840--
840--
841+-- S.chunksOf n f = S.parseChunks (FL.take n f)
842+--
841-- /Internal/
843-- /Internal/
842--
844--
843{-# INLINE take #-}
845{-# INLINE take #-}
src/Streamly/Internal/Data/Parser.hs+108−39
@@ -18,24 +18,29 @@ module Streamly.Internal.Data.Parser
18 (
18 (
19 Parser (..)
19 Parser (..)
20
20
21− -- * Parsers
21+ -- * Folds
22 , any
22 , any
23 , all
23 , all
24
24
25− , takeWhile
25+ , sepBy
26− , takeExact
26+ , sepByMax
27− , takeAtLeast
27+ , sepWithSuffix
28+ , wordBy
28
29
29− , endOn
30+ -- * Parsers
30− , endAfter
31+ , takeWhile
31− , endBefore
32+ , takeEQ
33+ , takeGE
32
34
33− , finishBy
35+ , sepWithPrefix
36+ -- , sepWithInfix
37+ , groupBy
34 )
38 )
35where
39where
36
40
37import Prelude
41import Prelude
38 hiding (any, all, takeWhile)
42 hiding (any, all, takeWhile)
43+
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(..))
41
46
@@ -45,9 +50,6 @@ import Streamly.Internal.Data.Strict
45-- Terminating folds
50-- Terminating folds
46-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
47--
52--
48−-- XXX any/all should be terminating folds when we have a terminating fold
49−-- type.
50−--
51-- |
53-- |
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.
93--
95--
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"
96--
98--
97-- /Internal/
99-- /Internal/
98--
100--
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
102
104
103 where
105 where
104
106
@@ -115,7 +117,7 @@ takeExact n (Fold fstep finitial fextract) = Parser step initial extract
115 where
117 where
116
118
117 err =
119 err =
118− "takeExact: Expecting exactly " ++ show n
120+ "takeEQ: Expecting exactly " ++ show n
119 ++ " elements, got " ++ show i
121 ++ " elements, got " ++ show i
120
122
121 f x =
123 f x =
@@ -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.
130--
132--
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"
133--
135--
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]
136--
138--
137-- /Internal/
139-- /Internal/
138--
140--
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
142
144
143 where
145 where
144
146
@@ -157,7 +159,7 @@ takeAtLeast n (Fold fstep finitial fextract) = Parser step initial extract
157 where
159 where
158
160
159 err =
161 err =
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
162
164
163 f x =
165 f x =
@@ -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
167
169
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.
169--
172--
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]
175--
178--
179+-- @
180+-- breakOn p = takeWhile (not p)
181+-- @
182+--
176-- /Internal/
183-- /Internal/
177--
184--
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.
199--
206--
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]
202--
209--
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],[]]
205--
212--
213+-- S.splitOn pred f = S.parseChunks (PR.sepBy pred f)
214+--
206-- /Internal/
215-- /Internal/
207--
216--
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
212
221
213 where
222 where
@@ -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.
229--
238--
239+-- S.splitWithSuffix pred f = S.parseChunks (PR.sepWithSuffix pred f)
240+--
230-- /Unimplemented/
241-- /Unimplemented/
231--
242--
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
237
248
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.
243--
254--
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+--
244-- /Unimplemented/
301-- /Unimplemented/
245--
302--
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
251
308
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.
315+--
316+-- * Stops - when the group ends.
317+-- * Fails - never.
318+--
319+-- S.groupsBy cmp f = S.parseChunks (PR.groupBy cmp f)
254--
320--
255-- /Unimplemented/
321-- /Unimplemented/
256--
322--
257−finishBy :: Parser m a x -> Fold m a y -> Parser m a (x, y)
323+{-# INLINABLE groupBy #-}
324+groupBy ::
325+ -- Monad m =>
326+ (a -> a -> Bool) -> Fold m a b -> Parser m a b
258−finishBy = undefined
327+groupBy = undefined