on efe0be3 help sign in
1544 lines 52 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 : 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>
48module Streamly.Internal.Data.Parser
49 (
50 K.Parser (..)
51 , D.ParseError (..)
52 , D.Step (..)
54 -- * Downgrade to Fold
55 , toFold
57 -- First order parsers
58 -- * Accumulators
59 , fromFold
60 , fromFoldMaybe
61 , fromPure
62 , fromEffect
63 , die
64 , dieM
66 -- * Map on input
67 , lmap
68 , lmapM
69 , filter
71 -- * Map on output
72 , rmapM
74 -- * Element parsers
75 , peek
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
88 -- * Sequence parsers (tokenizers)
89 --
90 -- | Parsers chained in series, if one parser terminates the composition
91 -- terminates.
93 , lookAhead
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
103 -- Grab a sequence of input elements by inspecting them
104 -- ** Exact match
105 , listEq
106 , listEqBy
107 , streamEqBy
108 , subsequenceBy
110 -- ** By predicate
111 , takeWhileP
112 , takeWhile
113 -- $takeWhile
114 , takeWhile1
115 , dropWhile
117 -- ** Separators
118 , takeEndBy
119 , takeEndBy_
120 , takeEndByEsc
121 -- , takeEndByEsc_
122 , takeStartBy
123 , takeStartBy_
124 , takeEitherSepBy
125 , wordBy
126 -- , wordByEsc
128 -- ** By comparing
129 , groupBy
130 , groupByRolling
131 , groupByRollingEither
133 -- ** Framing
134 -- , takeFramedBy
135 , takeFramedBy_
136 , takeFramedByEsc_
137 , takeFramedByGeneric
138 , wordFramedBy
139 , wordQuotedBy
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 -- @
149 -- Second order parsers (parsers using parsers)
150 -- * Binary Combinators
152 -- ** Sequential Applicative
153 , splitWith
154 , split_
156{-
157 -- ** Parallel Applicatives
158 , teeWith
159 , teeWithFst
160 , teeWithMin
161 -- , teeTill -- like manyTill but parallel
162-}
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
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
189 -- ** Sequential Alternative
190 , alt
192{-
193 -- ** Parallel Alternatives
194 , shortest
195 , longest
196 -- , fastest
197-}
199 -- * N-ary Combinators
200 -- ** Sequential Collection
201 , concatSequence
202 , concatMap
204 -- ** Sequential Repetition
205 , count
206 , countBetween
208 , manyP
209 , many
210 , some
211 , manyTillP
212 , manyTill
213 , manyThen
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.
221 -- ** Distribute to collection
222 -- ** Distribute to repetition
224 -- ** Interleaved collection
225 -- |
226 --
227 -- 1. Round robin
228 -- 2. Priority based
229 , roundRobin
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
242 -- ** Repeated Alternatives
243 , retryMaxTotal
244 , retryMaxSuccessive
245 , retry
247 -- * Deprecated
248 , next
249 )
250where
252import Streamly.Internal.Data.Fold.Type (Fold(..))
253import Streamly.Internal.Data.Parser.ParserK.Type (Parser)
255import qualified Data.Foldable as Foldable
256import qualified Streamly.Internal.Data.Fold.Type as FL
257import qualified Streamly.Internal.Data.Parser as D
258import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
260#ifdef USE_STREAMK
261import Streamly.Internal.Data.StreamK (Stream)
262import qualified Streamly.Internal.Data.StreamK as Stream
263#else
264import Streamly.Internal.Data.Stream.StreamD.Type (Stream)
265import qualified Streamly.Internal.Data.Stream.StreamD.Type as Stream
266#endif
268import Prelude hiding
269 ( any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either
270 , filter )
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
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 #-}
299toFold :: Monad m => Parser a m b -> Fold m a b
300toFold p = D.toFold $ D.fromParserK p
302-------------------------------------------------------------------------------
303-- Upgrade folds to parses
304-------------------------------------------------------------------------------
305--
306-- | Make a 'Parser' from a 'Fold'.
307--
308{-# INLINE fromFold #-}
309fromFold :: Monad m => Fold m a b -> Parser a m b
310fromFold = D.toParserK . D.fromFold
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 #-}
319fromFoldMaybe :: Monad m => String -> Fold m a (Maybe b) -> Parser a m b
320fromFoldMaybe err = D.toParserK . D.fromFoldMaybe err
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 #-}
331fromPure :: Monad m => b -> Parser a m b
332fromPure = D.toParserK . D.fromPure
333{-# RULES "fromPure fallback to CPS" [2]
334 forall a. D.toParserK (D.fromPure a) = K.fromPure a #-}
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 #-}
342fromEffect :: Monad m => m b -> Parser a m b
343fromEffect = K.fromEffect -- D.toParserK . D.fromEffect
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 #-}
351die :: Monad m => String -> Parser a m b
352die = D.toParserK . D.die
353{-# RULES "die fallback to CPS" [2]
354 forall a. D.toParserK (D.die a) = K.die a #-}
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 #-}
364dieM :: Monad m => m String -> Parser a m b
365dieM = D.toParserK . D.dieM
367-------------------------------------------------------------------------------
368-- Map on input
369-------------------------------------------------------------------------------
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 #-}
379lmap :: Monad m => (a -> b) -> Parser b m r -> Parser a m r
380lmap f p = D.toParserK $ D.lmap f $ D.fromParserK p
382-- | @lmapM f parser@ maps the monadic function @f@ on the input of the parser.
383--
384{-# INLINE lmapM #-}
385lmapM :: Monad m => (a -> m b) -> Parser b m r -> Parser a m r
386lmapM f p = D.toParserK $ D.lmapM f $ D.fromParserK p
388-- | @rmapM f parser@ maps the monadic function @f@ on the output of the parser.
389--
390-- >>> rmap = fmap
391{-# INLINE rmapM #-}
392rmapM :: Monad m => (b -> m c) -> Parser a m b -> Parser a m c
393rmapM f p = D.toParserK $ D.rmapM f $ D.fromParserK p
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 #-}
401filter :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
402filter f p = D.toParserK $ D.filter f $ D.fromParserK p
404-------------------------------------------------------------------------------
405-- Failing Parsers
406-------------------------------------------------------------------------------
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 #-}
419peek :: Monad m => Parser a m a
420peek = D.toParserK D.peek
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 #-}
428eof :: Monad m => Parser a m ()
429eof = D.toParserK D.eof
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 #-}
440satisfy :: Monad m => (a -> Bool) -> Parser a m a
441satisfy = D.toParserK . D.satisfy
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 #-}
449one :: Monad m => Parser a m a
450one = satisfy $ const True
452-- Alternate names: "only", "onlyThis".
454-- | Match a specific element.
455--
456-- >>> oneEq x = Parser.satisfy (== x)
457--
458{-# INLINE oneEq #-}
459oneEq :: (Monad m, Eq a) => a -> Parser a m a
460oneEq x = satisfy (== x)
462-- Alternate names: "exclude", "notThis".
464-- | Match anything other than the supplied element.
465--
466-- >>> oneNotEq x = Parser.satisfy (/= x)
467--
468{-# INLINE oneNotEq #-}
469oneNotEq :: (Monad m, Eq a) => a -> Parser a m a
470oneNotEq x = satisfy (/= x)
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 #-}
493oneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
494oneOf xs = satisfy (`Foldable.elem` xs)
496-- | See performance notes in 'oneOf'.
497--
498-- >>> noneOf xs = Parser.satisfy (`Foldable.notElem` xs)
499--
500{-# INLINE noneOf #-}
501noneOf :: (Monad m, Eq a, Foldable f) => f a -> Parser a m a
502noneOf xs = satisfy (`Foldable.notElem` xs)
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 #-}
511next :: Monad m => Parser a m (Maybe a)
512next = D.toParserK D.next
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 #-}
526maybe :: Monad m => (a -> Maybe b) -> Parser a m b
527maybe = D.toParserK . D.maybe
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 #-}
536either :: Monad m => (a -> Either String b) -> Parser a m b
537either = D.toParserK . D.either
539-------------------------------------------------------------------------------
540-- Taking elements
541-------------------------------------------------------------------------------
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 #-}
584takeBetween :: Monad m =>
585 Int -> Int -> Fold m a b -> Parser a m b
586takeBetween m n = D.toParserK . D.takeBetween m n
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 #-}
598takeEQ :: Monad m => Int -> Fold m a b -> Parser a m b
599takeEQ n = D.toParserK . D.takeEQ n
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 #-}
616takeGE :: Monad m => Int -> Fold m a b -> Parser a m b
617takeGE n = D.toParserK . D.takeGE n
619-------------------------------------------------------------------------------
620-- Take until a condition
621-------------------------------------------------------------------------------
623-- $takeWhile
624-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
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 #-}
643takeWhileP :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
644takeWhileP cond p = D.toParserK $ D.takeWhileP cond (D.fromParserK p)
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 #-}
664takeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
665takeWhile cond = D.toParserK . D.takeWhile cond
666-- takeWhile cond f = takeWhileP cond (fromFold f)
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 #-}
673takeWhile1 :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
674takeWhile1 cond = D.toParserK . D.takeWhile1 cond
675-- takeWhile1 cond f = takeWhileP cond (takeBetween 1 maxBound f)
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 #-}
685dropWhile :: Monad m => (a -> Bool) -> Parser a m ()
686dropWhile p = takeWhile p FL.drain
688-------------------------------------------------------------------------------
689-- Separators
690-------------------------------------------------------------------------------
692-- XXX We can remove Maybe from esc
693{-# INLINE takeFramedByGeneric #-}
694takeFramedByGeneric :: Monad m =>
695 Maybe (a -> Bool)
696 -> Maybe (a -> Bool)
697 -> Maybe (a -> Bool)
698 -> Fold m a b
699 -> Parser a m b
700takeFramedByGeneric esc begin end f =
701 D.toParserK $ D.takeFramedByGeneric esc begin end f
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 #-}
721takeEndBy :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
722takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
723-- takeEndBy = takeEndByEsc (const False)
725-- | Like 'takeEndBy' but the separator is dropped.
726--
727-- See also "Streamly.Data.Fold.takeEndBy_".
728--
729-- /Pre-release/
730--
731{-# INLINE takeEndBy_ #-}
732takeEndBy_ :: Monad m => (a -> Bool) -> Parser a m b -> Parser a m b
733takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
734{-
735takeEndBy_ isEnd p =
736 takeFramedByGeneric Nothing Nothing (Just isEnd) (toFold p)
737-}
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 #-}
744takeEitherSepBy :: -- Monad m =>
745 (a -> Bool) -> Fold m (Either a b) c -> Parser a m c
746takeEitherSepBy _cond = undefined -- D.toParserK . D.takeEitherSepBy cond
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 #-}
773takeStartBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
774takeStartBy cond = D.toParserK . D.takeStartBy cond
776-- | Like 'takeStartBy' but drops the separator.
777--
778-- >>> takeStartBy_ isBegin = Parser.takeFramedByGeneric Nothing (Just isBegin) Nothing
779--
780{-# INLINE takeStartBy_ #-}
781takeStartBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
782takeStartBy_ isBegin = takeFramedByGeneric Nothing (Just isBegin) Nothing
784-------------------------------------------------------------------------------
785-- Quoting and Escaping
786-------------------------------------------------------------------------------
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 #-}
794takeEndByEsc :: Monad m =>
795 (a -> Bool) -> (a -> Bool) -> Parser a m b -> Parser a m b
796takeEndByEsc isEsc isEnd p =
797 D.toParserK $ D.takeEndByEsc isEsc isEnd (D.fromParserK p)
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_ #-}
821takeFramedByEsc_ :: Monad m =>
822 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
823takeFramedByEsc_ 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)
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_ #-}
834takeFramedBy_ :: Monad m =>
835 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser a m b
836takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
837-- takeFramedBy_ isBegin isEnd =
838-- takeFramedByGeneric (Just (const False)) (Just isBegin) (Just isEnd)
840-------------------------------------------------------------------------------
841-- Grouping and words
842-------------------------------------------------------------------------------
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 #-}
864wordBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser a m b
865wordBy f = D.toParserK . D.wordBy f
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 #-}
887wordFramedBy :: 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
894wordFramedBy isEsc isBegin isEnd isSpc =
895 D.toParserK . D.wordFramedBy isEsc isBegin isEnd isSpc
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 #-}
918wordQuotedBy :: (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
927wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc =
928 D.toParserK . D.wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc
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 #-}
957groupBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
958groupBy eq = D.toParserK . D.groupBy eq
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 #-}
991groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser a m b
992groupByRolling eq = D.toParserK . D.groupByRolling eq
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'.
1003-- /Pre-release/
1004{-# INLINE groupByRollingEither #-}
1005groupByRollingEither :: Monad m =>
1006 (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser a m (Either b c)
1007groupByRollingEither eq f1 = D.toParserK . D.groupByRollingEither eq f1
1009-- | Like 'listEqBy' but uses a stream instead of a list and does not return
1010-- the stream.
1012-- See also: "Streamly.Data.Stream.streamEqBy"
1014{-# INLINE streamEqBy #-}
1015streamEqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Parser a m ()
1016streamEqBy cmp = D.toParserK . D.streamEqBy cmp
1018-- | Match the given sequence of elements using the given comparison function.
1019-- Returns the original sequence if successful.
1021-- Definition:
1023-- >>> listEqBy cmp xs = Parser.streamEqBy cmp (Stream.fromList xs) *> Parser.fromPure xs
1025-- Examples:
1027-- >>> Stream.parse (Parser.listEqBy (==) "string") $ Stream.fromList "string"
1028-- Right "string"
1030-- >>> Stream.parse (Parser.listEqBy (==) "mismatch") $ Stream.fromList "match"
1031-- Left (ParseError "streamEqBy: mismtach occurred")
1033{-# INLINE listEqBy #-}
1034listEqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser a m [a]
1035-- listEqBy cmp xs = D.toParserK (D.listEqBy cmp xs)
1036listEqBy cmp xs = streamEqBy cmp (Stream.fromList xs) *> fromPure xs
1038-- Rename to "list".
1039-- | Match the input sequence with the supplied list and return it if
1040-- successful.
1042-- >>> listEq = Parser.listEqBy (==)
1044{-# INLINE listEq #-}
1045listEq :: (Monad m, Eq a) => [a] -> Parser a m [a]
1046listEq = listEqBy (==)
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 #-}
1053subsequenceBy :: -- Monad m =>
1054 (a -> a -> Bool) -> Stream m a -> Parser a m ()
1055subsequenceBy = undefined
1058-- Should go in Data.Parser.Regex in streamly package so that it can depend on
1059-- regex backends.
1060{-# INLINE regexPosix #-}
1061regexPosix :: -- Monad m =>
1062 Regex -> Parser m a (Maybe (Array (MatchOffset, MatchLength)))
1063regexPosix = undefined
1065{-# INLINE regexPCRE #-}
1066regexPCRE :: -- Monad m =>
1067 Regex -> Parser m a (Maybe (Array (MatchOffset, MatchLength)))
1068regexPCRE = undefined
1071-------------------------------------------------------------------------------
1072-- nested parsers
1073-------------------------------------------------------------------------------
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.
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.
1085-- This implementation is strict in the second argument, therefore, the
1086-- following will fail:
1088-- >>> Stream.parse (Parser.splitWith const (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1089-- *** Exception: Prelude.undefined
1090-- ...
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.
1097-- Many combinators can be expressed using @splitWith@ and other parser
1098-- primitives. Some common idioms are described below,
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-- @
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-- @
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-- @
1115-- /Pre-release/
1117{-# INLINE splitWith #-}
1118splitWith :: Monad m
1119 => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1120splitWith f p1 p2 =
1121 D.toParserK $ D.splitWith f (D.fromParserK p1) (D.fromParserK p2)
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.
1129-- This implementation is strict in the second argument, therefore, the
1130-- following will fail:
1132-- >>> Stream.parse (Parser.split_ (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1133-- *** Exception: Prelude.undefined
1134-- ...
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.
1141-- /Pre-release/
1143{-# INLINE split_ #-}
1144split_ :: Monad m => Parser x m a -> Parser x m b -> Parser x m b
1145split_ p1 p2 = D.toParserK $ D.split_ (D.fromParserK p1) (D.fromParserK p2)
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.
1152-- /Pre-release/
1154{-# INLINE teeWith #-}
1155teeWith :: Monad m
1156 => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1157teeWith f p1 p2 =
1158 D.toParserK $ D.teeWith f (D.fromParserK p1) (D.fromParserK p2)
1160-- | Like 'teeWith' but ends parsing and zips the results, if available,
1161-- whenever the first parser ends.
1163-- /Pre-release/
1165{-# INLINE teeWithFst #-}
1166teeWithFst :: Monad m
1167 => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1168teeWithFst f p1 p2 =
1169 D.toParserK $ D.teeWithFst f (D.fromParserK p1) (D.fromParserK p2)
1171-- | Like 'teeWith' but ends parsing and zips the results, if available,
1172-- whenever any of the parsers ends or fails.
1174-- /Unimplemented/
1176{-# INLINE teeWithMin #-}
1177teeWithMin :: Monad m
1178 => (a -> b -> c) -> Parser x m a -> Parser x m b -> Parser x m c
1179teeWithMin f p1 p2 =
1180 D.toParserK $ D.teeWithMin f (D.fromParserK p1) (D.fromParserK p2)
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.
1187-- Note: This implementation is not lazy in the second argument. The following
1188-- will fail:
1190-- >>> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
1191-- Right 1
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.
1198-- /Pre-release/
1200{-# INLINE alt #-}
1201alt :: Monad m => Parser x m a -> Parser x m a -> Parser x m a
1202alt p1 p2 = D.toParserK $ D.alt (D.fromParserK p1) (D.fromParserK p2)
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.
1209-- /Pre-release/
1211{-# INLINE shortest #-}
1212shortest :: Monad m
1213 => Parser x m a -> Parser x m a -> Parser x m a
1214shortest p1 p2 = D.toParserK $ D.shortest (D.fromParserK p1) (D.fromParserK p2)
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.
1220-- /Pre-release/
1222{-# INLINE longest #-}
1223longest :: Monad m
1224 => Parser x m a -> Parser x m a -> Parser x m a
1225longest p1 p2 = D.toParserK $ D.longest (D.fromParserK p1) (D.fromParserK p2)
1228-- | Run a parser without consuming the input.
1230{-# INLINE lookAhead #-}
1231lookAhead :: Monad m => Parser a m b -> Parser a m b
1232lookAhead p = D.toParserK $ D.lookAhead $ D.fromParserK p
1234-- | Takes at-most @n@ input elements.
1236-- * Stops - when the collecting parser stops.
1237-- * Fails - when the collecting parser fails.
1239-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 2 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1240-- Right [1,2]
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")
1245-- /Internal/
1246{-# INLINE takeP #-}
1247takeP :: Monad m => Int -> Parser a m b -> Parser a m b
1248takeP i p = D.toParserK $ D.takeP i $ D.fromParserK p
1250-------------------------------------------------------------------------------
1251-- Sequential Collection
1252-------------------------------------------------------------------------------
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.
1258-- An even more efficient implementation can use ParserD type Parser in
1259-- the stream.
1261-- /Pre-release/
1263{-# INLINE concatSequence #-}
1264concatSequence ::
1265 Monad m =>
1266 Fold m b c -> Stream m (Parser a m b) -> Parser a m c
1267concatSequence f p =
1268 let sp = fmap D.fromParserK p
1269 in D.toParserK $ D.sequence sp f
1271-- | Map a 'Parser' returning function on the result of a 'Parser'.
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.
1278-- /Pre-release/
1280{-# INLINE concatMap #-}
1281concatMap :: Monad m
1282 => (b -> Parser a m c) -> Parser a m b -> Parser a m c
1283concatMap f p = D.toParserK $ D.concatMap (D.fromParserK . f) (D.fromParserK p)
1286-------------------------------------------------------------------------------
1287-- Alternative Collection
1288-------------------------------------------------------------------------------
1290-- | @choice parsers@ applies the @parsers@ in order and returns the first
1291-- successful parse.
1293-- This is same as 'asum' but more efficient.
1295-- /Broken/
1297{-# INLINE choice #-}
1298choice ::
1299 (Functor t, Foldable t, Monad m) => t (Parser a m b) -> Parser a m b
1300choice ps = D.toParserK $ D.choice $ D.fromParserK <$> ps
1303-------------------------------------------------------------------------------
1304-- Sequential Repetition
1305-------------------------------------------------------------------------------
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.
1310-- /Unimplemented/
1312{-# INLINE manyP #-}
1313manyP :: -- Monad m =>
1314 Parser a m b -> Parser b m c -> Parser a m c
1315manyP _p _f = undefined -- D.toParserK $ D.manyP (D.fromParserK p) f
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.
1320-- Stops: when the downstream fold stops or the parser fails.
1321-- Fails: never, produces zero or more results.
1323-- >>> many = Parser.countBetween 0 maxBound
1325-- Compare with 'Control.Applicative.many'.
1327{-# INLINE many #-}
1328many :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
1329many p f = D.toParserK $ D.many (D.fromParserK p) f
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.
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.
1338-- Stops: when the downstream fold stops or the parser fails.
1339-- Fails: if it stops without producing a single result.
1341-- >>> some p f = Parser.manyP p (Parser.takeGE 1 f)
1342-- >>> some = Parser.countBetween 1 maxBound
1344-- Compare with 'Control.Applicative.some'.
1346{-# INLINE some #-}
1347some :: Monad m => Parser a m b -> Fold m b c -> Parser a m c
1348some p f = D.toParserK $ D.some (D.fromParserK p) f
1349-- some p f = manyP p (takeGE 1 f)
1350-- some = countBetween 1 maxBound
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.
1356-- >>> countBetween m n p f = Parser.manyP p (Parser.takeBetween m n f)
1358-- /Unimplemented/
1360{-# INLINE countBetween #-}
1361countBetween :: -- Monad m =>
1362 Int -> Int -> Parser a m b -> Fold m b c -> Parser a m c
1363countBetween _m _n _p = undefined
1364-- countBetween m n p f = manyP p (takeBetween m n f)
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.
1370-- >>> count n = Parser.countBetween n n
1371-- >>> count n p f = Parser.manyP p (Parser.takeEQ n f)
1373-- /Unimplemented/
1375{-# INLINE count #-}
1376count :: -- Monad m =>
1377 Int -> Parser a m b -> Fold m b c -> Parser a m c
1378count n = countBetween n n
1379-- count n p f = manyP p (takeEQ n f)
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.
1384-- We can implemnent parsers like the following using 'manyTillP':
1386-- @
1387-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
1388-- @
1390-- /Unimplemented/
1392{-# INLINE manyTillP #-}
1393manyTillP :: -- Monad m =>
1394 Parser a m b -> Parser a m x -> Parser b m c -> Parser a m c
1395manyTillP _p1 _p2 _f = undefined
1396 -- D.toParserK $ D.manyTillP (D.fromParserK p1) (D.fromParserK p2) f
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.
1404-- Stops when the fold @f@ stops.
1406{-# INLINE manyTill #-}
1407manyTill :: 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
1413manyTill collect test f =
1414 D.toParserK $ D.manyTill (D.fromParserK collect) (D.fromParserK test) f
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.
1421-- For example, this can be used to find a key frame in a video stream after an
1422-- error.
1424-- /Unimplemented/
1426{-# INLINE manyThen #-}
1427manyThen :: -- (Foldable t, Monad m) =>
1428 Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1429manyThen _parser _recover _f = undefined
1431-------------------------------------------------------------------------------
1432-- Interleaving
1433-------------------------------------------------------------------------------
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.
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.
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.
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.
1456{-# INLINE deintercalate #-}
1457deintercalate :: Monad m =>
1458 Parser a m x
1459 -> Parser a m y
1460 -> Fold m (Either x y) z
1461 -> Parser a m z
1462deintercalate contentL contentR sink =
1463 D.toParserK
1464 $ D.deintercalate
1465 (D.fromParserK contentL) (D.fromParserK contentR) sink
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.
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.
1473{-# INLINE sepBy1 #-}
1474sepBy1 :: Monad m =>
1475 Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1476sepBy1 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
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.
1486-- >>> sepBy p1 p2 sink = Parser.deintercalate p1 p2 (Fold.catLefts sink)
1487-- >>> sepBy content sep sink = Parser.sepBy1 content sep sink <|> return mempty
1489{-# INLINE sepBy #-}
1490sepBy :: Monad m =>
1491 Parser a m b -> Parser a m x -> Fold m b c -> Parser a m c
1492sepBy content sep sink =
1493 D.toParserK $ D.sepBy (D.fromParserK content) (D.fromParserK sep) sink
1494-- sepBy sink = deintercalate (FL.catLefts sink)
1496-------------------------------------------------------------------------------
1497-- Interleaving a collection of parsers
1498-------------------------------------------------------------------------------
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.
1504-- /Unimplemented/
1506{-# INLINE roundRobin #-}
1507roundRobin :: -- (Foldable t, Monad m) =>
1508 t (Parser a m b) -> Fold m b c -> Parser a m c
1509roundRobin _ps _f = undefined
1511-------------------------------------------------------------------------------
1512-- Repeated Alternatives
1513-------------------------------------------------------------------------------
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.
1519-- /Unimplemented/
1521{-# INLINE retryMaxTotal #-}
1522retryMaxTotal :: -- (Monad m) =>
1523 Int -> Parser a m b -> Fold m b c -> Parser a m c
1524retryMaxTotal _n _p _f = undefined
1526-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
1528-- /Unimplemented/
1530{-# INLINE retryMaxSuccessive #-}
1531retryMaxSuccessive :: -- (Monad m) =>
1532 Int -> Parser a m b -> Fold m b c -> Parser a m c
1533retryMaxSuccessive _n _p _f = undefined
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.
1539-- /Unimplemented/
1541{-# INLINE retry #-}
1542retry :: -- (Monad m) =>
1543 Parser a m b -> Parser a m b
1544retry _p = undefined