on 3e53339 help sign in
1011 lines 33 kB history raw
1{-# OPTIONS_GHC -Wno-orphans #-}
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 : experimental
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>
48module Streamly.Internal.Data.Parser
49 (
50 K.Parser (..)
51 , D.ParseError (..)
52 , D.Step (..)
54 -- First order parsers
55 -- * Accumulators
56 , fromFold
57 , yield
58 , yieldM
59 , die
60 , dieM
62 -- * Element parsers
63 , peek
64 , eof
65 , satisfy
66 , maybe
67 , either
69 -- * Sequence parsers
70 --
71 -- | Parsers chained in series, if one parser terminates the composition
72 -- terminates.
74 -- | Grab a sequence of input elements without inspecting them
75 , takeBetween
76 -- , take -- takeBetween 0 n
77 , takeEQ -- takeBetween n n
78 , takeGE -- takeBetween n maxBound
80 -- Grab a sequence of input elements by inspecting them
81 , lookAhead
82 , takeWhileP
83 , takeWhile
84 -- $takeWhile
85 , takeWhile1
86 , drainWhile
88 , sliceSepBy
89 , sliceBeginWith
90 , sliceSepWith
91 , escapedSliceSepBy
92 , escapedFrameBy
93 , wordBy
94 , groupBy
95 , eqBy
96 -- | Unimplemented
97 --
98 -- @
99 -- , prefixOf -- match any prefix of a given string
100 -- , suffixOf -- match any suffix of a given string
101 -- , infixOf -- match any substring of a given string
102 -- @
104 -- Second order parsers (parsers using parsers)
105 -- * Binary Combinators
107 -- ** Sequential Applicative
108 , splitWith
109 , split_
111 -- ** Parallel Applicatives
112 , teeWith
113 , teeWithFst
114 , teeWithMin
115 -- , teeTill -- like manyTill but parallel
117 -- ** Sequential Interleaving
118 -- Use two folds, run a primary parser, its rejected values go to the
119 -- secondary parser.
120 , deintercalate
122 -- ** Sequential Alternative
123 , alt
125 -- ** Parallel Alternatives
126 , shortest
127 , longest
128 -- , fastest
130 -- * N-ary Combinators
131 -- ** Sequential Collection
132 , concatSequence
133 , concatMap
135 -- ** Sequential Repetition
136 , count
137 , countBetween
139 , manyP
140 , many
141 , some
142 , manyTillP
143 , manyTill
144 , manyThen
146 -- ** Special cases
147 -- | TODO: traditional implmentations of these may be of limited use. For
148 -- example, consider parsing lines separated by @\\r\\n@. The main parser
149 -- will have to detect and exclude the sequence @\\r\\n@ anyway so that we
150 -- can apply the "sep" parser.
151 --
152 -- We can instead implement these as special cases of deintercalate.
153 --
154 -- @
155 -- , endBy
156 -- , sepBy
157 -- , sepEndBy
158 -- , beginBy
159 -- , sepBeginBy
160 -- , sepAroundBy
161 -- @
163 -- * Distribution
164 --
165 -- | A simple and stupid impl would be to just convert the stream to an
166 -- array and give the array reference to all consumers. The array can be
167 -- grown on demand by any consumer and truncated when nonbody needs it.
169 -- ** Distribute to collection
170 -- ** Distribute to repetition
172 -- ** Interleaved collection
173 -- |
174 --
175 -- 1. Round robin
176 -- 2. Priority based
177 , roundRobin
179 -- ** Collection of Alternatives
180 -- | Unimplemented
181 --
182 -- @
183 -- , shortestN
184 -- , longestN
185 -- , fastestN -- first N successful in time
186 -- , choiceN -- first N successful in position
187 -- @
188 , choice -- first successful in position
190 -- ** Repeated Alternatives
191 , retryMaxTotal
192 , retryMaxSuccessive
193 , retry
194 )
195where
197import Control.Monad.Catch (MonadCatch)
198import Prelude
199 hiding (any, all, take, takeWhile, sequence, concatMap, maybe, either)
201import Streamly.Internal.Data.Fold.Types (Fold(..))
202import Streamly.Internal.Data.Parser.ParserK.Types (Parser)
204import qualified Streamly.Internal.Data.Fold as FL
205import qualified Streamly.Internal.Data.Parser.ParserD as D
206import qualified Streamly.Internal.Data.Parser.ParserK.Types as K
208-------------------------------------------------------------------------------
209-- Upgrade folds to parses
210-------------------------------------------------------------------------------
211--
212-- | Make a 'Parser' from a 'Fold'.
213--
214-- /Internal/
215--
216{-# INLINE fromFold #-}
217fromFold :: MonadCatch m => Fold m a b -> Parser m a b
218fromFold = K.toParserK . D.fromFold
220-------------------------------------------------------------------------------
221-- Terminating but not failing folds
222-------------------------------------------------------------------------------
223--
224-- This is the dual of stream "yield".
225--
226-- | A parser that always yields a pure value without consuming any input.
227--
228-- /Internal/
229--
230{-# INLINE [3] yield #-}
231yield :: MonadCatch m => b -> Parser m a b
232yield = K.toParserK . D.yield
233{-# RULES "yield fallback to CPS" [2]
234 forall a. K.toParserK (D.yield a) = K.yield a #-}
236-- This is the dual of stream "yieldM".
237--
238-- | A parser that always yields the result of an effectful action without
239-- consuming any input.
240--
241-- /Internal/
242--
243{-# INLINE yieldM #-}
244yieldM :: MonadCatch m => m b -> Parser m a b
245yieldM = K.yieldM -- K.toParserK . D.yieldM
247-- This is the dual of "nil".
248--
249-- | A parser that always fails with an error message without consuming
250-- any input.
251--
252-- /Internal/
253--
254{-# INLINE [3] die #-}
255die :: MonadCatch m => String -> Parser m a b
256die = K.toParserK . D.die
257{-# RULES "die fallback to CPS" [2]
258 forall a. K.toParserK (D.die a) = K.die a #-}
260-- This is the dual of "nilM".
261--
262-- | A parser that always fails with an effectful error message and without
263-- consuming any input.
264--
265-- /Internal/
266--
267{-# INLINE dieM #-}
268dieM :: MonadCatch m => m String -> Parser m a b
269dieM = K.toParserK . D.dieM
271-------------------------------------------------------------------------------
272-- Failing Parsers
273-------------------------------------------------------------------------------
275-- | Peek the head element of a stream, without consuming it. Fails if it
276-- encounters end of input.
277--
278-- >>> S.parse ((,) <$> PR.peek <*> PR.satisfy (> 0)) $ S.fromList [1]
279-- (1,1)
280--
281-- @
282-- peek = lookAhead (satisfy True)
283-- @
284--
285-- /Internal/
286--
287{-# INLINE peek #-}
288peek :: MonadCatch m => Parser m a a
289peek = K.toParserK D.peek
291-- | Succeeds if we are at the end of input, fails otherwise.
292--
293-- >>> S.parse ((,) <$> PR.satisfy (> 0) <*> PR.eof) $ S.fromList [1]
294-- > (1,())
295--
296-- /Internal/
297--
298{-# INLINE eof #-}
299eof :: MonadCatch m => Parser m a ()
300eof = K.toParserK D.eof
302-- | Returns the next element if it passes the predicate, fails otherwise.
303--
304-- >>> S.parse (PR.satisfy (== 1)) $ S.fromList [1,0,1]
305-- > 1
306--
307-- /Internal/
308--
309{-# INLINE satisfy #-}
310satisfy :: MonadCatch m => (a -> Bool) -> Parser m a a
311satisfy = K.toParserK . D.satisfy
313-- | Map a 'Maybe' returning function on the next element in the stream. The
314-- parser fails if the function returns 'Nothing' otherwise returns the 'Just'
315-- value.
316--
317-- /Internal/
318--
319{-# INLINE maybe #-}
320maybe :: MonadCatch m => (a -> Maybe b) -> Parser m a b
321maybe = K.toParserK . D.maybe
323-- | Map an 'Either' returning function on the next element in the stream. If
324-- the function returns 'Left err', the parser fails with the error message
325-- @err@ otherwise returns the 'Right' value.
326--
327-- /Internal/
328--
329{-# INLINE either #-}
330either :: MonadCatch m => (a -> Either String b) -> Parser m a b
331either = K.toParserK . D.either
333-------------------------------------------------------------------------------
334-- Taking elements
335-------------------------------------------------------------------------------
337-- | @takeBetween m n@ takes a minimum of @m@ and a maximum of @n@ input
338-- elements and folds them using the supplied fold.
339--
340-- Stops after @n@ elements.
341-- Fails if the stream ends before @m@ elements could be taken.
342--
343-- Examples: -
344--
345-- @
346-- takeBetween' low high ls = S.parse prsr (S.fromList ls)
347-- where prsr = P.takeBetween low high FL.toList
348-- @
349--
350-- >>> takeBetween' 2 4 [1, 2, 3, 4, 5]
351-- > [1,2,3,4]
352--
353-- >>> takeBetween' 2 4 [1, 2]
354-- > [1,2]
355--
356-- >>> takeBetween' 2 4 [1]
357-- > ParseError "takeBetween: Expecting alteast 2 elements, got 1"
358--
359-- >>> takeBetween' 0 0 [1, 2]
360-- > []
361--
362-- >>> takeBetween' 0 1 []
363-- > []
364--
365-- @takeBetween@ is the most general take operation, other take operations can
366-- be defined in terms of takeBetween. For example:
367--
368-- @
369-- take = takeBetween 0 n -- equivalent of takeLE
370-- take1 = takeBetween 1 n -- equivalent of takeLE1
371-- takeEQ = takeBetween n n
372-- takeGE = takeBetween n maxBound
373-- @
374--
375-- /Internal/
376--
377{-# INLINE takeBetween #-}
378takeBetween :: MonadCatch m =>
379 Int -> Int -> Fold m a b -> Parser m a b
380takeBetween m n = K.toParserK . D.takeBetween m n
382-- | Stops after taking exactly @n@ input elements.
383--
384-- * Stops - after consuming @n@ elements.
385-- * Fails - if the stream or the collecting fold ends before it can collect
386-- exactly @n@ elements.
387--
388-- >>> S.parse (PR.takeEQ 4 FL.toList) $ S.fromList [1,0,1]
389-- > "takeEQ: Expecting exactly 4 elements, got 3"
390--
391-- /Internal/
392--
393{-# INLINE takeEQ #-}
394takeEQ :: MonadCatch m => Int -> Fold m a b -> Parser m a b
395takeEQ n = K.toParserK . D.takeEQ n
397-- | Take at least @n@ input elements, but can collect more.
398--
399-- * Stops - when the collecting fold stops.
400-- * Fails - if the stream or the collecting fold ends before producing @n@
401-- elements.
402--
403-- >>> S.parse (PR.takeGE 4 FL.toList) $ S.fromList [1,0,1]
404-- > "takeGE: Expecting at least 4 elements, got only 3"
405--
406-- >>> S.parse (PR.takeGE 4 FL.toList) $ S.fromList [1,0,1,0,1]
407-- > [1,0,1,0,1]
408--
409-- /Internal/
410--
411{-# INLINE takeGE #-}
412takeGE :: MonadCatch m => Int -> Fold m a b -> Parser m a b
413takeGE n = K.toParserK . D.takeGE n
415-- $takeWhile
416-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
418-- | Like 'takeWhile' but uses a 'Parser' instead of a 'Fold' to collect the
419-- input. The combinator stops when the condition fails or if the collecting
420-- parser stops.
421--
422-- This is a generalized version of takeWhile, for example 'takeWhile1' can be
423-- implemented in terms of this:
424--
425-- @
426-- takeWhile1 cond p = takeWhile cond (takeBetween 1 maxBound p)
427-- @
428--
429-- Stops: when the condition fails or the collecting parser stops.
430-- Fails: when the collecting parser fails.
431--
432-- /Unimplemented/
433--
434{-# INLINE takeWhileP #-}
435takeWhileP :: -- MonadCatch m =>
436 (a -> Bool) -> Parser m a b -> Parser m a b
437takeWhileP _cond = undefined -- K.toParserK . D.takeWhileP cond
439-- | Collect stream elements until an element fails the predicate. The element
440-- on which the predicate fails is returned back to the input stream.
441--
442-- * Stops - when the predicate fails or the collecting fold stops.
443-- * Fails - never.
444--
445-- >>> S.parse (PR.takeWhile (== 0) FL.toList) $ S.fromList [0,0,1,0,1]
446-- > [0,0]
447--
448-- We can implement a @breakOn@ using 'takeWhile':
449--
450-- @
451-- breakOn p = takeWhile (not p)
452-- @
453--
454-- /Internal/
455--
456{-# INLINE takeWhile #-}
457takeWhile :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
458takeWhile cond = K.toParserK . D.takeWhile cond
460-- | Like 'takeWhile' but takes at least one element otherwise fails.
461--
462-- /Internal/
463--
464{-# INLINE takeWhile1 #-}
465takeWhile1 :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
466takeWhile1 cond = K.toParserK . D.takeWhile1 cond
468-- | Drain the input as long as the predicate succeeds, running the effects and
469-- discarding the results.
470--
471-- This is also called @skipWhile@ in some parsing libraries.
472--
473-- /Internal/
474--
475{-# INLINE drainWhile #-}
476drainWhile :: MonadCatch m => (a -> Bool) -> Parser m a ()
477drainWhile p = takeWhile p FL.drain
479-- | @sliceSepBy cond parser@ parses a slice of the input using @parser@ until
480-- @cond@ succeeds or the parser stops.
481--
482-- This is a generalized slicing parser which can be used to implement other
483-- parsers e.g.:
484--
485-- @
486-- sliceSepByMax cond n p = sliceBy cond (take n p)
487-- sliceSepByBetween cond m n p = sliceBy cond (takeBetween m n p)
488-- @
489--
490-- /Unimplemented/
491--
492{-# INLINABLE sliceSepBy #-}
493sliceSepBy :: -- MonadCatch m =>
494 (a -> Bool) -> Parser m a b -> Parser m a b
495sliceSepBy _cond = undefined -- K.toParserK . D.sliceSepBy cond
497-- | Like 'sliceSepBy' but does not drop the separator element, instead
498-- separator is emitted as a separate element in the output.
499--
500-- /Unimplemented/
501{-# INLINABLE sliceSepWith #-}
502sliceSepWith :: -- MonadCatch m =>
503 (a -> Bool) -> Fold m a b -> Parser m a b
504sliceSepWith _cond = undefined -- K.toParserK . D.sliceSepBy cond
506-- | Collect stream elements until an elements passes the predicate, return the
507-- last element on which the predicate succeeded back to the input stream. If
508-- the predicate succeeds on the first element itself then it is kept in the
509-- stream and we continue collecting. The succeeding element is treated as a
510-- prefix separator which is kept in the output segement.
511--
512-- * Stops - when the predicate succeeds in non-leading position.
513-- * Fails - never.
514--
515-- S.splitWithPrefix pred f = S.parseMany (PR.sliceBeginWith pred f)
516--
517-- /Unimplemented/
518--
519{-# INLINABLE sliceBeginWith #-}
520sliceBeginWith ::
521 -- Monad m =>
522 (a -> Bool) -> Fold m a b -> Parser m a b
523sliceBeginWith = undefined
525-- | Like 'sliceSepBy' but the separator elements can be escaped using an
526-- escape char determined by the second predicate.
527--
528-- /Unimplemented/
529{-# INLINABLE escapedSliceSepBy #-}
530escapedSliceSepBy :: -- MonadCatch m =>
531 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
532escapedSliceSepBy _cond _esc = undefined
533 -- K.toParserK . D.escapedSliceSepBy cond esc
535-- | @escapedFrameBy begin end escape@ parses a string framed using @begin@ and
536-- @end@ as the frame begin and end marker elements and @escape@ as an escaping
537-- element to escape the occurrence of the framing elements within the frame.
538-- Nested frames are allowed, but nesting is removed when parsing.
539--
540-- For example,
541--
542-- >>> escapedFrameBy (== '{') (== '}') (== '\\') S.toList $ S.fromList "{hello}"
543-- > "hello"
544--
545-- >>> escapedFrameBy (== '{') (== '}') (== '\\') S.toList $ S.fromList "{hello {world}}"
546-- > "hello world"
547--
548-- >>> escapedFrameBy (== '{') (== '}') (== '\\') S.toList $ S.fromList "{hello \\{world\\}}"
549-- > "hello {world}"
550--
551-- >>> escapedFrameBy (== '{') (== '}') (== '\\') S.toList $ S.fromList "{hello {world}"
552-- > ParseError "Unterminated '{'"
553--
554-- /Unimplemented/
555{-# INLINABLE escapedFrameBy #-}
556escapedFrameBy :: -- MonadCatch m =>
557 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
558escapedFrameBy _begin _end _escape _p = undefined
559 -- K.toParserK . D.frameBy begin end escape p
561-- | Like 'splitOn' but strips leading, trailing, and repeated separators.
562-- Therefore, @".a..b."@ having '.' as the separator would be parsed as
563-- @["a","b"]@. In other words, its like parsing words from whitespace
564-- separated text.
565--
566-- * Stops - when it finds a word separator after a non-word element
567-- * Fails - never.
568--
569-- @
570-- S.wordsBy pred f = S.parseMany (PR.wordBy pred f)
571-- @
572--
573{-# INLINE wordBy #-}
574wordBy :: MonadCatch m => (a -> Bool) -> Fold m a b -> Parser m a b
575wordBy f = K.toParserK . D.wordBy f
577-- | @groupBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
578-- first group, then if @a \`cmp` b@ is 'True' @b@ is also assigned to the same
579-- group. If @a \`cmp` c@ is 'True' then @c@ is also assigned to the same
580-- group and so on. When the comparison fails a new group is started. Each
581-- group is folded using the 'Fold' @f@ and the result of the fold is emitted
582-- in the output stream.
583--
584-- * Stops - when the comparison fails.
585-- * Fails - never.
586--
587-- @
588-- S.groupsBy cmp f = S.parseMany (PR.groupBy cmp f)
589-- @
590--
591-- /Unimplemented/
592--
593{-# INLINABLE groupBy #-}
594groupBy :: MonadCatch m => (a -> a -> Bool) -> Fold m a b -> Parser m a b
595groupBy cmp = K.toParserK . D.groupBy cmp
597-- | Match the given sequence of elements using the given comparison function.
598--
599-- >>> S.parse $ S.eqBy (==) "string" $ S.fromList "string"
600--
601-- >>> S.parse $ S.eqBy (==) "mismatch" $ S.fromList "match"
602-- > *** Exception: ParseError "eqBy: failed, yet to match 7 elements"
603--
604-- /Internal/
605--
606{-# INLINE eqBy #-}
607eqBy :: MonadCatch m => (a -> a -> Bool) -> [a] -> Parser m a ()
608eqBy cmp = K.toParserK . D.eqBy cmp
610-------------------------------------------------------------------------------
611-- nested parsers
612-------------------------------------------------------------------------------
614-- | Sequential parser application. Apply two parsers sequentially to an input
615-- stream. The input is provided to the first parser, when it is done the
616-- remaining input is provided to the second parser. If both the parsers
617-- succeed their outputs are combined using the supplied function. The
618-- operation fails if any of the parsers fail.
619--
620-- Note: This is a parsing dual of appending streams using
621-- 'Streamly.Prelude.serial', it splits the streams using two parsers and zips
622-- the results.
623--
624-- This implementation is strict in the second argument, therefore, the
625-- following will fail:
626--
627-- >>> S.parse (PR.splitWith const (PR.satisfy (> 0)) undefined) $ S.fromList [1]
628--
629-- Compare with 'Applicative' instance method '<*>'. This implementation allows
630-- stream fusion but has quadratic complexity. This can fuse with other
631-- operations and can be faster than 'Applicative' instance for small number
632-- (less than 8) of compositions.
633--
634-- /Internal/
635--
636{-# INLINE splitWith #-}
637splitWith :: MonadCatch m
638 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
639splitWith f p1 p2 =
640 K.toParserK $ D.splitWith f (K.fromParserK p1) (K.fromParserK p2)
642-- | Sequential parser application ignoring the output of the first parser.
643-- Apply two parsers sequentially to an input stream. The input is provided to
644-- the first parser, when it is done the remaining input is provided to the
645-- second parser. The output of the parser is the output of the second parser.
646-- The operation fails if any of the parsers fail.
647--
648-- This implementation is strict in the second argument, therefore, the
649-- following will fail:
650--
651-- >>> S.parse (split_ (PR.satisfy (> 0)) undefined) $ S.fromList [1]
652--
653-- Compare with 'Applicative' instance method '*>'. This implementation allows
654-- stream fusion but has quadratic complexity. This can fuse with other
655-- operations, and can be faster than 'Applicative' instance for small
656-- number (less than 8) of compositions.
657--
658-- /Internal/
659--
660{-# INLINE split_ #-}
661split_ :: MonadCatch m => Parser m x a -> Parser m x b -> Parser m x b
662split_ p1 p2 = K.toParserK $ D.split_ (K.fromParserK p1) (K.fromParserK p2)
664-- | @teeWith f p1 p2@ distributes its input to both @p1@ and @p2@ until both
665-- of them succeed or anyone of them fails and combines their output using @f@.
666-- The parser succeeds if both the parsers succeed.
667--
668-- /Internal/
669--
670{-# INLINE teeWith #-}
671teeWith :: MonadCatch m
672 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
673teeWith f p1 p2 =
674 K.toParserK $ D.teeWith f (K.fromParserK p1) (K.fromParserK p2)
676-- | Like 'teeWith' but ends parsing and zips the results, if available,
677-- whenever the first parser ends.
678--
679-- /Internal/
680--
681{-# INLINE teeWithFst #-}
682teeWithFst :: MonadCatch m
683 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
684teeWithFst f p1 p2 =
685 K.toParserK $ D.teeWithFst f (K.fromParserK p1) (K.fromParserK p2)
687-- | Like 'teeWith' but ends parsing and zips the results, if available,
688-- whenever any of the parsers ends or fails.
689--
690-- /Unimplemented/
691--
692{-# INLINE teeWithMin #-}
693teeWithMin :: MonadCatch m
694 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
695teeWithMin f p1 p2 =
696 K.toParserK $ D.teeWithMin f (K.fromParserK p1) (K.fromParserK p2)
698-- | Sequential alternative. Apply the input to the first parser and return the
699-- result if the parser succeeds. If the first parser fails then backtrack and
700-- apply the same input to the second parser and return the result.
701--
702-- Note: This implementation is not lazy in the second argument. The following
703-- will fail:
704--
705-- >>> S.parse (PR.satisfy (> 0) `PR.alt` undefined) $ S.fromList [1..10]
706--
707-- Compare with 'Alternative' instance method '<|>'. This implementation allows
708-- stream fusion but has quadratic complexity. This can fuse with other
709-- operations and can be much faster than 'Alternative' instance for small
710-- number (less than 8) of alternatives.
711--
712-- /Internal/
713--
714{-# INLINE alt #-}
715alt :: MonadCatch m => Parser m x a -> Parser m x a -> Parser m x a
716alt p1 p2 = K.toParserK $ D.alt (K.fromParserK p1) (K.fromParserK p2)
718-- | Shortest alternative. Apply both parsers in parallel but choose the result
719-- from the one which consumed least input i.e. take the shortest succeeding
720-- parse.
721--
722-- /Internal/
723--
724{-# INLINE shortest #-}
725shortest :: MonadCatch m
726 => Parser m x a -> Parser m x a -> Parser m x a
727shortest p1 p2 = K.toParserK $ D.shortest (K.fromParserK p1) (K.fromParserK p2)
729-- | Longest alternative. Apply both parsers in parallel but choose the result
730-- from the one which consumed more input i.e. take the longest succeeding
731-- parse.
732--
733-- /Internal/
734--
735{-# INLINE longest #-}
736longest :: MonadCatch m
737 => Parser m x a -> Parser m x a -> Parser m x a
738longest p1 p2 = K.toParserK $ D.longest (K.fromParserK p1) (K.fromParserK p2)
740-- | Run a parser without consuming the input.
741--
742-- /Internal/
743--
744{-# INLINE lookAhead #-}
745lookAhead :: MonadCatch m => Parser m a b -> Parser m a b
746lookAhead p = K.toParserK $ D.lookAhead $ K.fromParserK p
748-------------------------------------------------------------------------------
749-- Interleaving
750-------------------------------------------------------------------------------
751--
752-- To deinterleave we can chain two parsers one behind the other. The input is
753-- given to the first parser and the input definitively rejected by the first
754-- parser is given to the second parser.
755--
756-- We can either have the parsers themselves buffer the input or use the shared
757-- global buffer to hold it until none of the parsers need it. When the first
758-- parser returns Skip (i.e. rewind) we let the second parser consume the
759-- rejected input and when it is done we move the cursor forward to the first
760-- parser again. This will require a "move forward" command as well.
761--
762-- To implement grep we can use three parsers, one to find the pattern, one
763-- to store the context behind the pattern and one to store the context in
764-- front of the pattern. When a match occurs we need to emit the accumulator of
765-- all the three parsers. One parser can count the line numbers to provide the
766-- line number info.
767--
768-- | Apply two parsers alternately to an input stream. The input stream is
769-- considered an interleaving of two patterns. The two parsers represent the
770-- two patterns.
771--
772-- This undoes a "gintercalate" of two streams.
773--
774-- /Unimplemented/
775--
776{-# INLINE deintercalate #-}
777deintercalate ::
778 -- Monad m =>
779 Fold m a y -> Parser m x a
780 -> Fold m b z -> Parser m x b
781 -> Parser m x (y, z)
782deintercalate = undefined
784-------------------------------------------------------------------------------
785-- Sequential Collection
786-------------------------------------------------------------------------------
787--
788-- | @concatSequence f t@ collects sequential parses of parsers in the
789-- container @t@ using the fold @f@. Fails if the input ends or any of the
790-- parsers fail.
791--
792-- This is same as 'Data.Traversable.sequence' but more efficient.
793--
794-- /Unimplemented/
795--
796{-# INLINE concatSequence #-}
797concatSequence ::
798 -- Foldable t =>
799 Fold m b c -> t (Parser m a b) -> Parser m a c
800concatSequence _f _p = undefined
802-- | Map a 'Parser' returning function on the result of a 'Parser'.
803--
804-- Compare with 'Monad' instance method '>>='. This implementation allows
805-- stream fusion but has quadratic complexity. This can fuse with other
806-- operations and can be much faster than 'Monad' instance for small number
807-- (less than 8) of compositions.
808--
809-- /Internal/
810--
811{-# INLINE concatMap #-}
812concatMap :: MonadCatch m
813 => (b -> Parser m a c) -> Parser m a b -> Parser m a c
814concatMap f p = K.toParserK $ D.concatMap (K.fromParserK . f) (K.fromParserK p)
816-------------------------------------------------------------------------------
817-- Alternative Collection
818-------------------------------------------------------------------------------
819--
820-- | @choice parsers@ applies the @parsers@ in order and returns the first
821-- successful parse.
822--
823-- This is same as 'asum' but more efficient.
824--
825-- /Unimplemented/
826--
827{-# INLINE choice #-}
828choice ::
829 -- Foldable t =>
830 t (Parser m a b) -> Parser m a b
831choice _ps = undefined
833-------------------------------------------------------------------------------
834-- Sequential Repetition
835-------------------------------------------------------------------------------
836--
837-- $many
838-- TODO "many" is essentially a Fold because it cannot fail. So it can be
839-- downgraded to a Fold. Or we can make the return type a Fold instead and
840-- upgrade that to a parser when needed.
842-- | Like 'many' but uses a 'Parser' instead of a 'Fold' to collect the
843-- results. Parsing stops or fails if the collecting parser stops or fails.
844--
845-- /Unimplemented/
846--
847{-# INLINE manyP #-}
848manyP :: -- MonadCatch m =>
849 Parser m b c -> Parser m a b -> Parser m a c
850manyP _f _p = undefined -- K.toParserK $ D.manyP f (K.fromParserK p)
852-- | Collect zero or more parses. Apply the supplied parser repeatedly on the
853-- input stream and push the parse results to a downstream fold.
854--
855-- Stops: when the downstream fold stops or the parser fails.
856-- Fails: never, produces zero or more results.
857--
858-- Compare with 'Control.Applicative.many'.
859--
860-- /Internal/
861--
862{-# INLINE many #-}
863many :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
864many f p = K.toParserK $ D.many f (K.fromParserK p)
865-- many = countBetween 0 maxBound
867-- Note: many1 would perhaps be a better name for this and consistent with
868-- other names like takeWhile1. But we retain the name "some" for
869-- compatibility.
870--
871-- | Collect one or more parses. Apply the supplied parser repeatedly on the
872-- input stream and push the parse results to a downstream fold.
873--
874-- Stops: when the downstream fold stops or the parser fails.
875-- Fails: if it stops without producing a single result.
876--
877-- @some fld parser = many (takeGE 1 fld) parser@
878--
879-- Compare with 'Control.Applicative.some'.
880--
881-- /Internal/
882--
883{-# INLINE some #-}
884some :: MonadCatch m => Fold m b c -> Parser m a b -> Parser m a c
885some f p = K.toParserK $ D.some f (K.fromParserK p)
886-- some f p = manyP (takeGE 1 f) p
887-- many = countBetween 1 maxBound
889-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
890-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
891-- the input ends or the parser fails before @m@ results are collected.
892--
893-- /Unimplemented/
894--
895{-# INLINE countBetween #-}
896countBetween ::
897 -- MonadCatch m =>
898 Int -> Int -> Fold m b c -> Parser m a b -> Parser m a c
899countBetween _m _n _f = undefined
900-- countBetween m n f p = manyP (takeBetween m n f) p
902-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
903-- the fold @f@. Fails if the input ends or the parser fails before @n@
904-- results are collected.
905--
906-- /Unimplemented/
907--
908{-# INLINE count #-}
909count ::
910 -- MonadCatch m =>
911 Int -> Fold m b c -> Parser m a b -> Parser m a c
912count n = countBetween n n
913-- count n f p = manyP (takeEQ n f) p
915-- | Like 'manyTill' but uses a 'Parser' to collect the results instead of a
916-- 'Fold'. Parsing stops or fails if the collecting parser stops or fails.
917--
918-- We can implemnent parsers like the following using 'manyTillP':
919--
920-- @
921-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
922-- @
923--
924-- /Unimplemented/
925--
926{-# INLINE manyTillP #-}
927manyTillP :: -- MonadCatch m =>
928 Parser m b c -> Parser m a b -> Parser m a x -> Parser m a c
929manyTillP _f _p1 _p2 = undefined
930 -- K.toParserK $ D.manyTillP f (K.fromParserK p1) (K.fromParserK p2)
932-- | @manyTill f collect test@ tries the parser @test@ on the input, if @test@
933-- fails it backtracks and tries @collect@, after @collect@ succeeds @test@ is
934-- tried again and so on. The parser stops when @test@ succeeds. The output of
935-- @test@ is discarded and the output of @collect@ is accumulated by the
936-- supplied fold. The parser fails if @collect@ fails.
937--
938-- Stops when the fold @f@ stops.
939--
940-- /Internal/
941--
942{-# INLINE manyTill #-}
943manyTill :: MonadCatch m
944 => Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
945manyTill f p1 p2 =
946 K.toParserK $ D.manyTill f (K.fromParserK p1) (K.fromParserK p2)
948-- | @manyThen f collect recover@ repeats the parser @collect@ on the input and
949-- collects the output in the supplied fold. If the the parser @collect@ fails,
950-- parser @recover@ is run until it stops and then we start repeating the
951-- parser @collect@ again. The parser fails if the recovery parser fails.
952--
953-- For example, this can be used to find a key frame in a video stream after an
954-- error.
955--
956-- /Unimplemented/
957--
958{-# INLINE manyThen #-}
959manyThen :: -- (Foldable t, MonadCatch m) =>
960 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
961manyThen _f _parser _recover = undefined
963-------------------------------------------------------------------------------
964-- Interleaving a collection of parsers
965-------------------------------------------------------------------------------
966--
967-- | Apply a collection of parsers to an input stream in a round robin fashion.
968-- Each parser is applied until it stops and then we repeat starting with the
969-- the first parser again.
970--
971-- /Unimplemented/
972--
973{-# INLINE roundRobin #-}
974roundRobin :: -- (Foldable t, MonadCatch m) =>
975 Fold m b c -> t (Parser m a b) -> Parser m a c
976roundRobin _f _ps = undefined
978-------------------------------------------------------------------------------
979-- Repeated Alternatives
980-------------------------------------------------------------------------------
982-- | Keep trying a parser up to a maximum of @n@ failures. When the parser
983-- fails the input consumed till now is dropped and the new instance is tried
984-- on the fresh input.
985--
986-- /Unimplemented/
987--
988{-# INLINE retryMaxTotal #-}
989retryMaxTotal :: -- (MonadCatch m) =>
990 Int -> Fold m b c -> Parser m a b -> Parser m a c
991retryMaxTotal _n _f _p = undefined
993-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
994--
995-- /Unimplemented/
996--
997{-# INLINE retryMaxSuccessive #-}
998retryMaxSuccessive :: -- (MonadCatch m) =>
999 Int -> Fold m b c -> Parser m a b -> Parser m a c
1000retryMaxSuccessive _n _f _p = undefined
1002-- | Keep trying a parser until it succeeds. When the parser fails the input
1003-- consumed till now is dropped and the new instance is tried on the fresh
1004-- input.
1006-- /Unimplemented/
1008{-# INLINE retry #-}
1009retry :: -- (MonadCatch m) =>
1010 Parser m a b -> Parser m a b
1011retry _p = undefined