{-# LANGUAGE UnboxedTuples #-}

-- | Basic parser building blocks.

module FlatParse.Stateful.Base
  (
  -- * Bytewise
    eof
  , take
  , take#
  , takeUnsafe#
  , takeRest
  , skip
  , skip#
  , skipBack
  , skipBack#
  , atSkip#
  , atSkipUnsafe#

  -- * Combinators
  , branch
  , notFollowedBy
  , chainl
  , chainr
  , lookahead
  , ensure
  , ensure#
  , withEnsure
  , withEnsure1
  , withEnsure#
  , isolate
  , isolate#
  , isolateUnsafe#

  -- ** Non-specific (TODO)
  , skipMany
  , skipSome

  -- * Errors and failures
  , failed
  , try
  , err
  , withError
  , withAnyResult
  , fails
  , cut
  , cutting
  , optional
  , optional_
  , withOption
  ) where

import Prelude hiding ( take )

import FlatParse.Stateful.Parser
import qualified FlatParse.Common.Assorted as Common

import GHC.Exts
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B
import GHC.ForeignPtr ( ForeignPtr(..) )
import qualified Control.Applicative

-- | The failing parser. By default, parser choice `(<|>)` arbitrarily
--   backtracks on parser failure. This is a synonym for `Control.Applicative.empty`.
failed :: ParserT st r e a
failed :: forall (st :: ZeroBitType) r e a. ParserT st r e a
failed = ParserT st r e a
forall a. ParserT st r e a
forall (f :: * -> *) a. Alternative f => f a
Control.Applicative.empty
{-# inline failed #-}

-- | Throw a parsing error. By default, parser choice `(<|>)` can't backtrack
--   on parser error. Use `try` to convert an error to a recoverable failure.
err :: e -> ParserT st r e a
err :: forall e (st :: ZeroBitType) r a. e -> ParserT st r e a
err e
e = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
_fp !r
_r Addr#
_eob Addr#
_s Int#
_n st
st -> st -> e -> Res# st e a
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st e
e
{-# inline err #-}

-- | Run the parser, if an error is thrown, handle it with the given function.
withError :: ParserT st r e b -> (e -> ParserT st r e b) -> ParserT st r e b
withError :: forall (st :: ZeroBitType) r e b.
ParserT st r e b -> (e -> ParserT st r e b) -> ParserT st r e b
withError (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
f) e -> ParserT st r e b
hdl = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
-> ParserT st r e b
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT ((ForeignPtrContents
  -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
 -> ParserT st r e b)
-> (ForeignPtrContents
    -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
-> ParserT st r e b
forall a b. (a -> b) -> a -> b
$ \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
f ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
  Err# st
st' e
e -> case e -> ParserT st r e b
hdl e
e of
    ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
g -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
g ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st'
  Res# st e b
x -> Res# st e b
x
{-# inline withError #-}

-- | Run the parser, and handle each possible result.
withAnyResult
  :: ParserT st r t a         -- ^ The parser to run.
  -> (a -> ParserT st r e b)  -- ^ The parser to run in case of success.
  -> ParserT st r e b         -- ^ The parser to run in case of failure.
  -> (t -> ParserT st r e b)  -- ^ The parser to run in case of error.
  -> ParserT st r e b
withAnyResult :: forall (st :: ZeroBitType) r t a e b.
ParserT st r t a
-> (a -> ParserT st r e b)
-> ParserT st r e b
-> (t -> ParserT st r e b)
-> ParserT st r e b
withAnyResult (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st t a
first) a -> ParserT st r e b
whenSuccess (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
whenFailure) t -> ParserT st r e b
whenError =
  (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
-> ParserT st r e b
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st t a
first ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
      OK# st
st' a
a Addr#
s' Int#
n' -> ParserT st r e b
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e b
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# (a -> ParserT st r e b
whenSuccess a
a) ForeignPtrContents
fp r
r Addr#
eob Addr#
s' Int#
n' st
st'
      Fail# st
st'       -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
whenFailure ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st'
      Err# st
st' t
e      -> ParserT st r e b
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e b
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# (t -> ParserT st r e b
whenError t
e) ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st'
{-# INLINE withAnyResult #-}

-- | Convert a parsing error into failure.
try :: ParserT st r e a -> ParserT st r e a
try :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e a
try (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
  Err# st
st' e
_ -> st -> Res# st e a
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st'
  Res# st e a
x          -> Res# st e a
x
{-# inline try #-}

-- | Convert a parsing failure to a success.
fails :: ParserT st r e a -> ParserT st r e ()
fails :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
fails (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ())
-> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
  case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
    OK#   st
st' a
_ Addr#
_ Int#
_ -> st -> Res# st e ()
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st'
    Fail# st
st'       -> st -> () -> Addr# -> Int# -> Res# st e ()
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK#   st
st' () Addr#
s Int#
n
    Err#  st
st' e
e     -> st -> e -> Res# st e ()
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err#  st
st' e
e
{-# inline fails #-}

-- | Convert a parsing failure to an error.
cut :: ParserT st r e a -> e -> ParserT st r e a
cut :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> e -> ParserT st r e a
cut (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) e
e = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
  Fail# st
st' -> st -> e -> Res# st e a
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' e
e
  Res# st e a
x         -> Res# st e a
x
{-# inline cut #-}

-- | Run the parser, if we get a failure, throw the given error, but if we get an error, merge the
--   inner and the newly given errors using the @e -> e -> e@ function. This can be useful for
--   implementing parsing errors which may propagate hints or accummulate contextual information.
cutting :: ParserT st r e a -> e -> (e -> e -> e) -> ParserT st r e a
cutting :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> e -> (e -> e -> e) -> ParserT st r e a
cutting (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) e
e e -> e -> e
merge = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
  Fail# st
st'    -> st -> e -> Res# st e a
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' e
e
  Err#  st
st' e
e' -> st -> e -> Res# st e a
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' (e -> Res# st e a) -> e -> Res# st e a
forall a b. (a -> b) -> a -> b
$! e -> e -> e
merge e
e' e
e
  Res# st e a
x            -> Res# st e a
x
{-# inline cutting #-}

-- | Convert a parsing failure to a `Maybe`. If possible, use `withOption`
--   instead.
optional :: ParserT st r e a -> ParserT st r e (Maybe a)
optional :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e (Maybe a)
optional ParserT st r e a
p = (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ParserT st r e a -> ParserT st r e (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParserT st r e a
p) ParserT st r e (Maybe a)
-> ParserT st r e (Maybe a) -> ParserT st r e (Maybe a)
forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e a -> ParserT st r e a
<|> Maybe a -> ParserT st r e (Maybe a)
forall a. a -> ParserT st r e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
{-# inline optional #-}

-- | Convert a parsing failure to a `()`.
optional_ :: ParserT st r e a -> ParserT st r e ()
optional_ :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
optional_ ParserT st r e a
p = (() () -> ParserT st r e a -> ParserT st r e ()
forall a b. a -> ParserT st r e b -> ParserT st r e a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParserT st r e a
p) ParserT st r e () -> ParserT st r e () -> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e a -> ParserT st r e a
<|> () -> ParserT st r e ()
forall a. a -> ParserT st r e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
{-# inline optional_ #-}

-- | CPS'd version of `optional`. This is usually more efficient, since it gets
--   rid of the extra `Maybe` allocation.
withOption
    :: ParserT st r e a -> (a -> ParserT st r e ret)
    -> ParserT st r e ret -> ParserT st r e ret
withOption :: forall (st :: ZeroBitType) r e a ret.
ParserT st r e a
-> (a -> ParserT st r e ret)
-> ParserT st r e ret
-> ParserT st r e ret
withOption (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) a -> ParserT st r e ret
just (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
nothing) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret)
-> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
      OK#   st
st' a
a Addr#
s Int#
n' -> ParserT st r e ret
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e ret
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# (a -> ParserT st r e ret
just a
a) ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n' st
st'
      Fail# st
st'        -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
nothing ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st'
      Err#  st
st' e
e      -> st -> e -> Res# st e ret
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' e
e
{-# inline withOption #-}

--------------------------------------------------------------------------------

-- | Succeed if the input is empty.
eof :: ParserT st r e ()
eof :: forall (st :: ZeroBitType) r e. ParserT st r e ()
eof = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ())
-> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob Addr#
s of
  Int#
1# -> st -> () -> Addr# -> Int# -> Res# st e ()
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK#   st
st () Addr#
s Int#
n
  Int#
_  -> st -> Res# st e ()
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline eof #-}

-- | Save the parsing state, then run a parser, then restore the state.
lookahead :: ParserT st r e a -> ParserT st r e a
lookahead :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e a
lookahead (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
  case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
    OK# st
st' a
a Addr#
_ Int#
n -> st -> a -> Addr# -> Int# -> Res# st e a
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK# st
st' a
a Addr#
s Int#
n
    Res# st e a
x             -> Res# st e a
x
{-# inline lookahead #-}

-- | @isolate n p@ runs the parser @p@ isolated to the next @n@ bytes.
--   All isolated bytes must be consumed.
--
-- Throws a runtime error if given a negative integer.
isolate :: Int -> ParserT st r e a -> ParserT st r e a
isolate :: forall (st :: ZeroBitType) r e a.
Int -> ParserT st r e a -> ParserT st r e a
isolate = (Int# -> ParserT st r e a -> ParserT st r e a)
-> Int -> ParserT st r e a -> ParserT st r e a
forall r. (Int# -> r) -> Int -> r
Common.withIntUnwrap# Int# -> ParserT st r e a -> ParserT st r e a
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
isolate#
{-# inline isolate #-}

-- | @isolate# n# p@ runs the parser @p@ isolated to the next @n#@ bytes.
--   All isolated bytes must be consumed.
--
-- Throws a runtime error if given a negative integer.
isolate# :: Int# -> ParserT st r e a -> ParserT st r e a
isolate# :: forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
isolate# Int#
n# ParserT st r e a
p = Int# -> ParserT st r e a -> ParserT st r e a
forall r. Int# -> r -> r
Common.withPosInt# Int#
n# (Int# -> ParserT st r e a -> ParserT st r e a
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
isolateUnsafe# Int#
n# ParserT st r e a
p)
{-# inline isolate# #-}

-- | @isolateUnsafe# i# p@ runs the parser @p@ isolated to the next @i#@ bytes.
--   All isolated bytes must be consumed.
--
-- Undefined behaviour if given a negative integer.
isolateUnsafe# :: Int# -> ParserT st r e ret -> ParserT st r e ret
isolateUnsafe# :: forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
isolateUnsafe# Int#
i# (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p) =
    Int# -> ParserT st r e ret -> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
withEnsure# Int#
i# (ParserT st r e ret -> ParserT st r e ret)
-> ParserT st r e ret -> ParserT st r e ret
forall a b. (a -> b) -> a -> b
$ (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret)
-> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
        let s' :: Addr#
s' = Addr# -> Int# -> Addr#
plusAddr# Addr#
s Int#
i#
        in  case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p ForeignPtrContents
fp r
r Addr#
s' Addr#
s Int#
n st
st of
              OK# st
st' ret
a Addr#
s'' Int#
n' ->
                case Addr# -> Addr# -> Int#
eqAddr# Addr#
s' Addr#
s'' of
                  Int#
1# -> st -> ret -> Addr# -> Int# -> Res# st e ret
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK#   st
st' ret
a Addr#
s'' Int#
n'
                  Int#
_  -> st -> Res# st e ret
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st'
              Res# st e ret
x -> Res# st e ret
x
{-# inline isolateUnsafe# #-}

-- | An analogue of the list `foldl` function: first parse a @b@, then parse zero or more @a@-s,
--   and combine the results in a left-nested way by the @b -> a -> b@ function. Note: this is not
--   the usual `chainl` function from the parsec libraries!
chainl :: (b -> a -> b) -> ParserT st r e b -> ParserT st r e a -> ParserT st r e b
chainl :: forall b a (st :: ZeroBitType) r e.
(b -> a -> b)
-> ParserT st r e b -> ParserT st r e a -> ParserT st r e b
chainl b -> a -> b
f ParserT st r e b
start ParserT st r e a
elem = ParserT st r e b
start ParserT st r e b -> (b -> ParserT st r e b) -> ParserT st r e b
forall a b.
ParserT st r e a -> (a -> ParserT st r e b) -> ParserT st r e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= b -> ParserT st r e b
go where
  go :: b -> ParserT st r e b
go b
b = ParserT st r e a
-> (a -> ParserT st r e b) -> ParserT st r e b -> ParserT st r e b
forall (st :: ZeroBitType) r e a ret.
ParserT st r e a
-> (a -> ParserT st r e ret)
-> ParserT st r e ret
-> ParserT st r e ret
withOption ParserT st r e a
elem (\ !a
a -> b -> ParserT st r e b
go (b -> ParserT st r e b) -> b -> ParserT st r e b
forall a b. (a -> b) -> a -> b
$! b -> a -> b
f b
b a
a) (b -> ParserT st r e b
forall a. a -> ParserT st r e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
b)
{-# inline chainl #-}

-- | An analogue of the list `foldr` function: parse zero or more @a@-s, terminated by a @b@, and
--   combine the results in a right-nested way using the @a -> b -> b@ function. Note: this is not
--   the usual `chainr` function from the parsec libraries!
chainr :: (a -> b -> b) -> ParserT st r e a -> ParserT st r e b -> ParserT st r e b
chainr :: forall a b (st :: ZeroBitType) r e.
(a -> b -> b)
-> ParserT st r e a -> ParserT st r e b -> ParserT st r e b
chainr a -> b -> b
f (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
elem) (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
end) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
-> ParserT st r e b
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
go where
  go :: ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
go ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st = case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
elem ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
    OK#   st
st' a
a Addr#
s' Int#
n' -> case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
go ForeignPtrContents
fp r
r Addr#
eob Addr#
s' Int#
n' st
st' of
      OK# st
st'' b
b Addr#
s'' Int#
n'' -> let !b' :: b
b' = a -> b -> b
f a
a b
b in st -> b -> Addr# -> Int# -> Res# st e b
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK# st
st'' b
b' Addr#
s'' Int#
n''
      Res# st e b
x                  -> Res# st e b
x
    Fail# st
st'        -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b
end ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st'
    Err#  st
st' e
e      -> st -> e -> Res# st e b
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' e
e
{-# inline chainr #-}

-- | Branch on a parser: if the first argument succeeds, continue with the second, else with the third.
--   This can produce slightly more efficient code than `(<|>)`. Moreover, `ḃranch` does not
--   backtrack from the true/false cases.
branch :: ParserT st r e a -> ParserT st r e b -> ParserT st r e b -> ParserT st r e b
branch :: forall (st :: ZeroBitType) r e a b.
ParserT st r e a
-> ParserT st r e b -> ParserT st r e b -> ParserT st r e b
branch ParserT st r e a
pa ParserT st r e b
pt ParserT st r e b
pf = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e b)
-> ParserT st r e b
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st -> case ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# ParserT st r e a
pa ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
  OK#   st
st' a
_ Addr#
s Int#
n' -> ParserT st r e b
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e b
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# ParserT st r e b
pt ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n' st
st'
  Fail# st
st'        -> ParserT st r e b
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e b
forall (st :: ZeroBitType) r e a.
ParserT st r e a
-> ForeignPtrContents
-> r
-> Addr#
-> Addr#
-> Int#
-> st
-> Res# st e a
runParserT# ParserT st r e b
pf ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n  st
st'
  Err#  st
st' e
e      -> st -> e -> Res# st e b
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st' e
e
{-# inline branch #-}

-- | Succeed if the first parser succeeds and the second one fails.
notFollowedBy :: ParserT st r e a -> ParserT st r e b -> ParserT st r e a
notFollowedBy :: forall (st :: ZeroBitType) r e a b.
ParserT st r e a -> ParserT st r e b -> ParserT st r e a
notFollowedBy ParserT st r e a
p1 ParserT st r e b
p2 = ParserT st r e a
p1 ParserT st r e a -> ParserT st r e () -> ParserT st r e a
forall a b.
ParserT st r e a -> ParserT st r e b -> ParserT st r e a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParserT st r e b -> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
fails ParserT st r e b
p2
{-# inline notFollowedBy #-}

--------------------------------------------------------------------------------

-- | Assert that there are at least @n@ bytes remaining.
--
-- Undefined behaviour if given a negative integer.
ensure :: Int -> ParserT st r e ()
ensure :: forall (st :: ZeroBitType) r e. Int -> ParserT st r e ()
ensure = (Int# -> ParserT st r e ()) -> Int -> ParserT st r e ()
forall r. (Int# -> r) -> Int -> r
Common.withIntUnwrap# Int# -> ParserT st r e ()
forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
ensure#
{-# inline ensure #-}

-- | Assert that there are at least @n#@ bytes remaining.
--
-- Undefined behaviour if given a negative integer.
ensure# :: Int# -> ParserT st r e ()
ensure# :: forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
ensure# Int#
n# = Int# -> ParserT st r e () -> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
withEnsure# Int#
n# (() -> ParserT st r e ()
forall a. a -> ParserT st r e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
{-# inline ensure# #-}

-- TODO: András: withEnsure operations seem superfluous to me?
-- There's no unboxing in vanilla ensure that could be broken.

-- | Assert that there are at least @n#@ bytes remaining (CPS).
--
-- Undefined behaviour if given a negative integer.
withEnsure :: Int -> ParserT st r e ret -> ParserT st r e ret
withEnsure :: forall (st :: ZeroBitType) r e a.
Int -> ParserT st r e a -> ParserT st r e a
withEnsure = (Int# -> ParserT st r e ret -> ParserT st r e ret)
-> Int -> ParserT st r e ret -> ParserT st r e ret
forall r. (Int# -> r) -> Int -> r
Common.withIntUnwrap# Int# -> ParserT st r e ret -> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
withEnsure#
{-# inline withEnsure #-}

-- | Assert that there is at least 1 byte remaining (CPS).
--
-- Undefined behaviour if given a negative integer.
withEnsure1 :: ParserT st r e ret -> ParserT st r e ret
withEnsure1 :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e a
withEnsure1 (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret)
-> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob Addr#
s of
      Int#
0# -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st
      Int#
_  -> st -> Res# st e ret
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline withEnsure1 #-}

-- | Assert that there are at least @n#@ bytes remaining (CPS).
--
-- Undefined behaviour if given a negative integer.
withEnsure# :: Int# -> ParserT st r e ret -> ParserT st r e ret
withEnsure# :: forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
withEnsure# Int#
n# (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret)
-> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    case Int#
n# Int# -> Int# -> Int#
<=# Addr# -> Addr# -> Int#
minusAddr# Addr#
eob Addr#
s of
      Int#
1# -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st
      Int#
_  -> st -> Res# st e ret
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline withEnsure# #-}

--------------------------------------------------------------------------------

-- | Read @n@ bytes as a 'ByteString'. Fails if fewer than @n@ bytes are
--   available.
--
-- Throws a runtime error if given a negative integer.
--
-- This does no copying. The 'B.ByteString' returned is a "slice" of the input,
-- and will keep it alive. To avoid this, use 'B.copy' on the output.
take :: Int -> ParserT st r e B.ByteString
take :: forall (st :: ZeroBitType) r e. Int -> ParserT st r e ByteString
take (I# Int#
n#) = Int# -> ParserT st r e ByteString
forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ByteString
take# Int#
n#
{-# inline take #-}

-- | Read @n#@ bytes as a 'ByteString'. Fails if fewer than @n#@ bytes are
--   available.
--
-- Throws a runtime error if given a negative integer.
--
-- This does no copying. The 'B.ByteString' returned is a "slice" of the input,
-- and will keep it alive. To avoid this, use 'B.copy' on the output.
take# :: Int# -> ParserT st r e B.ByteString
take# :: forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ByteString
take# Int#
n# = Int# -> ParserT st r e ByteString -> ParserT st r e ByteString
forall r. Int# -> r -> r
Common.withPosInt# Int#
n# (Int# -> ParserT st r e ByteString
forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ByteString
takeUnsafe# Int#
n#)
{-# inline take# #-}

-- | Read @i#@ bytes as a 'ByteString'. Fails if newer than @i#@ bytes are
--   available.
--
-- Undefined behaviour if given a negative integer.
--
-- This does no copying. The 'B.ByteString' returned is a "slice" of the input,
-- and will keep it alive. To avoid this, use 'B.copy' on the output.
takeUnsafe# :: Int# -> ParserT st r e B.ByteString
takeUnsafe# :: forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ByteString
takeUnsafe# Int#
i# = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ByteString)
-> ParserT st r e ByteString
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    case Int#
i# Int# -> Int# -> Int#
<=# Addr# -> Addr# -> Int#
minusAddr# Addr#
eob Addr#
s of
      Int#
1# -> st -> ByteString -> Addr# -> Int# -> Res# st e ByteString
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK#   st
st (ForeignPtr Word8 -> Int -> Int -> ByteString
B.PS (Addr# -> ForeignPtrContents -> ForeignPtr Word8
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
s ForeignPtrContents
fp) Int
0 (Int# -> Int
I# Int#
i#)) (Addr# -> Int# -> Addr#
plusAddr# Addr#
s Int#
i#) Int#
n
      Int#
_  -> st -> Res# st e ByteString
forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline takeUnsafe# #-}

-- | Consume the rest of the input. May return the empty bytestring.
--
-- This does no copying. The 'B.ByteString' returned is a "slice" of the input,
-- and will keep it alive. To avoid this, use 'B.copy' on the output.
takeRest :: ParserT st r e B.ByteString
takeRest :: forall (st :: ZeroBitType) r e. ParserT st r e ByteString
takeRest = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ByteString)
-> ParserT st r e ByteString
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
  let i# :: Int#
i# = Addr# -> Addr# -> Int#
minusAddr# Addr#
eob Addr#
s
  in  st -> ByteString -> Addr# -> Int# -> Res# st e ByteString
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK# st
st (ForeignPtr Word8 -> Int -> Int -> ByteString
B.PS (Addr# -> ForeignPtrContents -> ForeignPtr Word8
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
s ForeignPtrContents
fp) Int
0 (Int# -> Int
I# Int#
i#)) Addr#
eob Int#
n
{-# inline takeRest #-}

-- | Skip forward @n@ bytes. Fails if fewer than @n@ bytes are available.
--
-- Throws a runtime error if given a negative integer.
skip :: Int -> ParserT st r e ()
skip :: forall (st :: ZeroBitType) r e. Int -> ParserT st r e ()
skip (I# Int#
n#) = Int# -> ParserT st r e ()
forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
skip# Int#
n#
{-# inline skip #-}

-- | Skip forward @n@ bytes. Fails if fewer than @n@ bytes are available.
--
-- Throws a runtime error if given a negative integer.
skip# :: Int# -> ParserT st r e ()
skip# :: forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
skip# Int#
n# = Int# -> ParserT st r e () -> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
atSkip# Int#
n# (() -> ParserT st r e ()
forall a. a -> ParserT st r e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
{-# inline skip# #-}

-- | Go back @i@ bytes in the input. Takes a positive integer.
--
-- Extremely unsafe. Makes no checks. Almost certainly a Bad Idea.
skipBack :: Int -> ParserT st r e ()
skipBack :: forall (st :: ZeroBitType) r e. Int -> ParserT st r e ()
skipBack = (Int# -> ParserT st r e ()) -> Int -> ParserT st r e ()
forall r. (Int# -> r) -> Int -> r
Common.withIntUnwrap# Int# -> ParserT st r e ()
forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
skipBack#
{-# inline skipBack #-}

-- | Go back @i#@ bytes in the input. Takes a positive integer.
--
-- Extremely unsafe. Makes no checks. Almost certainly a Bad Idea.
skipBack# :: Int# -> ParserT st r e ()
skipBack# :: forall (st :: ZeroBitType) r e. Int# -> ParserT st r e ()
skipBack# Int#
i# = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ())
-> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
    st -> () -> Addr# -> Int# -> Res# st e ()
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK# st
st () (Addr# -> Int# -> Addr#
plusAddr# Addr#
s (Int# -> Int#
negateInt# Int#
i#)) Int#
n
{-# inline skipBack# #-}

-- | Skip forward @n#@ bytes and run the given parser. Fails if fewer than @n#@
--   bytes are available.
--
-- Throws a runtime error if given a negative integer.
atSkip# :: Int# -> ParserT st r e ret -> ParserT st r e ret
atSkip# :: forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
atSkip# Int#
n# ParserT st r e ret
p = Int# -> ParserT st r e ret -> ParserT st r e ret
forall r. Int# -> r -> r
Common.withPosInt# Int#
n# (Int# -> ParserT st r e ret -> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
atSkipUnsafe# Int#
n# ParserT st r e ret
p)
{-# inline atSkip# #-}

-- | Skip forward @i#@ bytes and run the given parser. Fails if fewer than @i@
--   bytes are available.
--
-- Undefined behaviour if given a negative integer.
atSkipUnsafe# :: Int# -> ParserT st r e ret -> ParserT st r e ret
atSkipUnsafe# :: forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
atSkipUnsafe# Int#
i# (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p) =
    Int# -> ParserT st r e ret -> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
Int# -> ParserT st r e a -> ParserT st r e a
withEnsure# Int#
i# (ParserT st r e ret -> ParserT st r e ret)
-> ParserT st r e ret -> ParserT st r e ret
forall a b. (a -> b) -> a -> b
$ (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret)
-> ParserT st r e ret
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT \ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st ->
        ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ret
p ForeignPtrContents
fp r
r Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
s Int#
i#) Int#
n st
st
{-# inline atSkipUnsafe# #-}

--------------------------------------------------------------------------------

-- | Skip a parser zero or more times.
skipMany :: ParserT st r e a -> ParserT st r e ()
skipMany :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
skipMany (ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
f) = (ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ())
-> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
(ForeignPtrContents
 -> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a)
-> ParserT st r e a
ParserT ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ()
go where
  go :: ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ()
go ForeignPtrContents
fp !r
r Addr#
eob Addr#
s Int#
n st
st = case ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e a
f ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st of
    OK# st
st a
a Addr#
s Int#
n -> ForeignPtrContents
-> r -> Addr# -> Addr# -> Int# -> st -> Res# st e ()
go ForeignPtrContents
fp r
r Addr#
eob Addr#
s Int#
n st
st
    Fail# st
st     -> st -> () -> Addr# -> Int# -> Res# st e ()
forall (st :: ZeroBitType) a e.
st -> a -> Addr# -> Int# -> Res# st e a
OK# st
st () Addr#
s Int#
n
    Err# st
st e
e    -> st -> e -> Res# st e ()
forall (st :: ZeroBitType) e a. st -> e -> Res# st e a
Err# st
st e
e
{-# inline skipMany #-}

-- TODO identical to one from parser-combinators
-- | Skip a parser one or more times.
skipSome :: ParserT st r e a -> ParserT st r e ()
skipSome :: forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
skipSome ParserT st r e a
p = ParserT st r e a
p ParserT st r e a -> ParserT st r e () -> ParserT st r e ()
forall a b.
ParserT st r e a -> ParserT st r e b -> ParserT st r e b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParserT st r e a -> ParserT st r e ()
forall (st :: ZeroBitType) r e a.
ParserT st r e a -> ParserT st r e ()
skipMany ParserT st r e a
p
{-# inline skipSome #-}