@@ -33,8 +33,8 @@
33-- Failing parsers in this module throw the 'ParseError' exception.
33-- Failing parsers in this module throw the 'ParseError' exception.
35-- XXX As far as possible, try that the combinators in this module and in
35-- XXX As far as possible, try that the combinators in this module and in
36−-- "parser-combinators/parsec/megaparsec/attoparsec" have consistent names.
36+-- "Text.ParserCombinators.ReadP/parser-combinators/parsec/megaparsec/attoparsec"
37−-- takeP/takeWhileP?
37+-- have consistent names. takeP/takeWhileP/munch?
39module Streamly.Internal.Data.Parser
39module Streamly.Internal.Data.Parser
@@ -56,6 +56,16 @@ module Streamly.Internal.Data.Parser
58 -- * Sequence parsers
58 -- * Sequence parsers
60+ -- Parsers chained in series, if one parser terminates the composition
61+ -- terminates. Currently we are using folds to collect the output of the
62+ -- parsers but we can use Parsers instead of folds to make the composition
63+ -- more powerful. For example, we can do:
65+ -- sliceSepByMax cond n p = sliceBy cond (take n p)
66+ -- sliceSepByBetween cond m n p = sliceBy cond (takeBetween m n p)
67+ -- takeWhileBetween cond m n p = takeWhile cond (takeBetween m n p)
59 -- Grab a sequence of input elements without inspecting them
69 -- Grab a sequence of input elements without inspecting them
61 -- , takeBetween
71 -- , takeBetween
@@ -67,13 +77,17 @@ module Streamly.Internal.Data.Parser
67 -- Grab a sequence of input elements by inspecting them
77 -- Grab a sequence of input elements by inspecting them
68 , lookAhead
78 , lookAhead
69 , takeWhile
79 , takeWhile
70− -- , takeWhileBetween
71 , takeWhile1
80 , takeWhile1
72− , sepBy
81+ , sliceSepBy
73− , sepByMax
82+ , sliceSepByMax
74− -- , sepByBetween
83+ -- , sliceSepByBetween
75− , sepWithSuffix
84+ , sliceEndWith
76− , sepWithPrefix
85+ , sliceBeginWith
88+ -- , frameSepBy -- parse frames escaped by an escape char/sequence
@@ -84,41 +98,80 @@ module Streamly.Internal.Data.Parser
84 -- Second order parsers (parsers using parsers)
98 -- Second order parsers (parsers using parsers)
85 -- * Binary Combinators
99 -- * Binary Combinators
101+ -- ** Sequential Applicative
87− -- Parallel parsers
104+ -- ** Parallel Applicatives
88 , teeWith
105 , teeWith
89 , teeWithFst
106 , teeWithFst
90 , teeWithMin
107 , teeWithMin
108+ -- , teeTill -- like manyTill but parallel
110+ -- ** Sequential Interleaving
111+ -- Use two folds, run a primary parser, its rejected values go to the
112+ -- secondary parser.
92− -- Alternatives
115+ -- ** Parallel Alternatives
93 , shortest
116 , shortest
94 , longest
117 , longest
95 -- , fastest
118 -- , fastest
97 -- * N-ary Combinators
120 -- * N-ary Combinators
98− -- N-ary split applicative
121+ -- ** Sequential Collection
99− -- Run n actions in sequence
100 , sequence
122 , sequence
102− -- Repeat the same action in sequence
124+ -- ** Sequential Repetition
104− -- , splitEQ -- splitN/takeN/parseN = replicateM n
105− -- , splitGE -- splitEQ n, splitMany
107 , countBetween
126 , countBetween
108− , many -- splitMany/takeMany/parseMany
109− -- = splitGE 0 = countBetween 0 maxBound
110− , some -- splitMany1/takeMany1/parseMany1
111− -- = splitGE 1 = countBetween 1 maxBound
113 -- , countBetweenTill
127 -- , countBetweenTill
114− , manyTill -- splitBreakOn, manyTill, parseBreakOn
116− -- Run n actions in parallel
129+ , many
133+ -- -- ** Special cases
134+ -- XXX traditional implmentations of these may be of limited use. For
135+ -- example, consider parsing lines separated by "\r\n". The main parser
136+ -- will have to detect and exclude the sequence "\r\n" anyway so that we
137+ -- can apply the "sep" parser.
139+ -- We can instead implement these as special cases of deintercalate.
148+ -- -- * Distribution
150+ -- A simple and stupid impl would be to just convert the stream to an array
151+ -- and give the array reference to all consumers. The array can be grown on
152+ -- demand by any consumer and truncated when nonbody needs it.
154+ -- -- ** Distribute to collection
155+ -- -- ** Distribute to repetition
157+ -- -- ** Interleaved collection
160+ -- -- ** Interleaved repetition
161+ -- repeat one parser and when it fails run an error recovery parser
162+ -- e.g. to find a key frame in the stream after an error
164+ -- ** Collection of Alternatives
117 -- , shortestN
165 -- , shortestN
118 -- , longestN
166 -- , longestN
119 -- , fastestN -- first N successful in time
167 -- , fastestN -- first N successful in time
168+ -- , choiceN -- first N successful in position
120 , choice -- first successful in position
169 , choice -- first successful in position
121− -- , choiceN -- first N successful
170+
171+ -- -- ** Repeated Alternatives
172+ -- , retryMax -- try N times
173+ -- , retryUntil -- try until successful
174+ -- , retryUntilN -- try until successful n times
@@ -449,19 +502,19 @@ takeWhile1 predicate (Fold fstep finitial fextract) =
449-- * Stops - when the predicate succeeds.
502-- * Stops - when the predicate succeeds.
450-- * Fails - never.
503-- * Fails - never.
452−-- >>> S.parse (PR.sepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
505+-- >>> S.parse (PR.sliceSepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
453-- > [0,0]
506-- > [0,0]
455−-- S.splitOn pred f = S.splitParse (PR.sepBy pred f)
508+-- S.splitOn pred f = S.splitParse (PR.sliceSepBy pred f)
457−-- >>> S.toList $ S.splitParse (PR.sepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
510+-- >>> S.toList $ S.splitParse (PR.sliceSepBy (== 1) FL.toList) $ S.fromList [0,0,1,0,1]
458-- > [[0,0],[0],[]]
511-- > [[0,0],[0],[]]
460-- /Internal/
513-- /Internal/
462−{-# INLINABLE sepBy #-}
515+{-# INLINABLE sliceSepBy #-}
463−sepBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
516+sliceSepBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
464−sepBy predicate (Fold fstep finitial fextract) =
517+sliceSepBy predicate (Fold fstep finitial fextract) =
465 Parser step initial fextract
518 Parser step initial fextract
@@ -479,15 +532,15 @@ sepBy predicate (Fold fstep finitial fextract) =
479-- * Stops - when the predicate succeeds.
532-- * Stops - when the predicate succeeds.
480-- * Fails - never.
533-- * Fails - never.
482−-- S.splitWithSuffix pred f = S.splitParse (PR.sepWithSuffix pred f)
535+-- S.splitWithSuffix pred f = S.splitParse (PR.sliceEndWith pred f)
484-- /Unimplemented/
537-- /Unimplemented/
486−{-# INLINABLE sepWithSuffix #-}
539+{-# INLINABLE sliceEndWith #-}
487−sepWithSuffix ::
540+sliceEndWith ::
488 -- Monad m =>
541 -- Monad m =>
489 (a -> Bool) -> Fold m a b -> Parser m a b
542 (a -> Bool) -> Fold m a b -> Parser m a b
490−sepWithSuffix = undefined
543+sliceEndWith = undefined
492-- | Collect stream elements until an elements passes the predicate, return the
545-- | Collect stream elements until an elements passes the predicate, return the
493-- last element on which the predicate succeeded back to the input stream. If
546-- last element on which the predicate succeeded back to the input stream. If
@@ -498,15 +551,15 @@ sepWithSuffix = undefined
498-- * Stops - when the predicate succeeds in non-leading position.
551-- * Stops - when the predicate succeeds in non-leading position.
499-- * Fails - never.
552-- * Fails - never.
501−-- S.splitWithPrefix pred f = S.splitParse (PR.sepWithPrefix pred f)
554+-- S.splitWithPrefix pred f = S.splitParse (PR.sliceBeginWith pred f)
503-- /Unimplemented/
556-- /Unimplemented/
505−{-# INLINABLE sepWithPrefix #-}
558+{-# INLINABLE sliceBeginWith #-}
506−sepWithPrefix ::
559+sliceBeginWith ::
507 -- Monad m =>
560 -- Monad m =>
508 (a -> Bool) -> Fold m a b -> Parser m a b
561 (a -> Bool) -> Fold m a b -> Parser m a b
509−sepWithPrefix = undefined
562+sliceBeginWith = undefined
511-- | Split using a condition or a count whichever occurs first. This is a
564-- | Split using a condition or a count whichever occurs first. This is a
512-- hybrid of 'splitOn' and 'take'. The element on which the condition succeeds
565-- hybrid of 'splitOn' and 'take'. The element on which the condition succeeds
@@ -514,10 +567,10 @@ sepWithPrefix = undefined
515-- /Internal/
568-- /Internal/
517−{-# INLINABLE sepByMax #-}
570+{-# INLINABLE sliceSepByMax #-}
518−sepByMax :: Monad m
571+sliceSepByMax :: Monad m
519 => (a -> Bool) -> Int -> Fold m a b -> Parser m a b
572 => (a -> Bool) -> Int -> Fold m a b -> Parser m a b
520−sepByMax predicate cnt (Fold fstep finitial fextract) =
573+sliceSepByMax predicate cnt (Fold fstep finitial fextract) =
521 Parser step initial extract
574 Parser step initial extract
@@ -634,6 +687,46 @@ lookAhead (Parser step1 initial1 _) =
634 extract (Tuple' n _) = throwM $ ParseError $
687 extract (Tuple' n _) = throwM $ ParseError $
635 "lookAhead: end of input after consuming " ++ show n ++ " elements"
688 "lookAhead: end of input after consuming " ++ show n ++ " elements"
690+-------------------------------------------------------------------------------
692+-------------------------------------------------------------------------------
694+-- To deinterleave we can chain two parsers one behind the other. The input is
695+-- given to the first parser and the input definitively rejected by the first
696+-- parser is given to the second parser.
698+-- We can either have the parsers themselves buffer the input or use the shared
699+-- global buffer to hold it until none of the parsers need it. When the first
700+-- parser returns Skip (i.e. rewind) we let the second parser consume the
701+-- rejected input and when it is done we move the cursor forward to the first
702+-- parser again. This will require a "move forward" command as well.
704+-- To implement grep we can use three parsers, one to find the pattern, one
705+-- to store the context behind the pattern and one to store the context in
706+-- front of the pattern. When a match occurs we need to emit the accumulator of
707+-- all the three parsers. One parser can count the line numbers to provide the
710+-- | Apply two parsers alternately to an input stream. The input stream is
711+-- considered an interleaving of two patterns. The two parsers represent the
714+-- This undoes a "gintercalate" of two streams.
718+{-# INLINE deintercalate #-}
721+ Fold m a y -> Parser m x a
722+ -> Fold m b z -> Parser m x b
723+ -> Parser m x (y, z)
724+deintercalate = undefined
726+-------------------------------------------------------------------------------
727+-- Sequential Collection
728+-------------------------------------------------------------------------------
637-- | @sequence f t@ collects sequential parses of parsers in the container @t@
730-- | @sequence f t@ collects sequential parses of parsers in the container @t@
638-- using the fold @f@. Fails if the input ends or any of the parsers fail.
731-- using the fold @f@. Fails if the input ends or any of the parsers fail.
@@ -645,6 +738,10 @@ sequence ::
645 Fold m b c -> t (Parser m a b) -> Parser m a c
738 Fold m b c -> t (Parser m a b) -> Parser m a c
646sequence _f _p = undefined
739sequence _f _p = undefined
741+-------------------------------------------------------------------------------
742+-- Alternative Collection
743+-------------------------------------------------------------------------------
648-- | @choice parsers@ applies the @parsers@ in order and returns the first
745-- | @choice parsers@ applies the @parsers@ in order and returns the first
649-- successful parse.
746-- successful parse.
@@ -654,6 +751,10 @@ choice ::
654 t (Parser m a b) -> Parser m a b
751 t (Parser m a b) -> Parser m a b
655choice _ps = undefined
752choice _ps = undefined
754+-------------------------------------------------------------------------------
755+-- Sequential Repetition
756+-------------------------------------------------------------------------------
657-- XXX "many" is essentially a Fold because it cannot fail. So it can be
758-- XXX "many" is essentially a Fold because it cannot fail. So it can be
658-- downgraded to a Fold. Or we can make the return type a Fold instead and
759-- downgraded to a Fold. Or we can make the return type a Fold instead and
659-- upgrade that to a parser when needed.
760-- upgrade that to a parser when needed.
@@ -670,6 +771,7 @@ choice _ps = undefined
670{-# INLINE many #-}
771{-# INLINE many #-}
671many :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
772many :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
672many = splitMany
773many = splitMany
774+-- many = countBetween 0 maxBound
674-- | Collect one or more parses. Apply the supplied parser repeatedly on the
776-- | Collect one or more parses. Apply the supplied parser repeatedly on the
675-- input stream and accumulate the parse results as long as the parser
777-- input stream and accumulate the parse results as long as the parser
@@ -683,6 +785,8 @@ many = splitMany
683{-# INLINE some #-}
785{-# INLINE some #-}
684some :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
786some :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
685some = splitSome
787some = splitSome
788+-- some f p = many (takeGE 1 f) p
789+-- many = countBetween 1 maxBound
687-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
791-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
688-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
792-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
@@ -695,6 +799,7 @@ countBetween ::
695 -- MonadCatch m =>
799 -- MonadCatch m =>
696 Int -> Int -> Fold m b c -> Parser m a b -> Parser m a c
800 Int -> Int -> Fold m b c -> Parser m a b -> Parser m a c
697countBetween _m _n _f = undefined
801countBetween _m _n _f = undefined
802+-- countBetween m n f p = many (takeBetween m n f) p
699-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
804-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
700-- the fold @f@. Fails if the input ends or the parser fails before @n@
805-- the fold @f@. Fails if the input ends or the parser fails before @n@
@@ -707,6 +812,7 @@ count ::
707 -- MonadCatch m =>
812 -- MonadCatch m =>
708 Int -> Fold m b c -> Parser m a b -> Parser m a c
813 Int -> Fold m b c -> Parser m a b -> Parser m a c
709count n = countBetween n n
814count n = countBetween n n
815+-- count n f p = many (takeEQ n f) p
711data ManyTillState fs sr sl = ManyTillR Int fs sr | ManyTillL fs sl
817data ManyTillState fs sr sl = ManyTillR Int fs sr | ManyTillL fs sl