on master help sign in
Re-export entire submodules from Parser (#2525)
commit209e990b06b94a8fde008b46b04b48d1194e86ac authorRanjeet Ranjan <ranjeetr@composewell.com> dateMon 21 Aug 2023, 14:09 (3 years ago) parentbfe0169
11 files changed+37−1580
benchmark/Streamly/Benchmark/Data/ParserK.hs+1−1 core/src/Streamly/Data/ParserK.hs+1−1 core/src/Streamly/Internal/Data/Fold/Chunked.hs−1 core/src/Streamly/Internal/Data/Parser.hs+7−22 core/src/Streamly/Internal/Data/Parser/ParserDK.hs−1544 core/src/Streamly/Internal/Data/Parser/ParserD/Tee.hs → core/src/Streamly/Internal/Data/Parser/Tee.hs+1−1 core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs → core/src/Streamly/Internal/Data/Parser/Type.hs+1−1 core/src/Streamly/Internal/Data/ParserK.hs+16 core/src/Streamly/Internal/Data/Parser/ParserK/Type.hs → core/src/Streamly/Internal/Data/ParserK/Type.hs+2−2 core/src/Streamly/Internal/Data/StreamK.hs+3−3 core/streamly-core.cabal+5−4
benchmark/Streamly/Benchmark/Data/ParserK.hs+1−1
@@ -45,7 +45,7 @@ import qualified Streamly.Data.Stream as Stream
4545import qualified Streamly.Data.Fold as FL
4646import qualified Streamly.Internal.Data.Fold as Fold
4747import 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
4949import qualified Streamly.Internal.Data.StreamK as StreamK
5050
5151import Gauge
core/src/Streamly/Data/ParserK.hs+1−1
@@ -39,7 +39,7 @@ import Streamly.Internal.Data.Unbox (Unbox)
3939import Streamly.Internal.Data.Array (Array)
4040import qualified Streamly.Internal.Data.Parser as ParserD
4141
42−import Streamly.Internal.Data.Parser.ParserK.Type
42+import Streamly.Internal.Data.ParserK.Type
4343
4444{-# DEPRECATED fromFold "Please use \"ParserK.adaptC . Parser.fromFold\" instead." #-}
4545{-# INLINE fromFold #-}
core/src/Streamly/Internal/Data/Fold/Chunked.hs−1
@@ -73,7 +73,6 @@ import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
7373import qualified Streamly.Internal.Data.Array.Type as Array
7474import qualified Streamly.Internal.Data.Fold as Fold
7575import qualified Streamly.Internal.Data.Parser as ParserD
76−import qualified Streamly.Internal.Data.Parser.ParserD.Type as ParserD
7776import qualified Streamly.Internal.Data.Parser as Parser
7877
7978import Prelude hiding (concatMap, take)
core/src/Streamly/Internal/Data/Parser.hs+7−22
@@ -12,8 +12,11 @@ module Streamly.Internal.Data.Parser
1212 -- * Setup
1313 -- $setup
1414
15+ module Streamly.Internal.Data.Parser.Type
16+ --, module Streamly.Internal.Data.Parser.Tee
17+
1518 -- * Types
16− Parser (..)
19+ , Parser (..)
1720 , ParseError (..)
1821 , Step (..)
1922 , Initial (..)
@@ -25,19 +28,9 @@ module Streamly.Internal.Data.Parser
2528 -- * Accumulators
2629 , fromFold
2730 , fromFoldMaybe
28− , fromPure
29− , fromEffect
30− , die
31− , dieM
3231
3332 -- * Map on input
34− , lmap
35− , lmapM
3633 , postscan
37− , filter
38−
39− -- * Map on output
40− , rmapM
4134
4235 -- * Element parsers
4336 , peek
@@ -139,11 +132,6 @@ module Streamly.Internal.Data.Parser
139132
140133 -- Second order parsers (parsers using parsers)
141134 -- * Binary Combinators
142−
143− -- ** Sequential Applicative
144− , splitWith
145− , split_
146−
147135 {-
148136 -- ** Parallel Applicatives
149137 , teeWith
@@ -152,9 +140,6 @@ module Streamly.Internal.Data.Parser
152140 -- , teeTill -- like manyTill but parallel
153141 -}
154142
155− -- ** Sequential Alternative
156− , alt
157−
158143 {-
159144 -- ** Parallel Alternatives
160145 , shortest
@@ -165,7 +150,6 @@ module Streamly.Internal.Data.Parser
165150 -- * N-ary Combinators
166151 -- ** Sequential Collection
167152 , sequence
168− , concatMap
169153
170154 -- ** Sequential Repetition
171155 , count
@@ -273,11 +257,12 @@ import qualified Streamly.Internal.Data.Fold.Type as FL
273257import qualified Streamly.Internal.Data.Stream.Type as D
274258import qualified Streamly.Internal.Data.Stream.Generate as D
275259
260+import Streamly.Internal.Data.Parser.Type
261+--import Streamly.Internal.Data.Parser.Tee -- It's empty
262+
276263import Prelude hiding
277264 (any, all, take, takeWhile, sequence, concatMap, maybe, either, span
278265 , zip, filter, dropWhile)
279−-- import Streamly.Internal.Data.Parser.ParserD.Tee
280−import Streamly.Internal.Data.Parser.ParserD.Type
281266
282267#include "DocTestDataParser.hs"
283268
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 @@
2424-- some legit warnings, therefore, we have segregated only the code that uses
2525-- uni-pattern matches in this module.
2626
27−module Streamly.Internal.Data.Parser.ParserD.Tee
27+module Streamly.Internal.Data.Parser.Tee
2828 (
2929 {-
3030 -- 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 @@
173173-- * <http://hackage.haskell.org/package/attoparsec attoparsec>
174174-- * <http://hackage.haskell.org/package/parsec parsec>
175175
176−module Streamly.Internal.Data.Parser.ParserD.Type
176+module Streamly.Internal.Data.Parser.Type
177177 (
178178 -- * Setup
179179 -- $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 @@
2121-- <http://hackage.haskell.org/package/parser-combinators parser-combinators>
2222-- package can also be used with the 'ParserK' type.
2323
24−module Streamly.Internal.Data.Parser.ParserK.Type
24+module Streamly.Internal.Data.ParserK.Type
2525 (
2626 Step (..)
2727 , Input (..)
@@ -57,7 +57,7 @@ import qualified Streamly.Internal.Data.MutArray.Generic as GenArr
5757 ( getIndexUnsafeWith
5858 )
5959import 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
6161
6262-- Note: We cannot use an Array directly as input because we need to identify
6363-- 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(..))
138138import Streamly.Internal.Data.Array.Type (Array(..))
139139import Streamly.Internal.Data.Fold.Type (Fold(..))
140140import Streamly.Internal.Data.IOFinalizer (newIOFinalizer, runIOFinalizer)
141−import Streamly.Internal.Data.Parser.ParserK.Type (ParserK)
141+import Streamly.Internal.Data.ParserK.Type (ParserK)
142142import Streamly.Internal.Data.Producer.Type (Producer(..))
143143import Streamly.Internal.Data.SVar.Type (adaptState, defState)
144144import Streamly.Internal.Data.Unbox (sizeOf, Unbox)
@@ -148,8 +148,8 @@ import qualified Streamly.Internal.Data.Array.Type as Array
148148import qualified Streamly.Internal.Data.Array.Generic as GenArr
149149import qualified Streamly.Internal.Data.Fold.Type as FL
150150import qualified Streamly.Internal.Data.Parser as Parser
151−import qualified Streamly.Internal.Data.Parser.ParserD.Type as PR
152−import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
151+import qualified Streamly.Internal.Data.Parser.Type as PR
152+import qualified Streamly.Internal.Data.ParserK.Type as ParserK
153153import qualified Streamly.Internal.Data.Stream as Stream
154154import qualified Prelude
155155
core/streamly-core.cabal+5−4
@@ -292,8 +292,6 @@ library
292292 , Streamly.Internal.Data.SVar.Type
293293 , Streamly.Internal.Data.Refold.Type
294294 , Streamly.Internal.Data.Producer
295− , Streamly.Internal.Data.Parser.ParserK.Type
296− , Streamly.Internal.Data.Parser.ParserD.Type
297295
298296 -- streamly-core-array-types
299297 , Streamly.Internal.Data.Unbox
@@ -314,14 +312,13 @@ library
314312 , Streamly.Internal.Data.Stream.Common
315313 , Streamly.Internal.Data.Stream
316314
317− , Streamly.Internal.Data.Parser.ParserD.Tee
318−
319315 -- streamly-core-data
320316 , Streamly.Internal.Data.Builder
321317 , Streamly.Internal.Data.Unfold
322318 , Streamly.Internal.Data.Fold.Tee
323319 , Streamly.Internal.Data.Fold.Chunked
324320 , Streamly.Internal.Data.Parser
321+ , Streamly.Internal.Data.ParserK
325322 , Streamly.Internal.Data.Pipe
326323
327324 -- streamly-containers (non-base)
@@ -405,6 +402,10 @@ library
405402 , Streamly.Internal.Data.Fold.Container
406403 , Streamly.Internal.Data.Fold.Window
407404
405+ , Streamly.Internal.Data.Parser.Type
406+ , Streamly.Internal.Data.Parser.Tee
407+ , Streamly.Internal.Data.ParserK.Type
408+
408409 , Streamly.Internal.Data.Stream.Container
409410 , Streamly.Internal.Data.Stream.Eliminate
410411 , Streamly.Internal.Data.Stream.Exception