{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}

-- | A backtracking parser over the bytes of UTF-8 encoded text.
--
-- This module is intended for internal use only, and may change without warning
-- in subsequent releases.
module Yamlet.Internal.Parser.Monad
  ( -- * Parser
    P
  , Env (..)
  , ParseError (..)
  , runParser

    -- * Combinators
  , (<|>)
  , many
  , many_
  , optional
  , optional_
  , option
  , notFollowedBy

    -- * Primitives
  , env
  , pos
  , setPos
  , furthest
  , advance
  , addTagBytes
  , peek
  , peekAt
  , failure
  , guardP
  , throwAt
  , throwUnexpected
  , withEnd
  , withHandles
  , char
  , skipWhile
  , scan
  , Scanned (..)
  , withScan

    -- * Input access
  , byteAt
  , byteBefore
  , slice
  , toOffset
  ) where

import Control.Monad
import Data.Map.Strict qualified as M
import Data.Text qualified as T
import Data.Text.Array qualified as A
import Data.Text.Internal qualified as T
import Data.Word
import GHC.Exts (Int (I#), Int#, isTrue#, (+#), (>#))

import Yamlet.Internal.Syntax

-- | The input of the parser.
data Env = Env
  { Env -> Array
array :: !A.Array
  , Env -> Int
base :: !Int
  -- ^ The index of the first byte of the input.
  , Env -> Int
end :: !Int
  -- ^ The index past the last byte that the parser can read.
  , Env -> Int
streamEnd :: !Int
  -- ^ The index past the last byte of the input. A document ends before it
  -- at a document marker.
  , Env -> Map Text Text
handles :: !(M.Map T.Text T.Text)
  -- ^ The tag handles of the current document.
  }

-- | An error that no backtracking can recover from: an error at the index
-- with the message, or a failure at the index in the environment, whose
-- message the caller of the parser finds.
data ParseError
  = ParseError !Int !String
  | UnexpectedParseError !Env !Int

-- | The result of a parser: a value with the new position, a failure, or an
-- error. Both the value and the failure carry the furthest position at which
-- a parser failed, the likely location of a syntax error. The value also
-- carries the bytes that the prefixes of @%TAG@ directives added to the tags,
-- see 'addTagBytes'.
type Res# a = (# (# a, Int#, Int#, Int# #) | Int# | ParseError #)

pattern OK# :: a -> Int# -> Int# -> Int# -> Res# a
pattern $bOK# :: forall a. a -> Int# -> Int# -> Int# -> Res# a
$mOK# :: forall {r} {a}.
Res# a -> (a -> Int# -> Int# -> Int# -> r) -> ((# #) -> r) -> r
OK# a p f t = (# (# a, p, f, t #) | | #)

pattern Fail# :: Int# -> Res# a
pattern $bFail# :: forall a. Int# -> Res# a
$mFail# :: forall {r} {a}. Res# a -> (Int# -> r) -> ((# #) -> r) -> r
Fail# f = (# | f | #)

pattern Err# :: ParseError -> Res# a
pattern $bErr# :: forall a. ParseError -> Res# a
$mErr# :: forall {r} {a}. Res# a -> (ParseError -> r) -> ((# #) -> r) -> r
Err# e = (# | | e #)

{-# COMPLETE OK#, Fail#, Err# #-}

newtype P a = P (Env -> Int# -> Int# -> Int# -> Res# a)

runP :: P a -> Env -> Int# -> Int# -> Int# -> Res# a
runP :: forall a. P a -> Env -> Int# -> Int# -> Int# -> Res# a
runP (P Env -> Int# -> Int# -> Int# -> Res# a
g) = Env -> Int# -> Int# -> Int# -> Res# a
g

instance Functor P where
  fmap :: forall a b. (a -> b) -> P a -> P b
fmap a -> b
f (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# b) -> P b)
-> (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
    OK# a
a Int#
p' Int#
fu' Int#
t' -> b -> Int# -> Int# -> Int# -> Res# b
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (a -> b
f a
a) Int#
p' Int#
fu' Int#
t'
    Fail# Int#
fu' -> Int# -> Res# b
forall a. Int# -> Res# a
Fail# Int#
fu'
    Err# ParseError
err -> ParseError -> Res# b
forall a. ParseError -> Res# a
Err# ParseError
err

instance Applicative P where
  pure :: forall a. a -> P a
pure a
a = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
t -> a -> Int# -> Int# -> Int# -> Res# a
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# a
a Int#
p Int#
fu Int#
t
  <*> :: forall a b. P (a -> b) -> P a -> P b
(<*>) = P (a -> b) -> P a -> P b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
  P Env -> Int# -> Int# -> Int# -> Res# a
g *> :: forall a b. P a -> P b -> P b
*> P Env -> Int# -> Int# -> Int# -> Res# b
h = (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# b) -> P b)
-> (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
    OK# a
_ Int#
p' Int#
fu' Int#
t' -> Env -> Int# -> Int# -> Int# -> Res# b
h Env
e Int#
p' Int#
fu' Int#
t'
    Fail# Int#
fu' -> Int# -> Res# b
forall a. Int# -> Res# a
Fail# Int#
fu'
    Err# ParseError
err -> ParseError -> Res# b
forall a. ParseError -> Res# a
Err# ParseError
err

  -- The default builds the result with 'fmap' and '<*>'.
  P Env -> Int# -> Int# -> Int# -> Res# a
g <* :: forall a b. P a -> P b -> P a
<* P Env -> Int# -> Int# -> Int# -> Res# b
h = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
    OK# a
a Int#
p' Int#
fu' Int#
t' -> case Env -> Int# -> Int# -> Int# -> Res# b
h Env
e Int#
p' Int#
fu' Int#
t' of
      OK# b
_ Int#
p'' Int#
fu'' Int#
t'' -> a -> Int# -> Int# -> Int# -> Res# a
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# a
a Int#
p'' Int#
fu'' Int#
t''
      Fail# Int#
fu'' -> Int# -> Res# a
forall a. Int# -> Res# a
Fail# Int#
fu''
      Err# ParseError
err -> ParseError -> Res# a
forall a. ParseError -> Res# a
Err# ParseError
err
    Fail# Int#
fu' -> Int# -> Res# a
forall a. Int# -> Res# a
Fail# Int#
fu'
    Err# ParseError
err -> ParseError -> Res# a
forall a. ParseError -> Res# a
Err# ParseError
err

instance Monad P where
  P Env -> Int# -> Int# -> Int# -> Res# a
g >>= :: forall a b. P a -> (a -> P b) -> P b
>>= a -> P b
k = (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# b) -> P b)
-> (Env -> Int# -> Int# -> Int# -> Res# b) -> P b
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
    OK# a
a Int#
p' Int#
fu' Int#
t' -> P b -> Env -> Int# -> Int# -> Int# -> Res# b
forall a. P a -> Env -> Int# -> Int# -> Int# -> Res# a
runP (a -> P b
k a
a) Env
e Int#
p' Int#
fu' Int#
t'
    Fail# Int#
fu' -> Int# -> Res# b
forall a. Int# -> Res# a
Fail# Int#
fu'
    Err# ParseError
err -> ParseError -> Res# b
forall a. ParseError -> Res# a
Err# ParseError
err

-- | Run a parser from the given index. Return the result, the index after it
-- and the furthest failure.
runParser :: Env -> Int -> P a -> Either ParseError (Maybe a, Int, Int)
runParser :: forall a.
Env -> Int -> P a -> Either ParseError (Maybe a, Int, Int)
runParser Env
e (I# Int#
p) (P Env -> Int# -> Int# -> Int# -> Res# a
g) = case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
p Int#
0# of
  OK# a
a Int#
p' Int#
fu Int#
_ -> (Maybe a, Int, Int) -> Either ParseError (Maybe a, Int, Int)
forall a b. b -> Either a b
Right (a -> Maybe a
forall a. a -> Maybe a
Just a
a, Int# -> Int
I# Int#
p', Int# -> Int
I# Int#
fu)
  Fail# Int#
fu -> (Maybe a, Int, Int) -> Either ParseError (Maybe a, Int, Int)
forall a b. b -> Either a b
Right (Maybe a
forall a. Maybe a
Nothing, Int# -> Int
I# Int#
p, Int# -> Int
I# Int#
fu)
  Err# ParseError
err -> ParseError -> Either ParseError (Maybe a, Int, Int)
forall a b. a -> Either a b
Left ParseError
err

----------------------------------------
-- Combinators

infixl 3 <|>

-- | Ordered choice. Try the second parser if the first one fails.
(<|>) :: P a -> P a -> P a
P Env -> Int# -> Int# -> Int# -> Res# a
g <|> :: forall a. P a -> P a -> P a
<|> P Env -> Int# -> Int# -> Int# -> Res# a
h = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
  Fail# Int#
fu' -> Env -> Int# -> Int# -> Int# -> Res# a
h Env
e Int#
p Int#
fu' Int#
t
  Res# a
r -> Res# a
r

-- | Zero or more times. Stop if the parser succeeds without input.
many :: P a -> P [a]
many :: forall a. P a -> P [a]
many (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# [a]) -> P [a]
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# [a]) -> P [a])
-> (Env -> Int# -> Int# -> Int# -> Res# [a]) -> P [a]
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p0 Int#
fu0 Int#
t0 ->
  let go :: [a] -> Int# -> Int# -> Int# -> Res# [a]
go [a]
acc Int#
p Int#
fu Int#
t = case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
        OK# a
a Int#
p' Int#
fu' Int#
t'
          | Int# -> Bool
isTrue# (Int#
p' Int# -> Int# -> Int#
># Int#
p) -> [a] -> Int# -> Int# -> Int# -> Res# [a]
go (a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
acc) Int#
p' Int#
fu' Int#
t'
          | Bool
otherwise -> [a] -> Int# -> Int# -> Int# -> Res# [a]
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
acc) Int#
p Int#
fu' Int#
t
        Fail# Int#
fu' -> [a] -> Int# -> Int# -> Int# -> Res# [a]
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
acc) Int#
p Int#
fu' Int#
t
        Err# ParseError
err -> ParseError -> Res# [a]
forall a. ParseError -> Res# a
Err# ParseError
err
  in [a] -> Int# -> Int# -> Int# -> Res# [a]
go [] Int#
p0 Int#
fu0 Int#
t0

-- | Zero or more times, discard the results.
many_ :: P a -> P ()
many_ :: forall a. P a -> P ()
many_ (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p0 Int#
fu0 Int#
t0 ->
  let go :: Int# -> Int# -> Int# -> Res# ()
go Int#
p Int#
fu Int#
t = case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
        OK# a
_ Int#
p' Int#
fu' Int#
t'
          | Int# -> Bool
isTrue# (Int#
p' Int# -> Int# -> Int#
># Int#
p) -> Int# -> Int# -> Int# -> Res# ()
go Int#
p' Int#
fu' Int#
t'
          | Bool
otherwise -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p Int#
fu' Int#
t
        Fail# Int#
fu' -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p Int#
fu' Int#
t
        Err# ParseError
err -> ParseError -> Res# ()
forall a. ParseError -> Res# a
Err# ParseError
err
  in Int# -> Int# -> Int# -> Res# ()
go Int#
p0 Int#
fu0 Int#
t0

optional :: P a -> P (Maybe a)
optional :: forall a. P a -> P (Maybe a)
optional P a
p = (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> P a -> P (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> P a
p) P (Maybe a) -> P (Maybe a) -> P (Maybe a)
forall a. P a -> P a -> P a
<|> Maybe a -> P (Maybe a)
forall a. a -> P a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing

optional_ :: P a -> P ()
optional_ :: forall a. P a -> P ()
optional_ P a
p = P a -> P ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void P a
p P () -> P () -> P ()
forall a. P a -> P a -> P a
<|> () -> P ()
forall a. a -> P a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

option :: a -> P a -> P a
option :: forall a. a -> P a -> P a
option a
a P a
p = P a
p P a -> P a -> P a
forall a. P a -> P a -> P a
<|> a -> P a
forall a. a -> P a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

-- | Succeed without input if the parser fails. An error of the parser stays
-- an error, as in '<|>'.
notFollowedBy :: P a -> P ()
notFollowedBy :: forall a. P a -> P ()
notFollowedBy (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int# -> Int# -> Int# -> Res# a
g Env
e Int#
p Int#
fu Int#
t of
  OK# {} -> Int# -> Res# ()
forall a. Int# -> Res# a
Fail# (Int# -> Int# -> Int#
furthestOf Int#
p Int#
fu)
  Fail# Int#
_ -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p Int#
fu Int#
t
  Err# ParseError
err -> ParseError -> Res# ()
forall a. ParseError -> Res# a
Err# ParseError
err

-- | The furthest of a position where the parser failed and the furthest
-- failure so far.
furthestOf :: Int# -> Int# -> Int#
furthestOf :: Int# -> Int# -> Int#
furthestOf Int#
p Int#
fu = if Int# -> Bool
isTrue# (Int#
p Int# -> Int# -> Int#
># Int#
fu) then Int#
p else Int#
fu

----------------------------------------
-- Primitives

env :: P Env
env :: P Env
env = (Env -> Int# -> Int# -> Int# -> Res# Env) -> P Env
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Env) -> P Env)
-> (Env -> Int# -> Int# -> Int# -> Res# Env) -> P Env
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> Env -> Int# -> Int# -> Int# -> Res# Env
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# Env
e Int#
p Int#
fu Int#
t

pos :: P Int
pos :: P Int
pos = (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int)
-> (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
t -> Int -> Int# -> Int# -> Int# -> Res# Int
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (Int# -> Int
I# Int#
p) Int#
p Int#
fu Int#
t

setPos :: Int -> P ()
setPos :: Int -> P ()
setPos (I# Int#
p) = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
_ Int#
fu Int#
t -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p Int#
fu Int#
t

-- | The furthest position at which a parser failed so far.
furthest :: P Int
furthest :: P Int
furthest = (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int)
-> (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
t -> Int -> Int# -> Int# -> Int# -> Res# Int
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (Int# -> Int
I# Int#
fu) Int#
p Int#
fu Int#
t

advance :: Int -> P ()
advance :: Int -> P ()
advance (I# Int#
n) = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
t -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () (Int#
p Int# -> Int# -> Int#
+# Int#
n) Int#
fu Int#
t

-- | Add the bytes that the prefix of a @%TAG@ directive adds to a tag, and
-- return the bytes that such prefixes added so far. A parser that fails
-- drops its bytes, so only the tags of the result count.
addTagBytes :: Int -> P Int
addTagBytes :: Int -> P Int
addTagBytes (I# Int#
n) = (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int)
-> (Env -> Int# -> Int# -> Int# -> Res# Int) -> P Int
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
t -> let t' :: Int#
t' = Int#
t Int# -> Int# -> Int#
+# Int#
n in Int -> Int# -> Int# -> Int# -> Res# Int
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (Int# -> Int
I# Int#
t') Int#
p Int#
fu Int#
t'

-- | The byte at the current position, 0 at the end of the input.
peek :: P Word8
peek :: P Word8
peek = (Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8)
-> (Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> Word8 -> Int# -> Int# -> Int# -> Res# Word8
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (Env -> Int -> Word8
byteAt Env
e (Int# -> Int
I# Int#
p)) Int#
p Int#
fu Int#
t

-- | The byte at the given distance from the current position.
peekAt :: Int -> P Word8
peekAt :: Int -> P Word8
peekAt Int
k = (Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8)
-> (Env -> Int# -> Int# -> Int# -> Res# Word8) -> P Word8
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> Word8 -> Int# -> Int# -> Int# -> Res# Word8
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# (Env -> Int -> Word8
byteAt Env
e (Int# -> Int
I# Int#
p Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k)) Int#
p Int#
fu Int#
t

failure :: P a
failure :: forall a. P a
failure = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
p Int#
fu Int#
_ -> Int# -> Res# a
forall a. Int# -> Res# a
Fail# (Int# -> Int# -> Int#
furthestOf Int#
p Int#
fu)

guardP :: Bool -> P ()
guardP :: Bool -> P ()
guardP Bool
b = Bool -> P () -> P ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
b P ()
forall a. P a
failure

-- | Stop with an error at the given index.
throwAt :: Int -> String -> P a
throwAt :: forall a. Int -> String -> P a
throwAt Int
i String
msg = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
_ Int#
_ Int#
_ Int#
_ -> ParseError -> Res# a
forall a. ParseError -> Res# a
Err# (Int -> String -> ParseError
ParseError Int
i String
msg)

-- | Stop at the index, with an error whose message the caller of the parser
-- finds.
throwUnexpected :: Int -> P a
throwUnexpected :: forall a. Int -> P a
throwUnexpected Int
i = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
_ Int#
_ Int#
_ -> ParseError -> Res# a
forall a. ParseError -> Res# a
Err# (Env -> Int -> ParseError
UnexpectedParseError Env
e Int
i)

-- | Run a parser that cannot read past the given index.
withEnd :: Int -> P a -> P a
withEnd :: forall a. Int -> P a -> P a
withEnd Int
end (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> Env -> Int# -> Int# -> Int# -> Res# a
g Env
e {end = end} Int#
p Int#
fu Int#
t

withHandles :: M.Map T.Text T.Text -> P a -> P a
withHandles :: forall a. Map Text Text -> P a -> P a
withHandles Map Text Text
hs (P Env -> Int# -> Int# -> Int# -> Res# a
g) = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> Env -> Int# -> Int# -> Int# -> Res# a
g Env
e {handles = hs} Int#
p Int#
fu Int#
t

char :: Word8 -> P ()
char :: Word8 -> P ()
char Word8
w = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t ->
  if Env -> Int -> Word8
byteAt Env
e (Int# -> Int
I# Int#
p) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
w
    then () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () (Int#
p Int# -> Int# -> Int#
+# Int#
1#) Int#
fu Int#
t
    else Int# -> Res# ()
forall a. Int# -> Res# a
Fail# (Int# -> Int# -> Int#
furthestOf Int#
p Int#
fu)

skipWhile :: (Word8 -> Bool) -> P ()
skipWhile :: (Word8 -> Bool) -> P ()
skipWhile Word8 -> Bool
f = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t ->
  let go :: Int -> Int
go Int
i = if Word8 -> Bool
f (Env -> Int -> Word8
byteAt Env
e Int
i) then Int -> Int
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) else Int
i
  in case Int -> Int
go (Int# -> Int
I# Int#
p) of I# Int#
p' -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p' Int#
fu Int#
t

-- | The result of a scanning loop.
data Scanned a
  = -- | The value and the index after it.
    Done !Int !a
  | -- | The input does not match. The index is the location of the mismatch.
    NoMatch !Int
  | -- | An error at the index.
    Failed !Int !String

-- | Run a pure loop over the input from the current position.
withScan :: (Env -> Int -> Scanned a) -> P a
withScan :: forall a. (Env -> Int -> Scanned a) -> P a
withScan Env -> Int -> Scanned a
f = (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# a) -> P a)
-> (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int -> Scanned a
f Env
e (Int# -> Int
I# Int#
p) of
  Done (I# Int#
q) a
a -> a -> Int# -> Int# -> Int# -> Res# a
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# a
a Int#
q Int#
fu Int#
t
  NoMatch (I# Int#
q) -> Int# -> Res# a
forall a. Int# -> Res# a
Fail# (Int# -> Int# -> Int#
furthestOf Int#
q Int#
fu)
  Failed Int
i String
msg -> ParseError -> Res# a
forall a. ParseError -> Res# a
Err# (Int -> String -> ParseError
ParseError Int
i String
msg)

-- | Move to the index that the function computes from the current one.
scan :: (Env -> Int -> Int) -> P ()
scan :: (Env -> Int -> Int) -> P ()
scan Env -> Int -> Int
f = (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a. (Env -> Int# -> Int# -> Int# -> Res# a) -> P a
P ((Env -> Int# -> Int# -> Int# -> Res# ()) -> P ())
-> (Env -> Int# -> Int# -> Int# -> Res# ()) -> P ()
forall a b. (a -> b) -> a -> b
$ \Env
e Int#
p Int#
fu Int#
t -> case Env -> Int -> Int
f Env
e (Int# -> Int
I# Int#
p) of I# Int#
p' -> () -> Int# -> Int# -> Int# -> Res# ()
forall a. a -> Int# -> Int# -> Int# -> Res# a
OK# () Int#
p' Int#
fu Int#
t

----------------------------------------
-- Input access

byteAt :: Env -> Int -> Word8
byteAt :: Env -> Int -> Word8
byteAt Env
e Int
i
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Env
e.end = Array -> Int -> Word8
A.unsafeIndex Env
e.array Int
i
  | Bool
otherwise = Word8
0

-- | The byte before the index, 0 at the start of the input.
byteBefore :: Env -> Int -> Word8
byteBefore :: Env -> Int -> Word8
byteBefore Env
e Int
i
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Env
e.base = Array -> Int -> Word8
A.unsafeIndex Env
e.array (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  | Bool
otherwise = Word8
0

slice :: Env -> Int -> Int -> T.Text
slice :: Env -> Int -> Int -> Text
slice Env
e Int
i Int
j
  | Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
i = Array -> Int -> Int -> Text
T.Text Env
e.array Int
i (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i)
  -- With 'T.empty', GHC moves the content of an empty quoted key, e.g. in
  -- "'': x", to a constant, and builds the node of the key as a thunk that
  -- waits for the evaluation of 'T.empty'. A pragma on a copy of 'T.empty'
  -- does not prevent this. The heap check of the render tests finds this
  -- thunk.
  | Bool
otherwise = Array -> Int -> Int -> Text
T.Text Env
e.array Int
i Int
0

toOffset :: Env -> Int -> Offset
toOffset :: Env -> Int -> Offset
toOffset Env
e Int
i = Int -> Offset
Offset (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Env
e.base)