{-# LANGUAGE UnboxedTuples #-}

-- | Parsers for textual data (UTF-8, ASCII).

module FlatParse.Basic.Text
  (
  -- * UTF-8
    char, string
  , anyChar, skipAnyChar
  , satisfy, skipSatisfy
  , fusedSatisfy, skipFusedSatisfy
  , takeLine
  , takeRestString

  -- * ASCII
  , anyAsciiChar, skipAnyAsciiChar
  , satisfyAscii, skipSatisfyAscii

  -- ** ASCII-encoded numbers
  , anyAsciiDecimalWord
  , anyAsciiDecimalInt
  , anyAsciiDecimalInteger
  , anyAsciiHexWord
  , anyAsciiHexInt

  -- * Debugging parsers
  , traceLine
  , traceRest
  ) where

import FlatParse.Basic.Parser
import FlatParse.Basic.Base ( withEnsure1, lookahead, eof, branch )
import FlatParse.Basic.Bytes ( bytes )

import FlatParse.Common.GHCExts

import Language.Haskell.TH
import qualified FlatParse.Common.Numbers as Common
import qualified FlatParse.Common.Assorted as Common

-- | Parse any single Unicode character encoded using UTF-8 as a 'Char'.
anyChar :: ParserT st e Char
anyChar :: forall (st :: ZeroBitType) e. ParserT st e Char
anyChar = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
buf st
st -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob Addr#
buf of
  Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
  Int#
_  -> case Addr# -> Char#
Common.derefChar8# Addr#
buf of
    Char#
c1 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\x7F'# of
      Int#
1# -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK# st
st (Char# -> Char
C# Char#
c1) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#)
      Int#
_  -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#) of
        Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
        Int#
_ -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
1# of
          Char#
c2 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xDF'# of
            Int#
1# ->
              let resc :: Int#
resc = ((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xC0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
6#) Int# -> Int# -> Int#
`orI#`
                          (Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#)
              in forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK# st
st (Char# -> Char
C# (Int# -> Char#
chr# Int#
resc)) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
2#)
            Int#
_ -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
2#) of
              Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
              Int#
_  -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
2# of
                Char#
c3 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xEF'# of
                  Int#
1# ->
                    let resc :: Int#
resc = ((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xE0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
12#) Int# -> Int# -> Int#
`orI#`
                               ((Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#`  Int#
6#) Int# -> Int# -> Int#
`orI#`
                                (Char# -> Int#
ord# Char#
c3 Int# -> Int# -> Int#
-# Int#
0x80#)
                    in forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK# st
st (Char# -> Char
C# (Int# -> Char#
chr# Int#
resc)) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
3#)
                  Int#
_ -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
3#) of
                    Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
                    Int#
_  -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
3# of
                      Char#
c4 ->
                        let resc :: Int#
resc = ((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xF0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
18#) Int# -> Int# -> Int#
`orI#`
                                   ((Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
12#) Int# -> Int# -> Int#
`orI#`
                                   ((Char# -> Int#
ord# Char#
c3 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#`  Int#
6#) Int# -> Int# -> Int#
`orI#`
                                    (Char# -> Int#
ord# Char#
c4 Int# -> Int# -> Int#
-# Int#
0x80#)
                        in forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK# st
st (Char# -> Char
C# (Int# -> Char#
chr# Int#
resc)) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
4#)
{-# inline anyChar #-}

-- | Skip any single Unicode character encoded using UTF-8.
skipAnyChar :: ParserT st e ()
skipAnyChar :: forall (st :: ZeroBitType) e. ParserT st e ()
skipAnyChar = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
buf st
st -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob Addr#
buf of
  Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
  Int#
_  -> case Addr# -> Char#
Common.derefChar8# Addr#
buf of
    Char#
c1 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\x7F'# of
      Int#
1# -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK# st
st () (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#)
      Int#
_  ->
        let buf' :: Addr#
buf' =
              case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xDF'# of
                Int#
1# -> Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
2#
                Int#
_  -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xEF'# of
                    Int#
1# -> Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
3#
                    Int#
_ ->  Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
4#
        in case Addr# -> Addr# -> Int#
leAddr# Addr#
buf' Addr#
eob of
             Int#
1# -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st () Addr#
buf'
             Int#
_  -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline skipAnyChar #-}

withSatisfy
    :: (Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfy :: forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfy Char -> Bool
f Char -> ParserT st e r
p = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case forall (st :: ZeroBitType) e a.
ParserT st e a
-> ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a
runParserT# forall (st :: ZeroBitType) e. ParserT st e Char
anyChar ForeignPtrContents
fp Addr#
eob Addr#
s st
st of
      -- This is OK# unfolded, to silence incomplete pattern warnings
      -- in GHC <= 8.8.4.
      (# st
st, (# (# Char
c, Addr#
s #) | | #) #) | Char -> Bool
f Char
c -> forall (st :: ZeroBitType) e a.
ParserT st e a
-> ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a
runParserT# (Char -> ParserT st e r
p Char
c) ForeignPtrContents
fp Addr#
eob Addr#
s st
st

      (# st
st, ResI# Any Char
_ #)                          -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline withSatisfy #-}

-- | Parse a UTF-8 'Char' for which a predicate holds.
satisfy :: (Char -> Bool) -> ParserT st e Char
satisfy :: forall (st :: ZeroBitType) e. (Char -> Bool) -> ParserT st e Char
satisfy Char -> Bool
f = forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfy Char -> Bool
f forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# inline satisfy #-}

-- | Skip a UTF-8 `Char` for which a predicate holds.
skipSatisfy :: (Char -> Bool) -> ParserT st e ()
skipSatisfy :: forall (st :: ZeroBitType) e. (Char -> Bool) -> ParserT st e ()
skipSatisfy Char -> Bool
f = forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfy Char -> Bool
f (\Char
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
{-# inline skipSatisfy #-}

withSatisfyAscii :: (Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfyAscii :: forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfyAscii Char -> Bool
f Char -> ParserT st e r
p = forall (st :: ZeroBitType) e r. ParserT st e r -> ParserT st e r
withEnsure1 forall a b. (a -> b) -> a -> b
$ forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case Addr# -> Char#
Common.derefChar8# Addr#
s of
      Char#
c1 | Char -> Bool
f (Char# -> Char
C# Char#
c1) -> forall (st :: ZeroBitType) e a.
ParserT st e a
-> ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a
runParserT# (Char -> ParserT st e r
p (Char# -> Char
C# Char#
c1)) ForeignPtrContents
fp Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
s Int#
1#) st
st
         | Bool
otherwise -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline withSatisfyAscii #-}

-- | Parse an ASCII `Char` for which a predicate holds.
--
-- Assumption: the predicate must only return 'True' for ASCII-range characters.
-- Otherwise this function might read a 128-255 range byte, thereby breaking
-- UTF-8 decoding.
satisfyAscii :: (Char -> Bool) -> ParserT st e Char
satisfyAscii :: forall (st :: ZeroBitType) e. (Char -> Bool) -> ParserT st e Char
satisfyAscii Char -> Bool
f = forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfyAscii Char -> Bool
f forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# inline satisfyAscii #-}

-- | Skip an ASCII `Char` for which a predicate holds. Assumption: the predicate
--   must only return `True` for ASCII-range characters.
skipSatisfyAscii :: (Char -> Bool) -> ParserT st e ()
skipSatisfyAscii :: forall (st :: ZeroBitType) e. (Char -> Bool) -> ParserT st e ()
skipSatisfyAscii Char -> Bool
f = forall (st :: ZeroBitType) e r.
(Char -> Bool) -> (Char -> ParserT st e r) -> ParserT st e r
withSatisfyAscii Char -> Bool
f (\Char
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
{-# inline skipSatisfyAscii #-}

-- | This is a variant of `satisfy` which allows more optimization. We can pick four testing
--   functions for the four cases for the possible number of bytes in the UTF-8 character. So in
--   @fusedSatisfy f1 f2 f3 f4@, if we read a one-byte character, the result is scrutinized with
--   @f1@, for two-bytes, with @f2@, and so on. This can result in dramatic lexing speedups.
--
--   For example, if we want to accept any letter, the naive solution would be to use
--   `Data.Char.isLetter`, but this accesses a large lookup table of Unicode character classes. We
--   can do better with @fusedSatisfy isLatinLetter isLetter isLetter isLetter@, since here the
--   `isLatinLetter` is inlined into the UTF-8 decoding, and it probably handles a great majority of
--   all cases without accessing the character table.
fusedSatisfy :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> ParserT st e Char
fusedSatisfy :: forall (st :: ZeroBitType) e.
(Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> ParserT st e Char
fusedSatisfy Char -> Bool
f1 Char -> Bool
f2 Char -> Bool
f3 Char -> Bool
f4 = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
buf st
st ->
    case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob Addr#
buf of
      Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
      Int#
_  -> case Addr# -> Char#
Common.derefChar8# Addr#
buf of
        Char#
c1 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\x7F'# of
          Int#
1# | Char -> Bool
f1 (Char# -> Char
C# Char#
c1) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Char# -> Char
C# Char#
c1) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#)
             | Bool
otherwise  -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
          Int#
_  -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#) of
            Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
            Int#
_ -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
1# of
              Char#
c2 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xDF'# of
                Int#
1# ->
                  let resc :: Char
resc = Char# -> Char
C# (Int# -> Char#
chr# (((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xC0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
6#) Int# -> Int# -> Int#
`orI#`
                                       (Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#)))
                  in case Char -> Bool
f2 Char
resc of
                       Bool
True -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st Char
resc (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
2#)
                       Bool
_    -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
                Int#
_ -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
2#) of
                  Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
                  Int#
_  -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
2# of
                    Char#
c3 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\xEF'# of
                      Int#
1# ->
                        let resc :: Char
resc = Char# -> Char
C# (Int# -> Char#
chr# (((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xE0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
12#) Int# -> Int# -> Int#
`orI#`
                                             ((Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#`  Int#
6#) Int# -> Int# -> Int#
`orI#`
                                             (Char# -> Int#
ord# Char#
c3 Int# -> Int# -> Int#
-# Int#
0x80#)))
                        in case Char -> Bool
f3 Char
resc of
                             Bool
True -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st Char
resc (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
3#)
                             Bool
_    -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
                      Int#
_ -> case Addr# -> Addr# -> Int#
eqAddr# Addr#
eob (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
3#) of
                        Int#
1# -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
                        Int#
_  -> case Addr# -> Int# -> Char#
indexCharOffAddr# Addr#
buf Int#
3# of
                          Char#
c4 ->
                            let resc :: Char
resc = Char# -> Char
C# (Int# -> Char#
chr# (((Char# -> Int#
ord# Char#
c1 Int# -> Int# -> Int#
-# Int#
0xF0#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
18#) Int# -> Int# -> Int#
`orI#`
                                                 ((Char# -> Int#
ord# Char#
c2 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#` Int#
12#) Int# -> Int# -> Int#
`orI#`
                                                 ((Char# -> Int#
ord# Char#
c3 Int# -> Int# -> Int#
-# Int#
0x80#) Int# -> Int# -> Int#
`uncheckedIShiftL#`  Int#
6#) Int# -> Int# -> Int#
`orI#`
                                                  (Char# -> Int#
ord# Char#
c4 Int# -> Int# -> Int#
-# Int#
0x80#)))
                            in case Char -> Bool
f4 Char
resc of
                                 Bool
True -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st Char
resc (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
4#)
                                 Bool
_    -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline fusedSatisfy #-}

-- | Skipping variant of `fusedSatisfy`.
skipFusedSatisfy :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser e ()
skipFusedSatisfy :: forall e.
(Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> Parser e ()
skipFusedSatisfy Char -> Bool
f1 Char -> Bool
f2 Char -> Bool
f3 Char -> Bool
f4 = () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (st :: ZeroBitType) e.
(Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> (Char -> Bool)
-> ParserT st e Char
fusedSatisfy Char -> Bool
f1 Char -> Bool
f2 Char -> Bool
f3 Char -> Bool
f4
{-# inline skipFusedSatisfy #-}

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

-- | Parse a non-empty ASCII decimal digit sequence as a 'Word'.
--   Fails on overflow.
anyAsciiDecimalWord :: ParserT st e Word
anyAsciiDecimalWord :: forall (st :: ZeroBitType) e. ParserT st e Word
anyAsciiDecimalWord = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case Addr# -> Addr# -> (# (# #) | (# Word#, Addr# #) #)
Common.anyAsciiDecimalWord# Addr#
eob Addr#
s of
      (# | (# Word#
w, Addr#
s' #) #) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Word# -> Word
W# Word#
w) Addr#
s'
      (# (##) | #)        -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiDecimalWord #-}

-- | Parse a non-empty ASCII decimal digit sequence as a positive 'Int'.
--   Fails on overflow.
anyAsciiDecimalInt :: ParserT st e Int
anyAsciiDecimalInt :: forall (st :: ZeroBitType) e. ParserT st e Int
anyAsciiDecimalInt = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case Addr# -> Addr# -> (# (# #) | (# Int#, Addr# #) #)
Common.anyAsciiDecimalInt# Addr#
eob Addr#
s of
      (# | (# Int#
n, Addr#
s' #) #) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Int# -> Int
I# Int#
n) Addr#
s'
      (# (##) | #)        -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiDecimalInt #-}

-- | Parse a non-empty ASCII decimal digit sequence as a positive 'Integer'.
anyAsciiDecimalInteger :: ParserT st e Integer
anyAsciiDecimalInteger :: forall (st :: ZeroBitType) e. ParserT st e Integer
anyAsciiDecimalInteger = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case ForeignPtrContents
-> Addr# -> Addr# -> (# (# #) | (# Integer, Addr# #) #)
Common.anyAsciiDecimalInteger# ForeignPtrContents
fp Addr#
eob Addr#
s of
      (# | (# Integer
i, Addr#
s' #) #) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st Integer
i Addr#
s'
      (# (##) | #)        -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiDecimalInteger #-}

-- | Parse a non-empty, case-insensitive ASCII hexadecimal digit sequence as a
--   'Word'.
--   Fails on overflow.
anyAsciiHexWord :: ParserT st e Word
anyAsciiHexWord :: forall (st :: ZeroBitType) e. ParserT st e Word
anyAsciiHexWord = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case Addr# -> Addr# -> (# (# #) | (# Word#, Addr# #) #)
Common.anyAsciiHexWord# Addr#
eob Addr#
s of
      (# | (# Word#
w, Addr#
s' #) #) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Word# -> Word
W# Word#
w) Addr#
s'
      (# (##) | #)        -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiHexWord #-}

-- | Parse a non-empty, case-insensitive ASCII hexadecimal digit sequence as a
--   positive 'Int'.
--   Fails on overflow.
anyAsciiHexInt :: ParserT st e Int
anyAsciiHexInt :: forall (st :: ZeroBitType) e. ParserT st e Int
anyAsciiHexInt = forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
s st
st ->
    case Addr# -> Addr# -> (# (# #) | (# Int#, Addr# #) #)
Common.anyAsciiHexInt# Addr#
eob Addr#
s of
      (# | (# Int#
n, Addr#
s' #) #) -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Int# -> Int
I# Int#
n) Addr#
s'
      (# (##) | #)        -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiHexInt #-}

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

-- | Parse any single ASCII character (a single byte) as a 'Char'.
--
-- More efficient than 'anyChar' for ASCII-only input.
anyAsciiChar :: ParserT st e Char
anyAsciiChar :: forall (st :: ZeroBitType) e. ParserT st e Char
anyAsciiChar = forall (st :: ZeroBitType) e r. ParserT st e r -> ParserT st e r
withEnsure1 forall a b. (a -> b) -> a -> b
$ forall (st :: ZeroBitType) e a.
(ForeignPtrContents -> Addr# -> Addr# -> st -> Res# st e a)
-> ParserT st e a
ParserT \ForeignPtrContents
fp Addr#
eob Addr#
buf st
st ->
    case Addr# -> Char#
Common.derefChar8# Addr#
buf of
      Char#
c1 -> case Char#
c1 Char# -> Char# -> Int#
`leChar#` Char#
'\x7F'# of
              Int#
1# -> forall (st :: ZeroBitType) a e. st -> a -> Addr# -> Res# st e a
OK#   st
st (Char# -> Char
C# Char#
c1) (Addr# -> Int# -> Addr#
plusAddr# Addr#
buf Int#
1#)
              Int#
_  -> forall (st :: ZeroBitType) e a. st -> Res# st e a
Fail# st
st
{-# inline anyAsciiChar #-}

-- | Skip any single ASCII character (a single byte).
--
-- More efficient than 'skipAnyChar' for ASCII-only input.
skipAnyAsciiChar :: ParserT st e ()
skipAnyAsciiChar :: forall (st :: ZeroBitType) e. ParserT st e ()
skipAnyAsciiChar = () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (st :: ZeroBitType) e. ParserT st e Char
anyAsciiChar
{-# inline skipAnyAsciiChar #-}

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

-- | Parse a UTF-8 character literal. This is a template function, you can use it as
--   @$(char \'x\')@, for example, and the splice in this case has type @Parser e ()@.
char :: Char -> Q Exp
char :: Char -> Q Exp
char Char
c = String -> Q Exp
string [Char
c]

-- | Parse a UTF-8 string literal. This is a template function, you can use it as @$(string "foo")@,
--   for example, and the splice has type @Parser e ()@.
string :: String -> Q Exp
string :: String -> Q Exp
string String
str = [Word] -> Q Exp
bytes (String -> [Word]
Common.strToBytes String
str)

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

-- | Parse the rest of the current line as a `String`. Assumes UTF-8 encoding,
--   throws an error if the encoding is invalid.
takeLine :: ParserT st e String
takeLine :: forall (st :: ZeroBitType) e. ParserT st e String
takeLine = forall (st :: ZeroBitType) e a b.
ParserT st e a
-> ParserT st e b -> ParserT st e b -> ParserT st e b
branch forall (st :: ZeroBitType) e. ParserT st e ()
eof (forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"") do
  Char
c <- forall (st :: ZeroBitType) e. ParserT st e Char
anyChar
  case Char
c of
    Char
'\n' -> forall (f :: * -> *) a. Applicative f => a -> f a
pure String
""
    Char
_    -> (Char
cforall a. a -> [a] -> [a]
:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (st :: ZeroBitType) e. ParserT st e String
takeLine

-- | Parse the rest of the current line as a `String`, but restore the parsing state.
--   Assumes UTF-8 encoding. This can be used for debugging.
traceLine :: ParserT st e String
traceLine :: forall (st :: ZeroBitType) e. ParserT st e String
traceLine = forall (st :: ZeroBitType) e r. ParserT st e r -> ParserT st e r
lookahead forall (st :: ZeroBitType) e. ParserT st e String
takeLine

-- | Take the rest of the input as a `String`. Assumes UTF-8 encoding.
takeRestString :: ParserT st e String
takeRestString :: forall (st :: ZeroBitType) e. ParserT st e String
takeRestString = forall (st :: ZeroBitType) e a b.
ParserT st e a
-> ParserT st e b -> ParserT st e b -> ParserT st e b
branch forall (st :: ZeroBitType) e. ParserT st e ()
eof (forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"") do
  Char
c <- forall (st :: ZeroBitType) e. ParserT st e Char
anyChar
  String
cs <- forall (st :: ZeroBitType) e. ParserT st e String
takeRestString
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Char
cforall a. a -> [a] -> [a]
:String
cs)

-- | Get the rest of the input as a `String`, but restore the parsing state. Assumes UTF-8 encoding.
--   This can be used for debugging.
traceRest :: ParserT st e String
traceRest :: forall (st :: ZeroBitType) e. ParserT st e String
traceRest = forall (st :: ZeroBitType) e r. ParserT st e r -> ParserT st e r
lookahead forall (st :: ZeroBitType) e. ParserT st e String
takeRestString