on ba01fcd help sign in
1535 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 , element
80 , except
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 , eqBy
106 , matchBy
107 , list
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 Data.Functor (($>))
252import Prelude hiding
253 ( any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either
254 , filter )
256import Streamly.Internal.Data.Fold.Type (Fold(..))
257import Streamly.Internal.Data.Parser.ParserK.Type (Parser)
258import Streamly.Internal.Data.Stream.Type (Stream)
260import qualified Streamly.Internal.Data.Fold.Type as FL
261import qualified Streamly.Internal.Data.Parser.ParserD as D
262import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
263import qualified Streamly.Internal.Data.Stream.Type as Stream
265--
266-- $setup
267-- >>> :m
268-- >>> :set -package streamly
269-- >>> import Prelude hiding (any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either, filter)
270-- >>> import Control.Applicative ((<|>))
271-- >>> import Data.Char (isSpace)
272-- >>> import qualified Data.Maybe as Maybe
273-- >>> import qualified Streamly.Data.Stream as Stream
274-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse, parseMany)
275-- >>> import qualified Streamly.Internal.Data.Fold as Fold
276-- >>> import qualified Streamly.Internal.Data.Parser as Parser
278-------------------------------------------------------------------------------
279-- Downgrade a parser to a Fold
280-------------------------------------------------------------------------------
281--
282-- | Make a 'Fold' from a 'Parser'. The fold just throws an exception if the
283-- parser fails or tries to backtrack.
284--
285-- This can be useful in combinators that accept a Fold and we know that a
286-- Parser cannot fail or failure exception is acceptable as there is no way to
287-- recover.
288--
289-- /Pre-release/
290--
291{-# INLINE toFold #-}
292toFold :: Monad m => Parser m a b -> Fold m a b
293toFold p = D.toFold $ D.fromParserK p
295-------------------------------------------------------------------------------
296-- Upgrade folds to parses
297-------------------------------------------------------------------------------
298--
299-- | Make a 'Parser' from a 'Fold'.
300--
301-- /Pre-release/
302--
303{-# INLINE fromFold #-}
304fromFold :: Monad m => Fold m a b -> Parser m a b
305fromFold = D.toParserK . D.fromFold
307-- | Convert a Maybe returning fold to an error returning parser. The first
308-- argument is the error message that the parser would return when the fold
309-- returns Nothing.
310--
311-- /Pre-release/
312--
313{-# INLINE fromFoldMaybe #-}
314fromFoldMaybe :: Monad m => String -> Fold m a (Maybe b) -> Parser m a b
315fromFoldMaybe err = D.toParserK . D.fromFoldMaybe err
317-------------------------------------------------------------------------------
318-- Terminating but not failing folds
319-------------------------------------------------------------------------------
320--
321-- This is the dual of stream "fromPure".
322--
323-- | A parser that always yields a pure value without consuming any input.
324--
325-- /Pre-release/
326--
327{-# INLINE [3] fromPure #-}
328fromPure :: Monad m => b -> Parser m a b
329fromPure = D.toParserK . D.fromPure
330{-# RULES "fromPure fallback to CPS" [2]
331 forall a. D.toParserK (D.fromPure a) = K.fromPure a #-}
333-- This is the dual of stream "fromEffect".
334--
335-- | A parser that always yields the result of an effectful action without
336-- consuming any input.
337--
338-- /Pre-release/
339--
340{-# INLINE fromEffect #-}
341fromEffect :: Monad m => m b -> Parser m a b
342fromEffect = K.fromEffect -- D.toParserK . D.fromEffect
344-- This is the dual of "nil".
345--
346-- | A parser that always fails with an error message without consuming
347-- any input.
348--
349-- /Pre-release/
350--
351{-# INLINE [3] die #-}
352die :: Monad m => String -> Parser m a b
353die = D.toParserK . D.die
354{-# RULES "die fallback to CPS" [2]
355 forall a. D.toParserK (D.die a) = K.die a #-}
357-- This is the dual of "nilM".
358--
359-- | A parser that always fails with an effectful error message and without
360-- consuming any input.
361--
362-- /Pre-release/
363--
364{-# INLINE dieM #-}
365dieM :: Monad m => m String -> Parser m a b
366dieM = D.toParserK . D.dieM
368-------------------------------------------------------------------------------
369-- Map on input
370-------------------------------------------------------------------------------
372-- | @lmap f parser@ maps the function @f@ on the input of the parser.
373--
374-- >>> Stream.parse (Parser.lmap (\x -> x * x) (Parser.fromFold Fold.sum)) (Stream.enumerateFromTo 1 100)
375-- 338350
376--
377-- > lmap = Parser.lmapM return
378--
379-- /Internal/
380{-# INLINE lmap #-}
381lmap :: Monad m => (a -> b) -> Parser m b r -> Parser m a r
382lmap f p = D.toParserK $ D.lmap f $ D.fromParserK p
384-- | @lmapM f parser@ maps the monadic function @f@ on the input of the parser.
385--
386-- /Internal/
387{-# INLINE lmapM #-}
388lmapM :: Monad m => (a -> m b) -> Parser m b r -> Parser m a r
389lmapM f p = D.toParserK $ D.lmapM f $ D.fromParserK p
391-- | @rmapM f parser@ maps the monadic function @f@ on the output of the parser.
392--
393-- /Internal/
394{-# INLINE rmapM #-}
395rmapM :: Monad m => (b -> m c) -> Parser m a b -> Parser m a c
396rmapM f p = D.toParserK $ D.rmapM f $ D.fromParserK p
398-- | Include only those elements that pass a predicate.
399--
400-- >>> Stream.parse (Parser.filter (> 5) (Parser.fromFold Fold.sum)) $ Stream.fromList [1..10]
401-- 40
402--
403-- /Internal/
404{-# INLINE filter #-}
405filter :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
406filter f p = D.toParserK $ D.filter f $ D.fromParserK p
408-------------------------------------------------------------------------------
409-- Failing Parsers
410-------------------------------------------------------------------------------
412-- | Peek the head element of a stream, without consuming it. Fails if it
413-- encounters end of input.
414--
415-- >>> Stream.parse ((,) <$> Parser.peek <*> Parser.satisfy (> 0)) $ Stream.fromList [1]
416-- (1,1)
417--
418-- @
419-- peek = lookAhead (satisfy True)
420-- @
421--
422-- /Pre-release/
423--
424{-# INLINE peek #-}
425peek :: Monad m => Parser m a a
426peek = D.toParserK D.peek
428-- | Succeeds if we are at the end of input, fails otherwise.
429--
430-- >>> Stream.parse ((,) <$> Parser.satisfy (> 0) <*> Parser.eof) $ Stream.fromList [1]
431-- (1,())
432--
433-- /Pre-release/
434--
435{-# INLINE eof #-}
436eof :: Monad m => Parser m a ()
437eof = D.toParserK D.eof
439-- | Returns the next element if it passes the predicate, fails otherwise.
440--
441-- >>> Stream.parse (Parser.satisfy (== 1)) $ Stream.fromList [1,0,1]
442-- 1
443--
444-- >>> toMaybe f x = if f x then Just x else Nothing
445-- >>> satisfy f = Parser.maybe (toMaybe f)
446--
447-- /Pre-release/
448--
449{-# INLINE satisfy #-}
450satisfy :: Monad m => (a -> Bool) -> Parser m a a
451satisfy = D.toParserK . D.satisfy
453-- | Consume one element from the head of the stream. Fails if it encounters
454-- end of input.
455--
456-- >>> one = Parser.satisfy $ const True
457--
458-- /Pre-release/
459--
460{-# INLINE one #-}
461one :: Monad m => Parser m a a
462one = satisfy $ const True
464-- | Match a specific element.
465--
466-- >>> element x = Parser.satisfy (== x)
467--
468{-# INLINE element #-}
469element :: (Monad m, Eq a) => a -> Parser m a a
470element x = satisfy (== x)
472-- | Match anything other than the supplied element.
473--
474-- >>> except x = Parser.satisfy (/= x)
475--
476{-# INLINE except #-}
477except :: (Monad m, Eq a) => a -> Parser m a a
478except x = satisfy (/= x)
480-- | Match any one of the elements in the supplied list.
481--
482-- >>> oneOf xs = Parser.satisfy (`elem` xs)
483--
484-- When performance matters a pattern matching predicate could be more
485-- efficient than a list:
486--
487-- @
488-- let p x =
489-- case x of
490-- 'a' -> True
491-- 'e' -> True
492-- _ -> False
493-- in satisfy p
494-- @
495--
496-- GHC may use a binary search instead of linear search in the list.
497-- Alternatively, you can also use an array instead of list for storage and
498-- search.
499--
500{-# INLINE oneOf #-}
501oneOf :: (Monad m, Eq a) => [a] -> Parser m a a
502oneOf xs = satisfy (`elem` xs)
504-- | See performance notes in 'oneOf'.
505--
506-- >>> noneOf xs = Parser.satisfy (`notElem` xs)
507--
508{-# INLINE noneOf #-}
509noneOf :: (Monad m, Eq a) => [a] -> Parser m a a
510noneOf xs = satisfy (`notElem` xs)
512-- | Return the next element of the input. Returns 'Nothing'
513-- on end of input. Also known as 'head'.
514--
515-- /Pre-release/
516--
517{-# DEPRECATED next "Please use \"fromFold Fold.one\" instead" #-}
518{-# INLINE next #-}
519next :: Monad m => Parser m a (Maybe a)
520next = D.toParserK D.next
522-- | Map a 'Maybe' returning function on the next element in the stream. The
523-- parser fails if the function returns 'Nothing' otherwise returns the 'Just'
524-- value.
525--
526-- >>> toEither = Maybe.maybe (Left "maybe: predicate failed") Right
527-- >>> maybe f = Parser.either (toEither . f)
528--
529-- >>> maybe f = Parser.fromFoldMaybe "maybe: predicate failed" (Fold.maybe f)
530--
531-- /Pre-release/
532--
533{-# INLINE maybe #-}
534maybe :: Monad m => (a -> Maybe b) -> Parser m a b
535maybe = D.toParserK . D.maybe
537-- | Map an 'Either' returning function on the next element in the stream. If
538-- the function returns 'Left err', the parser fails with the error message
539-- @err@ otherwise returns the 'Right' value.
540--
541-- /Pre-release/
542--
543{-# INLINE either #-}
544either :: Monad m => (a -> Either String b) -> Parser m a b
545either = D.toParserK . D.either
547-------------------------------------------------------------------------------
548-- Taking elements
549-------------------------------------------------------------------------------
551-- | @takeBetween m n@ takes a minimum of @m@ and a maximum of @n@ input
552-- elements and folds them using the supplied fold.
553--
554-- Stops after @n@ elements.
555-- Fails if the stream ends before @m@ elements could be taken.
556--
557-- Examples: -
558--
559-- @
560-- >>> :{
561-- takeBetween' low high ls = Stream.parse prsr (Stream.fromList ls)
562-- where prsr = Parser.takeBetween low high Fold.toList
563-- :}
564--
565-- @
566--
567-- >>> takeBetween' 2 4 [1, 2, 3, 4, 5]
568-- [1,2,3,4]
569--
570-- >>> takeBetween' 2 4 [1, 2]
571-- [1,2]
572--
573-- >>> takeBetween' 2 4 [1]
574-- *** Exception: ParseError "takeBetween: Expecting alteast 2 elements, got 1"
575--
576-- >>> takeBetween' 0 0 [1, 2]
577-- []
578--
579-- >>> takeBetween' 0 1 []
580-- []
581--
582-- @takeBetween@ is the most general take operation, other take operations can
583-- be defined in terms of takeBetween. For example:
584--
585-- >>> take n = Parser.takeBetween 0 n
586-- >>> takeEQ n = Parser.takeBetween n n
587-- >>> takeGE n = Parser.takeBetween n maxBound
588--
589-- /Pre-release/
590--
591{-# INLINE takeBetween #-}
592takeBetween :: Monad m =>
593 Int -> Int -> Fold m a b -> Parser m a b
594takeBetween m n = D.toParserK . D.takeBetween m n
596-- | Stops after taking exactly @n@ input elements.
597--
598-- * Stops - after consuming @n@ elements.
599-- * Fails - if the stream or the collecting fold ends before it can collect
600-- exactly @n@ elements.
601--
602-- >>> Stream.parse (Parser.takeEQ 4 Fold.toList) $ Stream.fromList [1,0,1]
603-- *** Exception: ParseError "takeEQ: Expecting exactly 4 elements, input terminated on 3"
604--
605-- /Pre-release/
606--
607{-# INLINE takeEQ #-}
608takeEQ :: Monad m => Int -> Fold m a b -> Parser m a b
609takeEQ n = D.toParserK . D.takeEQ n
611-- | Take at least @n@ input elements, but can collect more.
612--
613-- * Stops - when the collecting fold stops.
614-- * Fails - if the stream or the collecting fold ends before producing @n@
615-- elements.
616--
617-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1]
618-- *** Exception: ParseError "takeGE: Expecting at least 4 elements, input terminated on 3"
619--
620-- >>> Stream.parse (Parser.takeGE 4 Fold.toList) $ Stream.fromList [1,0,1,0,1]
621-- [1,0,1,0,1]
622--
623-- /Pre-release/
624--
625{-# INLINE takeGE #-}
626takeGE :: Monad m => Int -> Fold m a b -> Parser m a b
627takeGE n = D.toParserK . D.takeGE n
629-------------------------------------------------------------------------------
630-- Take until a condition
631-------------------------------------------------------------------------------
633-- $takeWhile
634-- Note: This is called @takeWhileP@ and @munch@ in some parser libraries.
636-- XXX We should perhaps use only takeWhileP and rename it to takeWhile.
637--
638-- | Like 'takeWhile' but uses a 'Parser' instead of a 'Fold' to collect the
639-- input. The combinator stops when the condition fails or if the collecting
640-- parser stops.
641--
642-- Other interesting parsers can be implemented in terms of this parser:
643--
644-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
645-- >>> takeWhileBetween cond m n p = Parser.takeWhileP cond (Parser.takeBetween m n p)
646--
647-- Stops: when the condition fails or the collecting parser stops.
648-- Fails: when the collecting parser fails.
649--
650-- /Pre-release/
651--
652{-# INLINE takeWhileP #-}
653takeWhileP :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
654takeWhileP cond p = D.toParserK $ D.takeWhileP cond (D.fromParserK p)
656-- | Collect stream elements until an element fails the predicate. The element
657-- on which the predicate fails is returned back to the input stream.
658--
659-- * Stops - when the predicate fails or the collecting fold stops.
660-- * Fails - never.
661--
662-- >>> Stream.parse (Parser.takeWhile (== 0) Fold.toList) $ Stream.fromList [0,0,1,0,1]
663-- [0,0]
664--
665-- >>> takeWhile cond f = Parser.takeWhileP cond (Parser.fromFold f)
666--
667-- We can implement a @breakOn@ using 'takeWhile':
668--
669-- @
670-- breakOn p = takeWhile (not p)
671-- @
672--
673-- /Pre-release/
674--
675{-# INLINE takeWhile #-}
676takeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
677takeWhile cond = D.toParserK . D.takeWhile cond
678-- takeWhile cond f = takeWhileP cond (fromFold f)
680-- | Like 'takeWhile' but takes at least one element otherwise fails.
681--
682-- >>> takeWhile1 cond p = Parser.takeWhileP cond (Parser.takeBetween 1 maxBound p)
683--
684-- /Pre-release/
685--
686{-# INLINE takeWhile1 #-}
687takeWhile1 :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
688takeWhile1 cond = D.toParserK . D.takeWhile1 cond
689-- takeWhile1 cond f = takeWhileP cond (takeBetween 1 maxBound f)
691-- | Drain the input as long as the predicate succeeds, running the effects and
692-- discarding the results.
693--
694-- This is also called @skipWhile@ in some parsing libraries.
695--
696-- >>> dropWhile p = Parser.takeWhile p Fold.drain
697--
698-- /Pre-release/
699--
700{-# INLINE dropWhile #-}
701dropWhile :: Monad m => (a -> Bool) -> Parser m a ()
702dropWhile p = takeWhile p FL.drain
704-------------------------------------------------------------------------------
705-- Separators
706-------------------------------------------------------------------------------
708-- XXX We can remove Maybe from esc
709{-# INLINE takeFramedByGeneric #-}
710takeFramedByGeneric :: Monad m =>
711 Maybe (a -> Bool)
712 -> Maybe (a -> Bool)
713 -> Maybe (a -> Bool)
714 -> Fold m a b
715 -> Parser m a b
716takeFramedByGeneric esc begin end f =
717 D.toParserK $ D.takeFramedByGeneric esc begin end f
719-- | @takeEndBy cond parser@ parses a token that ends by a separator chosen by
720-- the supplied predicate. The separator is also taken with the token.
721--
722-- This can be combined with other parsers to implement other interesting
723-- parsers as follows:
724--
725-- >>> takeEndByLE cond n p = Parser.takeEndBy cond (Parser.fromFold $ Fold.take n p)
726-- >>> takeEndByBetween cond m n p = Parser.takeEndBy cond (Parser.takeBetween m n p)
727--
728-- >>> takeEndBy = Parser.takeEndByEsc (const False)
729--
730-- See also "Streamly.Data.Fold.takeEndBy". Unlike the fold, the collecting
731-- parser in the takeEndBy parser can decide whether to fail or not if the
732-- stream does not end with separator.
733--
734-- /Pre-release/
735--
736{-# INLINE takeEndBy #-}
737takeEndBy :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
738takeEndBy cond = D.toParserK . D.takeEndBy cond . D.fromParserK
739-- takeEndBy = takeEndByEsc (const False)
741-- | Like 'takeEndBy' but the separator is dropped.
742--
743-- See also "Streamly.Data.Fold.takeEndBy_".
744--
745-- /Pre-release/
746--
747{-# INLINE takeEndBy_ #-}
748takeEndBy_ :: Monad m => (a -> Bool) -> Parser m a b -> Parser m a b
749takeEndBy_ cond = D.toParserK . D.takeEndBy_ cond . D.fromParserK
750{-
751takeEndBy_ isEnd p =
752 takeFramedByGeneric Nothing Nothing (Just isEnd) (toFold p)
753-}
755-- | Take either the separator or the token. Separator is a Left value and
756-- token is Right value.
757--
758-- /Unimplemented/
759{-# INLINE takeEitherSepBy #-}
760takeEitherSepBy :: -- Monad m =>
761 (a -> Bool) -> Fold m (Either a b) c -> Parser m a c
762takeEitherSepBy _cond = undefined -- D.toParserK . D.takeEitherSepBy cond
764-- | Parse a token that starts with an element chosen by the predicate. The
765-- parser fails if the input does not start with the selected element.
766--
767-- * Stops - when the predicate succeeds in non-leading position.
768-- * Fails - when the predicate fails in the leading position.
769--
770-- >>> splitWithPrefix p f = Stream.parseMany (Parser.takeStartBy p f)
771--
772-- Examples: -
773--
774-- >>> p = Parser.takeStartBy (== ',') Fold.toList
775-- >>> leadingComma = Stream.parse p . Stream.fromList
776-- >>> leadingComma "a,b"
777-- *** Exception: ParseError "takeStartBy: missing frame start"
778-- ...
779-- >>> leadingComma ",,"
780-- ","
781-- >>> leadingComma ",a,b"
782-- ",a"
783-- >>> leadingComma ""
784-- ""
785--
786-- /Pre-release/
787--
788{-# INLINE takeStartBy #-}
789takeStartBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
790takeStartBy cond = D.toParserK . D.takeStartBy cond
792-- | Like 'takeStartBy' but drops the separator.
793--
794-- >>> takeStartBy_ isBegin = Parser.takeFramedByGeneric Nothing (Just isBegin) Nothing
795--
796{-# INLINE takeStartBy_ #-}
797takeStartBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
798takeStartBy_ isBegin = takeFramedByGeneric Nothing (Just isBegin) Nothing
800-------------------------------------------------------------------------------
801-- Quoting and Escaping
802-------------------------------------------------------------------------------
804-- | Like 'takeEndBy' but the separator elements can be escaped using an
805-- escape char determined by the first predicate. The escape characters are
806-- removed.
807--
808-- /pre-release/
809{-# INLINE takeEndByEsc #-}
810takeEndByEsc :: Monad m =>
811 (a -> Bool) -> (a -> Bool) -> Parser m a b -> Parser m a b
812takeEndByEsc isEsc isEnd p =
813 D.toParserK $ D.takeEndByEsc isEsc isEnd (D.fromParserK p)
815-- | @takeFramedByEsc_ isEsc isBegin isEnd fold@ parses a token framed using a
816-- begin and end predicate, and an escape character. The frame begin and end
817-- characters lose their special meaning if preceded by the escape character.
818--
819-- Nested frames are allowed if begin and end markers are different, nested
820-- frames must be balanced unless escaped, nested frame markers are emitted as
821-- it is.
822--
823-- For example,
824--
825-- >>> p = Parser.takeFramedByEsc_ (== '\\') (== '{') (== '}') Fold.toList
826-- >>> Stream.parse p $ Stream.fromList "{hello}"
827-- "hello"
828-- >>> Stream.parse p $ Stream.fromList "{hello {world}}"
829-- "hello {world}"
830-- >>> Stream.parse p $ Stream.fromList "{hello \\{world}"
831-- "hello {world"
832-- >>> Stream.parse p $ Stream.fromList "{hello {world}"
833-- *** Exception: ParseError "takeFramedByEsc_: missing frame end"
834--
835-- /Pre-release/
836{-# INLINE takeFramedByEsc_ #-}
837takeFramedByEsc_ :: Monad m =>
838 (a -> Bool) -> (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
839takeFramedByEsc_ isEsc isBegin isEnd f =
840 D.toParserK $ D.takeFramedByEsc_ isEsc isBegin isEnd f
841-- takeEndByEsc_ isEsc isEnd p =
842-- takeFramedByGeneric (Just isEsc) Nothing (Just isEnd) (toFold p)
844-- | @takeFramedBy_ isBegin isEnd fold@ parses a token framed by a begin and an
845-- end predicate.
846--
847-- >>> takeFramedBy_ = Parser.takeFramedByEsc_ (const False)
848--
849{-# INLINE takeFramedBy_ #-}
850takeFramedBy_ :: Monad m =>
851 (a -> Bool) -> (a -> Bool) -> Fold m a b -> Parser m a b
852takeFramedBy_ isBegin isEnd f = D.toParserK $ D.takeFramedBy_ isBegin isEnd f
853-- takeFramedBy_ isBegin isEnd =
854-- takeFramedByGeneric (Just (const False)) (Just isBegin) (Just isEnd)
856-------------------------------------------------------------------------------
857-- Grouping and words
858-------------------------------------------------------------------------------
860-- Note we can also get words using something like:
861-- sepBy FL.toList (takeWhile (not . p) Fold.toList) (dropWhile p)
862--
863-- But that won't be as efficient and ergonomic.
864--
865-- | Like 'splitOn' but strips leading, trailing, and repeated separators.
866-- Therefore, @".a..b."@ having '.' as the separator would be parsed as
867-- @["a","b"]@. In other words, its like parsing words from whitespace
868-- separated text.
869--
870-- * Stops - when it finds a word separator after a non-word element
871-- * Fails - never.
872--
873-- >>> wordBy = Parser.wordFramedBy (const False) (const False) (const False)
874--
875-- @
876-- S.wordsBy pred f = S.parseMany (PR.wordBy pred f)
877-- @
878--
879{-# INLINE wordBy #-}
880wordBy :: Monad m => (a -> Bool) -> Fold m a b -> Parser m a b
881wordBy f = D.toParserK . D.wordBy f
883-- | Like 'wordBy' but treats anything inside a pair of quotes as a single
884-- word, the quotes can be escaped by an escape character. Recursive quotes
885-- are possible if quote begin and end characters are different, quotes must be
886-- balanced. Outermost quotes are stripped.
887--
888-- >>> braces = Parser.wordFramedBy (== '\\') (== '{') (== '}') isSpace Fold.toList
889-- >>> Stream.parse braces $ Stream.fromList "{ab} cd"
890-- "ab"
891-- >>> Stream.parse braces $ Stream.fromList "{ab}{cd}"
892-- "abcd"
893-- >>> Stream.parse braces $ Stream.fromList "a{b} cd"
894-- "ab"
895-- >>> Stream.parse braces $ Stream.fromList "a{{b}} cd"
896-- "a{b}"
897--
898-- >>> quotes = Parser.wordFramedBy (== '\\') (== '"') (== '"') isSpace Fold.toList
899-- >>> Stream.parse quotes $ Stream.fromList "\"a\"\"b\""
900-- "ab"
901--
902-- /Pre-release/
903{-# INLINE wordFramedBy #-}
904wordFramedBy :: Monad m =>
905 (a -> Bool) -- ^ Escape
906 -> (a -> Bool) -- ^ left quote
907 -> (a -> Bool) -- ^ right quote
908 -> (a -> Bool) -- ^ word seperator
909 -> Fold m a b
910 -> Parser m a b
911wordFramedBy isEsc isBegin isEnd isSpc =
912 D.toParserK . D.wordFramedBy isEsc isBegin isEnd isSpc
914-- | Like 'wordFramedBy' but the closing quote is determined by the opening
915-- quote. The first quote begin starts a quote that is closed by its
916-- corresponding closing quote.
917--
918-- 'wordFramedBy' and 'wordQuotedBy' both allow multiple quote characters based
919-- on the predicates but 'wordQuotedBy' always fixes the quote at the first
920-- occurrence and then it is closed only by the corresponding closing quote.
921-- Therefore, other quoting characters can be embedded inside it as normal
922-- characters. On the other hand, 'wordFramedBy' would close the quote as soon
923-- as it encounters any of the closing quotes.
924--
925-- >>> q = (`elem` ['"', '\''])
926-- >>> p kQ = Parser.wordQuotedBy kQ (== '\\') q q id isSpace Fold.toList
927--
928-- >>> Stream.parse (p False) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
929-- "ab'c;d\"ef"
930--
931-- >>> Stream.parse (p True) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
932-- "a\"b'c\";'d\"e'f"
933--
934{-# INLINE wordQuotedBy #-}
935wordQuotedBy :: (Monad m, Eq a) =>
936 Bool -- ^ keep the quotes in the output
937 -> (a -> Bool) -- ^ Escape
938 -> (a -> Bool) -- ^ left quote
939 -> (a -> Bool) -- ^ right quote
940 -> (a -> a) -- ^ get right quote from left quote
941 -> (a -> Bool) -- ^ word seperator
942 -> Fold m a b
943 -> Parser m a b
944wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc =
945 D.toParserK . D.wordQuotedBy keepQuotes isEsc isBegin isEnd toRight isSpc
947-- | Given an input stream @[a,b,c,...]@ and a comparison function @cmp@, the
948-- parser assigns the element @a@ to the first group, then if @a \`cmp` b@ is
949-- 'True' @b@ is also assigned to the same group. If @a \`cmp` c@ is 'True'
950-- then @c@ is also assigned to the same group and so on. When the comparison
951-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
952-- the result of the fold is the result of the parser.
953--
954-- * Stops - when the comparison fails.
955-- * Fails - never.
956--
957-- >>> :{
958-- runGroupsBy eq =
959-- Stream.fold Fold.toList
960-- . Stream.parseMany (Parser.groupBy eq Fold.toList)
961-- . Stream.fromList
962-- :}
963--
964-- >>> runGroupsBy (<) []
965-- []
966--
967-- >>> runGroupsBy (<) [1]
968-- [[1]]
969--
970-- >>> runGroupsBy (<) [3, 5, 4, 1, 2, 0]
971-- [[3,5,4],[1,2],[0]]
972--
973-- /Pre-release/
974--
975{-# INLINE groupBy #-}
976groupBy :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser m a b
977groupBy eq = D.toParserK . D.groupBy eq
979-- | Unlike 'groupBy' this combinator performs a rolling comparison of two
980-- successive elements in the input stream. Assuming the input stream
981-- is @[a,b,c,...]@ and the comparison function is @cmp@, the parser
982-- first assigns the element @a@ to the first group, then if @a \`cmp` b@ is
983-- 'True' @b@ is also assigned to the same group. If @b \`cmp` c@ is 'True'
984-- then @c@ is also assigned to the same group and so on. When the comparison
985-- fails the parser is terminated. Each group is folded using the 'Fold' @f@ and
986-- the result of the fold is the result of the parser.
987--
988-- * Stops - when the comparison fails.
989-- * Fails - never.
990--
991-- >>> :{
992-- runGroupsByRolling eq =
993-- Stream.fold Fold.toList
994-- . Stream.parseMany (Parser.groupByRolling eq Fold.toList)
995-- . Stream.fromList
996-- :}
997--
998-- >>> runGroupsByRolling (<) []
999-- []
1001-- >>> runGroupsByRolling (<) [1]
1002-- [[1]]
1004-- >>> runGroupsByRolling (<) [3, 5, 4, 1, 2, 0]
1005-- [[3,5],[4],[1,2],[0]]
1007-- /Pre-release/
1009{-# INLINE groupByRolling #-}
1010groupByRolling :: Monad m => (a -> a -> Bool) -> Fold m a b -> Parser m a b
1011groupByRolling eq = D.toParserK . D.groupByRolling eq
1013-- | Like 'groupByRolling', but if the predicate is 'True' then collects using
1014-- the first fold as long as the predicate holds 'True', if the predicate is
1015-- 'False' collects using the second fold as long as it remains 'False'.
1016-- Returns 'Left' for the first case and 'Right' for the second case.
1018-- For example, if we want to detect sorted sequences in a stream, both
1019-- ascending and descending cases we can use 'groupByRollingEither (<=)
1020-- Fold.toList Fold.toList'.
1022-- /Pre-release/
1023{-# INLINE groupByRollingEither #-}
1024groupByRollingEither :: Monad m =>
1025 (a -> a -> Bool) -> Fold m a b -> Fold m a c -> Parser m a (Either b c)
1026groupByRollingEither eq f1 = D.toParserK . D.groupByRollingEither eq f1
1028-- | Match the given sequence of elements using the given comparison function.
1030-- >>> Stream.parse (Parser.eqBy (==) "string") $ Stream.fromList "string"
1032-- >>> Stream.parse (Parser.eqBy (==) "mismatch") $ Stream.fromList "match"
1033-- *** Exception: ParseError "eqBy: failed, yet to match 7 elements"
1035-- /Pre-release/
1037{-# INLINE eqBy #-}
1038eqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser m a ()
1039eqBy cmp = D.toParserK . D.eqBy cmp
1041-- | Like eqBy but uses a stream instead of a list
1042{-# INLINE matchBy #-}
1043matchBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Parser m a ()
1044matchBy cmp = D.toParserK . D.matchBy cmp . Stream.toStreamD
1046-- | Match the input sequence with the supplied list and return it if
1047-- successful.
1049-- /Pre-release/
1050{-# INLINE list #-}
1051list :: (Monad m, Eq a) => [a] -> Parser m a [a]
1052list xs = eqBy (==) xs $> xs
1054-------------------------------------------------------------------------------
1055-- nested parsers
1056-------------------------------------------------------------------------------
1058-- | Sequential parser application. Apply two parsers sequentially to an input
1059-- stream. The input is provided to the first parser, when it is done the
1060-- remaining input is provided to the second parser. If both the parsers
1061-- succeed their outputs are combined using the supplied function. The
1062-- operation fails if any of the parsers fail.
1064-- Note: This is a parsing dual of appending streams using
1065-- 'Streamly.Prelude.serial', it splits the streams using two parsers and zips
1066-- the results.
1068-- This implementation is strict in the second argument, therefore, the
1069-- following will fail:
1071-- >>> Stream.parse (Parser.serialWith const (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1072-- *** Exception: Prelude.undefined
1073-- ...
1075-- Compare with 'Applicative' instance method '<*>'. This implementation allows
1076-- stream fusion but has quadratic complexity. This can fuse with other
1077-- operations and can be faster than 'Applicative' instance for small number
1078-- (less than 8) of compositions.
1080-- Many combinators can be expressed using @serialWith@ and other parser
1081-- primitives. Some common idioms are described below,
1083-- @
1084-- span :: (a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1085-- span pred f1 f2 = serialWith (,) ('takeWhile' pred f1) ('fromFold' f2)
1086-- @
1088-- @
1089-- spanBy :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1090-- spanBy eq f1 f2 = serialWith (,) ('groupBy' eq f1) ('fromFold' f2)
1091-- @
1093-- @
1094-- spanByRolling :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser m a b
1095-- spanByRolling eq f1 f2 = serialWith (,) ('groupByRolling' eq f1) ('fromFold' f2)
1096-- @
1098-- /Pre-release/
1100{-# INLINE serialWith #-}
1101serialWith :: Monad m
1102 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1103serialWith f p1 p2 =
1104 D.toParserK $ D.serialWith f (D.fromParserK p1) (D.fromParserK p2)
1106-- | Sequential parser application ignoring the output of the first parser.
1107-- Apply two parsers sequentially to an input stream. The input is provided to
1108-- the first parser, when it is done the remaining input is provided to the
1109-- second parser. The output of the parser is the output of the second parser.
1110-- The operation fails if any of the parsers fail.
1112-- This implementation is strict in the second argument, therefore, the
1113-- following will fail:
1115-- >>> Stream.parse (Parser.split_ (Parser.satisfy (> 0)) undefined) $ Stream.fromList [1]
1116-- *** Exception: Prelude.undefined
1117-- ...
1119-- Compare with 'Applicative' instance method '*>'. This implementation allows
1120-- stream fusion but has quadratic complexity. This can fuse with other
1121-- operations, and can be faster than 'Applicative' instance for small
1122-- number (less than 8) of compositions.
1124-- /Pre-release/
1126{-# INLINE split_ #-}
1127split_ :: Monad m => Parser m x a -> Parser m x b -> Parser m x b
1128split_ p1 p2 = D.toParserK $ D.split_ (D.fromParserK p1) (D.fromParserK p2)
1131-- | @teeWith f p1 p2@ distributes its input to both @p1@ and @p2@ until both
1132-- of them succeed or anyone of them fails and combines their output using @f@.
1133-- The parser succeeds if both the parsers succeed.
1135-- /Pre-release/
1137{-# INLINE teeWith #-}
1138teeWith :: Monad m
1139 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1140teeWith f p1 p2 =
1141 D.toParserK $ D.teeWith f (D.fromParserK p1) (D.fromParserK p2)
1143-- | Like 'teeWith' but ends parsing and zips the results, if available,
1144-- whenever the first parser ends.
1146-- /Pre-release/
1148{-# INLINE teeWithFst #-}
1149teeWithFst :: Monad m
1150 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1151teeWithFst f p1 p2 =
1152 D.toParserK $ D.teeWithFst f (D.fromParserK p1) (D.fromParserK p2)
1154-- | Like 'teeWith' but ends parsing and zips the results, if available,
1155-- whenever any of the parsers ends or fails.
1157-- /Unimplemented/
1159{-# INLINE teeWithMin #-}
1160teeWithMin :: Monad m
1161 => (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
1162teeWithMin f p1 p2 =
1163 D.toParserK $ D.teeWithMin f (D.fromParserK p1) (D.fromParserK p2)
1166-- | Sequential alternative. Apply the input to the first parser and return the
1167-- result if the parser succeeds. If the first parser fails then backtrack and
1168-- apply the same input to the second parser and return the result.
1170-- Note: This implementation is not lazy in the second argument. The following
1171-- will fail:
1173-- >>> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
1174-- 1
1176-- Compare with 'Alternative' instance method '<|>'. This implementation allows
1177-- stream fusion but has quadratic complexity. This can fuse with other
1178-- operations and can be much faster than 'Alternative' instance for small
1179-- number (less than 8) of alternatives.
1181-- /Pre-release/
1183{-# INLINE alt #-}
1184alt :: Monad m => Parser m x a -> Parser m x a -> Parser m x a
1185alt p1 p2 = D.toParserK $ D.alt (D.fromParserK p1) (D.fromParserK p2)
1188-- | Shortest alternative. Apply both parsers in parallel but choose the result
1189-- from the one which consumed least input i.e. take the shortest succeeding
1190-- parse.
1192-- /Pre-release/
1194{-# INLINE shortest #-}
1195shortest :: Monad m
1196 => Parser m x a -> Parser m x a -> Parser m x a
1197shortest p1 p2 = D.toParserK $ D.shortest (D.fromParserK p1) (D.fromParserK p2)
1199-- | Longest alternative. Apply both parsers in parallel but choose the result
1200-- from the one which consumed more input i.e. take the longest succeeding
1201-- parse.
1203-- /Pre-release/
1205{-# INLINE longest #-}
1206longest :: Monad m
1207 => Parser m x a -> Parser m x a -> Parser m x a
1208longest p1 p2 = D.toParserK $ D.longest (D.fromParserK p1) (D.fromParserK p2)
1211-- | Run a parser without consuming the input.
1213-- /Pre-release/
1215{-# INLINE lookAhead #-}
1216lookAhead :: Monad m => Parser m a b -> Parser m a b
1217lookAhead p = D.toParserK $ D.lookAhead $ D.fromParserK p
1219-- | Takes at-most @n@ input elements.
1221-- * Stops - when the collecting parser stops.
1222-- * Fails - when the collecting parser fails.
1224-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 2 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1225-- [1,2]
1227-- >>> Stream.parse (Parser.takeP 4 (Parser.takeEQ 5 Fold.toList)) $ Stream.fromList [1, 2, 3, 4, 5]
1228-- *** Exception: ParseError "takeEQ: Expecting exactly 5 elements, input terminated on 4"
1230-- /Internal/
1231{-# INLINE takeP #-}
1232takeP :: Monad m => Int -> Parser m a b -> Parser m a b
1233takeP i p = D.toParserK $ D.takeP i $ D.fromParserK p
1235-------------------------------------------------------------------------------
1236-- Sequential Collection
1237-------------------------------------------------------------------------------
1239-- | @concatSequence f p@ collects sequential parses of parsers in a
1240-- serial stream @p@ using the fold @f@. Fails if the input ends or any
1241-- of the parsers fail.
1243-- An even more efficient implementation can use ParserD type Parser in
1244-- the stream.
1246-- /Pre-release/
1248{-# INLINE concatSequence #-}
1249concatSequence ::
1250 Monad m =>
1251 Fold m b c -> Stream m (Parser m a b) -> Parser m a c
1252concatSequence f p =
1253 let sp = fmap D.fromParserK $ Stream.toStreamD p
1254 in D.toParserK $ D.sequence f sp
1256-- | Map a 'Parser' returning function on the result of a 'Parser'.
1258-- Compare with 'Monad' instance method '>>='. This implementation allows
1259-- stream fusion but has quadratic complexity. This can fuse with other
1260-- operations and can be much faster than 'Monad' instance for small number
1261-- (less than 8) of compositions.
1263-- /Pre-release/
1265{-# INLINE concatMap #-}
1266concatMap :: Monad m
1267 => (b -> Parser m a c) -> Parser m a b -> Parser m a c
1268concatMap f p = D.toParserK $ D.concatMap (D.fromParserK . f) (D.fromParserK p)
1271-------------------------------------------------------------------------------
1272-- Alternative Collection
1273-------------------------------------------------------------------------------
1275-- | @choice parsers@ applies the @parsers@ in order and returns the first
1276-- successful parse.
1278-- This is same as 'asum' but more efficient.
1280-- /Broken/
1282{-# INLINE choice #-}
1283choice ::
1284 (Functor t, Foldable t, Monad m) => t (Parser m a b) -> Parser m a b
1285choice ps = D.toParserK $ D.choice $ D.fromParserK <$> ps
1288-------------------------------------------------------------------------------
1289-- Sequential Repetition
1290-------------------------------------------------------------------------------
1292-- | Like 'many' but uses a 'Parser' instead of a 'Fold' to collect the
1293-- results. Parsing stops or fails if the collecting parser stops or fails.
1295-- /Unimplemented/
1297{-# INLINE manyP #-}
1298manyP :: -- Monad m =>
1299 Parser m a b -> Parser m b c -> Parser m a c
1300manyP _p _f = undefined -- D.toParserK $ D.manyP (D.fromParserK p) f
1302-- | Collect zero or more parses. Apply the supplied parser repeatedly on the
1303-- input stream and push the parse results to a downstream fold.
1305-- Stops: when the downstream fold stops or the parser fails.
1306-- Fails: never, produces zero or more results.
1308-- >>> many = Parser.countBetween 0 maxBound
1310-- Compare with 'Control.Applicative.many'.
1312-- /Pre-release/
1314{-# INLINE many #-}
1315many :: Monad m => Parser m a b -> Fold m b c -> Parser m a c
1316many p f = D.toParserK $ D.many (D.fromParserK p) f
1318-- Note: many1 would perhaps be a better name for this and consistent with
1319-- other names like takeWhile1. But we retain the name "some" for
1320-- compatibility.
1322-- | Collect one or more parses. Apply the supplied parser repeatedly on the
1323-- input stream and push the parse results to a downstream fold.
1325-- Stops: when the downstream fold stops or the parser fails.
1326-- Fails: if it stops without producing a single result.
1328-- >>> some p f = Parser.manyP p (Parser.takeGE 1 f)
1329-- >>> some = Parser.countBetween 1 maxBound
1331-- Compare with 'Control.Applicative.some'.
1333-- /Pre-release/
1335{-# INLINE some #-}
1336some :: Monad m => Parser m a b -> Fold m b c -> Parser m a c
1337some p f = D.toParserK $ D.some (D.fromParserK p) f
1338-- some p f = manyP p (takeGE 1 f)
1339-- some = countBetween 1 maxBound
1341-- | @countBetween m n f p@ collects between @m@ and @n@ sequential parses of
1342-- parser @p@ using the fold @f@. Stop after collecting @n@ results. Fails if
1343-- the input ends or the parser fails before @m@ results are collected.
1345-- >>> countBetween m n p f = Parser.manyP p (Parser.takeBetween m n f)
1347-- /Unimplemented/
1349{-# INLINE countBetween #-}
1350countBetween :: -- Monad m =>
1351 Int -> Int -> Parser m a b -> Fold m b c -> Parser m a c
1352countBetween _m _n _p = undefined
1353-- countBetween m n p f = manyP p (takeBetween m n f)
1355-- | @count n f p@ collects exactly @n@ sequential parses of parser @p@ using
1356-- the fold @f@. Fails if the input ends or the parser fails before @n@
1357-- results are collected.
1359-- >>> count n = Parser.countBetween n n
1360-- >>> count n p f = Parser.manyP p (Parser.takeEQ n f)
1362-- /Unimplemented/
1364{-# INLINE count #-}
1365count :: -- Monad m =>
1366 Int -> Parser m a b -> Fold m b c -> Parser m a c
1367count n = countBetween n n
1368-- count n p f = manyP p (takeEQ n f)
1370-- | Like 'manyTill' but uses a 'Parser' to collect the results instead of a
1371-- 'Fold'. Parsing stops or fails if the collecting parser stops or fails.
1373-- We can implemnent parsers like the following using 'manyTillP':
1375-- @
1376-- countBetweenTill m n f p = manyTillP (takeBetween m n f) p
1377-- @
1379-- /Unimplemented/
1381{-# INLINE manyTillP #-}
1382manyTillP :: -- Monad m =>
1383 Parser m a b -> Parser m a x -> Parser m b c -> Parser m a c
1384manyTillP _p1 _p2 _f = undefined
1385 -- D.toParserK $ D.manyTillP (D.fromParserK p1) (D.fromParserK p2) f
1387-- | @manyTill f test collect@ tries the parser @test@ on the input, if @test@
1388-- fails it backtracks and tries @collect@, after @collect@ succeeds @test@ is
1389-- tried again and so on. The parser stops when @test@ succeeds. The output of
1390-- @test@ is discarded and the output of @collect@ is accumulated by the
1391-- supplied fold. The parser fails if @collect@ fails.
1393-- Stops when the fold @f@ stops.
1395-- /Pre-release/
1397{-# INLINE manyTill #-}
1398manyTill :: Monad m
1399 => Parser m a b -> Parser m a x -> Fold m b c -> Parser m a c
1400manyTill p1 p2 f =
1401 D.toParserK $ D.manyTill f (D.fromParserK p1) (D.fromParserK p2)
1403-- | @manyThen f collect recover@ repeats the parser @collect@ on the input and
1404-- collects the output in the supplied fold. If the the parser @collect@ fails,
1405-- parser @recover@ is run until it stops and then we start repeating the
1406-- parser @collect@ again. The parser fails if the recovery parser fails.
1408-- For example, this can be used to find a key frame in a video stream after an
1409-- error.
1411-- /Unimplemented/
1413{-# INLINE manyThen #-}
1414manyThen :: -- (Foldable t, Monad m) =>
1415 Parser m a b -> Parser m a x -> Fold m b c -> Parser m a c
1416manyThen _parser _recover _f = undefined
1418-------------------------------------------------------------------------------
1419-- Interleaving
1420-------------------------------------------------------------------------------
1422-- To deinterleave we can chain two parsers one behind the other. The input is
1423-- given to the first parser and the input definitively rejected by the first
1424-- parser is given to the second parser.
1426-- We can either have the parsers themselves buffer the input or use the shared
1427-- global buffer to hold it until none of the parsers need it. When the first
1428-- parser returns Skip (i.e. rewind) we let the second parser consume the
1429-- rejected input and when it is done we move the cursor forward to the first
1430-- parser again. This will require a "move forward" command as well.
1432-- To implement grep we can use three parsers, one to find the pattern, one
1433-- to store the context behind the pattern and one to store the context in
1434-- front of the pattern. When a match occurs we need to emit the accumulator of
1435-- all the three parsers. One parser can count the line numbers to provide the
1436-- line number info.
1438-- XXX rename this to intercalate
1439-- | Apply two parsers alternately to an input stream. The input stream is
1440-- considered an interleaving of two patterns. The two parsers represent the
1441-- two patterns.
1443-- This undoes a "gintercalate" of two streams.
1445-- /Pre-release/
1447{-# INLINE deintercalate #-}
1448deintercalate :: Monad m =>
1449 Fold m (Either x y) z
1450 -> Parser m a x
1451 -> Parser m a y
1452 -> Parser m a z
1453deintercalate sink contentL contentR =
1454 D.toParserK
1455 $ D.deintercalate
1456 sink (D.fromParserK contentL) (D.fromParserK contentR)
1458-- | Parse items separated by a separator parsed by the supplied parser. At
1459-- least one item must be present for the parser to succeed.
1461-- Note that this can go in infinite loop if both the parsers fail on some
1462-- input. Detection of that would make the implementation more complex.
1464{-# INLINE sepBy1 #-}
1465sepBy1 :: Monad m =>
1466 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1467sepBy1 sink p sep = do
1468 x <- p
1469 f <- fromEffect $ FL.initialize sink
1470 f1 <- fromEffect $ FL.snoc f x
1471 many (sep >> p) f1
1473-- | Run the content parser first, when it is done, the separator parser is
1474-- run, when it is done content parser is run again and so on. If none of the
1475-- parsers consumes an input then parser returns a failure.
1477-- >>> sepBy sink = Parser.deintercalate (Fold.lefts sink)
1478-- >>> sepBy sink content sep = Parser.sepBy1 sink content sep <|> return mempty
1480{-# INLINE sepBy #-}
1481sepBy :: Monad m =>
1482 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1483sepBy sink content sep =
1484 D.toParserK $ D.sepBy sink (D.fromParserK content) (D.fromParserK sep)
1485-- sepBy sink = deintercalate (FL.lefts sink)
1487-------------------------------------------------------------------------------
1488-- Interleaving a collection of parsers
1489-------------------------------------------------------------------------------
1491-- | Apply a collection of parsers to an input stream in a round robin fashion.
1492-- Each parser is applied until it stops and then we repeat starting with the
1493-- the first parser again.
1495-- /Unimplemented/
1497{-# INLINE roundRobin #-}
1498roundRobin :: -- (Foldable t, Monad m) =>
1499 t (Parser m a b) -> Fold m b c -> Parser m a c
1500roundRobin _ps _f = undefined
1502-------------------------------------------------------------------------------
1503-- Repeated Alternatives
1504-------------------------------------------------------------------------------
1506-- | Keep trying a parser up to a maximum of @n@ failures. When the parser
1507-- fails the input consumed till now is dropped and the new instance is tried
1508-- on the fresh input.
1510-- /Unimplemented/
1512{-# INLINE retryMaxTotal #-}
1513retryMaxTotal :: -- (Monad m) =>
1514 Int -> Parser m a b -> Fold m b c -> Parser m a c
1515retryMaxTotal _n _p _f = undefined
1517-- | Like 'retryMaxTotal' but aborts after @n@ successive failures.
1519-- /Unimplemented/
1521{-# INLINE retryMaxSuccessive #-}
1522retryMaxSuccessive :: -- (Monad m) =>
1523 Int -> Parser m a b -> Fold m b c -> Parser m a c
1524retryMaxSuccessive _n _p _f = undefined
1526-- | Keep trying a parser until it succeeds. When the parser fails the input
1527-- consumed till now is dropped and the new instance is tried on the fresh
1528-- input.
1530-- /Unimplemented/
1532{-# INLINE retry #-}
1533retry :: -- (Monad m) =>
1534 Parser m a b -> Parser m a b
1535retry _p = undefined