on e856425 help sign in
1541 lines 50 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 , eqBy
109 -- ** By predicate
110 , takeWhileP
111 , takeWhile
112 -- $takeWhile
113 , takeWhile1
114 , dropWhile
116 -- ** Separators
117 , takeEndBy
118 , takeEndBy_
119 , takeEndByEsc
120 -- , takeEndByEsc_
121 , takeStartBy
122 , takeStartBy_
123 , takeEitherSepBy
124 , wordBy
125 -- , wordByEsc
127 -- ** By comparing
128 , groupBy
129 , groupByRolling
130 , groupByRollingEither
132 -- ** Framing
133 -- , takeFramedBy
134 , takeFramedBy_
135 , takeFramedByEsc_
136 , takeFramedByGeneric
137 , wordFramedBy
138 , wordQuotedBy
140 -- | Unimplemented
141 --
142 -- @
143 -- , prefixOf -- match any prefix of a given string
144 -- , suffixOf -- match any suffix of a given string
145 -- , infixOf -- match any substring of a given string
146 -- @
148 -- Second order parsers (parsers using parsers)
149 -- * Binary Combinators
151 -- ** Sequential Applicative
152 , serialWith
153 , split_
155{-
156 -- ** Parallel Applicatives
157 , teeWith
158 , teeWithFst
159 , teeWithMin
160 -- , teeTill -- like manyTill but parallel
161-}
163 -- ** Sequential Interleaving
164 -- Use two folds, run a primary parser, its rejected values go to the
165 -- secondary parser.
166 , deintercalate
167 -- , deintercalatePrefix
168 -- , deintercalateSuffix
170 -- *** Special cases
171 -- | TODO: traditional implmentations of these may be of limited use. For
172 -- example, consider parsing lines separated by @\\r\\n@. The main parser
173 -- will have to detect and exclude the sequence @\\r\\n@ anyway so that we
174 -- can apply the "sep" parser.
175 --
176 -- We can instead implement these as special cases of deintercalate.
177 --
178 -- @
179 -- , endBy
180 -- , sepEndBy
181 -- , beginBy
182 -- , sepBeginBy
183 -- , sepAroundBy
184 -- @
185 , sepBy1
186 , sepBy
188 -- ** Sequential Alternative
189 , alt
191{-
192 -- ** Parallel Alternatives
193 , shortest
194 , longest
195 -- , fastest
196-}
198 -- * N-ary Combinators
199 -- ** Sequential Collection
200 , concatSequence
201 , concatMap
203 -- ** Sequential Repetition
204 , count
205 , countBetween
207 , manyP
208 , many
209 , some
210 , manyTillP
211 , manyTill
212 , manyThen
214 -- * Distribution
215 --
216 -- | A simple and stupid impl would be to just convert the stream to an
217 -- array and give the array reference to all consumers. The array can be
218 -- grown on demand by any consumer and truncated when nonbody needs it.
220 -- ** Distribute to collection
221 -- ** Distribute to repetition
223 -- ** Interleaved collection
224 -- |
225 --
226 -- 1. Round robin
227 -- 2. Priority based
228 , roundRobin
230 -- ** Collection of Alternatives
231 -- | Unimplemented
232 --
233 -- @
234 -- , shortestN
235 -- , longestN
236 -- , fastestN -- first N successful in time
237 -- , choiceN -- first N successful in position
238 -- @
239 -- , choice -- first successful in position
241 -- ** Repeated Alternatives
242 , retryMaxTotal
243 , retryMaxSuccessive
244 , retry
246 -- * Deprecated
247 , next
248 )
249where
251import Streamly.Internal.Data.Fold.Type (Fold(..))
252import Streamly.Internal.Data.Parser.ParserK.Type (Parser)
253import Streamly.Internal.Data.Stream.Type (Stream)
255import qualified Streamly.Internal.Data.Fold.Type as FL
256import qualified Streamly.Internal.Data.Parser.ParserD as D
257import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
258import qualified Streamly.Internal.Data.Stream.Type as Stream
260import Prelude hiding
261 ( any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either
262 , filter )
264--
265-- $setup
266-- >>> :m
267-- >>> :set -package streamly
268-- >>> import Prelude hiding (any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either, filter)
269-- >>> import Control.Applicative ((<|>))
270-- >>> import Data.Char (isSpace)
271-- >>> import qualified Data.Maybe as Maybe
272-- >>> import qualified Streamly.Data.Stream as Stream
273-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse, parseMany)
274-- >>> import qualified Streamly.Internal.Data.Fold as Fold
275-- >>> import qualified Streamly.Internal.Data.Parser as Parser
277-------------------------------------------------------------------------------
278-- Downgrade a parser to a Fold
279-------------------------------------------------------------------------------
280--
281-- | Make a 'Fold' from a 'Parser'. The fold just throws an exception if the
282-- parser fails or tries to backtrack.
283--
284-- This can be useful in combinators that accept a Fold and we know that a
285-- Parser cannot fail or failure exception is acceptable as there is no way to
286-- recover.
287--
288-- /Pre-release/
289--
290{-# INLINE toFold #-}
291toFold :: Monad m => Parser m a b -> Fold m a b
292toFold p = D.toFold $ D.fromParserK p
294-------------------------------------------------------------------------------
295-- Upgrade folds to parses
296-------------------------------------------------------------------------------
297--
298-- | Make a 'Parser' from a 'Fold'.
299--
300-- /Pre-release/
301--
302{-# INLINE fromFold #-}
303fromFold :: Monad m => Fold m a b -> Parser m a b
304fromFold = D.toParserK . D.fromFold
306-- | Convert a Maybe returning fold to an error returning parser. The first
307-- argument is the error message that the parser would return when the fold
308-- returns Nothing.
309--
310-- /Pre-release/
311--
312{-# INLINE fromFoldMaybe #-}
313fromFoldMaybe :: Monad m => String -> Fold m a (Maybe b) -> Parser m a b
314fromFoldMaybe err = D.toParserK . D.fromFoldMaybe err
316-------------------------------------------------------------------------------
317-- Terminating but not failing folds
318-------------------------------------------------------------------------------
319--
320-- This is the dual of stream "fromPure".
321--
322-- | A parser that always yields a pure value without consuming any input.
323--
324-- /Pre-release/
325--
326{-# INLINE [3] fromPure #-}
327fromPure :: Monad m => b -> Parser m a b
328fromPure = D.toParserK . D.fromPure
329{-# RULES "fromPure fallback to CPS" [2]
330 forall a. D.toParserK (D.fromPure a) = K.fromPure a #-}
332-- This is the dual of stream "fromEffect".
333--
334-- | A parser that always yields the result of an effectful action without
335-- consuming any input.
336--
337-- /Pre-release/
338--
339{-# INLINE fromEffect #-}
340fromEffect :: Monad m => m b -> Parser m a b
341fromEffect = K.fromEffect -- D.toParserK . D.fromEffect
343-- This is the dual of "nil".
344--
345-- | A parser that always fails with an error message without consuming
346-- any input.
347--
348-- /Pre-release/
349--
350{-# INLINE [3] die #-}
351die :: Monad m => String -> Parser m a 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 m a 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-- 338350
375--
376-- > lmap = Parser.lmapM return
377--
378-- /Internal/
379{-# INLINE lmap #-}
380lmap :: Monad m => (a -> b) -> Parser m b r -> Parser m a r
381lmap f p = D.toParserK $ D.lmap f $ D.fromParserK p
383-- | @lmapM f parser@ maps the monadic function @f@ on the input of the parser.
384--
385-- /Internal/
386{-# INLINE lmapM #-}
387lmapM :: Monad m => (a -> m b) -> Parser m b r -> Parser m a r
388lmapM f p = D.toParserK $ D.lmapM f $ D.fromParserK p
390-- | @rmapM f parser@ maps the monadic function @f@ on the output of the parser.
391--
392-- /Internal/
393{-# INLINE rmapM #-}
394rmapM :: Monad m => (b -> m c) -> Parser m a b -> Parser m a c
395rmapM f p = D.toParserK $ D.rmapM f $ D.fromParserK p
397-- | Include only those elements that pass a predicate.
398--
399-- >>> Stream.parse (Parser.filter (> 5) (Parser.fromFold Fold.sum)) $ Stream.fromList [1..10]
400-- 40
401--
402-- /Internal/
403{-# INLINE filter #-}
404filter :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
405filter f p = D.toParserK $ D.filter f $ D.fromParserK p
407-------------------------------------------------------------------------------
408-- Failing Parsers
409-------------------------------------------------------------------------------
411-- | Peek the head element of a stream, without consuming it. Fails if it
412-- encounters end of input.
413--
414-- >>> Stream.parse ((,) <$> Parser.peek <*> Parser.satisfy (> 0)) $ Stream.fromList [1]
415-- (1,1)
416--
417-- @
418-- peek = lookAhead (satisfy True)
419-- @
420--
421-- /Pre-release/
422--
423{-# INLINE peek #-}
424peek :: Monad m => Parser m a a
425peek = D.toParserK D.peek
427-- | Succeeds if we are at the end of input, fails otherwise.
428--
429-- >>> Stream.parse ((,) <$> Parser.satisfy (> 0) <*> Parser.eof) $ Stream.fromList [1]
430-- (1,())
431--
432-- /Pre-release/
433--
434{-# INLINE eof #-}
435eof :: Monad m => Parser m a ()
436eof = D.toParserK D.eof
438-- | Returns the next element if it passes the predicate, fails otherwise.
439--
440-- >>> Stream.parse (Parser.satisfy (== 1)) $ Stream.fromList [1,0,1]
441-- 1
442--
443-- >>> toMaybe f x = if f x then Just x else Nothing
444-- >>> satisfy f = Parser.maybe (toMaybe f)
445--
446-- /Pre-release/
447--
448{-# INLINE satisfy #-}
449satisfy :: Monad m => (a -> Bool) -> Parser m a a
450satisfy = D.toParserK . D.satisfy
452-- | Consume one element from the head of the stream. Fails if it encounters
453-- end of input.
454--
455-- >>> one = Parser.satisfy $ const True
456--
457-- /Pre-release/
458--
459{-# INLINE one #-}
460one :: Monad m => Parser m a a
461one = satisfy $ const True
463-- | Match a specific element.
464--
465-- >>> oneEq x = Parser.satisfy (== x)
466--
467{-# INLINE oneEq #-}
468oneEq :: (Monad m, Eq a) => a -> Parser m a a
469oneEq x = satisfy (== x)
471-- | Match anything other than the supplied element.
472--
473-- >>> oneNotEq x = Parser.satisfy (/= x)
474--
475{-# INLINE oneNotEq #-}
476oneNotEq :: (Monad m, Eq a) => a -> Parser m a a
477oneNotEq x = satisfy (/= x)
479-- | Match any one of the elements in the supplied list.
480--
481-- >>> oneOf xs = Parser.satisfy (`elem` xs)
482--
483-- When performance matters a pattern matching predicate could be more
484-- efficient than a list:
485--
486-- @
487-- let p x =
488-- case x of
489-- 'a' -> True
490-- 'e' -> True
491-- _ -> False
492-- in satisfy p
493-- @
494--
495-- GHC may use a binary search instead of linear search in the list.
496-- Alternatively, you can also use an array instead of list for storage and
497-- search.
498--
499{-# INLINE oneOf #-}
500oneOf :: (Monad m, Eq a) => [a] -> Parser m a a
501oneOf xs = satisfy (`elem` xs)
503-- | See performance notes in 'oneOf'.
504--
505-- >>> noneOf xs = Parser.satisfy (`notElem` xs)
506--
507{-# INLINE noneOf #-}
508noneOf :: (Monad m, Eq a) => [a] -> Parser m a a
509noneOf xs = satisfy (`notElem` xs)
511-- | Return the next element of the input. Returns 'Nothing'
512-- on end of input. Also known as 'head'.
513--
514-- /Pre-release/
515--
516{-# DEPRECATED next "Please use \"fromFold Fold.one\" instead" #-}
517{-# INLINE next #-}
518next :: Monad m => Parser m a (Maybe a)
519next = D.toParserK D.next
521-- | Map a 'Maybe' returning function on the next element in the stream. The
522-- parser fails if the function returns 'Nothing' otherwise returns the 'Just'
523-- value.
524--
525-- >>> toEither = Maybe.maybe (Left "maybe: predicate failed") Right
526-- >>> maybe f = Parser.either (toEither . f)
527--
528-- >>> maybe f = Parser.fromFoldMaybe "maybe: predicate failed" (Fold.maybe f)
529--
530-- /Pre-release/
531--
532{-# INLINE maybe #-}
533maybe :: Monad m => (a -> Maybe b) -> Parser m a b
534maybe = D.toParserK . D.maybe
536-- | Map an 'Either' returning function on the next element in the stream. If
537-- the function returns 'Left err', the parser fails with the error message
538-- @err@ otherwise returns the 'Right' value.
539--
540-- /Pre-release/
541--
542{-# INLINE either #-}
543either :: Monad m => (a -> Either String b) -> Parser m a b
544either = D.toParserK . D.either
546-------------------------------------------------------------------------------
547-- Taking elements
548-------------------------------------------------------------------------------
550-- | @takeBetween m n@ takes a minimum of @m@ and a maximum of @n@ input
551-- elements and folds them using the supplied fold.
552--
553-- Stops after @n@ elements.
554-- Fails if the stream ends before @m@ elements could be taken.
555--
556-- Examples: -
557--
558-- @
559-- >>> :{
560-- takeBetween' low high ls = Stream.parse prsr (Stream.fromList ls)
561-- where prsr = Parser.takeBetween low high Fold.toList
562-- :}
563--
564-- @
565--
566-- >>> takeBetween' 2 4 [1, 2, 3, 4, 5]
567-- [1,2,3,4]
568--
569-- >>> takeBetween' 2 4 [1, 2]
570-- [1,2]
571--
572-- >>> takeBetween' 2 4 [1]
573-- *** Exception: ParseError "takeBetween: Expecting alteast 2 elements, got 1"
574--
575-- >>> takeBetween' 0 0 [1, 2]
576-- []
577--
578-- >>> takeBetween' 0 1 []
579-- []
580--
581-- @takeBetween@ is the most general take operation, other take operations can
582-- be defined in terms of takeBetween. For example:
583--
584-- >>> take n = Parser.takeBetween 0 n
585-- >>> takeEQ n = Parser.takeBetween n n
586-- >>> takeGE n = Parser.takeBetween n maxBound
587--
588-- /Pre-release/
589--
590{-# INLINE takeBetween #-}
591takeBetween :: Monad m =>
592 Int -> Int -> Fold m a b -> Parser m a b
593takeBetween m n = D.toParserK . D.takeBetween m n
595-- | Stops after taking exactly @n@ input elements.
596--
597-- * Stops - after consuming @n@ elements.
598-- * Fails - if the stream or the collecting fold ends before it can collect
599-- exactly @n@ elements.
600--
601-- >>> Stream.parse (Parser.takeEQ 4 Fold.toList) $ Stream.fromList [1,0,1]
602-- *** Exception: ParseError "takeEQ: Expecting exactly 4 elements, input terminated on 3"
603--
604-- /Pre-release/
605--
606{-# INLINE takeEQ #-}
607takeEQ :: Monad m => Int -> Fold m a b -> Parser m a b
608takeEQ n = D.toParserK . D.takeEQ n
610-- | Take at least @n@ input elements, but can collect more.
611--
612-- * Stops - when the collecting fold stops.
613-- * Fails - if the stream or the collecting fold ends before producing @n@
614-- elements.
615--
616-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1]
617-- *** Exception: ParseError "takeGE: Expecting at least 4 elements, input terminated on 3"
618--
619-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1,0,1]
620-- [1,0,1,0,1]
621--
622-- /Pre-release/
623--
624{-# INLINE takeGE #-}
625takeGE :: Monad m => Int -> Fold m a b -> Parser m a b
626takeGE n = D.toParserK . D.takeGE n
628-------------------------------------------------------------------------------
629-- Take until a condition
630-------------------------------------------------------------------------------
632-- $takeWhile
633-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
635-- XXX We should perhaps use only takeWhileP and rename it to takeWhile.
636--
637-- | Like 'takeWhile' but uses a 'Parser' instead of a 'Fold' to collect the
638-- input. The combinator stops when the condition fails or if the collecting
639-- parser stops.
640--
641-- Other interesting parsers can be implemented in terms of this parser:
642--
643-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
644-- >>> takeWhileBetween cond m n p = Parser.takeWhileP cond (Parser.takeBetween m n p)
645--
646-- Stops: when the condition fails or the collecting parser stops.
647-- Fails: when the collecting parser fails.
648--
649-- /Pre-release/
650--
651{-# INLINE takeWhileP #-}
652takeWhileP :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
653takeWhileP cond p = D.toParserK $ D.takeWhileP cond (D.fromParserK p)
655-- | Collect stream elements until an element fails the predicate. The element
656-- on which the predicate fails is returned back to the input stream.
657--
658-- * Stops - when the predicate fails or the collecting fold stops.
659-- * Fails - never.
660--
661-- >>> Stream.parse (Parser.takeWhile (== 0) Fold.toList) $ Stream.fromList [0,0,1,0,1]
662-- [0,0]
663--
664-- >>> takeWhile cond f = Parser.takeWhileP cond (Parser.fromFold f)
665--
666-- We can implement a @breakOn@ using 'takeWhile':
667--
668-- @
669-- breakOn p = takeWhile (not p)
670-- @
671--
672-- /Pre-release/
673--
674{-# INLINE takeWhile #-}
675takeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
676takeWhile cond = D.toParserK . D.takeWhile cond
677-- takeWhile cond f = takeWhileP cond (fromFold f)
679-- | Like 'takeWhile' but takes at least one element otherwise fails.
680--
681-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
682--
683-- /Pre-release/
684--
685{-# INLINE takeWhile1 #-}
686takeWhile1 :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
687takeWhile1 cond = D.toParserK . D.takeWhile1 cond
688-- takeWhile1 cond f = takeWhileP cond (takeBetween 1 maxBound f)
690-- | Drain the input as long as the predicate succeeds, running the effects and
691-- discarding the results.
692--
693-- This is also called @skipWhile@ in some parsing libraries.
694--
695-- >>> dropWhile p = Parser.takeWhile p Fold.drain
696--
697-- /Pre-release/
698--
699{-# INLINE dropWhile #-}
700dropWhile :: Monad m => (a -> Bool) -> Parser m a ()
701dropWhile p = takeWhile p FL.drain
703-------------------------------------------------------------------------------
704-- Separators
705-------------------------------------------------------------------------------
707-- XXX We can remove Maybe from esc
708{-# INLINE takeFramedByGeneric #-}
709takeFramedByGeneric :: Monad m =>
710 Maybe (a -> Bool)
711 -> Maybe (a -> Bool)
712 -> Maybe (a -> Bool)
713 -> Fold m a b
714 -> Parser m a b
715takeFramedByGeneric esc begin end f =
716 D.toParserK $ D.takeFramedByGeneric esc begin end f
718-- | @takeEndBy cond parser@ parses a token that ends by a separator chosen by
719-- the supplied predicate. The separator is also taken with the token.
720--
721-- This can be combined with other parsers to implement other interesting
722-- parsers as follows:
723--
724-- >>> takeEndByLE cond n p = Parser.takeEndBy cond (Parser.fromFold $ Fold.take n p)
725-- >>> takeEndByBetween cond m n p = Parser.takeEndBy cond (Parser.takeBetween m n p)
726--
727-- >>> takeEndBy = Parser.takeEndByEsc (const False)
728--
729-- See also "Streamly.Data.Fold.takeEndBy". Unlike the fold, the collecting
730-- parser in the takeEndBy parser can decide whether to fail or not if the
731-- stream does not end with separator.
732--
733-- /Pre-release/
734--
735{-# INLINE takeEndBy #-}
736takeEndBy :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
737takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
738-- takeEndBy = takeEndByEsc (const False)
740-- | Like 'takeEndBy' but the separator is dropped.
741--
742-- See also "Streamly.Data.Fold.takeEndBy_".
743--
744-- /Pre-release/
745--
746{-# INLINE takeEndBy_ #-}
747takeEndBy_ :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
748takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
749{-
750takeEndBy_ isEnd p =
751 takeFramedByGeneric Nothing Nothing (Just isEnd) (toFold p)
752-}
754-- | Take either the separator or the token. Separator is a Left value and
755-- token is Right value.
756--
757-- /Unimplemented/
758{-# INLINE takeEitherSepBy #-}
759takeEitherSepBy :: -- Monad m =>
760 (a -> Bool) -> Fold m (Either a b) c -> Parser m a c
761takeEitherSepBy _cond = undefined -- D.toParserK . D.takeEitherSepBy cond
763-- | Parse a token that starts with an element chosen by the predicate. The
764-- parser fails if the input does not start with the selected element.
765--
766-- * Stops - when the predicate succeeds in non-leading position.
767-- * Fails - when the predicate fails in the leading position.
768--
769-- >>> splitWithPrefix p f = Stream.parseMany (Parser.takeStartBy p f)
770--
771-- Examples: -
772--
773-- >>> p = Parser.takeStartBy (== ',') Fold.toList
774-- >>> leadingComma = Stream.parse p . Stream.fromList
775-- >>> leadingComma "a,b"
776-- *** Exception: ParseError "takeStartBy: missing frame start"
777-- ...
778-- >>> leadingComma ",,"
779-- ","
780-- >>> leadingComma ",a,b"
781-- ",a"
782-- >>> leadingComma ""
783-- ""
784--
785-- /Pre-release/
786--
787{-# INLINE takeStartBy #-}
788takeStartBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
789takeStartBy cond = D.toParserK . D.takeStartBy cond
791-- | Like 'takeStartBy' but drops the separator.
792--
793-- >>> takeStartBy_ isBegin = Parser.takeFramedByGeneric Nothing (Just isBegin) Nothing
794--
795{-# INLINE takeStartBy_ #-}
796takeStartBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
797takeStartBy_ isBegin = takeFramedByGeneric Nothing (Just isBegin) Nothing
799-------------------------------------------------------------------------------
800-- Quoting and Escaping
801-------------------------------------------------------------------------------
803-- | Like 'takeEndBy' but the separator elements can be escaped using an
804-- escape char determined by the first predicate. The escape characters are
805-- removed.
806--
807-- /pre-release/
808{-# INLINE takeEndByEsc #-}
809takeEndByEsc :: Monad m =>
810 (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
811takeEndByEsc isEsc isEnd p =
812 D.toParserK $ D.takeEndByEsc isEsc isEnd (D.fromParserK p)
814-- | @takeFramedByEsc_ isEsc isBegin isEnd fold@ parses a token framed using a
815-- begin and end predicate, and an escape character. The frame begin and end
816-- characters lose their special meaning if preceded by the escape character.
817--
818-- Nested frames are allowed if begin and end markers are different, nested
819-- frames must be balanced unless escaped, nested frame markers are emitted as
820-- it is.
821--
822-- For example,
823--
824-- >>> p = Parser.takeFramedByEsc_ (== '\\') (== '{') (== '}') Fold.toList
825-- >>> Stream.parse p $ Stream.fromList "{hello}"
826-- "hello"
827-- >>> Stream.parse p $ Stream.fromList "{hello {world}}"
828-- "hello {world}"
829-- >>> Stream.parse p $ Stream.fromList "{hello \\{world}"
830-- "hello {world"
831-- >>> Stream.parse p $ Stream.fromList "{hello {world}"
832-- *** Exception: ParseError "takeFramedByEsc_: missing frame end"
833--
834-- /Pre-release/
835{-# INLINE takeFramedByEsc_ #-}
836takeFramedByEsc_ :: Monad m =>
837 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
838takeFramedByEsc_ isEsc isBegin isEnd f =
839 D.toParserK $ D.takeFramedByEsc_ isEsc isBegin isEnd f
840-- takeEndByEsc_ isEsc isEnd p =
841-- takeFramedByGeneric (Just isEsc) Nothing (Just isEnd) (toFold p)
843-- | @takeFramedBy_ isBegin isEnd fold@ parses a token framed by a begin and an
844-- end predicate.
845--
846-- >>> takeFramedBy_ = Parser.takeFramedByEsc_ (const False)
847--
848{-# INLINE takeFramedBy_ #-}
849takeFramedBy_ :: Monad m =>
850 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
851takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
852-- takeFramedBy_ isBegin isEnd =
853-- takeFramedByGeneric (Just (const False)) (Just isBegin) (Just isEnd)
855-------------------------------------------------------------------------------
856-- Grouping and words
857-------------------------------------------------------------------------------
859-- Note we can also get words using something like:
860-- sepBy FL.toList (takeWhile (not . p) Fold.toList) (dropWhile p)
861--
862-- But that won't be as efficient and ergonomic.
863--
864-- | Like 'splitOn' but strips leading, trailing, and repeated separators.
865-- Therefore, @".a..b."@ having '.' as the separator would be parsed as
866-- @["a","b"]@. In other words, its like parsing words from whitespace
867-- separated text.
868--
869-- * Stops - when it finds a word separator after a non-word element
870-- * Fails - never.
871--
872-- >>> wordBy = Parser.wordFramedBy (const False) (const False) (const False)
873--
874-- @
875-- S.wordsBy pred f = S.parseMany (PR.wordBy pred f)
876-- @
877--
878{-# INLINE wordBy #-}
879wordBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
880wordBy f = D.toParserK . D.wordBy f
882-- | Like 'wordBy' but treats anything inside a pair of quotes as a single
883-- word, the quotes can be escaped by an escape character. Recursive quotes
884-- are possible if quote begin and end characters are different, quotes must be
885-- balanced. Outermost quotes are stripped.
886--
887-- >>> braces = Parser.wordFramedBy (== '\\') (== '{') (== '}') isSpace Fold.toList
888-- >>> Stream.parse braces $ Stream.fromList "{ab} cd"
889-- "ab"
890-- >>> Stream.parse braces $ Stream.fromList "{ab}{cd}"
891-- "abcd"
892-- >>> Stream.parse braces $ Stream.fromList "a{b} cd"
893-- "ab"
894-- >>> Stream.parse braces $ Stream.fromList "a{{b}} cd"
895-- "a{b}"
896--
897-- >>> quotes = Parser.wordFramedBy (== '\\') (== '"') (== '"') isSpace Fold.toList
898-- >>> Stream.parse quotes $ Stream.fromList "\"a\"\"b\""
899-- "ab"
900--
901-- /Pre-release/
902{-# INLINE wordFramedBy #-}
903wordFramedBy :: Monad m =>
904 (a -> Bool) -- ^ Escape
905 -> (a -> Bool) -- ^ left quote
906 -> (a -> Bool) -- ^ right quote
907 -> (a -> Bool) -- ^ word seperator
908 -> Fold m a b
909 -> Parser m a b
910wordFramedBy isEsc isBegin isEnd isSpc =
911 D.toParserK . D.wordFramedBy isEsc isBegin isEnd isSpc
913-- | Like 'wordFramedBy' but the closing quote is determined by the opening
914-- quote. The first quote begin starts a quote that is closed by its
915-- corresponding closing quote.
916--
917-- 'wordFramedBy' and 'wordQuotedBy' both allow multiple quote characters based
918-- on the predicates but 'wordQuotedBy' always fixes the quote at the first
919-- occurrence and then it is closed only by the corresponding closing quote.
920-- Therefore, other quoting characters can be embedded inside it as normal
921-- characters. On the other hand, 'wordFramedBy' would close the quote as soon
922-- as it encounters any of the closing quotes.
923--
924-- >>> q = (`elem` ['"', '\''])
925-- >>> p kQ = Parser.wordQuotedBy kQ (== '\\') q q id isSpace Fold.toList
926--
927-- >>> Stream.parse (p False) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
928-- "ab'c;d\"ef"
929--
930-- >>> Stream.parse (p True) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
931-- "a\"b'c\";'d\"e'f"
932--
933{-# INLINE wordQuotedBy #-}
934wordQuotedBy :: (Monad m, Eq a) =>
935 Bool -- ^ keep the quotes in the output
936 -> (a -> Bool) -- ^ Escape
937 -> (a -> Bool) -- ^ left quote
938 -> (a -> Bool) -- ^ right quote
939 -> (a -> a) -- ^ get right quote from left quote
940 -> (a -> Bool) -- ^ word seperator
941 -> Fold m a b
942 -> Parser m a b
943wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc =
944 D.toParserK . D.wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc
946-- | Given an input stream @[a,b,c,...]@ and a comparison function @cmp@, the
947-- parser assigns the element @a@ to the first group, then if @a \`cmp` b@ is
948-- 'True' @b@ is also assigned to the same group. If @a \`cmp` c@ is 'True'
949-- then @c@ is also assigned to the same group and so on. When the comparison
950-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
951-- the result of the fold is the result of the parser.
952--
953-- * Stops - when the comparison fails.
954-- * Fails - never.
955--
956-- >>> :{
957-- runGroupsBy eq =
958-- Stream.fold Fold.toList
959-- . Stream.parseMany (Parser.groupBy eq Fold.toList)
960-- . Stream.fromList
961-- :}
962--
963-- >>> runGroupsBy (<) []
964-- []
965--
966-- >>> runGroupsBy (<) [1]
967-- [[1]]
968--
969-- >>> runGroupsBy (<) [3, 5, 4, 1, 2, 0]
970-- [[3,5,4],[1,2],[0]]
971--
972-- /Pre-release/
973--
974{-# INLINE groupBy #-}
975groupBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser m a b
976groupBy eq = D.toParserK . D.groupBy eq
978-- | Unlike 'groupBy' this combinator performs a rolling comparison of two
979-- successive elements in the input stream. Assuming the input stream
980-- is @[a,b,c,...]@ and the comparison function is @cmp@, the parser
981-- first assigns the element @a@ to the first group, then if @a \`cmp` b@ is
982-- 'True' @b@ is also assigned to the same group. If @b \`cmp` c@ is 'True'
983-- then @c@ is also assigned to the same group and so on. When the comparison
984-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
985-- the result of the fold is the result of the parser.
986--
987-- * Stops - when the comparison fails.
988-- * Fails - never.
989--
990-- >>> :{
991-- runGroupsByRolling eq =
992-- Stream.fold Fold.toList
993-- . Stream.parseMany (Parser.groupByRolling eq Fold.toList)
994-- . Stream.fromList
995-- :}
996--
997-- >>> runGroupsByRolling (<) []
998-- []
999--
1000-- >>> runGroupsByRolling (<) [1]
1001-- [[1]]
1003-- >>> runGroupsByRolling (<) [3, 5, 4, 1, 2, 0]
1004-- [[3,5],[4],[1,2],[0]]
1006-- /Pre-release/
1008{-# INLINE groupByRolling #-}
1009groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser m a b
1010groupByRolling eq = D.toParserK . D.groupByRolling eq
1012-- | Like 'groupByRolling', but if the predicate is 'True' then collects using
1013-- the first fold as long as the predicate holds 'True', if the predicate is
1014-- 'False' collects using the second fold as long as it remains 'False'.
1015-- Returns 'Left' for the first case and 'Right' for the second case.
1017-- For example, if we want to detect sorted sequences in a stream, both
1018-- ascending and descending cases we can use 'groupByRollingEither (<=)
1019-- Fold.toList Fold.toList'.
1021-- /Pre-release/
1022{-# INLINE groupByRollingEither #-}
1023groupByRollingEither :: Monad m =>
1024 (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser m a (Either b c)
1025groupByRollingEither eq f1 = D.toParserK . D.groupByRollingEither eq f1
1027-- | Match the given sequence of elements using the given comparison function.
1028-- Returns the original sequence if successful.
1030-- >>> Stream.parse (Parser.listEqBy (==) "string") $ Stream.fromList "string"
1031-- "string"
1033-- >>> Stream.parse (Parser.listEqBy (==) "mismatch") $ Stream.fromList "match"
1034-- *** Exception: ParseError "listEqBy: failed, yet to match 7 elements"
1036-- /Pre-release/
1038{-# INLINE listEqBy #-}
1039listEqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser m a [a]
1040listEqBy cmp xs = D.toParserK (D.listEqBy cmp xs)
1042-- | Like 'listEqBy' but uses a stream instead of a list and does not return
1043-- the stream.
1045-- /Pre-release/
1046{-# INLINE eqBy #-}
1047eqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Parser m a ()
1048eqBy cmp = D.toParserK . D.eqBy cmp . Stream.toStreamD
1050-- | Match the input sequence with the supplied list and return it if
1051-- successful.
1053-- >>> listEq = Parser.listEqBy (==)
1055-- /Pre-release/
1056{-# INLINE listEq #-}
1057listEq :: (Monad m, Eq a) => [a] -> Parser m a [a]
1058listEq = listEqBy (==)
1060-------------------------------------------------------------------------------
1061-- nested parsers
1062-------------------------------------------------------------------------------
1064-- | Sequential parser application. Apply two parsers sequentially to an input
1065-- stream. The input is provided to the first parser, when it is done the
1066-- remaining input is provided to the second parser. If both the parsers
1067-- succeed their outputs are combined using the supplied function. The
1068-- operation fails if any of the parsers fail.
1070-- Note: This is a parsing dual of appending streams using
1071-- 'Streamly.Prelude.serial', it splits the streams using two parsers and zips
1072-- the results.
1074-- This implementation is strict in the second argument, therefore, the
1075-- following will fail:
1077-- >>> Stream.parse (Parser.serialWith const (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1078-- *** Exception: Prelude.undefined
1079-- ...
1081-- Compare with 'Applicative' instance method '<*>'. This implementation allows
1082-- stream fusion but has quadratic complexity. This can fuse with other
1083-- operations and can be faster than 'Applicative' instance for small number
1084-- (less than 8) of compositions.
1086-- Many combinators can be expressed using @serialWith@ and other parser
1087-- primitives. Some common idioms are described below,
1089-- @
1090-- span :: (a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1091-- span pred f1 f2 = serialWith (,) ('takeWhile' pred f1) ('fromFold' f2)
1092-- @
1094-- @
1095-- spanBy :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1096-- spanBy eq f1 f2 = serialWith (,) ('groupBy' eq f1) ('fromFold' f2)
1097-- @
1099-- @
1100-- spanByRolling :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1101-- spanByRolling eq f1 f2 = serialWith (,) ('groupByRolling' eq f1) ('fromFold' f2)
1102-- @
1104-- /Pre-release/
1106{-# INLINE serialWith #-}
1107serialWith :: Monad m
1108 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1109serialWith f p1 p2 =
1110 D.toParserK $ D.serialWith f (D.fromParserK p1) (D.fromParserK p2)
1112-- | Sequential parser application ignoring the output of the first parser.
1113-- Apply two parsers sequentially to an input stream. The input is provided to
1114-- the first parser, when it is done the remaining input is provided to the
1115-- second parser. The output of the parser is the output of the second parser.
1116-- The operation fails if any of the parsers fail.
1118-- This implementation is strict in the second argument, therefore, the
1119-- following will fail:
1121-- >>> Stream.parse (Parser.split_ (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1122-- *** Exception: Prelude.undefined
1123-- ...
1125-- Compare with 'Applicative' instance method '*>'. This implementation allows
1126-- stream fusion but has quadratic complexity. This can fuse with other
1127-- operations, and can be faster than 'Applicative' instance for small
1128-- number (less than 8) of compositions.
1130-- /Pre-release/
1132{-# INLINE split_ #-}
1133split_ :: Monad m => Parser m x a -> Parser m x b -> Parser m x b
1134split_ p1 p2 = D.toParserK $ D.split_ (D.fromParserK p1) (D.fromParserK p2)
1137-- | @teeWith f p1 p2@ distributes its input to both @p1@ and @p2@ until both
1138-- of them succeed or anyone of them fails and combines their output using @f@.
1139-- The parser succeeds if both the parsers succeed.
1141-- /Pre-release/
1143{-# INLINE teeWith #-}
1144teeWith :: Monad m
1145 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1146teeWith f p1 p2 =
1147 D.toParserK $ D.teeWith f (D.fromParserK p1) (D.fromParserK p2)
1149-- | Like 'teeWith' but ends parsing and zips the results, if available,
1150-- whenever the first parser ends.
1152-- /Pre-release/
1154{-# INLINE teeWithFst #-}
1155teeWithFst :: Monad m
1156 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1157teeWithFst f p1 p2 =
1158 D.toParserK $ D.teeWithFst f (D.fromParserK p1) (D.fromParserK p2)
1160-- | Like 'teeWith' but ends parsing and zips the results, if available,
1161-- whenever any of the parsers ends or fails.
1163-- /Unimplemented/
1165{-# INLINE teeWithMin #-}
1166teeWithMin :: Monad m
1167 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1168teeWithMin f p1 p2 =
1169 D.toParserK $ D.teeWithMin f (D.fromParserK p1) (D.fromParserK p2)
1172-- | Sequential alternative. Apply the input to the first parser and return the
1173-- result if the parser succeeds. If the first parser fails then backtrack and
1174-- apply the same input to the second parser and return the result.
1176-- Note: This implementation is not lazy in the second argument. The following
1177-- will fail:
1179-- >>> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
1180-- 1
1182-- Compare with 'Alternative' instance method '<|>'. This implementation allows
1183-- stream fusion but has quadratic complexity. This can fuse with other
1184-- operations and can be much faster than 'Alternative' instance for small
1185-- number (less than 8) of alternatives.
1187-- /Pre-release/
1189{-# INLINE alt #-}
1190alt :: Monad m => Parser m x a -> Parser m x a -> Parser m x a
1191alt p1 p2 = D.toParserK $ D.alt (D.fromParserK p1) (D.fromParserK p2)
1194-- | Shortest alternative. Apply both parsers in parallel but choose the result
1195-- from the one which consumed least input i.e. take the shortest succeeding
1196-- parse.
1198-- /Pre-release/
1200{-# INLINE shortest #-}
1201shortest :: Monad m
1202 => Parser m x a -> Parser m x a -> Parser m x a
1203shortest p1 p2 = D.toParserK $ D.shortest (D.fromParserK p1) (D.fromParserK p2)
1205-- | Longest alternative. Apply both parsers in parallel but choose the result
1206-- from the one which consumed more input i.e. take the longest succeeding
1207-- parse.
1209-- /Pre-release/
1211{-# INLINE longest #-}
1212longest :: Monad m
1213 => Parser m x a -> Parser m x a -> Parser m x a
1214longest p1 p2 = D.toParserK $ D.longest (D.fromParserK p1) (D.fromParserK p2)
1217-- | Run a parser without consuming the input.
1219-- /Pre-release/
1221{-# INLINE lookAhead #-}
1222lookAhead :: Monad m => Parser m a b -> Parser m a b
1223lookAhead p = D.toParserK $ D.lookAhead $ D.fromParserK p
1225-- | Takes at-most @n@ input elements.
1227-- * Stops - when the collecting parser stops.
1228-- * Fails - when the collecting parser fails.
1230-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 2 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1231-- [1,2]
1233-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 5 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1234-- *** Exception: ParseError "takeEQ: Expecting exactly 5 elements, input terminated on 4"
1236-- /Internal/
1237{-# INLINE takeP #-}
1238takeP :: Monad m => Int -> Parser m a b -> Parser m a b
1239takeP i p = D.toParserK $ D.takeP i $ D.fromParserK p
1241-------------------------------------------------------------------------------
1242-- Sequential Collection
1243-------------------------------------------------------------------------------
1245-- | @concatSequence f p@ collects sequential parses of parsers in a
1246-- serial stream @p@ using the fold @f@. Fails if the input ends or any
1247-- of the parsers fail.
1249-- An even more efficient implementation can use ParserD type Parser in
1250-- the stream.
1252-- /Pre-release/
1254{-# INLINE concatSequence #-}
1255concatSequence ::
1256 Monad m =>
1257 Fold m b c -> Stream m (Parser m a b) -> Parser m a c
1258concatSequence f p =
1259 let sp = fmap D.fromParserK $ Stream.toStreamD p
1260 in D.toParserK $ D.sequence sp f
1262-- | Map a 'Parser' returning function on the result of a 'Parser'.
1264-- Compare with 'Monad' instance method '>>='. This implementation allows
1265-- stream fusion but has quadratic complexity. This can fuse with other
1266-- operations and can be much faster than 'Monad' instance for small number
1267-- (less than 8) of compositions.
1269-- /Pre-release/
1271{-# INLINE concatMap #-}
1272concatMap :: Monad m
1273 => (b -> Parser m a c) -> Parser m a b -> Parser m a c
1274concatMap f p = D.toParserK $ D.concatMap (D.fromParserK . f) (D.fromParserK p)
1277-------------------------------------------------------------------------------
1278-- Alternative Collection
1279-------------------------------------------------------------------------------
1281-- | @choice parsers@ applies the @parsers@ in order and returns the first
1282-- successful parse.
1284-- This is same as 'asum' but more efficient.
1286-- /Broken/
1288{-# INLINE choice #-}
1289choice ::
1290 (Functor t, Foldable t, Monad m) => t (Parser m a b) -> Parser m a b
1291choice ps = D.toParserK $ D.choice $ D.fromParserK <$> ps
1294-------------------------------------------------------------------------------
1295-- Sequential Repetition
1296-------------------------------------------------------------------------------
1298-- | Like 'many' but uses a 'Parser' instead of a 'Fold' to collect the
1299-- results. Parsing stops or fails if the collecting parser stops or fails.
1301-- /Unimplemented/
1303{-# INLINE manyP #-}
1304manyP :: -- Monad m =>
1305 Parser m a b -> Parser m b c -> Parser m a c
1306manyP _p _f = undefined -- D.toParserK $ D.manyP (D.fromParserK p) f
1308-- | Collect zero or more parses. Apply the supplied parser repeatedly on the
1309-- input stream and push the parse results to a downstream fold.
1311-- Stops: when the downstream fold stops or the parser fails.
1312-- Fails: never, produces zero or more results.
1314-- >>> many = Parser.countBetween 0 maxBound
1316-- Compare with 'Control.Applicative.many'.
1318-- /Pre-release/
1320{-# INLINE many #-}
1321many :: Monad m => Parser m a b -> Fold m b c -> Parser m a c
1322many p f = D.toParserK $ D.many (D.fromParserK p) f
1324-- Note: many1 would perhaps be a better name for this and consistent with
1325-- other names like takeWhile1. But we retain the name "some" for
1326-- compatibility.
1328-- | Collect one or more parses. Apply the supplied parser repeatedly on the
1329-- input stream and push the parse results to a downstream fold.
1331-- Stops: when the downstream fold stops or the parser fails.
1332-- Fails: if it stops without producing a single result.
1334-- >>> some p f = Parser.manyP p (Parser.takeGE 1 f)
1335-- >>> some = Parser.countBetween 1 maxBound
1337-- Compare with 'Control.Applicative.some'.
1339-- /Pre-release/
1341{-# INLINE some #-}
1342some :: Monad m => Parser m a b -> Fold m b c -> Parser m a c
1343some p f = D.toParserK $ D.some (D.fromParserK p) f
1344-- some p f = manyP p (takeGE 1 f)
1345-- some = countBetween 1 maxBound
1347-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
1348-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
1349-- the input ends or the parser fails before @m@ results are collected.
1351-- >>> countBetween m n p f = Parser.manyP p (Parser.takeBetween m n f)
1353-- /Unimplemented/
1355{-# INLINE countBetween #-}
1356countBetween :: -- Monad m =>
1357 Int -> Int -> Parser m a b -> Fold m b c -> Parser m a c
1358countBetween _m _n _p = undefined
1359-- countBetween m n p f = manyP p (takeBetween m n f)
1361-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
1362-- the fold @f@. Fails if the input ends or the parser fails before @n@
1363-- results are collected.
1365-- >>> count n = Parser.countBetween n n
1366-- >>> count n p f = Parser.manyP p (Parser.takeEQ n f)
1368-- /Unimplemented/
1370{-# INLINE count #-}
1371count :: -- Monad m =>
1372 Int -> Parser m a b -> Fold m b c -> Parser m a c
1373count n = countBetween n n
1374-- count n p f = manyP p (takeEQ n f)
1376-- | Like 'manyTill' but uses a 'Parser' to collect the results instead of a
1377-- 'Fold'. Parsing stops or fails if the collecting parser stops or fails.
1379-- We can implemnent parsers like the following using 'manyTillP':
1381-- @
1382-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
1383-- @
1385-- /Unimplemented/
1387{-# INLINE manyTillP #-}
1388manyTillP :: -- Monad m =>
1389 Parser m a b -> Parser m a x -> Parser m b c -> Parser m a c
1390manyTillP _p1 _p2 _f = undefined
1391 -- D.toParserK $ D.manyTillP (D.fromParserK p1) (D.fromParserK p2) f
1393-- | @manyTill collect test f@ tries the parser @test@ on the input, if @test@
1394-- fails it backtracks and tries @collect@, after @collect@ succeeds @test@ is
1395-- tried again and so on. The parser stops when @test@ succeeds. The output of
1396-- @test@ is discarded and the output of @collect@ is accumulated by the
1397-- supplied fold. The parser fails if @collect@ fails.
1399-- Stops when the fold @f@ stops.
1401-- /Pre-release/
1403{-# INLINE manyTill #-}
1404manyTill :: Monad m
1405 => Parser m a b -> Parser m a x -> Fold m b c -> Parser m a c
1406manyTill collect test f =
1407 D.toParserK $ D.manyTill (D.fromParserK collect) (D.fromParserK test) f
1409-- | @manyThen f collect recover@ repeats the parser @collect@ on the input and
1410-- collects the output in the supplied fold. If the the parser @collect@ fails,
1411-- parser @recover@ is run until it stops and then we start repeating the
1412-- parser @collect@ again. The parser fails if the recovery parser fails.
1414-- For example, this can be used to find a key frame in a video stream after an
1415-- error.
1417-- /Unimplemented/
1419{-# INLINE manyThen #-}
1420manyThen :: -- (Foldable t, Monad m) =>
1421 Parser m a b -> Parser m a x -> Fold m b c -> Parser m a c
1422manyThen _parser _recover _f = undefined
1424-------------------------------------------------------------------------------
1425-- Interleaving
1426-------------------------------------------------------------------------------
1428-- To deinterleave we can chain two parsers one behind the other. The input is
1429-- given to the first parser and the input definitively rejected by the first
1430-- parser is given to the second parser.
1432-- We can either have the parsers themselves buffer the input or use the shared
1433-- global buffer to hold it until none of the parsers need it. When the first
1434-- parser returns Skip (i.e. rewind) we let the second parser consume the
1435-- rejected input and when it is done we move the cursor forward to the first
1436-- parser again. This will require a "move forward" command as well.
1438-- To implement grep we can use three parsers, one to find the pattern, one
1439-- to store the context behind the pattern and one to store the context in
1440-- front of the pattern. When a match occurs we need to emit the accumulator of
1441-- all the three parsers. One parser can count the line numbers to provide the
1442-- line number info.
1444-- XXX rename this to intercalate
1445-- | Apply two parsers alternately to an input stream. The input stream is
1446-- considered an interleaving of two patterns. The two parsers represent the
1447-- two patterns.
1449-- This undoes a "gintercalate" of two streams.
1451-- /Pre-release/
1453{-# INLINE deintercalate #-}
1454deintercalate :: Monad m =>
1455 Parser m a x
1456 -> Parser m a y
1457 -> Fold m (Either x y) z
1458 -> Parser m a z
1459deintercalate contentL contentR sink =
1460 D.toParserK
1461 $ D.deintercalate
1462 (D.fromParserK contentL) (D.fromParserK contentR) sink
1464-- | Parse items separated by a separator parsed by the supplied parser. At
1465-- least one item must be present for the parser to succeed.
1467-- Note that this can go in infinite loop if both the parsers fail on some
1468-- input. Detection of that would make the implementation more complex.
1470{-# INLINE sepBy1 #-}
1471sepBy1 :: Monad m =>
1472 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1473sepBy1 sink p sep = do
1474 x <- p
1475 f <- fromEffect $ FL.initialize sink
1476 f1 <- fromEffect $ FL.snoc f x
1477 many (sep >> p) f1
1479-- | Run the content parser first, when it is done, the separator parser is
1480-- run, when it is done content parser is run again and so on. If none of the
1481-- parsers consumes an input then parser returns a failure.
1483-- >>> sepBy sink p1 p2 = Parser.deintercalate p1 p2 (Fold.lefts sink)
1484-- >>> sepBy sink content sep = Parser.sepBy1 sink content sep <|> return mempty
1486{-# INLINE sepBy #-}
1487sepBy :: Monad m =>
1488 Parser m a b -> Parser m a x -> Fold m b c -> Parser m a c
1489sepBy content sep sink =
1490 D.toParserK $ D.sepBy (D.fromParserK content) (D.fromParserK sep) sink
1491-- sepBy sink = deintercalate (FL.lefts sink)
1493-------------------------------------------------------------------------------
1494-- Interleaving a collection of parsers
1495-------------------------------------------------------------------------------
1497-- | Apply a collection of parsers to an input stream in a round robin fashion.
1498-- Each parser is applied until it stops and then we repeat starting with the
1499-- the first parser again.
1501-- /Unimplemented/
1503{-# INLINE roundRobin #-}
1504roundRobin :: -- (Foldable t, Monad m) =>
1505 t (Parser m a b) -> Fold m b c -> Parser m a c
1506roundRobin _ps _f = undefined
1508-------------------------------------------------------------------------------
1509-- Repeated Alternatives
1510-------------------------------------------------------------------------------
1512-- | Keep trying a parser up to a maximum of @n@ failures. When the parser
1513-- fails the input consumed till now is dropped and the new instance is tried
1514-- on the fresh input.
1516-- /Unimplemented/
1518{-# INLINE retryMaxTotal #-}
1519retryMaxTotal :: -- (Monad m) =>
1520 Int -> Parser m a b -> Fold m b c -> Parser m a c
1521retryMaxTotal _n _p _f = undefined
1523-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
1525-- /Unimplemented/
1527{-# INLINE retryMaxSuccessive #-}
1528retryMaxSuccessive :: -- (Monad m) =>
1529 Int -> Parser m a b -> Fold m b c -> Parser m a c
1530retryMaxSuccessive _n _p _f = undefined
1532-- | Keep trying a parser until it succeeds. When the parser fails the input
1533-- consumed till now is dropped and the new instance is tried on the fresh
1534-- input.
1536-- /Unimplemented/
1538{-# INLINE retry #-}
1539retry :: -- (Monad m) =>
1540 Parser m a b -> Parser m a b
1541retry _p = undefined