on master help sign in
Rename some parsers and add some TBD and comments
f51bbb2Harendra Kumar
benchmark/Streamly/Benchmark/FileIO/Stream.hs+1−1
@@ -612,7 +612,7 @@ inspect $ 'splitOnSuffix `hasNoType` ''D.ConcatMapUState
612{-# INLINE splitParseSepBy #-}
612{-# INLINE splitParseSepBy #-}
613splitParseSepBy :: Handle -> IO Int
613splitParseSepBy :: Handle -> IO Int
614splitParseSepBy inh =
614splitParseSepBy inh =
615− (S.length $ IP.splitParse (PR.sepBy (== lf) FL.drain)
615+ (S.length $ IP.splitParse (PR.sliceSepBy (== lf) FL.drain)
616 (S.unfold FH.read inh)) -- >>= print
616 (S.unfold FH.read inh)) -- >>= print
617
617
618-- | Words by space
618-- | Words by space
src/Streamly/Internal/Data/Parser.hs+147−41
@@ -33,8 +33,8 @@
33-- Failing parsers in this module throw the 'ParseError' exception.
33-- Failing parsers in this module throw the 'ParseError' exception.
34
34
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?
38
38
39module Streamly.Internal.Data.Parser
39module Streamly.Internal.Data.Parser
40 (
40 (
@@ -56,6 +56,16 @@ module Streamly.Internal.Data.Parser
56 , satisfy
56 , satisfy
57
57
58 -- * Sequence parsers
58 -- * Sequence parsers
59+ --
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:
64+ --
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)
68+ --
59 -- Grab a sequence of input elements without inspecting them
69 -- Grab a sequence of input elements without inspecting them
60 , take
70 , take
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
86+ -- , sliceSepWith
87+ --
88+ -- , frameSepBy -- parse frames escaped by an escape char/sequence
89+ -- , frameEndWith
90+ --
77 , wordBy
91 , wordBy
78 , groupBy
92 , groupBy
79 , eqBy
93 , eqBy
@@ -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
86
100
101+ -- ** Sequential Applicative
102+ , splitWith
103+
87− -- Parallel parsers
104+ -- ** Parallel Applicatives
88 , teeWith
105 , teeWith
89 , teeWithFst
106 , teeWithFst
90 , teeWithMin
107 , teeWithMin
108+ -- , teeTill -- like manyTill but parallel
109+
110+ -- ** Sequential Interleaving
111+ -- Use two folds, run a primary parser, its rejected values go to the
112+ -- secondary parser.
113+ , deintercalate
91
114
92− -- Alternatives
115+ -- ** Parallel Alternatives
93 , shortest
116 , shortest
94 , longest
117 , longest
95 -- , fastest
118 -- , fastest
96
119
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
101
123
102− -- Repeat the same action in sequence
124+ -- ** Sequential Repetition
103− -- , splitLE
104− -- , splitEQ -- splitN/takeN/parseN = replicateM n
105− -- , splitGE -- splitEQ n, splitMany
106 , count
125 , count
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
112−
113 -- , countBetweenTill
127 -- , countBetweenTill
114− , manyTill -- splitBreakOn, manyTill, parseBreakOn
115
128
116− -- Run n actions in parallel
129+ , many
130+ , some
131+ , manyTill
132+
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.
138+ --
139+ -- We can instead implement these as special cases of deintercalate.
140+ --
141+ -- , endBy
142+ -- , sepBy
143+ -- , sepEndBy
144+ -- , beginBy
145+ -- , sepBeginBy
146+ -- , sepAroundBy
147+
148+ -- -- * Distribution
149+ --
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.
153+ --
154+ -- -- ** Distribute to collection
155+ -- -- ** Distribute to repetition
156+
157+ -- -- ** Interleaved collection
158+ -- Round robin
159+ -- Priority based
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
163+
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
122 )
175 )
123where
176where
124
177
@@ -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.
451--
504--
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]
454--
507--
455−-- S.splitOn pred f = S.splitParse (PR.sepBy pred f)
508+-- S.splitOn pred f = S.splitParse (PR.sliceSepBy pred f)
456--
509--
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],[]]
459--
512--
460-- /Internal/
513-- /Internal/
461--
514--
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
466
519
467 where
520 where
@@ -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.
481--
534--
482−-- S.splitWithSuffix pred f = S.splitParse (PR.sepWithSuffix pred f)
535+-- S.splitWithSuffix pred f = S.splitParse (PR.sliceEndWith pred f)
483--
536--
484-- /Unimplemented/
537-- /Unimplemented/
485--
538--
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
491
544
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.
500--
553--
501−-- S.splitWithPrefix pred f = S.splitParse (PR.sepWithPrefix pred f)
554+-- S.splitWithPrefix pred f = S.splitParse (PR.sliceBeginWith pred f)
502--
555--
503-- /Unimplemented/
556-- /Unimplemented/
504--
557--
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
510
563
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
514--
567--
515-- /Internal/
568-- /Internal/
516--
569--
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
522
575
523 where
576 where
@@ -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"
636
689
690+-------------------------------------------------------------------------------
691+-- Interleaving
692+-------------------------------------------------------------------------------
693+--
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.
697+--
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.
703+--
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
708+-- line number info.
709+--
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
712+-- two patterns.
713+--
714+-- This undoes a "gintercalate" of two streams.
715+--
716+-- /Unimplemented/
717+--
718+{-# INLINE deintercalate #-}
719+deintercalate ::
720+ -- Monad m =>
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
725+
726+-------------------------------------------------------------------------------
727+-- Sequential Collection
728+-------------------------------------------------------------------------------
729+--
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.
639--
732--
@@ -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
647
740
741+-------------------------------------------------------------------------------
742+-- Alternative Collection
743+-------------------------------------------------------------------------------
744+--
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.
650--
747--
@@ -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
656
753
754+-------------------------------------------------------------------------------
755+-- Sequential Repetition
756+-------------------------------------------------------------------------------
757+--
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
673
775
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
686
790
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
698
803
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
710
816
711data ManyTillState fs sr sl = ManyTillR Int fs sr | ManyTillL fs sl
817data ManyTillState fs sr sl = ManyTillR Int fs sr | ManyTillL fs sl
712
818