-- |
-- Module      : Foundation.Parser
-- License     : BSD-style
-- Maintainer  : Haskell Foundation
-- Stability   : experimental
-- Portability : portable
--
-- The current implementation is mainly, if not copy/pasted, inspired from
-- `memory`'s Parser.
--
-- Foundation Parser makes use of the Foundation's @Collection@ and
-- @Sequential@ classes to allow you to define generic parsers over any
-- @Sequential@ of inpu.
--
-- This way you can easily implements parsers over @LString@, @String@.
--
--
-- > flip parseOnly "my.email@address.com" $ do
-- >    EmailAddress
-- >      <$> (takeWhile ((/=) '@' <*  element '@')
-- >      <*> takeAll
--

{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}

module Foundation.Parser
    ( Parser
    , parse
    , parseFeed
    , parseOnly
    , -- * Result
      Result(..)
    , ParseError(..)
    , reportError

    , -- * Parser source
      ParserSource(..)

    , -- * combinator
      peek
    , element
    , anyElement
    , elements
    , string

    , satisfy
    , satisfy_
    , take
    , takeWhile
    , takeAll

    , skip
    , skipWhile
    , skipAll

    , (<|>)
    , many
    , some
    , optional
    , repeat, Condition(..), And(..)
    ) where

import           Control.Applicative (Alternative, empty, (<|>), many, some, optional)
import           Control.Monad (MonadPlus, mzero, mplus)

import           Basement.Compat.Base
import           Basement.Types.OffsetSize
import           Foundation.Numerical
import           Foundation.Collection hiding (take, takeWhile)
import qualified Foundation.Collection as C
import           Foundation.String

-- Error handling -------------------------------------------------------------

-- | common parser error definition
data ParseError input
    = NotEnough (CountOf (Element input))
        -- ^ meaning the parser was short of @CountOf@ @Element@ of `input`.
    | NotEnoughParseOnly
        -- ^ The parser needed more data, only when using @parseOnly@
    | ExpectedElement (Element input) (Element input)
        -- ^ when using @element@
    | Expected (Chunk input) (Chunk input)
        -- ^ when using @elements@ or @string@
    | Satisfy (Maybe String)
        -- ^ the @satisfy@ or @satisfy_@ function failed,
  deriving (Typeable)
instance (Typeable input, Show input) => Exception (ParseError input)

instance Show input => Show (ParseError input) where
    show :: ParseError input -> String
show (NotEnough (CountOf Int
sz)) = String
"NotEnough: missing " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Int
sz forall a. Semigroup a => a -> a -> a
<> String
" element(s)"
    show ParseError input
NotEnoughParseOnly    = String
"NotEnough, parse only"
    show (ExpectedElement Element input
_ Element input
_) = String
"Expected _ but received _"
    show (Expected Chunk input
_ Chunk input
_)        = String
"Expected _ but received _"
    show (Satisfy Maybe String
Nothing)     = String
"Satisfy"
    show (Satisfy (Just String
s))    = String
"Satisfy: " forall a. Semigroup a => a -> a -> a
<> forall l. IsList l => l -> [Item l]
toList String
s

instance {-# OVERLAPPING #-} Show (ParseError String) where
    show :: ParseError String -> String
show (NotEnough (CountOf Int
sz)) = String
"NotEnough: missing " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Int
sz forall a. Semigroup a => a -> a -> a
<> String
" element(s)"
    show ParseError String
NotEnoughParseOnly    = String
"NotEnough, parse only"
    show (ExpectedElement Element String
a Element String
b) = String
"Expected "forall a. Semigroup a => a -> a -> a
<>forall a. Show a => a -> String
show Element String
aforall a. Semigroup a => a -> a -> a
<>String
" but received " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Element String
b
    show (Expected Chunk String
a Chunk String
b)        = String
"Expected "forall a. Semigroup a => a -> a -> a
<>forall a. Show a => a -> String
show Chunk String
aforall a. Semigroup a => a -> a -> a
<>String
" but received " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Chunk String
b
    show (Satisfy Maybe String
Nothing)     = String
"Satisfy"
    show (Satisfy (Just String
s))    = String
"Satisfy: " forall a. Semigroup a => a -> a -> a
<> forall l. IsList l => l -> [Item l]
toList String
s

-- Results --------------------------------------------------------------------

-- | result of executing the `parser` over the given `input`
data Result input result
    = ParseFailed (ParseError input)
        -- ^ the parser failed with the given @ParserError@
    | ParseOk     (Chunk input) result
        -- ^ the parser complete successfuly with the remaining @Chunk@
    | ParseMore   (Chunk input -> Result input result)
        -- ^ the parser needs more input, pass an empty @Chunk@ or @mempty@
        -- to tell the parser you don't have anymore inputs.

instance (Show k, Show input) => Show (Result input k) where
    show :: Result input k -> String
show (ParseFailed ParseError input
err) = String
"Parser failed: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show ParseError input
err
    show (ParseOk Chunk input
_ k
k) = String
"Parser succeed: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show k
k
    show (ParseMore Chunk input -> Result input k
_) = String
"Parser incomplete: need more"
instance Functor (Result input) where
    fmap :: forall a b. (a -> b) -> Result input a -> Result input b
fmap a -> b
f Result input a
r = case Result input a
r of
        ParseFailed ParseError input
err -> forall input result. ParseError input -> Result input result
ParseFailed ParseError input
err
        ParseOk Chunk input
rest a
a  -> forall input result. Chunk input -> result -> Result input result
ParseOk Chunk input
rest (a -> b
f a
a)
        ParseMore Chunk input -> Result input a
more -> forall input result.
(Chunk input -> Result input result) -> Result input result
ParseMore (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Chunk input -> Result input a
more)

-- Parser Source --------------------------------------------------------------

class (Sequential input, IndexedCollection input) => ParserSource input where
    type Chunk input

    nullChunk :: input -> Chunk input -> Bool

    appendChunk :: input -> Chunk input -> input

    subChunk :: input -> Offset (Element input) -> CountOf (Element input) -> Chunk input

    spanChunk :: input -> Offset (Element input) -> (Element input -> Bool) -> (Chunk input, Offset (Element input))

endOfParserSource :: ParserSource input => input -> Offset (Element input) -> Bool
endOfParserSource :: forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
l Offset (Element input)
off = Offset (Element input)
off forall ty. Offset ty -> CountOf ty -> Bool
.==# forall c. Collection c => c -> CountOf (Element c)
length input
l
{-# INLINE endOfParserSource #-}

-- Parser ---------------------------------------------------------------------

data NoMore = More | NoMore
  deriving (Int -> NoMore -> ShowS
[NoMore] -> ShowS
NoMore -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NoMore] -> ShowS
$cshowList :: [NoMore] -> ShowS
show :: NoMore -> String
$cshow :: NoMore -> String
showsPrec :: Int -> NoMore -> ShowS
$cshowsPrec :: Int -> NoMore -> ShowS
Show, NoMore -> NoMore -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NoMore -> NoMore -> Bool
$c/= :: NoMore -> NoMore -> Bool
== :: NoMore -> NoMore -> Bool
$c== :: NoMore -> NoMore -> Bool
Eq)

type Failure input         result = input -> Offset (Element input) -> NoMore -> ParseError input -> Result input result

type Success input result' result = input -> Offset (Element input) -> NoMore -> result'          -> Result input result

-- | Foundation's @Parser@ monad.
--
-- Its implementation is based on the parser in `memory`.
newtype Parser input result = Parser
    { forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser :: forall result'
                 . input -> Offset (Element input) -> NoMore
                -> Failure input        result'
                -> Success input result result'
                -> Result input result'
    }

instance Functor (Parser input) where
    fmap :: forall a b. (a -> b) -> Parser input a -> Parser input b
fmap a -> b
f Parser input a
fa = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input b result'
ok ->
        forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input a
fa input
buf Offset (Element input)
off NoMore
nm Failure input result'
err forall a b. (a -> b) -> a -> b
$ \input
buf' Offset (Element input)
off' NoMore
nm' a
a -> Success input b result'
ok input
buf' Offset (Element input)
off' NoMore
nm' (a -> b
f a
a)
    {-# INLINE fmap #-}

instance ParserSource input => Applicative (Parser input) where
    pure :: forall a. a -> Parser input a
pure a
a = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
_ Success input a result'
ok -> Success input a result'
ok input
buf Offset (Element input)
off NoMore
nm a
a
    {-# INLINE pure #-}
    Parser input (a -> b)
fab <*> :: forall a b.
Parser input (a -> b) -> Parser input a -> Parser input b
<*> Parser input a
fa = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf0 Offset (Element input)
off0 NoMore
nm0 Failure input result'
err Success input b result'
ok ->
        forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser  Parser input (a -> b)
fab input
buf0 Offset (Element input)
off0 NoMore
nm0 Failure input result'
err forall a b. (a -> b) -> a -> b
$ \input
buf1 Offset (Element input)
off1 NoMore
nm1 a -> b
ab ->
        forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ Parser input a
fa  input
buf1 Offset (Element input)
off1 NoMore
nm1 Failure input result'
err forall a b. (a -> b) -> a -> b
$ \input
buf2 Offset (Element input)
off2 NoMore
nm2 -> Success input b result'
ok input
buf2 Offset (Element input)
off2 NoMore
nm2 forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> b
ab
    {-# INLINE (<*>) #-}

instance ParserSource input => Monad (Parser input) where
    return :: forall a. a -> Parser input a
return = forall (f :: * -> *) a. Applicative f => a -> f a
pure
    {-# INLINE return #-}
    Parser input a
m >>= :: forall a b.
Parser input a -> (a -> Parser input b) -> Parser input b
>>= a -> Parser input b
k       = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input b result'
ok ->
        forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser  Parser input a
m     input
buf  Offset (Element input)
off  NoMore
nm  Failure input result'
err forall a b. (a -> b) -> a -> b
$ \input
buf' Offset (Element input)
off' NoMore
nm' a
a ->
        forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (a -> Parser input b
k a
a) input
buf' Offset (Element input)
off' NoMore
nm' Failure input result'
err Success input b result'
ok
    {-# INLINE (>>=) #-}

instance ParserSource input => MonadPlus (Parser input) where
    mzero :: forall a. Parser input a
mzero = forall a. HasCallStack => String -> a
error String
"Foundation.Parser.Internal.MonadPlus.mzero"
    mplus :: forall a. Parser input a -> Parser input a -> Parser input a
mplus Parser input a
f Parser input a
g = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input a result'
ok ->
        forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input a
f input
buf Offset (Element input)
off NoMore
nm (\input
buf' Offset (Element input)
_ NoMore
nm' ParseError input
_ -> forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input a
g input
buf' Offset (Element input)
off NoMore
nm' Failure input result'
err Success input a result'
ok) Success input a result'
ok
    {-# INLINE mplus #-}
instance ParserSource input => Alternative (Parser input) where
    empty :: forall a. Parser input a
empty = forall a. HasCallStack => String -> a
error String
"Foundation.Parser.Internal.Alternative.empty"
    <|> :: forall a. Parser input a -> Parser input a -> Parser input a
(<|>) = forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus
    {-# INLINE (<|>) #-}

runParser_ :: ParserSource input
           => Parser input result
           -> input
           -> Offset (Element input)
           -> NoMore
           -> Failure input        result'
           -> Success input result result'
           -> Result input         result'
runParser_ :: forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ Parser input result
parser input
buf Offset (Element input)
off NoMore
NoMore Failure input result'
err Success input result result'
ok = forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input result
parser input
buf Offset (Element input)
off NoMore
NoMore Failure input result'
err Success input result result'
ok
runParser_ Parser input result
parser input
buf Offset (Element input)
off NoMore
nm     Failure input result'
err Success input result result'
ok
    | forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off = forall input result.
(Chunk input -> Result input result) -> Result input result
ParseMore forall a b. (a -> b) -> a -> b
$ \Chunk input
chunk ->
        if forall input. ParserSource input => input -> Chunk input -> Bool
nullChunk input
buf Chunk input
chunk
            then forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input result
parser input
buf Offset (Element input)
off NoMore
NoMore Failure input result'
err Success input result result'
ok
            else forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input result
parser (forall input. ParserSource input => input -> Chunk input -> input
appendChunk input
buf Chunk input
chunk) Offset (Element input)
off NoMore
nm Failure input result'
err Success input result result'
ok
    | Bool
otherwise = forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input result
parser input
buf                    Offset (Element input)
off NoMore
nm Failure input result'
err Success input result result'
ok
{-# INLINE runParser_ #-}

-- | Run a parser on an @initial input.
--
-- If the Parser need more data than available, the @feeder function
-- is automatically called and fed to the More continuation.
parseFeed :: (ParserSource input, Monad m)
          => m (Chunk input)
          -> Parser input a
          -> input
          -> m (Result input a)
parseFeed :: forall input (m :: * -> *) a.
(ParserSource input, Monad m) =>
m (Chunk input) -> Parser input a -> input -> m (Result input a)
parseFeed m (Chunk input)
feeder Parser input a
p input
initial = Result input a -> m (Result input a)
loop forall a b. (a -> b) -> a -> b
$ forall input a.
ParserSource input =>
Parser input a -> input -> Result input a
parse Parser input a
p input
initial
  where loop :: Result input a -> m (Result input a)
loop (ParseMore Chunk input -> Result input a
k) = m (Chunk input)
feeder forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Result input a -> m (Result input a)
loop forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Chunk input -> Result input a
k)
        loop Result input a
r             = forall (m :: * -> *) a. Monad m => a -> m a
return Result input a
r

-- | Run a Parser on a ByteString and return a 'Result'
parse :: ParserSource input
      => Parser input a -> input -> Result input a
parse :: forall input a.
ParserSource input =>
Parser input a -> input -> Result input a
parse Parser input a
p input
s = forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input a
p input
s Offset (Element input)
0 NoMore
More forall input r.
input
-> Offset (Element input)
-> NoMore
-> ParseError input
-> Result input r
failure forall input r.
ParserSource input =>
input -> Offset (Element input) -> NoMore -> r -> Result input r
success

failure :: input -> Offset (Element input) -> NoMore -> ParseError input -> Result input r
failure :: forall input r.
input
-> Offset (Element input)
-> NoMore
-> ParseError input
-> Result input r
failure input
_ Offset (Element input)
_ NoMore
_ = forall input result. ParseError input -> Result input result
ParseFailed
{-# INLINE failure #-}

success :: ParserSource input => input -> Offset (Element input) -> NoMore -> r -> Result input r
success :: forall input r.
ParserSource input =>
input -> Offset (Element input) -> NoMore -> r -> Result input r
success input
buf Offset (Element input)
off NoMore
_ = forall input result. Chunk input -> result -> Result input result
ParseOk Chunk input
rest
  where
    !rest :: Chunk input
rest = forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off (forall c. Collection c => c -> CountOf (Element c)
length input
buf forall a. CountOf a -> CountOf a -> CountOf a
`sizeSub` forall a. Offset a -> CountOf a
offsetAsSize Offset (Element input)
off)
{-# INLINE success #-}

-- | parse only the given input
--
-- The left-over `Element input` will be ignored, if the parser call for more
-- data it will be continuously fed with `Nothing` (up to 256 iterations).
--
parseOnly :: (ParserSource input, Monoid (Chunk input))
          => Parser input a
          -> input
          -> Either (ParseError input) a
parseOnly :: forall input a.
(ParserSource input, Monoid (Chunk input)) =>
Parser input a -> input -> Either (ParseError input) a
parseOnly Parser input a
p input
i = case forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser Parser input a
p input
i Offset (Element input)
0 NoMore
NoMore forall input r.
input
-> Offset (Element input)
-> NoMore
-> ParseError input
-> Result input r
failure forall input r.
ParserSource input =>
input -> Offset (Element input) -> NoMore -> r -> Result input r
success of
    ParseFailed ParseError input
err  -> forall a b. a -> Either a b
Left ParseError input
err
    ParseOk     Chunk input
_ a
r  -> forall a b. b -> Either a b
Right a
r
    ParseMore   Chunk input -> Result input a
_    -> forall a b. a -> Either a b
Left forall input. ParseError input
NotEnoughParseOnly

-- ------------------------------------------------------------------------- --
--                              String Parser                                --
-- ------------------------------------------------------------------------- --

instance ParserSource String where
    type Chunk String = String
    nullChunk :: String -> Chunk String -> Bool
nullChunk String
_ = forall c. Collection c => c -> Bool
null
    {-# INLINE nullChunk #-}
    appendChunk :: String -> Chunk String -> String
appendChunk = forall a. Monoid a => a -> a -> a
mappend
    {-# INLINE appendChunk #-}
    subChunk :: String
-> Offset (Element String)
-> CountOf (Element String)
-> Chunk String
subChunk String
c Offset (Element String)
off CountOf (Element String)
sz = forall c. Sequential c => CountOf (Element c) -> c -> c
C.take CountOf (Element String)
sz forall a b. (a -> b) -> a -> b
$ forall c. Sequential c => CountOf (Element c) -> c -> c
C.drop (forall a. Offset a -> CountOf a
offsetAsSize Offset (Element String)
off) String
c
    {-# INLINE subChunk #-}
    spanChunk :: String
-> Offset (Element String)
-> (Element String -> Bool)
-> (Chunk String, Offset (Element String))
spanChunk String
buf Offset (Element String)
off Element String -> Bool
predicate =
        let c :: String
c      = forall c. Sequential c => CountOf (Element c) -> c -> c
C.drop (forall a. Offset a -> CountOf a
offsetAsSize Offset (Element String)
off) String
buf
            (String
t, String
_) = forall c. Sequential c => (Element c -> Bool) -> c -> (c, c)
C.span Element String -> Bool
predicate String
c
          in (String
t, Offset (Element String)
off forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` forall c. Collection c => c -> CountOf (Element c)
length String
t)
    {-# INLINE spanChunk #-}

instance ParserSource [a] where
    type Chunk [a] = [a]
    nullChunk :: [a] -> Chunk [a] -> Bool
nullChunk [a]
_ = forall c. Collection c => c -> Bool
null
    {-# INLINE nullChunk #-}
    appendChunk :: [a] -> Chunk [a] -> [a]
appendChunk = forall a. Monoid a => a -> a -> a
mappend
    {-# INLINE appendChunk #-}
    subChunk :: [a] -> Offset (Element [a]) -> CountOf (Element [a]) -> Chunk [a]
subChunk [a]
c Offset (Element [a])
off CountOf (Element [a])
sz = forall c. Sequential c => CountOf (Element c) -> c -> c
C.take CountOf (Element [a])
sz forall a b. (a -> b) -> a -> b
$ forall c. Sequential c => CountOf (Element c) -> c -> c
C.drop (forall a. Offset a -> CountOf a
offsetAsSize Offset (Element [a])
off) [a]
c
    {-# INLINE subChunk #-}
    spanChunk :: [a]
-> Offset (Element [a])
-> (Element [a] -> Bool)
-> (Chunk [a], Offset (Element [a]))
spanChunk [a]
buf Offset (Element [a])
off Element [a] -> Bool
predicate =
        let c :: [a]
c      = forall c. Sequential c => CountOf (Element c) -> c -> c
C.drop (forall a. Offset a -> CountOf a
offsetAsSize Offset (Element [a])
off) [a]
buf
            ([a]
t, [a]
_) = forall c. Sequential c => (Element c -> Bool) -> c -> (c, c)
C.span Element [a] -> Bool
predicate [a]
c
          in ([a]
t, Offset (Element [a])
off forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` forall c. Collection c => c -> CountOf (Element c)
length [a]
t)
    {-# INLINE spanChunk #-}

-- ------------------------------------------------------------------------- --
--                          Helpers                                          --
-- ------------------------------------------------------------------------- --

-- | helper function to report error when writing parsers
--
-- This way we can provide more detailed error when building custom
-- parsers and still avoid to use the naughty _fail_.
--
-- @
-- myParser :: Parser input Int
-- myParser = reportError $ Satisfy (Just "this function is not implemented...")
-- @
--
reportError :: ParseError input -> Parser input a
reportError :: forall input a. ParseError input -> Parser input a
reportError ParseError input
pe = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input a result'
_ -> Failure input result'
err input
buf Offset (Element input)
off NoMore
nm ParseError input
pe

-- | Get the next `Element input` from the parser
anyElement :: ParserSource input => Parser input (Element input)
anyElement :: forall input. ParserSource input => Parser input (Element input)
anyElement = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Element input) result'
ok ->
    case input
buf forall c.
IndexedCollection c =>
c -> Offset (Element c) -> Maybe (Element c)
! Offset (Element input)
off of
        Maybe (Element input)
Nothing -> Failure input result'
err input
buf Offset (Element input)
off        NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element input)
1
        Just Element input
x  -> Success input (Element input) result'
ok  input
buf (forall a. Enum a => a -> a
succ Offset (Element input)
off) NoMore
nm Element input
x
{-# INLINE anyElement #-}

-- | peek the first element from the input source without consuming it
--
-- Returns 'Nothing' if there is no more input to parse.
--
peek :: ParserSource input => Parser input (Maybe (Element input))
peek :: forall input.
ParserSource input =>
Parser input (Maybe (Element input))
peek = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Maybe (Element input)) result'
ok ->
    case input
buf forall c.
IndexedCollection c =>
c -> Offset (Element c) -> Maybe (Element c)
! Offset (Element input)
off of
        Maybe (Element input)
Nothing -> forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ Parser input (Maybe (Element input))
peekOnly input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Maybe (Element input)) result'
ok
        Just Element input
x  -> Success input (Maybe (Element input)) result'
ok input
buf Offset (Element input)
off NoMore
nm (forall a. a -> Maybe a
Just Element input
x)
  where
    peekOnly :: Parser input (Maybe (Element input))
peekOnly = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
_ Success input (Maybe (Element input)) result'
ok ->
        Success input (Maybe (Element input)) result'
ok input
buf Offset (Element input)
off NoMore
nm (input
buf forall c.
IndexedCollection c =>
c -> Offset (Element c) -> Maybe (Element c)
! Offset (Element input)
off)

element :: ( ParserSource input
           , Eq (Element input)
           , Element input ~ Element (Chunk input)
           )
        => Element input
        -> Parser input ()
element :: forall input.
(ParserSource input, Eq (Element input),
 Element input ~ Element (Chunk input)) =>
Element input -> Parser input ()
element Element input
expectedElement = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
    case input
buf forall c.
IndexedCollection c =>
c -> Offset (Element c) -> Maybe (Element c)
! Offset (Element input)
off of
        Maybe (Element input)
Nothing -> Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element (Chunk input))
1
        Just Element input
x | Element input
expectedElement forall a. Eq a => a -> a -> Bool
== Element input
x -> Success input () result'
ok  input
buf (forall a. Enum a => a -> a
succ Offset (Element input)
off) NoMore
nm ()
               | Bool
otherwise            -> Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. Element input -> Element input -> ParseError input
ExpectedElement Element input
expectedElement Element input
x
{-# INLINE element #-}

elements :: ( ParserSource input, Sequential (Chunk input)
            , Element (Chunk input) ~ Element input
            , Eq (Chunk input)
            )
         => Chunk input -> Parser input ()
elements :: forall input.
(ParserSource input, Sequential (Chunk input),
 Element (Chunk input) ~ Element input, Eq (Chunk input)) =>
Chunk input -> Parser input ()
elements = forall input.
(ParserSource input, Sequential (Chunk input),
 Element (Chunk input) ~ Element input, Eq (Chunk input)) =>
Chunk input -> Parser input ()
consumeEq
  where
    consumeEq :: ( ParserSource input
                 , Sequential (Chunk input)
                 , Element (Chunk input) ~ Element input
                 , Eq (Chunk input)
                 )
              => Chunk input -> Parser input ()
    consumeEq :: forall input.
(ParserSource input, Sequential (Chunk input),
 Element (Chunk input) ~ Element input, Eq (Chunk input)) =>
Chunk input -> Parser input ()
consumeEq Chunk input
expected = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
      if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off
        then
          Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element (Chunk input))
lenE
        else
          let !lenI :: Difference (Offset (Element input))
lenI = forall a. CountOf a -> Offset a
sizeAsOffset (forall c. Collection c => c -> CountOf (Element c)
length input
buf) forall a. Subtractive a => a -> a -> Difference a
- Offset (Element input)
off
           in if Difference (Offset (Element input))
lenI forall a. Ord a => a -> a -> Bool
>= CountOf (Element (Chunk input))
lenE
             then
              let a :: Chunk input
a = forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off CountOf (Element (Chunk input))
lenE
               in if Chunk input
a forall a. Eq a => a -> a -> Bool
== Chunk input
expected
                    then Success input () result'
ok input
buf (Offset (Element input)
off forall a. Additive a => a -> a -> a
+ forall a. CountOf a -> Offset a
sizeAsOffset CountOf (Element (Chunk input))
lenE) NoMore
nm ()
                    else Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. Chunk input -> Chunk input -> ParseError input
Expected Chunk input
expected Chunk input
a
             else
              let a :: Chunk input
a = forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off Difference (Offset (Element input))
lenI
                  (Chunk input
e', Chunk input
r) = forall c. Sequential c => CountOf (Element c) -> c -> (c, c)
splitAt Difference (Offset (Element input))
lenI Chunk input
expected
               in if Chunk input
a forall a. Eq a => a -> a -> Bool
== Chunk input
e'
                    then forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (forall input.
(ParserSource input, Sequential (Chunk input),
 Element (Chunk input) ~ Element input, Eq (Chunk input)) =>
Chunk input -> Parser input ()
consumeEq Chunk input
r) input
buf (Offset (Element input)
off forall a. Additive a => a -> a -> a
+ forall a. CountOf a -> Offset a
sizeAsOffset Difference (Offset (Element input))
lenI) NoMore
nm Failure input result'
err Success input () result'
ok
                    else Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. Chunk input -> Chunk input -> ParseError input
Expected Chunk input
e' Chunk input
a
      where
        !lenE :: CountOf (Element (Chunk input))
lenE = forall c. Collection c => c -> CountOf (Element c)
length Chunk input
expected
    {-# NOINLINE consumeEq #-}
{-# INLINE elements #-}

-- | take one element if satisfy the given predicate
satisfy :: ParserSource input => Maybe String -> (Element input -> Bool) -> Parser input (Element input)
satisfy :: forall input.
ParserSource input =>
Maybe String
-> (Element input -> Bool) -> Parser input (Element input)
satisfy Maybe String
desc Element input -> Bool
predicate = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Element input) result'
ok ->
    case input
buf forall c.
IndexedCollection c =>
c -> Offset (Element c) -> Maybe (Element c)
! Offset (Element input)
off of
        Maybe (Element input)
Nothing -> Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element input)
1
        Just Element input
x | Element input -> Bool
predicate Element input
x -> Success input (Element input) result'
ok  input
buf (forall a. Enum a => a -> a
succ Offset (Element input)
off) NoMore
nm Element input
x
               | Bool
otherwise   -> Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. Maybe String -> ParseError input
Satisfy Maybe String
desc
{-# INLINE satisfy #-}

-- | take one element if satisfy the given predicate
satisfy_ :: ParserSource input => (Element input -> Bool) -> Parser input (Element input)
satisfy_ :: forall input.
ParserSource input =>
(Element input -> Bool) -> Parser input (Element input)
satisfy_ = forall input.
ParserSource input =>
Maybe String
-> (Element input -> Bool) -> Parser input (Element input)
satisfy forall a. Maybe a
Nothing
{-# INLINE satisfy_ #-}

take :: ( ParserSource input
        , Sequential (Chunk input)
        , Element input ~ Element (Chunk input)
        )
     => CountOf (Element (Chunk input))
     -> Parser input (Chunk input)
take :: forall input.
(ParserSource input, Sequential (Chunk input),
 Element input ~ Element (Chunk input)) =>
CountOf (Element (Chunk input)) -> Parser input (Chunk input)
take CountOf (Element (Chunk input))
n = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Chunk input) result'
ok ->
    let lenI :: Difference (Offset (Element (Chunk input)))
lenI = forall a. CountOf a -> Offset a
sizeAsOffset (forall c. Collection c => c -> CountOf (Element c)
length input
buf) forall a. Subtractive a => a -> a -> Difference a
- Offset (Element input)
off
     in if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off Bool -> Bool -> Bool
&& CountOf (Element (Chunk input))
n forall a. Ord a => a -> a -> Bool
> CountOf (Element (Chunk input))
0
       then Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element (Chunk input))
n
       else case CountOf (Element (Chunk input))
n forall a. Subtractive a => a -> a -> Difference a
- Difference (Offset (Element (Chunk input)))
lenI of
              Just CountOf (Element (Chunk input))
s | CountOf (Element (Chunk input))
s forall a. Ord a => a -> a -> Bool
> CountOf (Element (Chunk input))
0 -> let h :: Chunk input
h = forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off Difference (Offset (Element (Chunk input)))
lenI
                                 in forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (forall input.
(ParserSource input, Sequential (Chunk input),
 Element input ~ Element (Chunk input)) =>
CountOf (Element (Chunk input)) -> Parser input (Chunk input)
take CountOf (Element (Chunk input))
s) input
buf (forall a. CountOf a -> Offset a
sizeAsOffset Difference (Offset (Element (Chunk input)))
lenI) NoMore
nm Failure input result'
err forall a b. (a -> b) -> a -> b
$
                                      \input
buf' Offset (Element input)
off' NoMore
nm' Chunk input
t -> Success input (Chunk input) result'
ok input
buf' Offset (Element input)
off' NoMore
nm' (Chunk input
h forall a. Semigroup a => a -> a -> a
<> Chunk input
t)
              Difference (CountOf (Element (Chunk input)))
_              -> Success input (Chunk input) result'
ok input
buf (Offset (Element input)
off forall a. Additive a => a -> a -> a
+ forall a. CountOf a -> Offset a
sizeAsOffset CountOf (Element (Chunk input))
n) NoMore
nm (forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off CountOf (Element (Chunk input))
n)

takeWhile :: ( ParserSource input, Sequential (Chunk input)
             )
          => (Element input -> Bool)
          -> Parser input (Chunk input)
takeWhile :: forall input.
(ParserSource input, Sequential (Chunk input)) =>
(Element input -> Bool) -> Parser input (Chunk input)
takeWhile Element input -> Bool
predicate = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input (Chunk input) result'
ok ->
    if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off
      then Success input (Chunk input) result'
ok input
buf Offset (Element input)
off NoMore
nm forall a. Monoid a => a
mempty
      else let (Chunk input
b1, Offset (Element input)
off') = forall input.
ParserSource input =>
input
-> Offset (Element input)
-> (Element input -> Bool)
-> (Chunk input, Offset (Element input))
spanChunk input
buf Offset (Element input)
off Element input -> Bool
predicate
            in if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off'
                  then forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (forall input.
(ParserSource input, Sequential (Chunk input)) =>
(Element input -> Bool) -> Parser input (Chunk input)
takeWhile Element input -> Bool
predicate) input
buf Offset (Element input)
off' NoMore
nm Failure input result'
err
                          forall a b. (a -> b) -> a -> b
$ \input
buf' Offset (Element input)
off'' NoMore
nm' Chunk input
b1T -> Success input (Chunk input) result'
ok input
buf' Offset (Element input)
off'' NoMore
nm' (Chunk input
b1 forall a. Semigroup a => a -> a -> a
<> Chunk input
b1T)
                  else Success input (Chunk input) result'
ok input
buf Offset (Element input)
off' NoMore
nm Chunk input
b1

-- | Take the remaining elements from the current position in the stream
takeAll :: (ParserSource input, Sequential (Chunk input)) => Parser input (Chunk input)
takeAll :: forall input.
(ParserSource input, Sequential (Chunk input)) =>
Parser input (Chunk input)
takeAll = forall input.
(ParserSource input, Sequential (Chunk input)) =>
Parser input ()
getAll forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall input. ParserSource input => Parser input (Chunk input)
returnBuffer
  where
    returnBuffer :: ParserSource input => Parser input (Chunk input)
    returnBuffer :: forall input. ParserSource input => Parser input (Chunk input)
returnBuffer = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
_ Success input (Chunk input) result'
ok ->
        let !lenI :: CountOf (Element input)
lenI = forall c. Collection c => c -> CountOf (Element c)
length input
buf
            !off' :: Offset (Element input)
off' = forall a. CountOf a -> Offset a
sizeAsOffset CountOf (Element input)
lenI
            !sz :: Difference (Offset (Element input))
sz   = Offset (Element input)
off' forall a. Subtractive a => a -> a -> Difference a
- Offset (Element input)
off
         in Success input (Chunk input) result'
ok input
buf Offset (Element input)
off' NoMore
nm (forall input.
ParserSource input =>
input
-> Offset (Element input) -> CountOf (Element input) -> Chunk input
subChunk input
buf Offset (Element input)
off Difference (Offset (Element input))
sz)
    {-# INLINE returnBuffer #-}

    getAll :: (ParserSource input, Sequential (Chunk input)) => Parser input ()
    getAll :: forall input.
(ParserSource input, Sequential (Chunk input)) =>
Parser input ()
getAll = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
      case NoMore
nm of
        NoMore
NoMore -> Success input () result'
ok input
buf Offset (Element input)
off NoMore
nm ()
        NoMore
More   -> forall input result.
(Chunk input -> Result input result) -> Result input result
ParseMore forall a b. (a -> b) -> a -> b
$ \Chunk input
nextChunk ->
          if forall input. ParserSource input => input -> Chunk input -> Bool
nullChunk input
buf Chunk input
nextChunk
            then Success input () result'
ok input
buf Offset (Element input)
off NoMore
NoMore ()
            else forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser forall input.
(ParserSource input, Sequential (Chunk input)) =>
Parser input ()
getAll (forall input. ParserSource input => input -> Chunk input -> input
appendChunk input
buf Chunk input
nextChunk) Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok
    {-# NOINLINE getAll #-}
{-# INLINE takeAll #-}

skip :: ParserSource input => CountOf (Element input) -> Parser input ()
skip :: forall input.
ParserSource input =>
CountOf (Element input) -> Parser input ()
skip CountOf (Element input)
n = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
    let lenI :: Difference (Offset (Element input))
lenI = forall a. CountOf a -> Offset a
sizeAsOffset (forall c. Collection c => c -> CountOf (Element c)
length input
buf) forall a. Subtractive a => a -> a -> Difference a
- Offset (Element input)
off
     in if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off Bool -> Bool -> Bool
&& CountOf (Element input)
n forall a. Ord a => a -> a -> Bool
> CountOf (Element input)
0
       then Failure input result'
err input
buf Offset (Element input)
off NoMore
nm forall a b. (a -> b) -> a -> b
$ forall input. CountOf (Element input) -> ParseError input
NotEnough CountOf (Element input)
n
       else case CountOf (Element input)
n forall a. Subtractive a => a -> a -> Difference a
- Difference (Offset (Element input))
lenI of
              Just CountOf (Element input)
s | CountOf (Element input)
s forall a. Ord a => a -> a -> Bool
> CountOf (Element input)
0 -> forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (forall input.
ParserSource input =>
CountOf (Element input) -> Parser input ()
skip CountOf (Element input)
s) input
buf (forall a. CountOf a -> Offset a
sizeAsOffset Difference (Offset (Element input))
lenI) NoMore
nm Failure input result'
err Success input () result'
ok
              Difference (CountOf (Element input))
_              -> Success input () result'
ok input
buf (Offset (Element input)
off forall a. Additive a => a -> a -> a
+ forall a. CountOf a -> Offset a
sizeAsOffset CountOf (Element input)
n) NoMore
nm ()

skipWhile :: ( ParserSource input, Sequential (Chunk input)
             )
          => (Element input -> Bool)
          -> Parser input ()
skipWhile :: forall input.
(ParserSource input, Sequential (Chunk input)) =>
(Element input -> Bool) -> Parser input ()
skipWhile Element input -> Bool
predicate = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
    if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off
      then Success input () result'
ok input
buf Offset (Element input)
off NoMore
nm ()
      else let (Chunk input
_, Offset (Element input)
off') = forall input.
ParserSource input =>
input
-> Offset (Element input)
-> (Element input -> Bool)
-> (Chunk input, Offset (Element input))
spanChunk input
buf Offset (Element input)
off Element input -> Bool
predicate
            in if forall input.
ParserSource input =>
input -> Offset (Element input) -> Bool
endOfParserSource input
buf Offset (Element input)
off'
                  then forall input result result'.
ParserSource input =>
Parser input result
-> input
-> Offset (Element input)
-> NoMore
-> Failure input result'
-> Success input result result'
-> Result input result'
runParser_ (forall input.
(ParserSource input, Sequential (Chunk input)) =>
(Element input -> Bool) -> Parser input ()
skipWhile Element input -> Bool
predicate) input
buf Offset (Element input)
off' NoMore
nm Failure input result'
err Success input () result'
ok
                  else Success input () result'
ok input
buf Offset (Element input)
off' NoMore
nm ()

-- | consume every chunk of the stream
--
skipAll :: (ParserSource input, Collection (Chunk input)) => Parser input ()
skipAll :: forall input.
(ParserSource input, Collection (Chunk input)) =>
Parser input ()
skipAll = forall input.
(ParserSource input, Collection (Chunk input)) =>
Parser input ()
flushAll
  where
    flushAll :: (ParserSource input, Collection (Chunk input)) => Parser input ()
    flushAll :: forall input.
(ParserSource input, Collection (Chunk input)) =>
Parser input ()
flushAll = forall input result.
(forall result'.
 input
 -> Offset (Element input)
 -> NoMore
 -> Failure input result'
 -> Success input result result'
 -> Result input result')
-> Parser input result
Parser forall a b. (a -> b) -> a -> b
$ \input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok ->
        let !off' :: Offset (Element input)
off' = forall a. CountOf a -> Offset a
sizeAsOffset forall a b. (a -> b) -> a -> b
$ forall c. Collection c => c -> CountOf (Element c)
length input
buf in
        case NoMore
nm of
            NoMore
NoMore -> Success input () result'
ok input
buf Offset (Element input)
off' NoMore
NoMore ()
            NoMore
More   -> forall input result.
(Chunk input -> Result input result) -> Result input result
ParseMore forall a b. (a -> b) -> a -> b
$ \Chunk input
nextChunk ->
              if forall c. Collection c => c -> Bool
null Chunk input
nextChunk
                then Success input () result'
ok input
buf Offset (Element input)
off' NoMore
NoMore ()
                else forall input result.
Parser input result
-> forall result'.
   input
   -> Offset (Element input)
   -> NoMore
   -> Failure input result'
   -> Success input result result'
   -> Result input result'
runParser forall input.
(ParserSource input, Collection (Chunk input)) =>
Parser input ()
flushAll input
buf Offset (Element input)
off NoMore
nm Failure input result'
err Success input () result'
ok
    {-# NOINLINE flushAll #-}
{-# INLINE skipAll #-}

string :: String -> Parser String ()
string :: String -> Parser String ()
string = forall input.
(ParserSource input, Sequential (Chunk input),
 Element (Chunk input) ~ Element input, Eq (Chunk input)) =>
Chunk input -> Parser input ()
elements
{-# INLINE string #-}

data Condition = Between !And | Exactly !Word
  deriving (Int -> Condition -> ShowS
[Condition] -> ShowS
Condition -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Condition] -> ShowS
$cshowList :: [Condition] -> ShowS
show :: Condition -> String
$cshow :: Condition -> String
showsPrec :: Int -> Condition -> ShowS
$cshowsPrec :: Int -> Condition -> ShowS
Show, Condition -> Condition -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Condition -> Condition -> Bool
$c/= :: Condition -> Condition -> Bool
== :: Condition -> Condition -> Bool
$c== :: Condition -> Condition -> Bool
Eq, Typeable)
data And = And !Word !Word
  deriving (And -> And -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: And -> And -> Bool
$c/= :: And -> And -> Bool
== :: And -> And -> Bool
$c== :: And -> And -> Bool
Eq, Typeable)
instance Show And where
    show :: And -> String
show (And Word
a Word
b) = forall a. Show a => a -> String
show Word
a forall a. Semigroup a => a -> a -> a
<> String
" and " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Word
b

-- | repeat the given parser a given amount of time
--
-- Unlike @some@ or @many@, this operation will bring more precision on how
-- many times you wish a parser to be sequenced.
--
-- ## Repeat @Exactly@ a number of time
--
-- > repeat (Exactly 6) (takeWhile ((/=) ',') <* element ',')
--
-- ## Repeat @Between@ lower `@And@` upper times
--
-- > repeat (Between $ 1 `And` 10) (takeWhile ((/=) ',') <* element ',')
--
repeat :: ParserSource input
       => Condition -> Parser input a -> Parser input [a]
repeat :: forall input a.
ParserSource input =>
Condition -> Parser input a -> Parser input [a]
repeat (Exactly Word
n) = forall input a.
ParserSource input =>
Word -> Parser input a -> Parser input [a]
repeatE Word
n
repeat (Between And
a) = forall input a.
ParserSource input =>
And -> Parser input a -> Parser input [a]
repeatA And
a

repeatE :: (ParserSource input)
        => Word -> Parser input a -> Parser input [a]
repeatE :: forall input a.
ParserSource input =>
Word -> Parser input a -> Parser input [a]
repeatE Word
0 Parser input a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return []
repeatE Word
n Parser input a
p = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser input a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall input a.
ParserSource input =>
Word -> Parser input a -> Parser input [a]
repeatE (Word
nforall a. Subtractive a => a -> a -> Difference a
-Word
1) Parser input a
p

repeatA :: (ParserSource input)
        => And -> Parser input a -> Parser input [a]
repeatA :: forall input a.
ParserSource input =>
And -> Parser input a -> Parser input [a]
repeatA (And Word
0 Word
0) Parser input a
_ = forall (m :: * -> *) a. Monad m => a -> m a
return []
repeatA (And Word
0 Word
n) Parser input a
p = ((:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser input a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall input a.
ParserSource input =>
And -> Parser input a -> Parser input [a]
repeatA (Word -> Word -> And
And Word
0     (Word
nforall a. Subtractive a => a -> a -> Difference a
-Word
1)) Parser input a
p) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (m :: * -> *) a. Monad m => a -> m a
return []
repeatA (And Word
l Word
u) Parser input a
p =  (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser input a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall input a.
ParserSource input =>
And -> Parser input a -> Parser input [a]
repeatA (Word -> Word -> And
And (Word
lforall a. Subtractive a => a -> a -> Difference a
-Word
1) (Word
uforall a. Subtractive a => a -> a -> Difference a
-Word
1)) Parser input a
p