packages feed

flatparse 0.3.4.0 → 0.3.5.0

raw patch · 8 files changed

+328/−170 lines, 8 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- FlatParse.Basic: byteStringed :: Parser e a -> (a -> ByteString -> Parser e b) -> Parser e b
- FlatParse.Basic: optioned :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b
- FlatParse.Basic: spanned :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b
- FlatParse.Stateful: byteStringed :: Parser e a -> (a -> ByteString -> Parser e b) -> Parser e b
- FlatParse.Stateful: instance GHC.Base.Applicative (FlatParse.Stateful.Parser e)
- FlatParse.Stateful: instance GHC.Base.Functor (FlatParse.Stateful.Parser e)
- FlatParse.Stateful: instance GHC.Base.Monad (FlatParse.Stateful.Parser e)
- FlatParse.Stateful: optioned :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b
- FlatParse.Stateful: spanned :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b
+ FlatParse.Basic: anyCString :: Parser e ByteString
+ FlatParse.Basic: anyCStringUnsafe :: Parser e ByteString
+ FlatParse.Basic: atAddr# :: Addr# -> Parser e a -> Parser e a
+ FlatParse.Basic: atSkip# :: Int# -> Parser e a -> Parser e a
+ FlatParse.Basic: lookaheadFromAddr# :: Addr# -> Parser e a -> Parser e a
+ FlatParse.Basic: skip :: Int -> Parser e ()
+ FlatParse.Basic: takeBs# :: Int# -> Parser e ByteString
+ FlatParse.Basic: takeBsOffAddr# :: Addr# -> Int# -> Int# -> Parser e ByteString
+ FlatParse.Basic: withAddr# :: (Addr# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withByteString :: Parser e a -> (a -> ByteString -> Parser e b) -> Parser e b
+ FlatParse.Basic: withOption :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b
+ FlatParse.Basic: withSpan :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b
+ FlatParse.Stateful: instance GHC.Base.Applicative (FlatParse.Stateful.Parser r e)
+ FlatParse.Stateful: instance GHC.Base.Functor (FlatParse.Stateful.Parser r e)
+ FlatParse.Stateful: instance GHC.Base.Monad (FlatParse.Stateful.Parser r e)
+ FlatParse.Stateful: withByteString :: Parser r e a -> (a -> ByteString -> Parser r e b) -> Parser r e b
+ FlatParse.Stateful: withOption :: Parser r e a -> (a -> Parser r e b) -> Parser r e b -> Parser r e b
+ FlatParse.Stateful: withSpan :: Parser r e a -> (a -> Span -> Parser r e b) -> Parser r e b
- FlatParse.Stateful: (<|>) :: Parser e a -> Parser e a -> Parser e a
+ FlatParse.Stateful: (<|>) :: Parser r e a -> Parser r e a -> Parser r e a
- FlatParse.Stateful: Parser :: (ForeignPtrContents -> Int# -> Addr# -> Addr# -> Int# -> Res# e a) -> Parser e a
+ FlatParse.Stateful: Parser :: (ForeignPtrContents -> r -> Addr# -> Addr# -> Int# -> Res# e a) -> Parser r e a
- FlatParse.Stateful: [runParser#] :: Parser e a -> ForeignPtrContents -> Int# -> Addr# -> Addr# -> Int# -> Res# e a
+ FlatParse.Stateful: [runParser#] :: Parser r e a -> ForeignPtrContents -> r -> Addr# -> Addr# -> Int# -> Res# e a
- FlatParse.Stateful: anyChar :: Parser e Char
+ FlatParse.Stateful: anyChar :: Parser r e Char
- FlatParse.Stateful: anyCharASCII :: Parser e Char
+ FlatParse.Stateful: anyCharASCII :: Parser r e Char
- FlatParse.Stateful: anyCharASCII_ :: Parser e ()
+ FlatParse.Stateful: anyCharASCII_ :: Parser r e ()
- FlatParse.Stateful: anyChar_ :: Parser e ()
+ FlatParse.Stateful: anyChar_ :: Parser r e ()
- FlatParse.Stateful: anyInt :: Parser e Int
+ FlatParse.Stateful: anyInt :: Parser r e Int
- FlatParse.Stateful: anyInt16 :: Parser e Int16
+ FlatParse.Stateful: anyInt16 :: Parser r e Int16
- FlatParse.Stateful: anyInt16be :: Parser e Int16
+ FlatParse.Stateful: anyInt16be :: Parser r e Int16
- FlatParse.Stateful: anyInt16le :: Parser e Int16
+ FlatParse.Stateful: anyInt16le :: Parser r e Int16
- FlatParse.Stateful: anyInt32 :: Parser e Int32
+ FlatParse.Stateful: anyInt32 :: Parser r e Int32
- FlatParse.Stateful: anyInt32be :: Parser e Int32
+ FlatParse.Stateful: anyInt32be :: Parser r e Int32
- FlatParse.Stateful: anyInt32le :: Parser e Int32
+ FlatParse.Stateful: anyInt32le :: Parser r e Int32
- FlatParse.Stateful: anyInt64 :: Parser e Int64
+ FlatParse.Stateful: anyInt64 :: Parser r e Int64
- FlatParse.Stateful: anyInt64be :: Parser e Int64
+ FlatParse.Stateful: anyInt64be :: Parser r e Int64
- FlatParse.Stateful: anyInt64le :: Parser e Int64
+ FlatParse.Stateful: anyInt64le :: Parser r e Int64
- FlatParse.Stateful: anyInt8 :: Parser e Int8
+ FlatParse.Stateful: anyInt8 :: Parser r e Int8
- FlatParse.Stateful: anyWord :: Parser e Word
+ FlatParse.Stateful: anyWord :: Parser r e Word
- FlatParse.Stateful: anyWord16 :: Parser e Word16
+ FlatParse.Stateful: anyWord16 :: Parser r e Word16
- FlatParse.Stateful: anyWord16_ :: Parser e ()
+ FlatParse.Stateful: anyWord16_ :: Parser r e ()
- FlatParse.Stateful: anyWord16be :: Parser e Word16
+ FlatParse.Stateful: anyWord16be :: Parser r e Word16
- FlatParse.Stateful: anyWord16le :: Parser e Word16
+ FlatParse.Stateful: anyWord16le :: Parser r e Word16
- FlatParse.Stateful: anyWord32 :: Parser e Word32
+ FlatParse.Stateful: anyWord32 :: Parser r e Word32
- FlatParse.Stateful: anyWord32_ :: Parser e ()
+ FlatParse.Stateful: anyWord32_ :: Parser r e ()
- FlatParse.Stateful: anyWord32be :: Parser e Word32
+ FlatParse.Stateful: anyWord32be :: Parser r e Word32
- FlatParse.Stateful: anyWord32le :: Parser e Word32
+ FlatParse.Stateful: anyWord32le :: Parser r e Word32
- FlatParse.Stateful: anyWord64 :: Parser e Word64
+ FlatParse.Stateful: anyWord64 :: Parser r e Word64
- FlatParse.Stateful: anyWord64_ :: Parser e ()
+ FlatParse.Stateful: anyWord64_ :: Parser r e ()
- FlatParse.Stateful: anyWord64be :: Parser e Word64
+ FlatParse.Stateful: anyWord64be :: Parser r e Word64
- FlatParse.Stateful: anyWord64le :: Parser e Word64
+ FlatParse.Stateful: anyWord64le :: Parser r e Word64
- FlatParse.Stateful: anyWord8 :: Parser e Word8
+ FlatParse.Stateful: anyWord8 :: Parser r e Word8
- FlatParse.Stateful: anyWord8_ :: Parser e ()
+ FlatParse.Stateful: anyWord8_ :: Parser r e ()
- FlatParse.Stateful: anyWord_ :: Parser e ()
+ FlatParse.Stateful: anyWord_ :: Parser r e ()
- FlatParse.Stateful: ask :: Parser e Int
+ FlatParse.Stateful: ask :: Parser r e r
- FlatParse.Stateful: branch :: Parser e a -> Parser e b -> Parser e b -> Parser e b
+ FlatParse.Stateful: branch :: Parser r e a -> Parser r e b -> Parser r e b -> Parser r e b
- FlatParse.Stateful: byte :: Word8 -> Parser e ()
+ FlatParse.Stateful: byte :: Word8 -> Parser r e ()
- FlatParse.Stateful: byteStringOf :: Parser e a -> Parser e ByteString
+ FlatParse.Stateful: byteStringOf :: Parser r e a -> Parser r e ByteString
- FlatParse.Stateful: chainl :: (b -> a -> b) -> Parser e b -> Parser e a -> Parser e b
+ FlatParse.Stateful: chainl :: (b -> a -> b) -> Parser r e b -> Parser r e a -> Parser r e b
- FlatParse.Stateful: chainr :: (a -> b -> b) -> Parser e a -> Parser e b -> Parser e b
+ FlatParse.Stateful: chainr :: (a -> b -> b) -> Parser r e a -> Parser r e b -> Parser r e b
- FlatParse.Stateful: cut :: Parser e a -> e -> Parser e a
+ FlatParse.Stateful: cut :: Parser r e a -> e -> Parser r e a
- FlatParse.Stateful: cutting :: Parser e a -> e -> (e -> e -> e) -> Parser e a
+ FlatParse.Stateful: cutting :: Parser r e a -> e -> (e -> e -> e) -> Parser r e a
- FlatParse.Stateful: empty :: Parser e a
+ FlatParse.Stateful: empty :: Parser r e a
- FlatParse.Stateful: ensureBytes# :: Int -> Parser e ()
+ FlatParse.Stateful: ensureBytes# :: Int -> Parser r e ()
- FlatParse.Stateful: eof :: Parser e ()
+ FlatParse.Stateful: eof :: Parser r e ()
- FlatParse.Stateful: err :: e -> Parser e a
+ FlatParse.Stateful: err :: e -> Parser r e a
- FlatParse.Stateful: fails :: Parser e a -> Parser e ()
+ FlatParse.Stateful: fails :: Parser r e a -> Parser r e ()
- FlatParse.Stateful: fusedSatisfy :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser e Char
+ FlatParse.Stateful: fusedSatisfy :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser r e Char
- FlatParse.Stateful: fusedSatisfy_ :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser e ()
+ FlatParse.Stateful: fusedSatisfy_ :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser r e ()
- FlatParse.Stateful: get :: Parser e Int
+ FlatParse.Stateful: get :: Parser r e Int
- FlatParse.Stateful: getPos :: Parser e Pos
+ FlatParse.Stateful: getPos :: Parser r e Pos
- FlatParse.Stateful: inSpan :: Span -> Parser e a -> Parser e a
+ FlatParse.Stateful: inSpan :: Span -> Parser r e a -> Parser r e a
- FlatParse.Stateful: isolate :: Int -> Parser e a -> Parser e a
+ FlatParse.Stateful: isolate :: Int -> Parser r e a -> Parser r e a
- FlatParse.Stateful: local :: (Int -> Int) -> Parser e a -> Parser e a
+ FlatParse.Stateful: local :: (r -> r) -> Parser r e a -> Parser r e a
- FlatParse.Stateful: lookahead :: Parser e a -> Parser e a
+ FlatParse.Stateful: lookahead :: Parser r e a -> Parser r e a
- FlatParse.Stateful: many :: Parser e a -> Parser e [a]
+ FlatParse.Stateful: many :: Parser r e a -> Parser r e [a]
- FlatParse.Stateful: many_ :: Parser e a -> Parser e ()
+ FlatParse.Stateful: many_ :: Parser r e a -> Parser r e ()
- FlatParse.Stateful: modify :: (Int -> Int) -> Parser e ()
+ FlatParse.Stateful: modify :: (Int -> Int) -> Parser r e ()
- FlatParse.Stateful: newtype Parser e a
+ FlatParse.Stateful: newtype Parser r e a
- FlatParse.Stateful: notFollowedBy :: Parser e a -> Parser e b -> Parser e a
+ FlatParse.Stateful: notFollowedBy :: Parser r e a -> Parser r e b -> Parser r e a
- FlatParse.Stateful: optional :: Parser e a -> Parser e (Maybe a)
+ FlatParse.Stateful: optional :: Parser r e a -> Parser r e (Maybe a)
- FlatParse.Stateful: optional_ :: Parser e a -> Parser e ()
+ FlatParse.Stateful: optional_ :: Parser r e a -> Parser r e ()
- FlatParse.Stateful: put :: Int -> Parser e ()
+ FlatParse.Stateful: put :: Int -> Parser r e ()
- FlatParse.Stateful: readInt :: Parser e Int
+ FlatParse.Stateful: readInt :: Parser r e Int
- FlatParse.Stateful: readInteger :: Parser e Integer
+ FlatParse.Stateful: readInteger :: Parser r e Integer
- FlatParse.Stateful: runParser :: Parser e a -> Int -> Int -> ByteString -> Result e a
+ FlatParse.Stateful: runParser :: Parser r e a -> r -> Int -> ByteString -> Result e a
- FlatParse.Stateful: runParserS :: Parser e a -> Int -> Int -> String -> Result e a
+ FlatParse.Stateful: runParserS :: Parser r e a -> r -> Int -> String -> Result e a
- FlatParse.Stateful: satisfy :: (Char -> Bool) -> Parser e Char
+ FlatParse.Stateful: satisfy :: (Char -> Bool) -> Parser r e Char
- FlatParse.Stateful: satisfyASCII :: (Char -> Bool) -> Parser e Char
+ FlatParse.Stateful: satisfyASCII :: (Char -> Bool) -> Parser r e Char
- FlatParse.Stateful: satisfyASCII_ :: (Char -> Bool) -> Parser e ()
+ FlatParse.Stateful: satisfyASCII_ :: (Char -> Bool) -> Parser r e ()
- FlatParse.Stateful: satisfy_ :: (Char -> Bool) -> Parser e ()
+ FlatParse.Stateful: satisfy_ :: (Char -> Bool) -> Parser r e ()
- FlatParse.Stateful: scan16# :: Word16 -> Parser e ()
+ FlatParse.Stateful: scan16# :: Word16 -> Parser r e ()
- FlatParse.Stateful: scan32# :: Word32 -> Parser e ()
+ FlatParse.Stateful: scan32# :: Word32 -> Parser r e ()
- FlatParse.Stateful: scan64# :: Word -> Parser e ()
+ FlatParse.Stateful: scan64# :: Word -> Parser r e ()
- FlatParse.Stateful: scan8# :: Word8 -> Parser e ()
+ FlatParse.Stateful: scan8# :: Word8 -> Parser r e ()
- FlatParse.Stateful: scanAny8# :: Parser e Word8
+ FlatParse.Stateful: scanAny8# :: Parser r e Word8
- FlatParse.Stateful: setBack# :: Int -> Parser e ()
+ FlatParse.Stateful: setBack# :: Int -> Parser r e ()
- FlatParse.Stateful: setPos :: Pos -> Parser e ()
+ FlatParse.Stateful: setPos :: Pos -> Parser r e ()
- FlatParse.Stateful: some :: Parser e a -> Parser e [a]
+ FlatParse.Stateful: some :: Parser r e a -> Parser r e [a]
- FlatParse.Stateful: some_ :: Parser e a -> Parser e ()
+ FlatParse.Stateful: some_ :: Parser r e a -> Parser r e ()
- FlatParse.Stateful: spanOf :: Parser e a -> Parser e Span
+ FlatParse.Stateful: spanOf :: Parser r e a -> Parser r e Span
- FlatParse.Stateful: takeBs :: Int -> Parser e ByteString
+ FlatParse.Stateful: takeBs :: Int -> Parser r e ByteString
- FlatParse.Stateful: takeLine :: Parser e String
+ FlatParse.Stateful: takeLine :: Parser r e String
- FlatParse.Stateful: takeRest :: Parser e String
+ FlatParse.Stateful: takeRest :: Parser r e String
- FlatParse.Stateful: takeRestBs :: Parser e ByteString
+ FlatParse.Stateful: takeRestBs :: Parser r e ByteString
- FlatParse.Stateful: traceLine :: Parser e String
+ FlatParse.Stateful: traceLine :: Parser r e String
- FlatParse.Stateful: traceRest :: Parser e String
+ FlatParse.Stateful: traceRest :: Parser r e String
- FlatParse.Stateful: try :: Parser e a -> Parser e a
+ FlatParse.Stateful: try :: Parser r e a -> Parser r e a
- FlatParse.Stateful: unsafeSpanToByteString :: Span -> Parser e ByteString
+ FlatParse.Stateful: unsafeSpanToByteString :: Span -> Parser r e ByteString
- FlatParse.Stateful: withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt16# :: (Int16'# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt32# :: (Int32'# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyInt64# :: (Int# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt64# :: (Int# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt8# :: (Int8'# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord16# :: (Word16'# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord32# :: (Word32'# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyWord64# :: (Word# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord64# :: (Word# -> Parser r e a) -> Parser r e a
- FlatParse.Stateful: withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord8# :: (Word8'# -> Parser r e a) -> Parser r e a

Files

bench/FPStateful.hs view
@@ -6,19 +6,22 @@  import FlatParse.Stateful +ws, open, close, ident, sexp, src :: Parser () () () ws      = many_ $(switch [| case _ of " " -> pure (); "\n" -> pure () |]) open    = $(char '(') >> ws close   = $(char ')') >> ws ident   = some_ (satisfyASCII_ isLatinLetter) >> ws sexp    = branch open (some_ sexp >> close) ident src     = sexp >> eof-runSexp = runParser src 0 0+runSexp = runParser src () 0 +longw, longws :: Parser () () () longw     = $(string "thisisalongkeyword") longws    = some_ (longw >> ws) >> eof-runLongws = runParser longws 0 0+runLongws = runParser longws () 0 +numeral, comma, numcsv :: Parser () () () numeral   = some_ (satisfyASCII_ isDigit) >> ws comma     = $(char ',') >> ws numcsv    = numeral >> many_ (comma >> numeral) >> eof-runNumcsv = runParser numcsv 0 0+runNumcsv = runParser numcsv () 0
flatparse.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           flatparse-version:        0.3.4.0+version:        0.3.5.0 synopsis:       High-performance parsing from strict bytestrings description:    @Flatparse@ is a high-performance parsing library, focusing on programming languages and                 human-readable data formats. See the README for more information:@@ -73,7 +73,7 @@     , integer-gmp     , template-haskell   if flag(dump)-    ghc-options: -ddump-simpl -ddump-stg -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file+    ghc-options: -ddump-simpl -ddump-stg-final -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file   if flag(llvm)     ghc-options: -fllvm   default-language: Haskell2010@@ -107,7 +107,7 @@     , hspec     , quickcheck-instances   if flag(dump)-    ghc-options: -ddump-simpl -ddump-stg -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file+    ghc-options: -ddump-simpl -ddump-stg-final -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file   if flag(llvm)     ghc-options: -fllvm   default-language: Haskell2010@@ -148,7 +148,7 @@     , parsec     , primitive   if flag(dump)-    ghc-options: -ddump-simpl -ddump-stg -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file+    ghc-options: -ddump-simpl -ddump-stg-final -ddump-cmm -dsuppress-all -dno-suppress-type-signatures -ddump-to-file   if flag(llvm)     ghc-options: -fllvm   default-language: Haskell2010
src/FlatParse/Basic.hs view
@@ -3,6 +3,9 @@ {-| This module implements a `Parser` supporting custom error types.  If you need efficient indentation parsing, use "FlatParse.Stateful" instead.++Many internals are exposed for hacking on and extending. These are generally+denoted by a @#@ hash suffix. -}  module FlatParse.Basic (@@ -27,7 +30,7 @@   , try   , optional   , optional_-  , optioned+  , withOption   , cut   , cutting @@ -35,6 +38,7 @@   , eof   , takeBs   , takeRestBs+  , skip   , char   , byte   , bytes@@ -72,6 +76,7 @@   , FlatParse.Internal.isLatinLetter   , FlatParse.Basic.readInt   , FlatParse.Basic.readInteger+  , anyCString    -- ** Explicit-endianness machine integers   , anyWord16le@@ -106,9 +111,9 @@   , setPos   , endPos   , spanOf-  , spanned+  , withSpan   , byteStringOf-  , byteStringed+  , withByteString   , inSpan    -- ** Position and span conversions@@ -131,14 +136,19 @@    -- * Internal functions   , ensureBytes#-  , scan8#-  , scan16#-  , scan32#-  , scan64#-  , scanAny8#-  , scanBytes#++  -- ** Unboxed arguments+  , takeBs#+  , atSkip#++  -- *** Location & address primitives   , setBack#+  , withAddr#+  , takeBsOffAddr#+  , lookaheadFromAddr#+  , atAddr# +  -- ** Machine integer continuation parsers   , withAnyWord8#   , withAnyWord16#   , withAnyWord32#@@ -148,6 +158,15 @@   , withAnyInt32#   , withAnyInt64# +  -- ** Unsafe+  , anyCStringUnsafe+  , scan8#+  , scan16#+  , scan32#+  , scan64#+  , scanAny8#+  , scanBytes#+   ) where  import Control.Monad@@ -317,7 +336,7 @@   x      -> x {-# inline try #-} --- | Convert a parsing failure to a `Maybe`. If possible, use `optioned` instead.+-- | Convert a parsing failure to a `Maybe`. If possible, use `withOption` instead. optional :: Parser e a -> Parser e (Maybe a) optional p = (Just <$> p) <|> pure Nothing {-# inline optional #-}@@ -329,12 +348,12 @@  -- | CPS'd version of `optional`. This is usually more efficient, since it gets rid of the --   extra `Maybe` allocation.-optioned :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b-optioned (Parser f) just (Parser nothing) = Parser \fp eob s -> case f fp eob s of+withOption :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b+withOption (Parser f) just (Parser nothing) = Parser \fp eob s -> case f fp eob s of   OK# a s -> runParser# (just a) fp eob s   Fail#   -> nothing fp eob s   Err# e  -> Err# e-{-# inline optioned #-}+{-# inline withOption #-}  -- | Convert a parsing failure to an error. cut :: Parser e a -> e -> Parser e a@@ -367,12 +386,7 @@ -- -- Throws a runtime error if given a negative integer. takeBs :: Int -> Parser e B.ByteString-takeBs (I# n#) = Parser \fp eob s -> case n# <=# minusAddr# eob s of-  1# -> -- have to runtime check for negative values, because they cause a hang-    case n# >=# 0# of-      1# -> OK# (B.PS (ForeignPtr s fp) 0 (I# n#)) (plusAddr# s n#)-      _  -> error "FlatParse.Basic.take: negative integer"-  _  -> Fail#+takeBs (I# n#) = takeBs# n# {-# inline takeBs #-}  -- | Consume the rest of the input. May return the empty bytestring.@@ -382,6 +396,13 @@   in  OK# (B.PS (ForeignPtr s fp) 0 (I# n#)) eob {-# inline takeRestBs #-} +-- | Skip forward @n@ bytes. Fails if fewer than @n@ bytes are available.+--+-- Throws a runtime error if given a negative integer.+skip :: Int -> Parser e ()+skip (I# os#) = atSkip# os# (pure ())+{-# inline skip #-}+ -- | 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@@ -780,14 +801,14 @@  -- | Bind the result together with the span of the result. CPS'd version of `spanOf` --   for better unboxing.-spanned :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b-spanned (Parser f) g = Parser \fp eob s -> case f fp eob s of+withSpan :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b+withSpan (Parser f) g = Parser \fp eob s -> case f fp eob s of   OK# a s' -> runParser# (g a (Span (addrToPos# eob s) (addrToPos# eob s'))) fp eob s'   x        -> unsafeCoerce# x-{-# inline spanned #-}+{-# inline withSpan #-}  -- | Return the `B.ByteString` consumed by a parser. Note: it's more efficient to use `spanOf` and---   `spanned` instead.+--   `withSpan` instead. byteStringOf :: Parser e a -> Parser e B.ByteString byteStringOf (Parser f) = Parser \fp eob s -> case f fp eob s of   OK# a s' -> OK# (B.PS (ForeignPtr s fp) 0 (I# (minusAddr# s' s))) s'@@ -795,17 +816,17 @@ {-# inline byteStringOf #-}  -- | CPS'd version of `byteStringOf`. Can be more efficient, because the result is more eagerly unboxed---   by GHC. It's more efficient to use `spanOf` or `spanned` instead.-byteStringed :: Parser e a -> (a -> B.ByteString -> Parser e b) -> Parser e b-byteStringed (Parser f) g = Parser \fp eob s -> case f fp eob s of+--   by GHC. It's more efficient to use `spanOf` or `withSpan` instead.+withByteString :: Parser e a -> (a -> B.ByteString -> Parser e b) -> Parser e b+withByteString (Parser f) g = Parser \fp eob s -> case f fp eob s of   OK# a s' -> runParser# (g a (B.PS (ForeignPtr s fp) 0 (I# (minusAddr# s' s)))) fp eob s'   x        -> unsafeCoerce# x-{-# inline byteStringed #-}+{-# inline withByteString #-}  -- | Run a parser in a given input span. The input position and the `Int` state is restored after --   the parser is finished, so `inSpan` does not consume input and has no side effect.  Warning: --   this operation may crash if the given span points outside the current parsing buffer. It's---   always safe to use `inSpan` if the span comes from a previous `spanned` or `spanOf` call on+--   always safe to use `inSpan` if the span comes from a previous `withSpan` or `spanOf` call on --   the current input. inSpan :: Span -> Parser e a -> Parser e a inSpan (Span s eob) (Parser f) = Parser \fp eob' s' ->@@ -1300,3 +1321,115 @@ anyInt64be :: Parser e Int64 anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#)))) {-# inline anyInt64be #-}++--------------------------------------------------------------------------------++-- | 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# -> Parser e a -> Parser e a+atSkip# os# (Parser p) = Parser \fp eob s -> case os# <=# minusAddr# eob s of+  1# -> case os# >=# 0# of+    1# -> p fp eob (plusAddr# s os#)+    _  -> error "FlatParse.Basic.atSkip#: negative integer"+  _  -> Fail#+{-# inline atSkip# #-}++-- | Read the given number of bytes as a 'ByteString'.+--+-- Throws a runtime error if given a negative integer.+takeBs# :: Int# -> Parser e B.ByteString+takeBs# n# = Parser \fp eob s -> case n# <=# minusAddr# eob s of+  1# -> -- have to runtime check for negative values, because they cause a hang+    case n# >=# 0# of+      1# -> OK# (B.PS (ForeignPtr s fp) 0 (I# n#)) (plusAddr# s n#)+      _  -> error "FlatParse.Basic.takeBs: negative integer"+  _  -> Fail#+{-# inline takeBs# #-}++--------------------------------------------------------------------------------++-- | Run a parser, passing it the current address the parser is at.+--+-- Useful for parsing offset-based data tables. For example, you may use this to+-- save the base address to use together with various 0-indexed offsets.+withAddr# :: (Addr# -> Parser e a) -> Parser e a+withAddr# p = Parser \fp eob s -> runParser# (p s) fp eob s+{-# inline withAddr# #-}++-- | @takeBsOffAddr# addr# offset# len#@ moves to @addr#@, skips @offset#@+--   bytes, reads @len#@ bytes into a 'ByteString', and restores the original+--   address.+--+-- The 'Addr#' should be from 'withAddr#'.+--+-- Useful for parsing offset-based data tables. For example, you may use this+-- together with 'withAddr#' to jump to an offset in your input and read some+-- data.+takeBsOffAddr# :: Addr# -> Int# -> Int# -> Parser e B.ByteString+takeBsOffAddr# addr# offset# len# =+    lookaheadFromAddr# addr# $ atSkip# offset# $ takeBs# len#+{-# inline takeBsOffAddr# #-}++-- | 'lookahead', but specify the address to lookahead from.+--+-- The 'Addr#' should be from 'withAddr#'.+lookaheadFromAddr# :: Addr# -> Parser e a -> Parser e a+lookaheadFromAddr# s = lookahead . atAddr# s+{-# inline lookaheadFromAddr# #-}++-- | Run a parser at the given address.+--+-- The 'Addr#' should be from 'withAddr#'.+--+-- This is a highly internal function -- you likely want 'lookaheadFromAddr#',+-- which will reset the address after running the parser.+atAddr# :: Addr# -> Parser e a -> Parser e a+atAddr# s (Parser p) = Parser \fp eob _ -> p fp eob s+{-# inline atAddr# #-}++--------------------------------------------------------------------------------++-- | Read a null-terminated bytestring (a C-style string).+--+-- Consumes the null terminator.+anyCString :: Parser e B.ByteString+anyCString = Parser \fp eob s -> go' fp eob s+  where+    go' fp eob s0 = go 0# s0+      where+        go n# s = case eqAddr# eob s of+          1# -> Fail#+          _  ->+            let s' = plusAddr# s 1#+            -- TODO below is a candidate for improving with ExtendedLiterals!+            in  case eqWord8# (indexWord8OffAddr''# s 0#) (wordToWord8''# 0##) of+                  1# -> OK# (B.PS (ForeignPtr s0 fp) 0 (I# n#)) s'+                  _  -> go (n# +# 1#) s'+{-# inline anyCString #-}++-- | Read a null-terminated bytestring (a C-style string), where the bytestring+--   is known to be null-terminated somewhere in the input.+--+-- Highly unsafe. Unless you have a guarantee that the string will be null+-- terminated before the input ends, use 'anyCString' instead. Honestly, I'm not+-- sure if this is a good function to define. But here it is.+--+-- Fails on GHC versions older than 9.0, since we make use of the+-- 'cstringLength#' primop introduced in GHC 9.0, and we aren't very useful+-- without it.+--+-- Consumes the null terminator.+anyCStringUnsafe :: Parser e B.ByteString+{-# inline anyCStringUnsafe #-}+#if MIN_VERSION_base(4,15,0)+anyCStringUnsafe = Parser \fp eob s ->+  case eqAddr# eob s of+    1# -> Fail#+    _  -> let n#  = cstringLength# s+              s'# = plusAddr# s (n# +# 1#)+           in OK# (B.PS (ForeignPtr s fp) 0 (I# n#)) s'#+#else+anyCStringUnsafe = error "Flatparse.Basic.anyCStringUnsafe: requires GHC 9.0 / base-4.15, not available on this compiler"+#endif
src/FlatParse/Examples/BasicLambda/Lexer.hs view
@@ -117,7 +117,7 @@ -- | Parse a line comment. lineComment :: Parser () lineComment =-  optioned anyWord8+  withOption anyWord8     (\case 10 -> ws            _  -> lineComment)     (pure ())
src/FlatParse/Examples/BasicLambda/Parser.hs view
@@ -49,7 +49,7 @@ --   keyword. ident :: Parser Name ident = token $ byteStringOf $-  spanned (identStartChar *> many_ identChar) (\_ span -> fails (isKeyword span))+  withSpan (identStartChar *> many_ identChar) (\_ span -> fails (isKeyword span))  -- | Parse an identifier, throw a precise error on failure. ident' :: Parser Name
src/FlatParse/Internal/UnboxedNumerics.hs view
@@ -109,5 +109,7 @@ extendWord8# w# = w# leWord8# :: Word8# -> Word8# -> Int# leWord8# w1# w2# = leWord# w1# w2#+eqWord8# :: Word8# -> Word8# -> Int#+eqWord8# w1# w2# = eqWord# w1# w2#  #endif
src/FlatParse/Stateful.hs view
@@ -1,8 +1,8 @@ {-# language UnboxedTuples #-}  {-|-This module implements a `Parser` supporting an `Int` reader environment, custom error types, and an-`Int` state.+This module implements a `Parser` supporting a custom reader environment, custom+error types and an `Int` state. -}  module FlatParse.Stateful (@@ -33,7 +33,7 @@   , try   , optional   , optional_-  , optioned+  , withOption   , cut   , cutting @@ -112,9 +112,9 @@   , setPos   , endPos   , spanOf-  , spanned+  , withSpan   , byteStringOf-  , byteStringed+  , withByteString   , inSpan    -- ** Position and span conversions@@ -201,10 +201,10 @@ pattern Fail# = (# | (# #) | #) {-# complete OK#, Err#, Fail# #-} --- | @Parser e a@ has an error type @e@ and a return type @a@.-newtype Parser e a = Parser {runParser# :: ForeignPtrContents -> Int# -> Addr# -> Addr# -> Int# -> Res# e a}+-- | @Parser r e a@ has a reader environment @r@, error type @e@ and a return type @a@.+newtype Parser r e a = Parser {runParser# :: ForeignPtrContents -> r -> Addr# -> Addr# -> Int# -> Res# e a} -instance Functor (Parser e) where+instance Functor (Parser r e) where   fmap f (Parser g) = Parser \fp !r eob s n -> case g fp r eob s n of     OK# a s n -> let !b = f a in OK# b s n     x         -> unsafeCoerce# x@@ -215,7 +215,7 @@     x         -> unsafeCoerce# x   {-# inline (<$) #-} -instance Applicative (Parser e) where+instance Applicative (Parser r e) where   pure a = Parser \fp !r eob s n -> OK# a s n   {-# inline pure #-}   Parser ff <*> Parser fa = Parser \fp !r eob s n -> case ff fp r eob s n of@@ -235,7 +235,7 @@     x         -> unsafeCoerce# x   {-# inline (*>) #-} -instance Monad (Parser e) where+instance Monad (Parser r e) where   return = pure   {-# inline return #-}   Parser fa >>= f = Parser \fp !r eob s n -> case fa fp r eob s n of@@ -262,10 +262,9 @@  -------------------------------------------------------------------------------- --- | Run a parser. The first `Int` argument is the reader environment, while the second one is the---   state.-runParser :: Parser e a -> Int -> Int -> B.ByteString -> Result e a-runParser (Parser f) (I# r) (I# n) b@(B.PS (ForeignPtr _ fp) _ (I# len)) = unsafeDupablePerformIO do+-- | Run a parser. The `Int` argument is the initial state.+runParser :: Parser r e a -> r -> Int -> B.ByteString -> Result e a+runParser (Parser f) !r (I# n) b@(B.PS (ForeignPtr _ fp) _ (I# len)) = unsafeDupablePerformIO do   B.unsafeUseAsCString b \(Ptr buf) -> do     let end = plusAddr# buf len     case f fp r end buf n of@@ -281,54 +280,54 @@ -- | Run a parser on a `String` input. Reminder: @OverloadedStrings@ for `B.ByteString` does not --   yield a valid UTF-8 encoding! For non-ASCII `B.ByteString` literal input, use `runParserS` or --   `packUTF8` for testing.-runParserS :: Parser e a -> Int -> Int -> String -> Result e a+runParserS :: Parser r e a -> r -> Int -> String -> Result e a runParserS pa r !n s = runParser pa r n (packUTF8 s)  --------------------------------------------------------------------------------  -- | Query the `Int` state.-get :: Parser e Int+get :: Parser r e Int get = Parser \fp !r eob s n -> OK# (I# n) s n {-# inline get #-}  -- | Write the `Int` state.-put :: Int -> Parser e ()+put :: Int -> Parser r e () put (I# n) = Parser \fp !r eob s _ -> OK# () s n {-# inline put #-}  -- | Modify the `Int` state.-modify :: (Int -> Int) -> Parser e ()+modify :: (Int -> Int) -> Parser r e () modify f = Parser \fp !r eob s n ->   case f (I# n) of     I# n -> OK# () s n {-# inline modify #-} --- | Query the `Int` environment.-ask :: Parser e Int-ask = Parser \fp !r eob s n -> OK# (I# r) s n+-- | Query the environment.+ask :: Parser r e r+ask = Parser \fp !r eob s n -> OK# r s n {-# inline ask #-}  -- | Run a parser in a modified environment.-local :: (Int -> Int) -> Parser e a -> Parser e a-local f (Parser g) = Parser \fp !r eob s n -> let !(I# r') = f (I# r) in g fp r' eob s n+local :: (r -> r) -> Parser r e a -> Parser r e a+local f (Parser g) = Parser \fp !r eob s n -> let !r' = f r in g fp r' eob s n {-# inline local #-}  --------------------------------------------------------------------------------  -- | The failing parser. By default, parser choice `(<|>)` arbitrarily backtracks --   on parser failure.-empty :: Parser e a+empty :: Parser r e a empty = Parser \fp !r eob s n -> Fail# {-# inline empty #-}  -- | 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 -> Parser e a+err :: e -> Parser r e a err e = Parser \fp !r eob s n -> Err# e {-# inline err #-}  -- | Save the parsing state, then run a parser, then restore the state.-lookahead :: Parser e a -> Parser e a+lookahead :: Parser r e a -> Parser r e a lookahead (Parser f) = Parser \fp !r eob s n ->   case f fp r eob s n of     OK# a _ _ -> OK# a s n@@ -336,7 +335,7 @@ {-# inline lookahead #-}  -- | Convert a parsing failure to a success.-fails :: Parser e a -> Parser e ()+fails :: Parser r e a -> Parser r e () fails (Parser f) = Parser \fp !r eob s n ->   case f fp r eob s n of     OK# _ _ _ -> Fail#@@ -345,33 +344,33 @@ {-# inline fails #-}  -- | Convert a parsing error into failure.-try :: Parser e a -> Parser e a+try :: Parser r e a -> Parser r e a try (Parser f) = Parser \fp !r eob s n -> case f fp r eob s n of   Err# _ -> Fail#   x      -> x {-# inline try #-} --- | Convert a parsing failure to a `Maybe`. If possible, use `optioned` instead.-optional :: Parser e a -> Parser e (Maybe a)+-- | Convert a parsing failure to a `Maybe`. If possible, use `withOption` instead.+optional :: Parser r e a -> Parser r e (Maybe a) optional p = (Just <$> p) <|> pure Nothing {-# inline optional #-}  -- | Convert a parsing failure to a `()`.-optional_ :: Parser e a -> Parser e ()+optional_ :: Parser r e a -> Parser r e () optional_ p = (() <$ p) <|> pure () {-# inline optional_ #-}  -- | CPS'd version of `optional`. This is usually more efficient, since it gets rid of the --   extra `Maybe` allocation.-optioned :: Parser e a -> (a -> Parser e b) -> Parser e b -> Parser e b-optioned (Parser f) just (Parser nothing) = Parser \fp !r eob s n -> case f fp r eob s n of+withOption :: Parser r e a -> (a -> Parser r e b) -> Parser r e b -> Parser r e b+withOption (Parser f) just (Parser nothing) = Parser \fp !r eob s n -> case f fp r eob s n of   OK# a s n -> runParser# (just a) fp r eob s n   Fail#     -> nothing fp r eob s n   Err# e    -> Err# e-{-# inline optioned #-}+{-# inline withOption #-}  -- | Convert a parsing failure to an error.-cut :: Parser e a -> e -> Parser e a+cut :: Parser r e a -> e -> Parser r e a cut (Parser f) e = Parser \fp !r eob s n -> case f fp r eob s n of   Fail# -> Err# e   x     -> x@@ -380,7 +379,7 @@ -- | 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 :: Parser e a -> e -> (e -> e -> e) -> Parser e a+cutting :: Parser r e a -> e -> (e -> e -> e) -> Parser r e a cutting (Parser f) e merge = Parser \fp !r eob s n -> case f fp r eob s n of   Fail#   -> Err# e   Err# e' -> let !e'' = merge e' e in Err# e''@@ -391,7 +390,7 @@   -- | Succeed if the input is empty.-eof :: Parser e ()+eof :: Parser r e () eof = Parser \fp !r eob s n -> case eqAddr# eob s of   1# -> OK# () s n   _  -> Fail#@@ -400,7 +399,7 @@ -- | Read the given number of bytes as a 'ByteString'. -- -- Throws a runtime error if given a negative integer.-takeBs :: Int -> Parser e B.ByteString+takeBs :: Int -> Parser r e B.ByteString takeBs (I# n#) = Parser \fp !r eob s n -> case n# <=# minusAddr# eob s of   1# -> -- have to runtime check for negative values, because they cause a hang     case n# >=# 0# of@@ -410,31 +409,31 @@ {-# inline takeBs #-}  -- | Consume the rest of the input. May return the empty bytestring.-takeRestBs :: Parser e B.ByteString+takeRestBs :: Parser r e B.ByteString takeRestBs = Parser \fp !r eob s n ->   let n# = minusAddr# eob s   in  OK# (B.PS (ForeignPtr s fp) 0 (I# n#)) eob n {-# inline takeRestBs #-}  -- | 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 \'x\')@, for example, and the splice in this case has type @Parser r e ()@. char :: Char -> Q Exp char c = string [c]  -- | Read a byte.-byte :: Word8 -> Parser e ()+byte :: Word8 -> Parser r e () byte w = ensureBytes# 1 >> scan8# w {-# inline byte #-}  -- | Read a sequence of bytes. This is a template function, you can use it as @$(bytes [3, 4, 5])@,---   for example, and the splice has type @Parser e ()@.+--   for example, and the splice has type @Parser r e ()@. bytes :: [Word] -> Q Exp bytes bytes = do   let !len = length bytes   [| ensureBytes# len >> $(scanBytes# bytes) |]  -- | 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 ()@.+--   for example, and the splice has type @Parser r e ()@. string :: String -> Q Exp string str = bytes (strToBytes str) @@ -477,7 +476,7 @@  {-| Switch expression with an optional first argument for performing a post-processing action after-every successful branch matching. For example, if we have @ws :: Parser e ()@ for a+every successful branch matching. For example, if we have @ws :: Parser r e ()@ for a whitespace parser, we might want to consume whitespace after matching on any of the switch cases. For that case, we can define a "lexeme" version of `switch` as follows. @@ -505,14 +504,14 @@   genTrie $! genSwitchTrie' postAction cases fallback  -- | Parse a UTF-8 `Char` for which a predicate holds.-satisfy :: (Char -> Bool) -> Parser e Char+satisfy :: (Char -> Bool) -> Parser r e Char satisfy f = Parser \fp !r eob s n -> case runParser# anyChar fp r eob s n of   OK# c s n | f c -> OK# c s n   _               -> Fail# {-#  inline satisfy #-}  -- | Skip a UTF-8 `Char` for which a predicate holds.-satisfy_ :: (Char -> Bool) -> Parser e ()+satisfy_ :: (Char -> Bool) -> Parser r e () satisfy_ f = Parser \fp !r eob s n -> case runParser# anyChar fp r eob s n of   OK# c s n | f c -> OK# () s n   _               -> Fail#@@ -521,7 +520,7 @@ -- | 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) -> Parser e Char+satisfyASCII :: (Char -> Bool) -> Parser r e Char satisfyASCII f = Parser \fp !r eob s n -> case eqAddr# eob s of   1# -> Fail#   _  -> case derefChar8# s of@@ -531,7 +530,7 @@  -- | Skip an ASCII `Char` for which a predicate holds.  Assumption: the --   predicate must only return `True` for ASCII-range characters.-satisfyASCII_ :: (Char -> Bool) -> Parser e ()+satisfyASCII_ :: (Char -> Bool) -> Parser r e () satisfyASCII_ f = () <$ satisfyASCII f {-# inline satisfyASCII_ #-} @@ -545,7 +544,7 @@ --   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) -> Parser e Char+fusedSatisfy :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser r e Char fusedSatisfy f1 f2 f3 f4 = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case derefChar8# buf of@@ -587,12 +586,12 @@ {-# inline fusedSatisfy #-}  -- | Skipping variant of `fusedSatisfy`.-fusedSatisfy_ :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser e ()+fusedSatisfy_ :: (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> (Char -> Bool) -> Parser r e () fusedSatisfy_ f1 f2 f3 f4 = () <$ fusedSatisfy f1 f2 f3 f4 {-# inline fusedSatisfy_ #-}  -- | Parse any UTF-8-encoded `Char`.-anyChar :: Parser e Char+anyChar :: Parser r e Char anyChar = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case derefChar8# buf of@@ -627,7 +626,7 @@ {-# inline anyChar #-}  -- | Skip any UTF-8-encoded `Char`.-anyChar_ :: Parser e ()+anyChar_ :: Parser r e () anyChar_ = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case derefChar8# buf of@@ -648,7 +647,7 @@  -- | Parse any `Char` in the ASCII range, fail if the next input character is not in the range. --   This is more efficient than `anyChar` if we are only working with ASCII.-anyCharASCII :: Parser e Char+anyCharASCII :: Parser r e Char anyCharASCII = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case derefChar8# buf of@@ -659,20 +658,20 @@  -- | Skip any `Char` in the ASCII range. More efficient than `anyChar_` if we're working only with --   ASCII.-anyCharASCII_ :: Parser e ()+anyCharASCII_ :: Parser r e () anyCharASCII_ = () <$ anyCharASCII {-# inline anyCharASCII_ #-}  -- | Read an `Int` from the input, as a non-empty digit sequence. The `Int` may --   overflow in the result.-readInt :: Parser e Int+readInt :: Parser r e Int readInt = Parser \fp r eob s n -> case FlatParse.Internal.readInt eob s of   (# (##) | #)        -> Fail#   (# | (# i, s' #) #) -> OK# (I# i) s' n {-# inline readInt #-}  -- | Read an `Integer` from the input, as a non-empty digit sequence.-readInteger :: Parser e Integer+readInteger :: Parser r e Integer readInteger = Parser \fp r eob s n -> case FlatParse.Internal.readInteger fp eob s of   (# (##) | #)        -> Fail#   (# | (# i, s' #) #) -> OK# i s' n@@ -684,7 +683,7 @@ -- | Choose between two parsers. If the first parser fails, try the second one, but if the first one --   throws an error, propagate the error. infixr 6 <|>-(<|>) :: Parser e a -> Parser e a -> Parser e a+(<|>) :: Parser r e a -> Parser r e a -> Parser r e a (<|>) (Parser f) (Parser g) = Parser \fp !r eob s n ->   case f fp r eob s n of     Fail# -> g fp r eob s n@@ -694,7 +693,7 @@ -- | 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 :: Parser e a -> Parser e b -> Parser e b -> Parser e b+branch :: Parser r e a -> Parser r e b -> Parser r e b -> Parser r e b branch pa pt pf = Parser \fp !r eob s n -> case runParser# pa fp r eob s n of   OK# _ s n -> runParser# pt fp r eob s n   Fail#     -> runParser# pf fp r eob s n@@ -704,7 +703,7 @@ -- | 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) -> Parser e b -> Parser e a -> Parser e b+chainl :: (b -> a -> b) -> Parser r e b -> Parser r e a -> Parser r e b chainl f start elem = start >>= go where   go b = do {!a <- elem; go $! f b a} <|> pure b {-# inline chainl #-}@@ -712,7 +711,7 @@ -- | 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) -> Parser e a -> Parser e b -> Parser e b+chainr :: (a -> b -> b) -> Parser r e a -> Parser r e b -> Parser r e b chainr f (Parser elem) (Parser end) = go where   go = Parser \fp !r eob s n -> case elem fp r eob s n of     OK# a s n -> case runParser# go fp r eob s n of@@ -725,7 +724,7 @@ -- | Run a parser zero or more times, collect the results in a list. Note: for optimal performance, --   try to avoid this. Often it is possible to get rid of the intermediate list by using a --   combinator or a custom parser.-many :: Parser e a -> Parser e [a]+many :: Parser r e a -> Parser r e [a] many (Parser f) = go where   go = Parser \fp !r eob s n -> case f fp r eob s n of     OK# a s n -> case runParser# go fp r eob s n of@@ -736,7 +735,7 @@ {-# inline many #-}  -- | Skip a parser zero or more times.-many_ :: Parser e a -> Parser e ()+many_ :: Parser r e a -> Parser r e () many_ (Parser f) = go where   go = Parser \fp !r eob s n -> case f fp r eob s n of     OK# a s n -> runParser# go fp r eob s n@@ -747,18 +746,18 @@ -- | Run a parser one or more times, collect the results in a list. Note: for optimal performance, --   try to avoid this. Often it is possible to get rid of the intermediate list by using a --   combinator or a custom parser.-some :: Parser e a -> Parser e [a]+some :: Parser r e a -> Parser r e [a] some p = (:) <$> p <*> many p {-# inline some #-}  -- | Skip a parser one or more times.-some_ :: Parser e a -> Parser e ()+some_ :: Parser r e a -> Parser r e () some_ pa = pa >> many_ pa {-# inline some_ #-}  -- | Succeed if the first parser succeeds and the second one fails. The parsing --   state is restored to the point of the first argument's success.-notFollowedBy :: Parser e a -> Parser e b -> Parser e a+notFollowedBy :: Parser r e a -> Parser r e b -> Parser r e a notFollowedBy p1 p2 = p1 <* lookahead (fails p2) {-# inline notFollowedBy #-} @@ -766,7 +765,7 @@ --   isolated bytes must be consumed. -- -- Throws a runtime error if given a negative integer.-isolate :: Int -> Parser e a -> Parser e a+isolate :: Int -> Parser r e a -> Parser r e a isolate (I# n#) p = Parser \fp !r eob s n ->   let s' = plusAddr# s n#   in  case n# <=# minusAddr# eob s of@@ -784,14 +783,14 @@ --------------------------------------------------------------------------------  -- | Get the current position in the input.-getPos :: Parser e Pos+getPos :: Parser r e Pos getPos = Parser \fp !r eob s n -> OK# (addrToPos# eob s) s n {-# inline getPos #-}  -- | Set the input position. Warning: this can result in crashes if the position points outside the --   current buffer. It is always safe to `setPos` values which came from `getPos` with the current --   input.-setPos :: Pos -> Parser e ()+setPos :: Pos -> Parser r e () setPos s = Parser \fp !r eob _ n -> OK# () (posToAddr# eob s) n {-# inline setPos #-} @@ -801,8 +800,8 @@ {-# inline endPos #-}  --- | Return the consumed span of a parser. Use `spanned` if possible for better efficiency.-spanOf :: Parser e a -> Parser e Span+-- | Return the consumed span of a parser. Use `withSpan` if possible for better efficiency.+spanOf :: Parser r e a -> Parser r e Span spanOf (Parser f) = Parser \fp !r eob s n -> case f fp r eob s n of   OK# a s' n -> OK# (Span (addrToPos# eob s) (addrToPos# eob s')) s' n   x          -> unsafeCoerce# x@@ -810,31 +809,31 @@  -- | Bind the result together with the span of the result. CPS'd version of `spanOf` --   for better unboxing.-spanned :: Parser e a -> (a -> Span -> Parser e b) -> Parser e b-spanned (Parser f) g = Parser \fp !r eob s n -> case f fp r eob s n of+withSpan :: Parser r e a -> (a -> Span -> Parser r e b) -> Parser r e b+withSpan (Parser f) g = Parser \fp !r eob s n -> case f fp r eob s n of   OK# a s' n -> runParser# (g a (Span (addrToPos# eob s) (addrToPos# eob s'))) fp r eob s' n   x          -> unsafeCoerce# x-{-# inline spanned #-}+{-# inline withSpan #-}  -- | Return the `B.ByteString` consumed by a parser. Note: it's more efficient to use `spanOf` and---   `spanned` instead.-byteStringOf :: Parser e a -> Parser e B.ByteString+--   `withSpan` instead.+byteStringOf :: Parser r e a -> Parser r e B.ByteString byteStringOf (Parser f) = Parser \fp !r eob s n -> case f fp r eob s n of   OK# a s' n -> OK# (B.PS (ForeignPtr s fp) 0 (I# (minusAddr# s' s))) s' n   x          -> unsafeCoerce# x {-# inline byteStringOf #-}  -- | CPS'd version of `byteStringOf`. Can be more efficient, because the result is more eagerly unboxed---   by GHC. It's more efficient to use `spanOf` or `spanned` instead.-byteStringed :: Parser e a -> (a -> B.ByteString -> Parser e b) -> Parser e b-byteStringed (Parser f) g = Parser \fp !r eob s n -> case f fp r eob s n of+--   by GHC. It's more efficient to use `spanOf` or `withSpan` instead.+withByteString :: Parser r e a -> (a -> B.ByteString -> Parser r e b) -> Parser r e b+withByteString (Parser f) g = Parser \fp !r eob s n -> case f fp r eob s n of   OK# a s' n -> runParser# (g a (B.PS (ForeignPtr s fp) 0 (I# (minusAddr# s' s)))) fp r eob s' n   x          -> unsafeCoerce# x-{-# inline byteStringed #-}+{-# inline withByteString #-}  -- | Create a `B.ByteString` from a `Span`. The result is invalid is the `Span` points --   outside the current buffer, or if the `Span` start is greater than the end position.-unsafeSpanToByteString :: Span -> Parser e B.ByteString+unsafeSpanToByteString :: Span -> Parser r e B.ByteString unsafeSpanToByteString (Span l r) =   lookahead (setPos l >> byteStringOf (setPos r)) {-# inline unsafeSpanToByteString #-}@@ -843,9 +842,9 @@ -- | Run a parser in a given input span. The input position and the `Int` state is restored after --   the parser is finished, so `inSpan` does not consume input and has no side effect.  Warning: --   this operation may crash if the given span points outside the current parsing buffer. It's---   always safe to use `inSpan` if the span comes from a previous `spanned` or `spanOf` call on+--   always safe to use `inSpan` if the span comes from a previous `withSpan` or `spanOf` call on --   the current input.-inSpan :: Span -> Parser e a -> Parser e a+inSpan :: Span -> Parser r e a -> Parser r e a inSpan (Span s eob) (Parser f) = Parser \fp !r eob' s' n' ->   case f fp r (posToAddr# eob' eob) (posToAddr# eob' s) n' of     OK# a _ _ -> OK# a s' n'@@ -857,7 +856,7 @@  -- | Parse the rest of the current line as a `String`. Assumes UTF-8 encoding, --   throws an error if the encoding is invalid.-takeLine :: Parser e String+takeLine :: Parser r e String takeLine =   branch eof (pure "") do   c <- anyChar@@ -867,28 +866,28 @@  -- | 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 :: Parser e String+traceLine :: Parser r e String traceLine = lookahead takeLine  -- | Take the rest of the input as a `String`. Assumes UTF-8 encoding.-takeRest :: Parser e String+takeRest :: Parser r e String takeRest = ((:) <$> anyChar <*> takeRest) <|> pure []  -- | 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 :: Parser e String+traceRest :: Parser r e String traceRest = lookahead traceRest  --------------------------------------------------------------------------------  -- | Convert an UTF-8-coded `B.ByteString` to a `String`. unpackUTF8 :: B.ByteString -> String-unpackUTF8 str = case runParser takeRest 0 0 str of+unpackUTF8 str = case runParser takeRest () 0 str of   OK a _ _ -> a   _        -> error "unpackUTF8: invalid encoding"  -- | Check that the input has at least the given number of bytes.-ensureBytes# :: Int -> Parser e ()+ensureBytes# :: Int -> Parser r e () ensureBytes# (I# len) = Parser \fp !r eob s n ->   case len  <=# minusAddr# eob s of     1# -> OK# () s n@@ -897,7 +896,7 @@  -- | Unsafely read a concrete byte from the input. It's not checked that the input has --   enough bytes.-scan8# :: Word8 -> Parser e ()+scan8# :: Word8 -> Parser r e () scan8# (W8# c) = Parser \fp !r eob s n ->   case indexWord8OffAddr# s 0# of     c' -> case eqWord8'# c c' of@@ -907,7 +906,7 @@  -- | Unsafely read two concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan16# :: Word16 -> Parser e ()+scan16# :: Word16 -> Parser r e () scan16# (W16# c) = Parser \fp !r eob s n ->   case indexWord16OffAddr# s 0# of     c' -> case eqWord16'# c c' of@@ -917,7 +916,7 @@  -- | Unsafely read four concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan32# :: Word32 -> Parser e ()+scan32# :: Word32 -> Parser r e () scan32# (W32# c) = Parser \fp !r eob s n ->   case indexWord32OffAddr# s 0# of     c' -> case eqWord32'# c c' of@@ -927,7 +926,7 @@  -- | Unsafely read eight concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan64# :: Word -> Parser e ()+scan64# :: Word -> Parser r e () scan64# (W# c) = Parser \fp !r eob s n ->   case indexWord64OffAddr# s 0# of     c' -> case eqWord# c c' of@@ -936,11 +935,11 @@ {-# inline scan64# #-}  -- | Unsafely read and return a byte from the input. It's not checked that the input is non-empty.-scanAny8# :: Parser e Word8+scanAny8# :: Parser r e Word8 scanAny8# = Parser \fp !r eob s n -> OK# (W8# (indexWord8OffAddr# s 0#)) (plusAddr# s 1#) n {-# inline scanAny8# #-} -scanPartial64# :: Int -> Word -> Parser e ()+scanPartial64# :: Int -> Word -> Parser r e () scanPartial64# (I# len) (W# w) = Parser \fp !r eob s n ->   case indexWordOffAddr# s 0# of     w' -> case uncheckedIShiftL# (8# -# len) 3# of@@ -952,12 +951,12 @@ {-# inline scanPartial64# #-}  -- | Decrease the current input position by the given number of bytes.-setBack# :: Int -> Parser e ()+setBack# :: Int -> Parser r e () setBack# (I# i) = Parser \fp !r eob s n ->   OK# () (plusAddr# s (negateInt# i)) n {-# inline setBack# #-} --- | Template function, creates a @Parser e ()@ which unsafely scans a given+-- | Template function, creates a @Parser r e ()@ which unsafely scans a given --   sequence of bytes. scanBytes# :: [Word] -> Q Exp scanBytes# bytes = do@@ -1074,56 +1073,56 @@  -------------------------------------------------------------------------------- -withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a+withAnyWord8# :: (Word8'# -> Parser r e a) -> Parser r e a withAnyWord8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case indexWord8OffAddr# buf 0# of     w# -> runParser# (p w#) fp r eob (plusAddr# buf 1#) n {-# inline withAnyWord8# #-} -withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a+withAnyWord16# :: (Word16'# -> Parser r e a) -> Parser r e a withAnyWord16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexWord16OffAddr# buf 0# of     w# -> runParser# (p w#) fp r eob (plusAddr# buf 2#) n {-# inline withAnyWord16# #-} -withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a+withAnyWord32# :: (Word32'# -> Parser r e a) -> Parser r e a withAnyWord32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexWord32OffAddr# buf 0# of     w# -> runParser# (p w#) fp r eob (plusAddr# buf 4#) n {-# inline withAnyWord32# #-} -withAnyWord64# :: (Word# -> Parser e a) -> Parser e a+withAnyWord64# :: (Word# -> Parser r e a) -> Parser r e a withAnyWord64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexWordOffAddr# buf 0# of     w# -> runParser# (p w#) fp r eob (plusAddr# buf 8#) n {-# inline withAnyWord64# #-} -withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a+withAnyInt8# :: (Int8'# -> Parser r e a) -> Parser r e a withAnyInt8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of   1# -> Fail#   _  -> case indexInt8OffAddr# buf 0# of     i# -> runParser# (p i#) fp r eob (plusAddr# buf 1#) n {-# inline withAnyInt8# #-} -withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a+withAnyInt16# :: (Int16'# -> Parser r e a) -> Parser r e a withAnyInt16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexInt16OffAddr# buf 0# of     i# -> runParser# (p i#) fp r eob (plusAddr# buf 2#) n {-# inline withAnyInt16# #-} -withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a+withAnyInt32# :: (Int32'# -> Parser r e a) -> Parser r e a withAnyInt32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexInt32OffAddr# buf 0# of     i# -> runParser# (p i#) fp r eob (plusAddr# buf 4#) n {-# inline withAnyInt32# #-} -withAnyInt64# :: (Int# -> Parser e a) -> Parser e a+withAnyInt64# :: (Int# -> Parser r e a) -> Parser r e a withAnyInt64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of   0# -> Fail#   _  -> case indexInt64OffAddr# buf 0# of@@ -1133,142 +1132,142 @@ --------------------------------------------------------------------------------  -- | Parse any 'Word8' (byte).-anyWord8 :: Parser e Word8+anyWord8 :: Parser r e Word8 anyWord8 = withAnyWord8# (\w# -> pure (W8# w#)) {-# inline anyWord8 #-}  -- | Skip any 'Word8' (byte).-anyWord8_ :: Parser e ()+anyWord8_ :: Parser r e () anyWord8_ = () <$ anyWord8 {-# inline anyWord8_ #-}  -- | Parse any 'Word16'.-anyWord16 :: Parser e Word16+anyWord16 :: Parser r e Word16 anyWord16 = withAnyWord16# (\w# -> pure (W16# w#)) {-# inline anyWord16 #-}  -- | Skip any 'Word16'.-anyWord16_ :: Parser e ()+anyWord16_ :: Parser r e () anyWord16_ = () <$ anyWord16 {-# inline anyWord16_ #-}  -- | Parse any 'Word32'.-anyWord32 :: Parser e Word32+anyWord32 :: Parser r e Word32 anyWord32 = withAnyWord32# (\w# -> pure (W32# w#)) {-# inline anyWord32 #-}  -- | Skip any 'Word32'.-anyWord32_ :: Parser e ()+anyWord32_ :: Parser r e () anyWord32_ = () <$ anyWord32 {-# inline anyWord32_ #-}  -- | Parse any 'Word64'.-anyWord64 :: Parser e Word64+anyWord64 :: Parser r e Word64 anyWord64 = withAnyWord64# (\w# -> pure (W64# w#)) {-# inline anyWord64 #-}  -- | Skip any 'Word64'.-anyWord64_ :: Parser e ()+anyWord64_ :: Parser r e () anyWord64_ = () <$ anyWord64 {-# inline anyWord64_ #-}  -- | Parse any 'Word'.-anyWord :: Parser e Word+anyWord :: Parser r e Word anyWord = withAnyWord64# (\w# -> pure (W# w#)) {-# inline anyWord #-}  -- | Skip any 'Word'.-anyWord_ :: Parser e ()+anyWord_ :: Parser r e () anyWord_ = () <$ anyWord {-# inline anyWord_ #-}  --------------------------------------------------------------------------------  -- | Parse any 'Int8'.-anyInt8 :: Parser e Int8+anyInt8 :: Parser r e Int8 anyInt8 = withAnyInt8# (\i# -> pure (I8# i#)) {-# inline anyInt8 #-}  -- | Parse any 'Int16'.-anyInt16 :: Parser e Int16+anyInt16 :: Parser r e Int16 anyInt16 = withAnyInt16# (\i# -> pure (I16# i#)) {-# inline anyInt16 #-}  -- | Parse any 'Int32'.-anyInt32 :: Parser e Int32+anyInt32 :: Parser r e Int32 anyInt32 = withAnyInt32# (\i# -> pure (I32# i#)) {-# inline anyInt32 #-}  -- | Parse any 'Int64'.-anyInt64 :: Parser e Int64+anyInt64 :: Parser r e Int64 anyInt64 = withAnyInt64# (\i# -> pure (I64# i#)) {-# inline anyInt64 #-}  -- | Parse any 'Int'.-anyInt :: Parser e Int+anyInt :: Parser r e Int anyInt = withAnyInt64# (\i# -> pure (I# i#)) {-# inline anyInt #-}  --------------------------------------------------------------------------------  -- | Parse any 'Word16' (little-endian).-anyWord16le :: Parser e Word16+anyWord16le :: Parser r e Word16 anyWord16le = anyWord16 {-# inline anyWord16le #-}  -- | Parse any 'Word16' (big-endian).-anyWord16be :: Parser e Word16+anyWord16be :: Parser r e Word16 anyWord16be = withAnyWord16# (\w# -> pure (W16# (byteSwap16'# w#))) {-# inline anyWord16be #-}  -- | Parse any 'Word32' (little-endian).-anyWord32le :: Parser e Word32+anyWord32le :: Parser r e Word32 anyWord32le = anyWord32 {-# inline anyWord32le #-}  -- | Parse any 'Word32' (big-endian).-anyWord32be :: Parser e Word32+anyWord32be :: Parser r e Word32 anyWord32be = withAnyWord32# (\w# -> pure (W32# (byteSwap32'# w#))) {-# inline anyWord32be #-}  -- | Parse any 'Word64' (little-endian).-anyWord64le :: Parser e Word64+anyWord64le :: Parser r e Word64 anyWord64le = anyWord64 {-# inline anyWord64le #-}  -- | Parse any 'Word64' (big-endian).-anyWord64be :: Parser e Word64+anyWord64be :: Parser r e Word64 anyWord64be = withAnyWord64# (\w# -> pure (W64# (byteSwap# w#))) {-# inline anyWord64be #-}  --------------------------------------------------------------------------------  -- | Parse any 'Int16' (little-endian).-anyInt16le :: Parser e Int16+anyInt16le :: Parser r e Int16 anyInt16le = anyInt16 {-# inline anyInt16le #-}  -- | Parse any 'Int16' (big-endian).-anyInt16be :: Parser e Int16+anyInt16be :: Parser r e Int16 anyInt16be = withAnyWord16# (\w# -> pure (I16# (word16ToInt16# (byteSwap16'# w#)))) {-# inline anyInt16be #-}  -- | Parse any 'Int32' (little-endian).-anyInt32le :: Parser e Int32+anyInt32le :: Parser r e Int32 anyInt32le = anyInt32 {-# inline anyInt32le #-}  -- | Parse any 'Int32' (big-endian).-anyInt32be :: Parser e Int32+anyInt32be :: Parser r e Int32 anyInt32be = withAnyWord32# (\w# -> pure (I32# (word32ToInt32# (byteSwap32'# w#)))) {-# inline anyInt32be #-}  -- | Parse any 'Int64' (little-endian).-anyInt64le :: Parser e Int64+anyInt64le :: Parser r e Int64 anyInt64le = anyInt64 {-# inline anyInt64le #-}  -- | Parse any 'Int64' (big-endian).-anyInt64be :: Parser e Int64+anyInt64be :: Parser r e Int64 anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#)))) {-# inline anyInt64be #-}
test/Test.hs view
@@ -53,8 +53,8 @@       it "can succeed when argument missing" $ optional empty `shouldParse` ""       it "propagates errors" $ optional (err "nope") `shouldParseErr` "" -    describe "optioned" $ do-      let opt p = optioned p (pure . reverse) (pure "bar")+    describe "withOption" $ do+      let opt p = withOption p (pure . reverse) (pure "bar")       it "handles success" $ opt (pure "foo") `shouldParseWith` ("", "oof")       it "handles failure" $ opt empty `shouldParseWith` ("", "bar")       it "handles error" $ opt (err "nope") `shouldParseErr` ""@@ -78,6 +78,11 @@       it "succeeds at end of file" $ eof `shouldParse` ""       it "fails with more input" $ eof `shouldParseFail` "more" +    describe "skip" $ do+      prop "skips to the end of input" $+        \(bs :: ByteString) ->+          (skip (B.length bs) >> eof) `shouldParse` bs+     describe "char" $ do       it "succeeds on that char" $ $(char 'a') `shouldParse` "a"       it "succeeds on multibyte char" $ $(char 'ȩ') `shouldParse` packUTF8 "ȩ"@@ -396,6 +401,13 @@       it "fails on negative integers" $ readInteger `shouldParseFail` "-5"       it "fails on empty input" $ readInteger `shouldParseFail` "" +    describe "anyCString" $ do+      prop "parses arbitrary null-terminated bytestrings" $+        \(bs :: ByteString) ->+          let bs' = B.snoc bs 0x00+              expected = B.takeWhile (/= 0x00) bs'+          in  anyCString `shouldParsePartialWith` (bs', expected)+     describe "Explicit-endianness machine integers" $ do       describe "Unsigned" $ do         prop "parses Word8s" $ do@@ -605,6 +617,15 @@      describe "unpackUTF8" $ do       pure ()++  describe "Location & address primitives" $ do+    it "valid lookaheadFromAddr# usage succeeds" $ do+      -- use Int#/Int64# directly because Word8# -> Int# is annoying on old GHCs+      let bs = B.pack [ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00+                      , 0xFF, 0x31, 0x32, 0x33, 0x00, 0xFF]+          p = withAddr# $ \addr# -> withAnyInt64# $ \os# ->+                  lookaheadFromAddr# addr# $ atSkip# os# $ anyCString+      p `shouldParsePartialWith` (bs, "123")  --------------------------------------------------------------------------------