on master help sign in
Re-export entire submodules from Parser (#2525)
209e990Ranjeet Ranjan
benchmark/Streamly/Benchmark/Data/ParserK.hs+1−1
@@ -45,7 +45,7 @@ import qualified Streamly.Data.Stream as Stream
45import qualified Streamly.Data.Fold as FL
45import qualified Streamly.Data.Fold as FL
46import qualified Streamly.Internal.Data.Fold as Fold
46import qualified Streamly.Internal.Data.Fold as Fold
47import qualified Streamly.Data.Parser as PRD
47import qualified Streamly.Data.Parser as PRD
48−import qualified Streamly.Internal.Data.Parser.ParserK.Type as PR
48+import qualified Streamly.Internal.Data.ParserK as PR
49import qualified Streamly.Internal.Data.StreamK as StreamK
49import qualified Streamly.Internal.Data.StreamK as StreamK
50
50
51import Gauge
51import Gauge
core/src/Streamly/Data/ParserK.hs+1−1
@@ -39,7 +39,7 @@ import Streamly.Internal.Data.Unbox (Unbox)
39import Streamly.Internal.Data.Array (Array)
39import Streamly.Internal.Data.Array (Array)
40import qualified Streamly.Internal.Data.Parser as ParserD
40import qualified Streamly.Internal.Data.Parser as ParserD
41
41
42−import Streamly.Internal.Data.Parser.ParserK.Type
42+import Streamly.Internal.Data.ParserK.Type
43
43
44{-# DEPRECATED fromFold "Please use \"ParserK.adaptC . Parser.fromFold\" instead." #-}
44{-# DEPRECATED fromFold "Please use \"ParserK.adaptC . Parser.fromFold\" instead." #-}
45{-# INLINE fromFold #-}
45{-# INLINE fromFold #-}
core/src/Streamly/Internal/Data/Fold/Chunked.hs−1
@@ -73,7 +73,6 @@ import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
73import qualified Streamly.Internal.Data.Array.Type as Array
73import qualified Streamly.Internal.Data.Array.Type as Array
74import qualified Streamly.Internal.Data.Fold as Fold
74import qualified Streamly.Internal.Data.Fold as Fold
75import qualified Streamly.Internal.Data.Parser as ParserD
75import qualified Streamly.Internal.Data.Parser as ParserD
76−import qualified Streamly.Internal.Data.Parser.ParserD.Type as ParserD
77import qualified Streamly.Internal.Data.Parser as Parser
76import qualified Streamly.Internal.Data.Parser as Parser
78
77
79import Prelude hiding (concatMap, take)
78import Prelude hiding (concatMap, take)
core/src/Streamly/Internal/Data/Parser.hs+7−22
@@ -12,8 +12,11 @@ module Streamly.Internal.Data.Parser
12 -- * Setup
12 -- * Setup
13 -- $setup
13 -- $setup
14
14
15+ module Streamly.Internal.Data.Parser.Type
16+ --, module Streamly.Internal.Data.Parser.Tee
17+
15 -- * Types
18 -- * Types
16− Parser (..)
19+ , Parser (..)
17 , ParseError (..)
20 , ParseError (..)
18 , Step (..)
21 , Step (..)
19 , Initial (..)
22 , Initial (..)
@@ -25,19 +28,9 @@ module Streamly.Internal.Data.Parser
25 -- * Accumulators
28 -- * Accumulators
26 , fromFold
29 , fromFold
27 , fromFoldMaybe
30 , fromFoldMaybe
28− , fromPure
29− , fromEffect
30− , die
31− , dieM
32
31
33 -- * Map on input
32 -- * Map on input
34− , lmap
35− , lmapM
36 , postscan
33 , postscan
37− , filter
38−
39− -- * Map on output
40− , rmapM
41
34
42 -- * Element parsers
35 -- * Element parsers
43 , peek
36 , peek
@@ -139,11 +132,6 @@ module Streamly.Internal.Data.Parser
139
132
140 -- Second order parsers (parsers using parsers)
133 -- Second order parsers (parsers using parsers)
141 -- * Binary Combinators
134 -- * Binary Combinators
142−
143− -- ** Sequential Applicative
144− , splitWith
145− , split_
146−
147 {-
135 {-
148 -- ** Parallel Applicatives
136 -- ** Parallel Applicatives
149 , teeWith
137 , teeWith
@@ -152,9 +140,6 @@ module Streamly.Internal.Data.Parser
152 -- , teeTill -- like manyTill but parallel
140 -- , teeTill -- like manyTill but parallel
153 -}
141 -}
154
142
155− -- ** Sequential Alternative
156− , alt
157−
158 {-
143 {-
159 -- ** Parallel Alternatives
144 -- ** Parallel Alternatives
160 , shortest
145 , shortest
@@ -165,7 +150,6 @@ module Streamly.Internal.Data.Parser
165 -- * N-ary Combinators
150 -- * N-ary Combinators
166 -- ** Sequential Collection
151 -- ** Sequential Collection
167 , sequence
152 , sequence
168− , concatMap
169
153
170 -- ** Sequential Repetition
154 -- ** Sequential Repetition
171 , count
155 , count
@@ -273,11 +257,12 @@ import qualified Streamly.Internal.Data.Fold.Type as FL
273import qualified Streamly.Internal.Data.Stream.Type as D
257import qualified Streamly.Internal.Data.Stream.Type as D
274import qualified Streamly.Internal.Data.Stream.Generate as D
258import qualified Streamly.Internal.Data.Stream.Generate as D
275
259
260+import Streamly.Internal.Data.Parser.Type
261+--import Streamly.Internal.Data.Parser.Tee -- It's empty
262+
276import Prelude hiding
263import Prelude hiding
277 (any, all, take, takeWhile, sequence, concatMap, maybe, either, span
264 (any, all, take, takeWhile, sequence, concatMap, maybe, either, span
278 , zip, filter, dropWhile)
265 , zip, filter, dropWhile)
279−-- import Streamly.Internal.Data.Parser.ParserD.Tee
280−import Streamly.Internal.Data.Parser.ParserD.Type
281
266
282#include "DocTestDataParser.hs"
267#include "DocTestDataParser.hs"
283
268
core/src/Streamly/Internal/Data/Parser/ParserDK.hsdeleted−1544
@@ -1,1544 +0,0 @@
1−{-# OPTIONS_GHC -Wno-orphans #-}
2−
3−-- |
4−-- Module : Streamly.Internal.Data.Parser
5−-- Copyright : (c) 2020 Composewell Technologies
6−-- License : BSD-3-Clause
7−-- Maintainer : streamly@composewell.com
8−-- Stability : pre-release
9−-- Portability : GHC
10−--
11−-- Fast backtracking parsers with stream fusion and native streaming
12−-- capability.
13−--
14−-- 'Applicative' and 'Control.Applicative.Alternative' type class based
15−-- combinators from the
16−-- <http://hackage.haskell.org/package/parser-combinators parser-combinators>
17−-- package can also be used with the 'Parser' type. However, there are two
18−-- important differences between @parser-combinators@ and the equivalent ones
19−-- provided in this module in terms of performance:
20−--
21−-- 1) @parser-combinators@ use plain Haskell lists to collect the results, in a
22−-- strict Monad like IO, the results are necessarily buffered before they can
23−-- be consumed. This may not perform optimally in streaming applications
24−-- processing large amounts of data. Equivalent combinators in this module can
25−-- consume the results of parsing using a 'Fold', thus providing a scalability
26−-- and a composable consumer.
27−--
28−-- 2) Several combinators in this module can be many times faster because of
29−-- stream fusion. For example, 'Streamly.Internal.Data.Parser.many' combinator
30−-- in this module is much faster than the 'Control.Applicative.many' combinator
31−-- of 'Control.Applicative.Alternative' type class.
32−--
33−-- = Errors
34−--
35−-- Failing parsers in this module throw the 'D.ParseError' exception.
36−--
37−-- = Naming
38−--
39−-- As far as possible, try that the names of the combinators in this module are
40−-- consistent with:
41−--
42−-- * <https://hackage.haskell.org/package/base/docs/Text-ParserCombinators-ReadP.html base/Text.ParserCombinators.ReadP>
43−-- * <http://hackage.haskell.org/package/parser-combinators parser-combinators>
44−-- * <http://hackage.haskell.org/package/megaparsec megaparsec>
45−-- * <http://hackage.haskell.org/package/attoparsec attoparsec>
46−-- * <http://hackage.haskell.org/package/parsec parsec>
47−
48−module Streamly.Internal.Data.Parser
49− (
50− K.Parser (..)
51− , D.ParseError (..)
52− , D.Step (..)
53−
54− -- * Downgrade to Fold
55− , toFold
56−
57− -- First order parsers
58− -- * Accumulators
59− , fromFold
60− , fromFoldMaybe
61− , fromPure
62− , fromEffect
63− , die
64− , dieM
65−
66− -- * Map on input
67− , lmap
68− , lmapM
69− , filter
70−
71− -- * Map on output
72− , rmapM
73−
74− -- * Element parsers
75− , peek
76−
77− -- All of these can be expressed in terms of either
78− , one
79− , oneEq
80− , oneNotEq
81− , oneOf
82− , noneOf
83− , eof
84− , satisfy
85− , maybe
86− , either
87−
88− -- * Sequence parsers (tokenizers)
89− --
90− -- | Parsers chained in series, if one parser terminates the composition
91− -- terminates.
92−
93− , lookAhead
94−
95− -- ** By length
96− -- | Grab a sequence of input elements without inspecting them
97− , takeBetween
98− -- , take -- takeBetween 0 n
99− , takeEQ -- takeBetween n n
100− , takeGE -- takeBetween n maxBound
101− , takeP
102−
103− -- Grab a sequence of input elements by inspecting them
104− -- ** Exact match
105− , listEq
106− , listEqBy
107− , streamEqBy
108− , subsequenceBy
109−
110− -- ** By predicate
111− , takeWhileP
112− , takeWhile
113− -- $takeWhile
114− , takeWhile1
115− , dropWhile
116−
117− -- ** Separators
118− , takeEndBy
119− , takeEndBy_
120− , takeEndByEsc
121− -- , takeEndByEsc_
122− , takeStartBy
123− , takeStartBy_
124− , takeEitherSepBy
125− , wordBy
126− -- , wordByEsc
127−
128− -- ** By comparing
129− , groupBy
130− , groupByRolling
131− , groupByRollingEither
132−
133− -- ** Framing
134− -- , takeFramedBy
135− , takeFramedBy_
136− , takeFramedByEsc_
137− , takeFramedByGeneric
138− , wordFramedBy
139− , wordQuotedBy
140−
141− -- | Unimplemented
142− --
143− -- @
144− -- , prefixOf -- match any prefix of a given string
145− -- , suffixOf -- match any suffix of a given string
146− -- , infixOf -- match any substring of a given string
147− -- @
148−
149− -- Second order parsers (parsers using parsers)
150− -- * Binary Combinators
151−
152− -- ** Sequential Applicative
153− , splitWith
154− , split_
155−
156−{-
157− -- ** Parallel Applicatives
158− , teeWith
159− , teeWithFst
160− , teeWithMin
161− -- , teeTill -- like manyTill but parallel
162−-}
163−
164− -- ** Sequential Interleaving
165− -- Use two folds, run a primary parser, its rejected values go to the
166− -- secondary parser.
167− , deintercalate
168− -- , deintercalatePrefix
169− -- , deintercalateSuffix
170−
171− -- *** Special cases
172− -- | TODO: traditional implmentations of these may be of limited use. For
173− -- example, consider parsing lines separated by @\\r\\n@. The main parser
174− -- will have to detect and exclude the sequence @\\r\\n@ anyway so that we
175− -- can apply the "sep" parser.
176− --
177− -- We can instead implement these as special cases of deintercalate.
178− --
179− -- @
180− -- , endBy
181− -- , sepEndBy
182− -- , beginBy
183− -- , sepBeginBy
184− -- , sepAroundBy
185− -- @
186− , sepBy1
187− , sepBy
188−
189− -- ** Sequential Alternative
190− , alt
191−
192−{-
193− -- ** Parallel Alternatives
194− , shortest
195− , longest
196− -- , fastest
197−-}
198−
199− -- * N-ary Combinators
200− -- ** Sequential Collection
201− , concatSequence
202− , concatMap
203−
204− -- ** Sequential Repetition
205− , count
206− , countBetween
207−
208− , manyP
209− , many
210− , some
211− , manyTillP
212− , manyTill
213− , manyThen
214−
215− -- * Distribution
216− --
217− -- | A simple and stupid impl would be to just convert the stream to an
218− -- array and give the array reference to all consumers. The array can be
219− -- grown on demand by any consumer and truncated when nonbody needs it.
220−
221− -- ** Distribute to collection
222− -- ** Distribute to repetition
223−
224− -- ** Interleaved collection
225− -- |
226− --
227− -- 1. Round robin
228− -- 2. Priority based
229− , roundRobin
230−
231− -- ** Collection of Alternatives
232− -- | Unimplemented
233− --
234− -- @
235− -- , shortestN
236− -- , longestN
237− -- , fastestN -- first N successful in time
238− -- , choiceN -- first N successful in position
239− -- @
240− -- , choice -- first successful in position
241−
242− -- ** Repeated Alternatives
243− , retryMaxTotal
244− , retryMaxSuccessive
245− , retry
246−
247− -- * Deprecated
248− , next
249− )
250−where
251−
252−import Streamly.Internal.Data.Fold.Type (Fold(..))
253−import Streamly.Internal.Data.Parser.ParserK.Type (Parser)
254−
255−import qualified Data.Foldable as Foldable
256−import qualified Streamly.Internal.Data.Fold.Type as FL
257−import qualified Streamly.Internal.Data.Parser as D
258−import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
259−
260−#ifdef USE_STREAMK
261−import Streamly.Internal.Data.StreamK (Stream)
262−import qualified Streamly.Internal.Data.StreamK as Stream
263−#else
264−import Streamly.Internal.Data.Stream.Type (Stream)
265−import qualified Streamly.Internal.Data.Stream.Type as Stream
266−#endif
267−
268−import Prelude hiding
269− ( any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either
270− , filter )
271−
272−--
273−-- $setup
274−-- >>> :m
275−-- >>> import Prelude hiding (any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either, filter)
276−-- >>> import Control.Applicative ((<|>))
277−-- >>> import Data.Char (isSpace)
278−-- >>> import qualified Data.Maybe as Maybe
279−-- >>> import qualified Data.Foldable as Foldable
280−-- >>> import qualified Streamly.Data.Stream as Stream
281−-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse, parseMany)
282−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
283−-- >>> import qualified Streamly.Internal.Data.Parser as Parser
284−
285−-------------------------------------------------------------------------------
286−-- Downgrade a parser to a Fold
287−-------------------------------------------------------------------------------
288−--
289−-- | Make a 'Fold' from a 'Parser'. The fold just throws an exception if the
290−-- parser fails or tries to backtrack.
291−--
292−-- This can be useful in combinators that accept a Fold and we know that a
293−-- Parser cannot fail or failure exception is acceptable as there is no way to
294−-- recover.
295−--
296−-- /Pre-release/
297−--
298−{-# INLINE toFold #-}
299−toFold :: Monad m => Parser a m b -> Fold m a b
300−toFold p = D.toFold $ D.fromParserK p
301−
302−-------------------------------------------------------------------------------
303−-- Upgrade folds to parses
304−-------------------------------------------------------------------------------
305−--
306−-- | Make a 'Parser' from a 'Fold'.
307−--
308−{-# INLINE fromFold #-}
309−fromFold :: Monad m => Fold m a b -> Parser a m b
310−fromFold = D.toParserK . D.fromFold
311−
312−-- | Convert a Maybe returning fold to an error returning parser. The first
313−-- argument is the error message that the parser would return when the fold
314−-- returns Nothing.
315−--
316−-- /Pre-release/
317−--
318−{-# INLINE fromFoldMaybe #-}
319−fromFoldMaybe :: Monad m => String -> Fold m a (Maybe b) -> Parser a m b
320−fromFoldMaybe err = D.toParserK . D.fromFoldMaybe err
321−
322−-------------------------------------------------------------------------------
323−-- Terminating but not failing folds
324−-------------------------------------------------------------------------------
325−--
326−-- This is the dual of stream "fromPure".
327−--
328−-- | A parser that always yields a pure value without consuming any input.
329−--
330−{-# INLINE [3] fromPure #-}
331−fromPure :: Monad m => b -> Parser a m b
332−fromPure = D.toParserK . D.fromPure
333−{-# RULES "fromPure fallback to CPS" [2]
334− forall a. D.toParserK (D.fromPure a) = K.fromPure a #-}
335−
336−-- This is the dual of stream "fromEffect".
337−--
338−-- | A parser that always yields the result of an effectful action without
339−-- consuming any input.
340−--
341−{-# INLINE fromEffect #-}
342−fromEffect :: Monad m => m b -> Parser a m b
343−fromEffect = K.fromEffect -- D.toParserK . D.fromEffect
344−
345−-- This is the dual of "nil".
346−--
347−-- | A parser that always fails with an error message without consuming
348−-- any input.
349−--
350−{-# INLINE [3] die #-}
351−die :: Monad m => String -> Parser a m b
352−die = D.toParserK . D.die
353−{-# RULES "die fallback to CPS" [2]
354− forall a. D.toParserK (D.die a) = K.die a #-}
355−
356−-- This is the dual of "nilM".
357−--
358−-- | A parser that always fails with an effectful error message and without
359−-- consuming any input.
360−--
361−-- /Pre-release/
362−--
363−{-# INLINE dieM #-}
364−dieM :: Monad m => m String -> Parser a m b
365−dieM = D.toParserK . D.dieM
366−
367−-------------------------------------------------------------------------------
368−-- Map on input
369−-------------------------------------------------------------------------------
370−
371−-- | @lmap f parser@ maps the function @f@ on the input of the parser.
372−--
373−-- >>> Stream.parse (Parser.lmap (\x -> x * x) (Parser.fromFold Fold.sum)) (Stream.enumerateFromTo 1 100)
374−-- Right 338350
375−--
376−-- > lmap = Parser.lmapM return
377−--
378−{-# INLINE lmap #-}
379−lmap :: Monad m => (a -> b) -> Parser b m r -> Parser a m r
380−lmap f p = D.toParserK $ D.lmap f $ D.fromParserK p
381−
382−-- | @lmapM f parser@ maps the monadic function @f@ on the input of the parser.
383−--
384−{-# INLINE lmapM #-}
385−lmapM :: Monad m => (a -> m b) -> Parser b m r -> Parser a m r
386−lmapM f p = D.toParserK $ D.lmapM f $ D.fromParserK p
387−
388−-- | @rmapM f parser@ maps the monadic function @f@ on the output of the parser.
389−--
390−-- >>> rmap = fmap
391−{-# INLINE rmapM #-}
392−rmapM :: Monad m => (b -> m c) -> Parser a m b -> Parser a m c
393−rmapM f p = D.toParserK $ D.rmapM f $ D.fromParserK p
394−
395−-- | Include only those elements that pass a predicate.
396−--
397−-- >>> Stream.parse (Parser.filter (> 5) (Parser.fromFold Fold.sum)) $ Stream.fromList [1..10]
398−-- Right 40
399−--
400−{-# INLINE filter #-}
401−filter :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
402−filter f p = D.toParserK $ D.filter f $ D.fromParserK p
403−
404−-------------------------------------------------------------------------------
405−-- Failing Parsers
406−-------------------------------------------------------------------------------
407−
408−-- | Peek the head element of a stream, without consuming it. Fails if it
409−-- encounters end of input.
410−--
411−-- >>> Stream.parse ((,) <$> Parser.peek <*> Parser.satisfy (> 0)) $ Stream.fromList [1]
412−-- Right (1,1)
413−--
414−-- @
415−-- peek = lookAhead (satisfy True)
416−-- @
417−--
418−{-# INLINE peek #-}
419−peek :: Monad m => Parser a m a
420−peek = D.toParserK D.peek
421−
422−-- | Succeeds if we are at the end of input, fails otherwise.
423−--
424−-- >>> Stream.parse ((,) <$> Parser.satisfy (> 0) <*> Parser.eof) $ Stream.fromList [1]
425−-- Right (1,())
426−--
427−{-# INLINE eof #-}
428−eof :: Monad m => Parser a m ()
429−eof = D.toParserK D.eof
430−
431−-- | Returns the next element if it passes the predicate, fails otherwise.
432−--
433−-- >>> Stream.parse (Parser.satisfy (== 1)) $ Stream.fromList [1,0,1]
434−-- Right 1
435−--
436−-- >>> toMaybe f x = if f x then Just x else Nothing
437−-- >>> satisfy f = Parser.maybe (toMaybe f)
438−--
439−{-# INLINE satisfy #-}
440−satisfy :: Monad m => (a -> Bool) -> Parser a m a
441−satisfy = D.toParserK . D.satisfy
442−
443−-- | Consume one element from the head of the stream. Fails if it encounters
444−-- end of input.
445−--
446−-- >>> one = Parser.satisfy $ const True
447−--
448−{-# INLINE one #-}
449−one :: Monad m => Parser a m a
450−one = satisfy $ const True
451−
452−-- Alternate names: "only", "onlyThis".
453−
454−-- | Match a specific element.
455−--
456−-- >>> oneEq x = Parser.satisfy (== x)
457−--
458−{-# INLINE oneEq #-}
459−oneEq :: (Monad m, Eq a) => a -> Parser a m a
460−oneEq x = satisfy (== x)
461−
462−-- Alternate names: "exclude", "notThis".
463−
464−-- | Match anything other than the supplied element.
465−--
466−-- >>> oneNotEq x = Parser.satisfy (/= x)
467−--
468−{-# INLINE oneNotEq #-}
469−oneNotEq :: (Monad m, Eq a) => a -> Parser a m a
470−oneNotEq x = satisfy (/= x)
471−
472−-- | Match any one of the elements in the supplied list.
473−--
474−-- >>> oneOf xs = Parser.satisfy (`Foldable.elem` xs)
475−--
476−-- When performance matters a pattern matching predicate could be more
477−-- efficient than a 'Foldable' datatype:
478−--
479−-- @
480−-- let p x =
481−-- case x of
482−-- 'a' -> True
483−-- 'e' -> True
484−-- _ -> False
485−-- in satisfy p
486−-- @
487−--
488−-- GHC may use a binary search instead of linear search in the list.
489−-- Alternatively, you can also use an array instead of list for storage and
490−-- search.
491−--
492−{-# INLINE oneOf #-}
493−oneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
494−oneOf xs = satisfy (`Foldable.elem` xs)
495−
496−-- | See performance notes in 'oneOf'.
497−--
498−-- >>> noneOf xs = Parser.satisfy (`Foldable.notElem` xs)
499−--
500−{-# INLINE noneOf #-}
501−noneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
502−noneOf xs = satisfy (`Foldable.notElem` xs)
503−
504−-- | Return the next element of the input. Returns 'Nothing'
505−-- on end of input. Also known as 'head'.
506−--
507−-- /Pre-release/
508−--
509−{-# DEPRECATED next "Please use \"fromFold Fold.one\" instead" #-}
510−{-# INLINE next #-}
511−next :: Monad m => Parser a m (Maybe a)
512−next = D.toParserK D.next
513−
514−-- | Map a 'Maybe' returning function on the next element in the stream. The
515−-- parser fails if the function returns 'Nothing' otherwise returns the 'Just'
516−-- value.
517−--
518−-- >>> toEither = Maybe.maybe (Left "maybe: predicate failed") Right
519−-- >>> maybe f = Parser.either (toEither . f)
520−--
521−-- >>> maybe f = Parser.fromFoldMaybe "maybe: predicate failed" (Fold.maybe f)
522−--
523−-- /Pre-release/
524−--
525−{-# INLINE maybe #-}
526−maybe :: Monad m => (a -> Maybe b) -> Parser a m b
527−maybe = D.toParserK . D.maybe
528−
529−-- | Map an 'Either' returning function on the next element in the stream. If
530−-- the function returns 'Left err', the parser fails with the error message
531−-- @err@ otherwise returns the 'Right' value.
532−--
533−-- /Pre-release/
534−--
535−{-# INLINE either #-}
536−either :: Monad m => (a -> Either String b) -> Parser a m b
537−either = D.toParserK . D.either
538−
539−-------------------------------------------------------------------------------
540−-- Taking elements
541−-------------------------------------------------------------------------------
542−
543−-- | @takeBetween m n@ takes a minimum of @m@ and a maximum of @n@ input
544−-- elements and folds them using the supplied fold.
545−--
546−-- Stops after @n@ elements.
547−-- Fails if the stream ends before @m@ elements could be taken.
548−--
549−-- Examples: -
550−--
551−-- @
552−-- >>> :{
553−-- takeBetween' low high ls = Stream.parse prsr (Stream.fromList ls)
554−-- where prsr = Parser.takeBetween low high Fold.toList
555−-- :}
556−--
557−-- @
558−--
559−-- >>> takeBetween' 2 4 [1, 2, 3, 4, 5]
560−-- Right [1,2,3,4]
561−--
562−-- >>> takeBetween' 2 4 [1, 2]
563−-- Right [1,2]
564−--
565−-- >>> takeBetween' 2 4 [1]
566−-- Left (ParseError "takeBetween: Expecting alteast 2 elements, got 1")
567−--
568−-- >>> takeBetween' 0 0 [1, 2]
569−-- Right []
570−--
571−-- >>> takeBetween' 0 1 []
572−-- Right []
573−--
574−-- @takeBetween@ is the most general take operation, other take operations can
575−-- be defined in terms of takeBetween. For example:
576−--
577−-- >>> take n = Parser.takeBetween 0 n
578−-- >>> takeEQ n = Parser.takeBetween n n
579−-- >>> takeGE n = Parser.takeBetween n maxBound
580−--
581−-- /Pre-release/
582−--
583−{-# INLINE takeBetween #-}
584−takeBetween :: Monad m =>
585− Int -> Int -> Fold m a b -> Parser a m b
586−takeBetween m n = D.toParserK . D.takeBetween m n
587−
588−-- | Stops after taking exactly @n@ input elements.
589−--
590−-- * Stops - after consuming @n@ elements.
591−-- * Fails - if the stream or the collecting fold ends before it can collect
592−-- exactly @n@ elements.
593−--
594−-- >>> Stream.parse (Parser.takeEQ 4 Fold.toList) $ Stream.fromList [1,0,1]
595−-- Left (ParseError "takeEQ: Expecting exactly 4 elements, input terminated on 3")
596−--
597−{-# INLINE takeEQ #-}
598−takeEQ :: Monad m => Int -> Fold m a b -> Parser a m b
599−takeEQ n = D.toParserK . D.takeEQ n
600−
601−-- | Take at least @n@ input elements, but can collect more.
602−--
603−-- * Stops - when the collecting fold stops.
604−-- * Fails - if the stream or the collecting fold ends before producing @n@
605−-- elements.
606−--
607−-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1]
608−-- Left (ParseError "takeGE: Expecting at least 4 elements, input terminated on 3")
609−--
610−-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1,0,1]
611−-- Right [1,0,1,0,1]
612−--
613−-- /Pre-release/
614−--
615−{-# INLINE takeGE #-}
616−takeGE :: Monad m => Int -> Fold m a b -> Parser a m b
617−takeGE n = D.toParserK . D.takeGE n
618−
619−-------------------------------------------------------------------------------
620−-- Take until a condition
621−-------------------------------------------------------------------------------
622−
623−-- $takeWhile
624−-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
625−
626−-- XXX We should perhaps use only takeWhileP and rename it to takeWhile.
627−--
628−-- | Like 'takeWhile' but uses a 'Parser' instead of a 'Fold' to collect the
629−-- input. The combinator stops when the condition fails or if the collecting
630−-- parser stops.
631−--
632−-- Other interesting parsers can be implemented in terms of this parser:
633−--
634−-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
635−-- >>> takeWhileBetween cond m n p = Parser.takeWhileP cond (Parser.takeBetween m n p)
636−--
637−-- Stops: when the condition fails or the collecting parser stops.
638−-- Fails: when the collecting parser fails.
639−--
640−-- /Pre-release/
641−--
642−{-# INLINE takeWhileP #-}
643−takeWhileP :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
644−takeWhileP cond p = D.toParserK $ D.takeWhileP cond (D.fromParserK p)
645−
646−-- | Collect stream elements until an element fails the predicate. The element
647−-- on which the predicate fails is returned back to the input stream.
648−--
649−-- * Stops - when the predicate fails or the collecting fold stops.
650−-- * Fails - never.
651−--
652−-- >>> Stream.parse (Parser.takeWhile (== 0) Fold.toList) $ Stream.fromList [0,0,1,0,1]
653−-- Right [0,0]
654−--
655−-- >>> takeWhile cond f = Parser.takeWhileP cond (Parser.fromFold f)
656−--
657−-- We can implement a @breakOn@ using 'takeWhile':
658−--
659−-- @
660−-- breakOn p = takeWhile (not p)
661−-- @
662−--
663−{-# INLINE takeWhile #-}
664−takeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
665−takeWhile cond = D.toParserK . D.takeWhile cond
666−-- takeWhile cond f = takeWhileP cond (fromFold f)
667−
668−-- | Like 'takeWhile' but takes at least one element otherwise fails.
669−--
670−-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
671−--
672−{-# INLINE takeWhile1 #-}
673−takeWhile1 :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
674−takeWhile1 cond = D.toParserK . D.takeWhile1 cond
675−-- takeWhile1 cond f = takeWhileP cond (takeBetween 1 maxBound f)
676−
677−-- | Drain the input as long as the predicate succeeds, running the effects and
678−-- discarding the results.
679−--
680−-- This is also called @skipWhile@ in some parsing libraries.
681−--
682−-- >>> dropWhile p = Parser.takeWhile p Fold.drain
683−--
684−{-# INLINE dropWhile #-}
685−dropWhile :: Monad m => (a -> Bool) -> Parser a m ()
686−dropWhile p = takeWhile p FL.drain
687−
688−-------------------------------------------------------------------------------
689−-- Separators
690−-------------------------------------------------------------------------------
691−
692−-- XXX We can remove Maybe from esc
693−{-# INLINE takeFramedByGeneric #-}
694−takeFramedByGeneric :: Monad m =>
695− Maybe (a -> Bool)
696− -> Maybe (a -> Bool)
697− -> Maybe (a -> Bool)
698− -> Fold m a b
699− -> Parser a m b
700−takeFramedByGeneric esc begin end f =
701− D.toParserK $ D.takeFramedByGeneric esc begin end f
702−
703−-- | @takeEndBy cond parser@ parses a token that ends by a separator chosen by
704−-- the supplied predicate. The separator is also taken with the token.
705−--
706−-- This can be combined with other parsers to implement other interesting
707−-- parsers as follows:
708−--
709−-- >>> takeEndByLE cond n p = Parser.takeEndBy cond (Parser.fromFold $ Fold.take n p)
710−-- >>> takeEndByBetween cond m n p = Parser.takeEndBy cond (Parser.takeBetween m n p)
711−--
712−-- >>> takeEndBy = Parser.takeEndByEsc (const False)
713−--
714−-- See also "Streamly.Data.Fold.takeEndBy". Unlike the fold, the collecting
715−-- parser in the takeEndBy parser can decide whether to fail or not if the
716−-- stream does not end with separator.
717−--
718−-- /Pre-release/
719−--
720−{-# INLINE takeEndBy #-}
721−takeEndBy :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
722−takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
723−-- takeEndBy = takeEndByEsc (const False)
724−
725−-- | Like 'takeEndBy' but the separator is dropped.
726−--
727−-- See also "Streamly.Data.Fold.takeEndBy_".
728−--
729−-- /Pre-release/
730−--
731−{-# INLINE takeEndBy_ #-}
732−takeEndBy_ :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
733−takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
734−{-
735−takeEndBy_ isEnd p =
736− takeFramedByGeneric Nothing Nothing (Just isEnd) (toFold p)
737−-}
738−
739−-- | Take either the separator or the token. Separator is a Left value and
740−-- token is Right value.
741−--
742−-- /Unimplemented/
743−{-# INLINE takeEitherSepBy #-}
744−takeEitherSepBy :: -- Monad m =>
745− (a -> Bool) -> Fold m (Either a b) c -> Parser a m c
746−takeEitherSepBy _cond = undefined -- D.toParserK . D.takeEitherSepBy cond
747−
748−-- | Parse a token that starts with an element chosen by the predicate. The
749−-- parser fails if the input does not start with the selected element.
750−--
751−-- * Stops - when the predicate succeeds in non-leading position.
752−-- * Fails - when the predicate fails in the leading position.
753−--
754−-- >>> splitWithPrefix p f = Stream.parseMany (Parser.takeStartBy p f)
755−--
756−-- Examples: -
757−--
758−-- >>> p = Parser.takeStartBy (== ',') Fold.toList
759−-- >>> leadingComma = Stream.parse p . Stream.fromList
760−-- >>> leadingComma "a,b"
761−-- Left (ParseError "takeStartBy: missing frame start")
762−-- ...
763−-- >>> leadingComma ",,"
764−-- Right ","
765−-- >>> leadingComma ",a,b"
766−-- Right ",a"
767−-- >>> leadingComma ""
768−-- Right ""
769−--
770−-- /Pre-release/
771−--
772−{-# INLINE takeStartBy #-}
773−takeStartBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
774−takeStartBy cond = D.toParserK . D.takeStartBy cond
775−
776−-- | Like 'takeStartBy' but drops the separator.
777−--
778−-- >>> takeStartBy_ isBegin = Parser.takeFramedByGeneric Nothing (Just isBegin) Nothing
779−--
780−{-# INLINE takeStartBy_ #-}
781−takeStartBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
782−takeStartBy_ isBegin = takeFramedByGeneric Nothing (Just isBegin) Nothing
783−
784−-------------------------------------------------------------------------------
785−-- Quoting and Escaping
786−-------------------------------------------------------------------------------
787−
788−-- | Like 'takeEndBy' but the separator elements can be escaped using an
789−-- escape char determined by the first predicate. The escape characters are
790−-- removed.
791−--
792−-- /pre-release/
793−{-# INLINE takeEndByEsc #-}
794−takeEndByEsc :: Monad m =>
795− (a -> Bool) -> (a -> Bool) -> Parser a m b -> Parser a m b
796−takeEndByEsc isEsc isEnd p =
797− D.toParserK $ D.takeEndByEsc isEsc isEnd (D.fromParserK p)
798−
799−-- | @takeFramedByEsc_ isEsc isBegin isEnd fold@ parses a token framed using a
800−-- begin and end predicate, and an escape character. The frame begin and end
801−-- characters lose their special meaning if preceded by the escape character.
802−--
803−-- Nested frames are allowed if begin and end markers are different, nested
804−-- frames must be balanced unless escaped, nested frame markers are emitted as
805−-- it is.
806−--
807−-- For example,
808−--
809−-- >>> p = Parser.takeFramedByEsc_ (== '\\') (== '{') (== '}') Fold.toList
810−-- >>> Stream.parse p $ Stream.fromList "{hello}"
811−-- Right "hello"
812−-- >>> Stream.parse p $ Stream.fromList "{hello {world}}"
813−-- Right "hello {world}"
814−-- >>> Stream.parse p $ Stream.fromList "{hello \\{world}"
815−-- Right "hello {world"
816−-- >>> Stream.parse p $ Stream.fromList "{hello {world}"
817−-- Left (ParseError "takeFramedByEsc_: missing frame end")
818−--
819−-- /Pre-release/
820−{-# INLINE takeFramedByEsc_ #-}
821−takeFramedByEsc_ :: Monad m =>
822− (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
823−takeFramedByEsc_ isEsc isBegin isEnd f =
824− D.toParserK $ D.takeFramedByEsc_ isEsc isBegin isEnd f
825−-- takeEndByEsc_ isEsc isEnd p =
826−-- takeFramedByGeneric (Just isEsc) Nothing (Just isEnd) (toFold p)
827−
828−-- | @takeFramedBy_ isBegin isEnd fold@ parses a token framed by a begin and an
829−-- end predicate.
830−--
831−-- >>> takeFramedBy_ = Parser.takeFramedByEsc_ (const False)
832−--
833−{-# INLINE takeFramedBy_ #-}
834−takeFramedBy_ :: Monad m =>
835− (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
836−takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
837−-- takeFramedBy_ isBegin isEnd =
838−-- takeFramedByGeneric (Just (const False)) (Just isBegin) (Just isEnd)
839−
840−-------------------------------------------------------------------------------
841−-- Grouping and words
842−-------------------------------------------------------------------------------
843−
844−-- Note we can also get words using something like:
845−-- sepBy FL.toList (takeWhile (not . p) Fold.toList) (dropWhile p)
846−--
847−-- But that won't be as efficient and ergonomic.
848−--
849−-- | Like 'splitOn' but strips leading, trailing, and repeated separators.
850−-- Therefore, @".a..b."@ having '.' as the separator would be parsed as
851−-- @["a","b"]@. In other words, its like parsing words from whitespace
852−-- separated text.
853−--
854−-- * Stops - when it finds a word separator after a non-word element
855−-- * Fails - never.
856−--
857−-- >>> wordBy = Parser.wordFramedBy (const False) (const False) (const False)
858−--
859−-- @
860−-- S.wordsBy pred f = S.parseMany (PR.wordBy pred f)
861−-- @
862−--
863−{-# INLINE wordBy #-}
864−wordBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
865−wordBy f = D.toParserK . D.wordBy f
866−
867−-- | Like 'wordBy' but treats anything inside a pair of quotes as a single
868−-- word, the quotes can be escaped by an escape character. Recursive quotes
869−-- are possible if quote begin and end characters are different, quotes must be
870−-- balanced. Outermost quotes are stripped.
871−--
872−-- >>> braces = Parser.wordFramedBy (== '\\') (== '{') (== '}') isSpace Fold.toList
873−-- >>> Stream.parse braces $ Stream.fromList "{ab} cd"
874−-- Right "ab"
875−-- >>> Stream.parse braces $ Stream.fromList "{ab}{cd}"
876−-- Right "abcd"
877−-- >>> Stream.parse braces $ Stream.fromList "a{b} cd"
878−-- Right "ab"
879−-- >>> Stream.parse braces $ Stream.fromList "a{{b}} cd"
880−-- Right "a{b}"
881−--
882−-- >>> quotes = Parser.wordFramedBy (== '\\') (== '"') (== '"') isSpace Fold.toList
883−-- >>> Stream.parse quotes $ Stream.fromList "\"a\"\"b\""
884−-- Right "ab"
885−--
886−{-# INLINE wordFramedBy #-}
887−wordFramedBy :: Monad m =>
888− (a -> Bool) -- ^ Escape
889− -> (a -> Bool) -- ^ left quote
890− -> (a -> Bool) -- ^ right quote
891− -> (a -> Bool) -- ^ word seperator
892− -> Fold m a b
893− -> Parser a m b
894−wordFramedBy isEsc isBegin isEnd isSpc =
895− D.toParserK . D.wordFramedBy isEsc isBegin isEnd isSpc
896−
897−-- | Like 'wordFramedBy' but the closing quote is determined by the opening
898−-- quote. The first quote begin starts a quote that is closed by its
899−-- corresponding closing quote.
900−--
901−-- 'wordFramedBy' and 'wordQuotedBy' both allow multiple quote characters based
902−-- on the predicates but 'wordQuotedBy' always fixes the quote at the first
903−-- occurrence and then it is closed only by the corresponding closing quote.
904−-- Therefore, other quoting characters can be embedded inside it as normal
905−-- characters. On the other hand, 'wordFramedBy' would close the quote as soon
906−-- as it encounters any of the closing quotes.
907−--
908−-- >>> q = (`elem` ['"', '\''])
909−-- >>> p kQ = Parser.wordQuotedBy kQ (== '\\') q q id isSpace Fold.toList
910−--
911−-- >>> Stream.parse (p False) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
912−-- Right "ab'c;d\"ef"
913−--
914−-- >>> Stream.parse (p True) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
915−-- Right "a\"b'c\";'d\"e'f"
916−--
917−{-# INLINE wordQuotedBy #-}
918−wordQuotedBy :: (Monad m, Eq a) =>
919− Bool -- ^ keep the quotes in the output
920− -> (a -> Bool) -- ^ Escape
921− -> (a -> Bool) -- ^ left quote
922− -> (a -> Bool) -- ^ right quote
923− -> (a -> a) -- ^ get right quote from left quote
924− -> (a -> Bool) -- ^ word seperator
925− -> Fold m a b
926− -> Parser a m b
927−wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc =
928− D.toParserK . D.wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc
929−
930−-- | Given an input stream @[a,b,c,...]@ and a comparison function @cmp@, the
931−-- parser assigns the element @a@ to the first group, then if @a \`cmp` b@ is
932−-- 'True' @b@ is also assigned to the same group. If @a \`cmp` c@ is 'True'
933−-- then @c@ is also assigned to the same group and so on. When the comparison
934−-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
935−-- the result of the fold is the result of the parser.
936−--
937−-- * Stops - when the comparison fails.
938−-- * Fails - never.
939−--
940−-- >>> :{
941−-- runGroupsBy eq =
942−-- Stream.fold Fold.toList
943−-- . Stream.parseMany (Parser.groupBy eq Fold.toList)
944−-- . Stream.fromList
945−-- :}
946−--
947−-- >>> runGroupsBy (<) []
948−-- []
949−--
950−-- >>> runGroupsBy (<) [1]
951−-- [Right [1]]
952−--
953−-- >>> runGroupsBy (<) [3, 5, 4, 1, 2, 0]
954−-- [Right [3,5,4],Right [1,2],Right [0]]
955−--
956−{-# INLINE groupBy #-}
957−groupBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
958−groupBy eq = D.toParserK . D.groupBy eq
959−
960−-- | Unlike 'groupBy' this combinator performs a rolling comparison of two
961−-- successive elements in the input stream. Assuming the input stream
962−-- is @[a,b,c,...]@ and the comparison function is @cmp@, the parser
963−-- first assigns the element @a@ to the first group, then if @a \`cmp` b@ is
964−-- 'True' @b@ is also assigned to the same group. If @b \`cmp` c@ is 'True'
965−-- then @c@ is also assigned to the same group and so on. When the comparison
966−-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
967−-- the result of the fold is the result of the parser.
968−--
969−-- * Stops - when the comparison fails.
970−-- * Fails - never.
971−--
972−-- >>> :{
973−-- runGroupsByRolling eq =
974−-- Stream.fold Fold.toList
975−-- . Stream.parseMany (Parser.groupByRolling eq Fold.toList)
976−-- . Stream.fromList
977−-- :}
978−--
979−-- >>> runGroupsByRolling (<) []
980−-- []
981−--
982−-- >>> runGroupsByRolling (<) [1]
983−-- [Right [1]]
984−--
985−-- >>> runGroupsByRolling (<) [3, 5, 4, 1, 2, 0]
986−-- [Right [3,5],Right [4],Right [1,2],Right [0]]
987−--
988−-- /Pre-release/
989−--
990−{-# INLINE groupByRolling #-}
991−groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
992−groupByRolling eq = D.toParserK . D.groupByRolling eq
993−
994−-- | Like 'groupByRolling', but if the predicate is 'True' then collects using
995−-- the first fold as long as the predicate holds 'True', if the predicate is
996−-- 'False' collects using the second fold as long as it remains 'False'.
997−-- Returns 'Left' for the first case and 'Right' for the second case.
998−--
999−-- For example, if we want to detect sorted sequences in a stream, both
1000−-- ascending and descending cases we can use 'groupByRollingEither (<=)
1001−-- Fold.toList Fold.toList'.
1002−--
1003−-- /Pre-release/
1004−{-# INLINE groupByRollingEither #-}
1005−groupByRollingEither :: Monad m =>
1006− (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (Either b c)
1007−groupByRollingEither eq f1 = D.toParserK . D.groupByRollingEither eq f1
1008−
1009−-- | Like 'listEqBy' but uses a stream instead of a list and does not return
1010−-- the stream.
1011−--
1012−-- See also: "Streamly.Data.Stream.streamEqBy"
1013−--
1014−{-# INLINE streamEqBy #-}
1015−streamEqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Parser a m ()
1016−streamEqBy cmp = D.toParserK . D.streamEqBy cmp
1017−
1018−-- | Match the given sequence of elements using the given comparison function.
1019−-- Returns the original sequence if successful.
1020−--
1021−-- Definition:
1022−--
1023−-- >>> listEqBy cmp xs = Parser.streamEqBy cmp (Stream.fromList xs) *> Parser.fromPure xs
1024−--
1025−-- Examples:
1026−--
1027−-- >>> Stream.parse (Parser.listEqBy (==) "string") $ Stream.fromList "string"
1028−-- Right "string"
1029−--
1030−-- >>> Stream.parse (Parser.listEqBy (==) "mismatch") $ Stream.fromList "match"
1031−-- Left (ParseError "streamEqBy: mismtach occurred")
1032−--
1033−{-# INLINE listEqBy #-}
1034−listEqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser a m [a]
1035−-- listEqBy cmp xs = D.toParserK (D.listEqBy cmp xs)
1036−listEqBy cmp xs = streamEqBy cmp (Stream.fromList xs) *> fromPure xs
1037−
1038−-- Rename to "list".
1039−-- | Match the input sequence with the supplied list and return it if
1040−-- successful.
1041−--
1042−-- >>> listEq = Parser.listEqBy (==)
1043−--
1044−{-# INLINE listEq #-}
1045−listEq :: (Monad m, Eq a) => [a] -> Parser a m [a]
1046−listEq = listEqBy (==)
1047−
1048−-- | Match if the input stream is a subsequence of the argument stream i.e. all
1049−-- the elements of the input stream occur, in order, in the argument stream.
1050−-- The elements do not have to occur consecutively. A sequence is considered a
1051−-- subsequence of itself.
1052−{-# INLINE subsequenceBy #-}
1053−subsequenceBy :: -- Monad m =>
1054− (a -> a -> Bool) -> Stream m a -> Parser a m ()
1055−subsequenceBy = undefined
1056−
1057−{-
1058−-- Should go in Data.Parser.Regex in streamly package so that it can depend on
1059−-- regex backends.
1060−{-# INLINE regexPosix #-}
1061−regexPosix :: -- Monad m =>
1062− Regex -> Parser m a (Maybe (Array (MatchOffset, MatchLength)))
1063−regexPosix = undefined
1064−
1065−{-# INLINE regexPCRE #-}
1066−regexPCRE :: -- Monad m =>
1067− Regex -> Parser m a (Maybe (Array (MatchOffset, MatchLength)))
1068−regexPCRE = undefined
1069−-}
1070−
1071−-------------------------------------------------------------------------------
1072−-- nested parsers
1073−-------------------------------------------------------------------------------
1074−
1075−-- | Sequential parser application. Apply two parsers sequentially to an input
1076−-- stream. The input is provided to the first parser, when it is done the
1077−-- remaining input is provided to the second parser. If both the parsers
1078−-- succeed their outputs are combined using the supplied function. The
1079−-- operation fails if any of the parsers fail.
1080−--
1081−-- Note: This is a parsing dual of appending streams using
1082−-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and zips
1083−-- the results.
1084−--
1085−-- This implementation is strict in the second argument, therefore, the
1086−-- following will fail:
1087−--
1088−-- >>> Stream.parse (Parser.splitWith const (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1089−-- *** Exception: Prelude.undefined
1090−-- ...
1091−--
1092−-- Compare with 'Applicative' instance method '<*>'. This implementation allows
1093−-- stream fusion but has quadratic complexity. This can fuse with other
1094−-- operations and can be faster than 'Applicative' instance for small number
1095−-- (less than 8) of compositions.
1096−--
1097−-- Many combinators can be expressed using @splitWith@ and other parser
1098−-- primitives. Some common idioms are described below,
1099−--
1100−-- @
1101−-- span :: (a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
1102−-- span pred f1 f2 = splitWith (,) ('takeWhile' pred f1) ('fromFold' f2)
1103−-- @
1104−--
1105−-- @
1106−-- spanBy :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
1107−-- spanBy eq f1 f2 = splitWith (,) ('groupBy' eq f1) ('fromFold' f2)
1108−-- @
1109−--
1110−-- @
1111−-- spanByRolling :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
1112−-- spanByRolling eq f1 f2 = splitWith (,) ('groupByRolling' eq f1) ('fromFold' f2)
1113−-- @
1114−--
1115−-- /Pre-release/
1116−--
1117−{-# INLINE splitWith #-}
1118−splitWith :: Monad m
1119− => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1120−splitWith f p1 p2 =
1121− D.toParserK $ D.splitWith f (D.fromParserK p1) (D.fromParserK p2)
1122−
1123−-- | Sequential parser application ignoring the output of the first parser.
1124−-- Apply two parsers sequentially to an input stream. The input is provided to
1125−-- the first parser, when it is done the remaining input is provided to the
1126−-- second parser. The output of the parser is the output of the second parser.
1127−-- The operation fails if any of the parsers fail.
1128−--
1129−-- This implementation is strict in the second argument, therefore, the
1130−-- following will fail:
1131−--
1132−-- >>> Stream.parse (Parser.split_ (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1133−-- *** Exception: Prelude.undefined
1134−-- ...
1135−--
1136−-- Compare with 'Applicative' instance method '*>'. This implementation allows
1137−-- stream fusion but has quadratic complexity. This can fuse with other
1138−-- operations, and can be faster than 'Applicative' instance for small
1139−-- number (less than 8) of compositions.
1140−--
1141−-- /Pre-release/
1142−--
1143−{-# INLINE split_ #-}
1144−split_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
1145−split_ p1 p2 = D.toParserK $ D.split_ (D.fromParserK p1) (D.fromParserK p2)
1146−
1147−{-
1148−-- | @teeWith f p1 p2@ distributes its input to both @p1@ and @p2@ until both
1149−-- of them succeed or anyone of them fails and combines their output using @f@.
1150−-- The parser succeeds if both the parsers succeed.
1151−--
1152−-- /Pre-release/
1153−--
1154−{-# INLINE teeWith #-}
1155−teeWith :: Monad m
1156− => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1157−teeWith f p1 p2 =
1158− D.toParserK $ D.teeWith f (D.fromParserK p1) (D.fromParserK p2)
1159−
1160−-- | Like 'teeWith' but ends parsing and zips the results, if available,
1161−-- whenever the first parser ends.
1162−--
1163−-- /Pre-release/
1164−--
1165−{-# INLINE teeWithFst #-}
1166−teeWithFst :: Monad m
1167− => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1168−teeWithFst f p1 p2 =
1169− D.toParserK $ D.teeWithFst f (D.fromParserK p1) (D.fromParserK p2)
1170−
1171−-- | Like 'teeWith' but ends parsing and zips the results, if available,
1172−-- whenever any of the parsers ends or fails.
1173−--
1174−-- /Unimplemented/
1175−--
1176−{-# INLINE teeWithMin #-}
1177−teeWithMin :: Monad m
1178− => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1179−teeWithMin f p1 p2 =
1180− D.toParserK $ D.teeWithMin f (D.fromParserK p1) (D.fromParserK p2)
1181−-}
1182−
1183−-- | Sequential alternative. Apply the input to the first parser and return the
1184−-- result if the parser succeeds. If the first parser fails then backtrack and
1185−-- apply the same input to the second parser and return the result.
1186−--
1187−-- Note: This implementation is not lazy in the second argument. The following
1188−-- will fail:
1189−--
1190−-- >>> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
1191−-- Right 1
1192−--
1193−-- Compare with 'Alternative' instance method '<|>'. This implementation allows
1194−-- stream fusion but has quadratic complexity. This can fuse with other
1195−-- operations and can be much faster than 'Alternative' instance for small
1196−-- number (less than 8) of alternatives.
1197−--
1198−-- /Pre-release/
1199−--
1200−{-# INLINE alt #-}
1201−alt :: Monad m => Parser x m a -> Parser x m a -> Parser x m a
1202−alt p1 p2 = D.toParserK $ D.alt (D.fromParserK p1) (D.fromParserK p2)
1203−
1204−{-
1205−-- | Shortest alternative. Apply both parsers in parallel but choose the result
1206−-- from the one which consumed least input i.e. take the shortest succeeding
1207−-- parse.
1208−--
1209−-- /Pre-release/
1210−--
1211−{-# INLINE shortest #-}
1212−shortest :: Monad m
1213− => Parser x m a -> Parser x m a -> Parser x m a
1214−shortest p1 p2 = D.toParserK $ D.shortest (D.fromParserK p1) (D.fromParserK p2)
1215−
1216−-- | Longest alternative. Apply both parsers in parallel but choose the result
1217−-- from the one which consumed more input i.e. take the longest succeeding
1218−-- parse.
1219−--
1220−-- /Pre-release/
1221−--
1222−{-# INLINE longest #-}
1223−longest :: Monad m
1224− => Parser x m a -> Parser x m a -> Parser x m a
1225−longest p1 p2 = D.toParserK $ D.longest (D.fromParserK p1) (D.fromParserK p2)
1226−-}
1227−
1228−-- | Run a parser without consuming the input.
1229−--
1230−{-# INLINE lookAhead #-}
1231−lookAhead :: Monad m => Parser a m b -> Parser a m b
1232−lookAhead p = D.toParserK $ D.lookAhead $ D.fromParserK p
1233−
1234−-- | Takes at-most @n@ input elements.
1235−--
1236−-- * Stops - when the collecting parser stops.
1237−-- * Fails - when the collecting parser fails.
1238−--
1239−-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 2 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1240−-- Right [1,2]
1241−--
1242−-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 5 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1243−-- Left (ParseError "takeEQ: Expecting exactly 5 elements, input terminated on 4")
1244−--
1245−-- /Internal/
1246−{-# INLINE takeP #-}
1247−takeP :: Monad m => Int -> Parser a m b -> Parser a m b
1248−takeP i p = D.toParserK $ D.takeP i $ D.fromParserK p
1249−
1250−-------------------------------------------------------------------------------
1251−-- Sequential Collection
1252−-------------------------------------------------------------------------------
1253−--
1254−-- | @concatSequence f p@ collects sequential parses of parsers in a
1255−-- serial stream @p@ using the fold @f@. Fails if the input ends or any
1256−-- of the parsers fail.
1257−--
1258−-- An even more efficient implementation can use ParserD type Parser in
1259−-- the stream.
1260−--
1261−-- /Pre-release/
1262−--
1263−{-# INLINE concatSequence #-}
1264−concatSequence ::
1265− Monad m =>
1266− Fold m b c -> Stream m (Parser a m b) -> Parser a m c
1267−concatSequence f p =
1268− let sp = fmap D.fromParserK p
1269− in D.toParserK $ D.sequence sp f
1270−
1271−-- | Map a 'Parser' returning function on the result of a 'Parser'.
1272−--
1273−-- Compare with 'Monad' instance method '>>='. This implementation allows
1274−-- stream fusion but has quadratic complexity. This can fuse with other
1275−-- operations and can be much faster than 'Monad' instance for small number
1276−-- (less than 8) of compositions.
1277−--
1278−-- /Pre-release/
1279−--
1280−{-# INLINE concatMap #-}
1281−concatMap :: Monad m
1282− => (b -> Parser a m c) -> Parser a m b -> Parser a m c
1283−concatMap f p = D.toParserK $ D.concatMap (D.fromParserK . f) (D.fromParserK p)
1284−
1285−{-
1286−-------------------------------------------------------------------------------
1287−-- Alternative Collection
1288−-------------------------------------------------------------------------------
1289−--
1290−-- | @choice parsers@ applies the @parsers@ in order and returns the first
1291−-- successful parse.
1292−--
1293−-- This is same as 'asum' but more efficient.
1294−--
1295−-- /Broken/
1296−--
1297−{-# INLINE choice #-}
1298−choice ::
1299− (Functor t, Foldable t, Monad m) => t (Parser a m b) -> Parser a m b
1300−choice ps = D.toParserK $ D.choice $ D.fromParserK <$> ps
1301−-}
1302−
1303−-------------------------------------------------------------------------------
1304−-- Sequential Repetition
1305−-------------------------------------------------------------------------------
1306−
1307−-- | Like 'many' but uses a 'Parser' instead of a 'Fold' to collect the
1308−-- results. Parsing stops or fails if the collecting parser stops or fails.
1309−--
1310−-- /Unimplemented/
1311−--
1312−{-# INLINE manyP #-}
1313−manyP :: -- Monad m =>
1314− Parser a m b -> Parser b m c -> Parser a m c
1315−manyP _p _f = undefined -- D.toParserK $ D.manyP (D.fromParserK p) f
1316−
1317−-- | Collect zero or more parses. Apply the supplied parser repeatedly on the
1318−-- input stream and push the parse results to a downstream fold.
1319−--
1320−-- Stops: when the downstream fold stops or the parser fails.
1321−-- Fails: never, produces zero or more results.
1322−--
1323−-- >>> many = Parser.countBetween 0 maxBound
1324−--
1325−-- Compare with 'Control.Applicative.many'.
1326−--
1327−{-# INLINE many #-}
1328−many :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
1329−many p f = D.toParserK $ D.many (D.fromParserK p) f
1330−
1331−-- Note: many1 would perhaps be a better name for this and consistent with
1332−-- other names like takeWhile1. But we retain the name "some" for
1333−-- compatibility.
1334−--
1335−-- | Collect one or more parses. Apply the supplied parser repeatedly on the
1336−-- input stream and push the parse results to a downstream fold.
1337−--
1338−-- Stops: when the downstream fold stops or the parser fails.
1339−-- Fails: if it stops without producing a single result.
1340−--
1341−-- >>> some p f = Parser.manyP p (Parser.takeGE 1 f)
1342−-- >>> some = Parser.countBetween 1 maxBound
1343−--
1344−-- Compare with 'Control.Applicative.some'.
1345−--
1346−{-# INLINE some #-}
1347−some :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
1348−some p f = D.toParserK $ D.some (D.fromParserK p) f
1349−-- some p f = manyP p (takeGE 1 f)
1350−-- some = countBetween 1 maxBound
1351−
1352−-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
1353−-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
1354−-- the input ends or the parser fails before @m@ results are collected.
1355−--
1356−-- >>> countBetween m n p f = Parser.manyP p (Parser.takeBetween m n f)
1357−--
1358−-- /Unimplemented/
1359−--
1360−{-# INLINE countBetween #-}
1361−countBetween :: -- Monad m =>
1362− Int -> Int -> Parser a m b -> Fold m b c -> Parser a m c
1363−countBetween _m _n _p = undefined
1364−-- countBetween m n p f = manyP p (takeBetween m n f)
1365−
1366−-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
1367−-- the fold @f@. Fails if the input ends or the parser fails before @n@
1368−-- results are collected.
1369−--
1370−-- >>> count n = Parser.countBetween n n
1371−-- >>> count n p f = Parser.manyP p (Parser.takeEQ n f)
1372−--
1373−-- /Unimplemented/
1374−--
1375−{-# INLINE count #-}
1376−count :: -- Monad m =>
1377− Int -> Parser a m b -> Fold m b c -> Parser a m c
1378−count n = countBetween n n
1379−-- count n p f = manyP p (takeEQ n f)
1380−
1381−-- | Like 'manyTill' but uses a 'Parser' to collect the results instead of a
1382−-- 'Fold'. Parsing stops or fails if the collecting parser stops or fails.
1383−--
1384−-- We can implemnent parsers like the following using 'manyTillP':
1385−--
1386−-- @
1387−-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
1388−-- @
1389−--
1390−-- /Unimplemented/
1391−--
1392−{-# INLINE manyTillP #-}
1393−manyTillP :: -- Monad m =>
1394− Parser a m b -> Parser a m x -> Parser b m c -> Parser a m c
1395−manyTillP _p1 _p2 _f = undefined
1396− -- D.toParserK $ D.manyTillP (D.fromParserK p1) (D.fromParserK p2) f
1397−
1398−-- | @manyTill chunking test f@ tries the parser @test@ on the input, if @test@
1399−-- fails it backtracks and tries @chunking@, after @chunking@ succeeds @test@ is
1400−-- tried again and so on. The parser stops when @test@ succeeds. The output of
1401−-- @test@ is discarded and the output of @chunking@ is accumulated by the
1402−-- supplied fold. The parser fails if @chunking@ fails.
1403−--
1404−-- Stops when the fold @f@ stops.
1405−--
1406−{-# INLINE manyTill #-}
1407−manyTill :: Monad m
1408− => Parser a m b -- ^ Chunking parser. Parses chunks of input.
1409− -> Parser a m x -- ^ Test parser. Parsing stops when this parser succeeds
1410− -- else backtract and run the chunking parser.
1411− -> Fold m b c -- ^ Folds the output of the chunking parser.
1412− -> Parser a m c
1413−manyTill collect test f =
1414− D.toParserK $ D.manyTill (D.fromParserK collect) (D.fromParserK test) f
1415−
1416−-- | @manyThen f collect recover@ repeats the parser @collect@ on the input and
1417−-- collects the output in the supplied fold. If the the parser @collect@ fails,
1418−-- parser @recover@ is run until it stops and then we start repeating the
1419−-- parser @collect@ again. The parser fails if the recovery parser fails.
1420−--
1421−-- For example, this can be used to find a key frame in a video stream after an
1422−-- error.
1423−--
1424−-- /Unimplemented/
1425−--
1426−{-# INLINE manyThen #-}
1427−manyThen :: -- (Foldable t, Monad m) =>
1428− Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1429−manyThen _parser _recover _f = undefined
1430−
1431−-------------------------------------------------------------------------------
1432−-- Interleaving
1433−-------------------------------------------------------------------------------
1434−--
1435−-- To deinterleave we can chain two parsers one behind the other. The input is
1436−-- given to the first parser and the input definitively rejected by the first
1437−-- parser is given to the second parser.
1438−--
1439−-- We can either have the parsers themselves buffer the input or use the shared
1440−-- global buffer to hold it until none of the parsers need it. When the first
1441−-- parser returns Skip (i.e. rewind) we let the second parser consume the
1442−-- rejected input and when it is done we move the cursor forward to the first
1443−-- parser again. This will require a "move forward" command as well.
1444−--
1445−-- To implement grep we can use three parsers, one to find the pattern, one
1446−-- to store the context behind the pattern and one to store the context in
1447−-- front of the pattern. When a match occurs we need to emit the accumulator of
1448−-- all the three parsers. One parser can count the line numbers to provide the
1449−-- line number info.
1450−
1451−-- XXX rename this to intercalate
1452−-- | Apply two parsers alternately to an input stream. The input stream is
1453−-- considered an interleaving of two patterns. The two parsers represent the
1454−-- two patterns.
1455−--
1456−{-# INLINE deintercalate #-}
1457−deintercalate :: Monad m =>
1458− Parser a m x
1459− -> Parser a m y
1460− -> Fold m (Either x y) z
1461− -> Parser a m z
1462−deintercalate contentL contentR sink =
1463− D.toParserK
1464− $ D.deintercalate
1465− (D.fromParserK contentL) (D.fromParserK contentR) sink
1466−
1467−-- | Parse items separated by a separator parsed by the supplied parser. At
1468−-- least one item must be present for the parser to succeed.
1469−--
1470−-- Note that this can go in infinite loop if both the parsers fail on some
1471−-- input. Detection of that would make the implementation more complex.
1472−--
1473−{-# INLINE sepBy1 #-}
1474−sepBy1 :: Monad m =>
1475− Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1476−sepBy1 p sep sink = do
1477− x <- p
1478− f <- fromEffect $ FL.reduce sink
1479− f1 <- fromEffect $ FL.snoc f x
1480− many (sep >> p) f1
1481−
1482−-- | Run the content parser first, when it is done, the separator parser is
1483−-- run, when it is done content parser is run again and so on. If none of the
1484−-- parsers consumes an input then parser returns a failure.
1485−--
1486−-- >>> sepBy p1 p2 sink = Parser.deintercalate p1 p2 (Fold.catLefts sink)
1487−-- >>> sepBy content sep sink = Parser.sepBy1 content sep sink <|> return mempty
1488−--
1489−{-# INLINE sepBy #-}
1490−sepBy :: Monad m =>
1491− Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1492−sepBy content sep sink =
1493− D.toParserK $ D.sepBy (D.fromParserK content) (D.fromParserK sep) sink
1494−-- sepBy sink = deintercalate (FL.catLefts sink)
1495−
1496−-------------------------------------------------------------------------------
1497−-- Interleaving a collection of parsers
1498−-------------------------------------------------------------------------------
1499−--
1500−-- | Apply a collection of parsers to an input stream in a round robin fashion.
1501−-- Each parser is applied until it stops and then we repeat starting with the
1502−-- the first parser again.
1503−--
1504−-- /Unimplemented/
1505−--
1506−{-# INLINE roundRobin #-}
1507−roundRobin :: -- (Foldable t, Monad m) =>
1508− t (Parser a m b) -> Fold m b c -> Parser a m c
1509−roundRobin _ps _f = undefined
1510−
1511−-------------------------------------------------------------------------------
1512−-- Repeated Alternatives
1513−-------------------------------------------------------------------------------
1514−
1515−-- | Keep trying a parser up to a maximum of @n@ failures. When the parser
1516−-- fails the input consumed till now is dropped and the new instance is tried
1517−-- on the fresh input.
1518−--
1519−-- /Unimplemented/
1520−--
1521−{-# INLINE retryMaxTotal #-}
1522−retryMaxTotal :: -- (Monad m) =>
1523− Int -> Parser a m b -> Fold m b c -> Parser a m c
1524−retryMaxTotal _n _p _f = undefined
1525−
1526−-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
1527−--
1528−-- /Unimplemented/
1529−--
1530−{-# INLINE retryMaxSuccessive #-}
1531−retryMaxSuccessive :: -- (Monad m) =>
1532− Int -> Parser a m b -> Fold m b c -> Parser a m c
1533−retryMaxSuccessive _n _p _f = undefined
1534−
1535−-- | Keep trying a parser until it succeeds. When the parser fails the input
1536−-- consumed till now is dropped and the new instance is tried on the fresh
1537−-- input.
1538−--
1539−-- /Unimplemented/
1540−--
1541−{-# INLINE retry #-}
1542−retry :: -- (Monad m) =>
1543− Parser a m b -> Parser a m b
1544−retry _p = undefined
core/src/Streamly/Internal/Data/Parser/ParserD/Tee.hs → core/src/Streamly/Internal/Data/Parser/Tee.hsrenamed+1−1
@@ -24,7 +24,7 @@
24-- some legit warnings, therefore, we have segregated only the code that uses
24-- some legit warnings, therefore, we have segregated only the code that uses
25-- uni-pattern matches in this module.
25-- uni-pattern matches in this module.
26
26
27−module Streamly.Internal.Data.Parser.ParserD.Tee
27+module Streamly.Internal.Data.Parser.Tee
28 (
28 (
29 {-
29 {-
30 -- Parallel zipped
30 -- Parallel zipped
core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs → core/src/Streamly/Internal/Data/Parser/Type.hsrenamed+1−1
@@ -173,7 +173,7 @@
173-- * <http://hackage.haskell.org/package/attoparsec attoparsec>
173-- * <http://hackage.haskell.org/package/attoparsec attoparsec>
174-- * <http://hackage.haskell.org/package/parsec parsec>
174-- * <http://hackage.haskell.org/package/parsec parsec>
175
175
176−module Streamly.Internal.Data.Parser.ParserD.Type
176+module Streamly.Internal.Data.Parser.Type
177 (
177 (
178 -- * Setup
178 -- * Setup
179 -- $setup
179 -- $setup
core/src/Streamly/Internal/Data/ParserK.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE CPP #-}
2+-- |
3+-- Module : Streamly.Internal.Data.ParserK
4+-- Copyright : (c) 2020 Composewell Technologies
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+
10+module Streamly.Internal.Data.ParserK
11+ (
12+ module Streamly.Internal.Data.ParserK.Type
13+ )
14+where
15+
16+import Streamly.Internal.Data.ParserK.Type
core/src/Streamly/Internal/Data/Parser/ParserK/Type.hs → core/src/Streamly/Internal/Data/ParserK/Type.hsrenamed+2−2
@@ -21,7 +21,7 @@
21-- <http://hackage.haskell.org/package/parser-combinators parser-combinators>
21-- <http://hackage.haskell.org/package/parser-combinators parser-combinators>
22-- package can also be used with the 'ParserK' type.
22-- package can also be used with the 'ParserK' type.
23
23
24−module Streamly.Internal.Data.Parser.ParserK.Type
24+module Streamly.Internal.Data.ParserK.Type
25 (
25 (
26 Step (..)
26 Step (..)
27 , Input (..)
27 , Input (..)
@@ -57,7 +57,7 @@ import qualified Streamly.Internal.Data.MutArray.Generic as GenArr
57 ( getIndexUnsafeWith
57 ( getIndexUnsafeWith
58 )
58 )
59import qualified Streamly.Internal.Data.Array.Generic as GenArr
59import qualified Streamly.Internal.Data.Array.Generic as GenArr
60−import qualified Streamly.Internal.Data.Parser.ParserD.Type as ParserD
60+import qualified Streamly.Internal.Data.Parser.Type as ParserD
61
61
62-- Note: We cannot use an Array directly as input because we need to identify
62-- Note: We cannot use an Array directly as input because we need to identify
63-- the end of input case using None. We cannot do that using nil Array as nil
63-- the end of input case using None. We cannot do that using nil Array as nil
core/src/Streamly/Internal/Data/StreamK.hs+3−3
@@ -138,7 +138,7 @@ import GHC.Types (SPEC(..))
138import Streamly.Internal.Data.Array.Type (Array(..))
138import Streamly.Internal.Data.Array.Type (Array(..))
139import Streamly.Internal.Data.Fold.Type (Fold(..))
139import Streamly.Internal.Data.Fold.Type (Fold(..))
140import Streamly.Internal.Data.IOFinalizer (newIOFinalizer, runIOFinalizer)
140import Streamly.Internal.Data.IOFinalizer (newIOFinalizer, runIOFinalizer)
141−import Streamly.Internal.Data.Parser.ParserK.Type (ParserK)
141+import Streamly.Internal.Data.ParserK.Type (ParserK)
142import Streamly.Internal.Data.Producer.Type (Producer(..))
142import Streamly.Internal.Data.Producer.Type (Producer(..))
143import Streamly.Internal.Data.SVar.Type (adaptState, defState)
143import Streamly.Internal.Data.SVar.Type (adaptState, defState)
144import Streamly.Internal.Data.Unbox (sizeOf, Unbox)
144import Streamly.Internal.Data.Unbox (sizeOf, Unbox)
@@ -148,8 +148,8 @@ import qualified Streamly.Internal.Data.Array.Type as Array
148import qualified Streamly.Internal.Data.Array.Generic as GenArr
148import qualified Streamly.Internal.Data.Array.Generic as GenArr
149import qualified Streamly.Internal.Data.Fold.Type as FL
149import qualified Streamly.Internal.Data.Fold.Type as FL
150import qualified Streamly.Internal.Data.Parser as Parser
150import qualified Streamly.Internal.Data.Parser as Parser
151−import qualified Streamly.Internal.Data.Parser.ParserD.Type as PR
151+import qualified Streamly.Internal.Data.Parser.Type as PR
152−import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
152+import qualified Streamly.Internal.Data.ParserK.Type as ParserK
153import qualified Streamly.Internal.Data.Stream as Stream
153import qualified Streamly.Internal.Data.Stream as Stream
154import qualified Prelude
154import qualified Prelude
155
155
core/streamly-core.cabal+5−4
@@ -292,8 +292,6 @@ library
292 , Streamly.Internal.Data.SVar.Type
292 , Streamly.Internal.Data.SVar.Type
293 , Streamly.Internal.Data.Refold.Type
293 , Streamly.Internal.Data.Refold.Type
294 , Streamly.Internal.Data.Producer
294 , Streamly.Internal.Data.Producer
295− , Streamly.Internal.Data.Parser.ParserK.Type
296− , Streamly.Internal.Data.Parser.ParserD.Type
297
295
298 -- streamly-core-array-types
296 -- streamly-core-array-types
299 , Streamly.Internal.Data.Unbox
297 , Streamly.Internal.Data.Unbox
@@ -314,14 +312,13 @@ library
314 , Streamly.Internal.Data.Stream.Common
312 , Streamly.Internal.Data.Stream.Common
315 , Streamly.Internal.Data.Stream
313 , Streamly.Internal.Data.Stream
316
314
317− , Streamly.Internal.Data.Parser.ParserD.Tee
318−
319 -- streamly-core-data
315 -- streamly-core-data
320 , Streamly.Internal.Data.Builder
316 , Streamly.Internal.Data.Builder
321 , Streamly.Internal.Data.Unfold
317 , Streamly.Internal.Data.Unfold
322 , Streamly.Internal.Data.Fold.Tee
318 , Streamly.Internal.Data.Fold.Tee
323 , Streamly.Internal.Data.Fold.Chunked
319 , Streamly.Internal.Data.Fold.Chunked
324 , Streamly.Internal.Data.Parser
320 , Streamly.Internal.Data.Parser
321+ , Streamly.Internal.Data.ParserK
325 , Streamly.Internal.Data.Pipe
322 , Streamly.Internal.Data.Pipe
326
323
327 -- streamly-containers (non-base)
324 -- streamly-containers (non-base)
@@ -405,6 +402,10 @@ library
405 , Streamly.Internal.Data.Fold.Container
402 , Streamly.Internal.Data.Fold.Container
406 , Streamly.Internal.Data.Fold.Window
403 , Streamly.Internal.Data.Fold.Window
407
404
405+ , Streamly.Internal.Data.Parser.Type
406+ , Streamly.Internal.Data.Parser.Tee
407+ , Streamly.Internal.Data.ParserK.Type
408+
408 , Streamly.Internal.Data.Stream.Container
409 , Streamly.Internal.Data.Stream.Container
409 , Streamly.Internal.Data.Stream.Eliminate
410 , Streamly.Internal.Data.Stream.Eliminate
410 , Streamly.Internal.Data.Stream.Exception
411 , Streamly.Internal.Data.Stream.Exception