-- |
-- Module      :  Data.ByteString.Parser
-- License     :  CC0-1.0
--
-- Maintainer  :  mordae@anilinux.org
-- Stability   :  unstable
-- Portability :  non-portable (ghc)
--
-- This module provides a parser for 'ByteString'.
--
--   * If you\'d like to parse ASCII text, you might want to take a look at
--     "Data.ByteString.Parser.Char8". It reuses the same 'Parser', but
--     provides functions working with 'Char' instead of 'Word8' as well as
--     more string utilities.
--
--   * If you\'d like to parse Unicode text, look instead at the
--     "Data.Text.Parser". Is is slower, but in a way more correct.
--

module Data.ByteString.Parser
  ( Parser(..)
  , parseOnly

    -- * Bytes
  , byte
  , notByte
  , anyByte
  , satisfy
  , peekByte

    -- * Strings
  , string
  , Data.ByteString.Parser.take
  , scan
  , runScanner
  , Data.ByteString.Parser.takeWhile
  , takeWhile1
  , takeTill
  , takeTill1

    -- * Combinators
  , provided
  , choice
  , Snack.Combinators.count
  , optional
  , eitherP
  , option
  , many
  , many1
  , manyTill
  , sepBy
  , sepBy1
  , wrap
  , match

    -- * End Of Input
  , takeByteString
  , endOfInput
  , atEnd

    -- * Miscelaneous
    -- |
    -- These are all generic methods, but since I sometimes forget about them,
    -- it is nice to have them listed here for reference what writing parsers.
  , Control.Applicative.empty
  , pure
  , guard
  , when
  , unless
  , void
  )
where
  import Prelude hiding (null, length, splitAt, take)

  import Control.Applicative
  import Control.Monad

  import Data.Maybe
  import Data.Word

  import Data.ByteString as BS
  import Data.ByteString.Unsafe as BS

  import Snack.Combinators


  newtype Parser a =
    Parser
      { forall a. Parser a -> ByteString -> Maybe (a, ByteString)
runParser :: ByteString -> Maybe (a, ByteString)
      }

  instance Functor Parser where
    {-# INLINE fmap #-}
    fmap :: forall a b. (a -> b) -> Parser a -> Parser b
fmap a -> b
fn Parser{ByteString -> Maybe (a, ByteString)
runParser :: ByteString -> Maybe (a, ByteString)
runParser :: forall a. Parser a -> ByteString -> Maybe (a, ByteString)
runParser} = (ByteString -> Maybe (b, ByteString)) -> Parser b
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
      case ByteString -> Maybe (a, ByteString)
runParser ByteString
inp of
        Just (a
res, ByteString
rest) -> (b, ByteString) -> Maybe (b, ByteString)
forall a. a -> Maybe a
Just (a -> b
fn a
res, ByteString
rest)
        Maybe (a, ByteString)
Nothing -> Maybe (b, ByteString)
forall a. Maybe a
Nothing

  instance Applicative Parser where
    {-# INLINE pure #-}
    pure :: forall a. a -> Parser a
pure a
x = (ByteString -> Maybe (a, ByteString)) -> Parser a
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp -> (a, ByteString) -> Maybe (a, ByteString)
forall a. a -> Maybe a
Just (a
x, ByteString
inp)

    {-# INLINE (<*>) #-}
    (Parser ByteString -> Maybe (a -> b, ByteString)
runFn) <*> :: forall a b. Parser (a -> b) -> Parser a -> Parser b
<*> (Parser ByteString -> Maybe (a, ByteString)
runArg) = (ByteString -> Maybe (b, ByteString)) -> Parser b
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
      case ByteString -> Maybe (a -> b, ByteString)
runFn ByteString
inp of
        Maybe (a -> b, ByteString)
Nothing -> Maybe (b, ByteString)
forall a. Maybe a
Nothing
        Just (a -> b
fn, ByteString
rest) ->
          case ByteString -> Maybe (a, ByteString)
runArg ByteString
rest of
            Maybe (a, ByteString)
Nothing -> Maybe (b, ByteString)
forall a. Maybe a
Nothing
            Just (a
x, ByteString
rest') -> (b, ByteString) -> Maybe (b, ByteString)
forall a. a -> Maybe a
Just (a -> b
fn a
x, ByteString
rest')

  instance Alternative Parser where
    {-# INLINE empty #-}
    empty :: forall a. Parser a
empty = (ByteString -> Maybe (a, ByteString)) -> Parser a
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
_ -> Maybe (a, ByteString)
forall a. Maybe a
Nothing

    {-# INLINE (<|>) #-}
    (Parser ByteString -> Maybe (a, ByteString)
runLeft) <|> :: forall a. Parser a -> Parser a -> Parser a
<|> (Parser ByteString -> Maybe (a, ByteString)
runRight) = (ByteString -> Maybe (a, ByteString)) -> Parser a
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
      case ByteString -> Maybe (a, ByteString)
runLeft ByteString
inp of
        Just (a, ByteString)
r  -> (a, ByteString) -> Maybe (a, ByteString)
forall a. a -> Maybe a
Just (a, ByteString)
r
        Maybe (a, ByteString)
Nothing -> ByteString -> Maybe (a, ByteString)
runRight ByteString
inp

  instance Monad Parser where
    {-# INLINE (>>=) #-}
    (Parser ByteString -> Maybe (a, ByteString)
runLeft) >>= :: forall a b. Parser a -> (a -> Parser b) -> Parser b
>>= a -> Parser b
right = (ByteString -> Maybe (b, ByteString)) -> Parser b
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
      case ByteString -> Maybe (a, ByteString)
runLeft ByteString
inp of
        Maybe (a, ByteString)
Nothing -> Maybe (b, ByteString)
forall a. Maybe a
Nothing
        Just (a
x, ByteString
more) -> Parser b -> ByteString -> Maybe (b, ByteString)
forall a. Parser a -> ByteString -> Maybe (a, ByteString)
runParser (a -> Parser b
right a
x) ByteString
more

  instance MonadPlus Parser

  instance MonadFail Parser where
    {-# INLINE CONLIKE fail #-}
    fail :: forall a. String -> Parser a
fail String
_ = Parser a
forall (m :: * -> *) a. MonadPlus m => m a
mzero


  -- |
  -- Discards the remaining input and returns just the parse result.
  -- You might want to combine it with 'endOfInput' for the best effect.
  --
  -- Example:
  --
  -- @
  -- parseOnly (pContacts \<* endOfInput) bstr
  -- @
  --
  {-# INLINE CONLIKE parseOnly #-}
  parseOnly :: Parser a -> ByteString -> Maybe a
  parseOnly :: forall a. Parser a -> ByteString -> Maybe a
parseOnly Parser a
par = \ByteString
inp -> (a, ByteString) -> a
forall a b. (a, b) -> a
fst ((a, ByteString) -> a) -> Maybe (a, ByteString) -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser a -> ByteString -> Maybe (a, ByteString)
forall a. Parser a -> ByteString -> Maybe (a, ByteString)
runParser Parser a
par ByteString
inp


  -- |
  -- Accepts a single, matching byte.
  --
  {-# INLINE CONLIKE byte #-}
  byte :: Word8 -> Parser Word8
  byte :: Word8 -> Parser Word8
byte Word8
c = (Word8 -> Bool) -> Parser Word8
satisfy (Word8
c ==)


  -- |
  -- Accepts a single, differing byte.
  --
  {-# INLINE CONLIKE notByte #-}
  notByte :: Word8 -> Parser Word8
  notByte :: Word8 -> Parser Word8
notByte Word8
c = (Word8 -> Bool) -> Parser Word8
satisfy (Word8
c /=)


  -- |
  -- Accepts a single byte.
  --
  {-# INLINE anyByte #-}
  anyByte :: Parser Word8
  anyByte :: Parser Word8
anyByte = (ByteString -> Maybe (Word8, ByteString)) -> Parser Word8
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    if ByteString -> Bool
null ByteString
inp
       then Maybe (Word8, ByteString)
forall a. Maybe a
Nothing
       else (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
unsafeHead ByteString
inp, ByteString -> ByteString
unsafeTail ByteString
inp)


  -- |
  -- Accepts a single byte matching the predicate.
  --
  {-# INLINE CONLIKE satisfy #-}
  satisfy :: (Word8 -> Bool) -> Parser Word8
  satisfy :: (Word8 -> Bool) -> Parser Word8
satisfy Word8 -> Bool
isOk = (ByteString -> Maybe (Word8, ByteString)) -> Parser Word8
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    if ByteString -> Bool
null ByteString
inp
       then Maybe (Word8, ByteString)
forall a. Maybe a
Nothing
       else let c :: Word8
c = ByteString -> Word8
unsafeHead ByteString
inp
             in if Word8 -> Bool
isOk Word8
c
                   then (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (Word8
c, ByteString -> ByteString
unsafeTail ByteString
inp)
                   else Maybe (Word8, ByteString)
forall a. Maybe a
Nothing


  -- |
  -- Peeks ahead, but does not consume.
  --
  -- Be careful, peeking behind end of the input fails.
  -- You might want to check using 'atEnd' beforehand.
  --
  {-# INLINE peekByte #-}
  peekByte :: Parser Word8
  peekByte :: Parser Word8
peekByte = (ByteString -> Maybe (Word8, ByteString)) -> Parser Word8
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    if ByteString -> Bool
null ByteString
inp
       then Maybe (Word8, ByteString)
forall a. Maybe a
Nothing
       else (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
unsafeHead ByteString
inp, ByteString
inp)


  -- |
  -- Accepts a matching string.
  --
  {-# INLINE CONLIKE string #-}
  string :: ByteString -> Parser ByteString
  string :: ByteString -> Parser ByteString
string ByteString
str = (ByteString -> Maybe (ByteString, ByteString)) -> Parser ByteString
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    let (ByteString
pfx, ByteString
sfx) = Int -> ByteString -> (ByteString, ByteString)
splitAt (ByteString -> Int
length ByteString
str) ByteString
inp
     in case ByteString
pfx ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
str of
          Bool
True -> (ByteString, ByteString) -> Maybe (ByteString, ByteString)
forall a. a -> Maybe a
Just (ByteString
pfx, ByteString
sfx)
          Bool
False -> Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing


  -- |
  -- Accepts given number of bytes.
  -- Fails when not enough bytes are available.
  --
  {-# INLINE CONLIKE take #-}
  take :: Int -> Parser ByteString
  take :: Int -> Parser ByteString
take Int
n = (ByteString -> Maybe (ByteString, ByteString)) -> Parser ByteString
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> ByteString -> Int
length ByteString
inp
       then Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
       else (ByteString, ByteString) -> Maybe (ByteString, ByteString)
forall a. a -> Maybe a
Just (Int -> ByteString -> (ByteString, ByteString)
splitAt Int
n ByteString
inp)


  -- |
  -- Scans ahead statefully and then accepts whatever bytes the scanner liked.
  -- Scanner returns 'Nothing' to mark end of the acceptable extent.
  --
  {-# INLINE CONLIKE scan #-}
  scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString
  scan :: forall s. s -> (s -> Word8 -> Maybe s) -> Parser ByteString
scan s
state s -> Word8 -> Maybe s
scanner = (ByteString, s) -> ByteString
forall a b. (a, b) -> a
fst ((ByteString, s) -> ByteString)
-> Parser (ByteString, s) -> Parser ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
forall s. s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
runScanner s
state s -> Word8 -> Maybe s
scanner


  -- |
  -- Like 'scan', but also returns the final scanner state.
  --
  {-# INLINE CONLIKE runScanner #-}
  runScanner :: s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
  runScanner :: forall s. s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
runScanner s
state s -> Word8 -> Maybe s
scanner = (ByteString -> Maybe ((ByteString, s), ByteString))
-> Parser (ByteString, s)
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    let (s
state', Int
n) = s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
forall s.
s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
scanBytes s
state s -> Word8 -> Maybe s
scanner Int
0 (ByteString -> [Word8]
unpack ByteString
inp)
        (ByteString
res, ByteString
more) = Int -> ByteString -> (ByteString, ByteString)
splitAt Int
n ByteString
inp
     in ((ByteString, s), ByteString)
-> Maybe ((ByteString, s), ByteString)
forall a. a -> Maybe a
Just ((ByteString
res, s
state'), ByteString
more)


  {-# INLINE scanBytes #-}
  scanBytes :: s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
  scanBytes :: forall s.
s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
scanBytes !s
state s -> Word8 -> Maybe s
_scanner !Int
n [] = (s
state, Int
n)
  scanBytes !s
state s -> Word8 -> Maybe s
scanner !Int
n (Word8
x:[Word8]
more) =
    case s -> Word8 -> Maybe s
scanner s
state Word8
x of
      Just s
state' -> s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
forall s.
s -> (s -> Word8 -> Maybe s) -> Int -> [Word8] -> (s, Int)
scanBytes s
state' s -> Word8 -> Maybe s
scanner (Int -> Int
forall a. Enum a => a -> a
succ Int
n) [Word8]
more
      Maybe s
Nothing -> (s
state, Int
n)


  -- |
  -- Efficiently consume as long as the input bytes match the predicate.
  -- An inverse of 'takeTill'.
  --
  {-# INLINE CONLIKE takeWhile #-}
  takeWhile :: (Word8 -> Bool) -> Parser ByteString
  takeWhile :: (Word8 -> Bool) -> Parser ByteString
takeWhile Word8 -> Bool
test = (Word8 -> Bool) -> Parser ByteString
takeTill (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
test)


  -- |
  -- Like 'Data.ByteString.Parser.takeWhile', but requires at least a single byte.
  --
  {-# INLINE CONLIKE takeWhile1 #-}
  takeWhile1 :: (Word8 -> Bool) -> Parser ByteString
  takeWhile1 :: (Word8 -> Bool) -> Parser ByteString
takeWhile1 Word8 -> Bool
test = (ByteString -> Bool) -> Parser ByteString -> Parser ByteString
forall (m :: * -> *) a.
(Alternative m, Monad m) =>
(a -> Bool) -> m a -> m a
provided (Bool -> Bool
not (Bool -> Bool) -> (ByteString -> Bool) -> ByteString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
null) (Parser ByteString -> Parser ByteString)
-> Parser ByteString -> Parser ByteString
forall a b. (a -> b) -> a -> b
$
                    (Word8 -> Bool) -> Parser ByteString
Data.ByteString.Parser.takeWhile Word8 -> Bool
test


  -- |
  -- Efficiently consume until a byte matching the predicate is found.
  -- An inverse of 'Data.ByteString.Parser.takeWhile'.
  --
  {-# INLINE CONLIKE takeTill #-}
  takeTill :: (Word8 -> Bool) -> Parser ByteString
  takeTill :: (Word8 -> Bool) -> Parser ByteString
takeTill Word8 -> Bool
test = (ByteString -> Maybe (ByteString, ByteString)) -> Parser ByteString
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    let n :: Int
n = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe (ByteString -> Int
length ByteString
inp) (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ (Word8 -> Bool) -> ByteString -> Maybe Int
findIndex Word8 -> Bool
test ByteString
inp
     in (ByteString, ByteString) -> Maybe (ByteString, ByteString)
forall a. a -> Maybe a
Just (Int -> ByteString -> (ByteString, ByteString)
splitAt Int
n ByteString
inp)


  -- |
  -- Same as 'takeTill', but requires at least a single byte.
  --
  {-# INLINE CONLIKE takeTill1 #-}
  takeTill1 :: (Word8 -> Bool) -> Parser ByteString
  takeTill1 :: (Word8 -> Bool) -> Parser ByteString
takeTill1 Word8 -> Bool
test = (ByteString -> Bool) -> Parser ByteString -> Parser ByteString
forall (m :: * -> *) a.
(Alternative m, Monad m) =>
(a -> Bool) -> m a -> m a
provided (Bool -> Bool
not (Bool -> Bool) -> (ByteString -> Bool) -> ByteString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
null) (Parser ByteString -> Parser ByteString)
-> Parser ByteString -> Parser ByteString
forall a b. (a -> b) -> a -> b
$
                    (Word8 -> Bool) -> Parser ByteString
Data.ByteString.Parser.takeTill Word8 -> Bool
test


  -- |
  -- Makes the parser not only return the result, but also the original
  -- matched extent.
  --
  {-# INLINE CONLIKE match #-}
  match :: Parser a -> Parser (ByteString, a)
  match :: forall a. Parser a -> Parser (ByteString, a)
match Parser a
par = (ByteString -> Maybe ((ByteString, a), ByteString))
-> Parser (ByteString, a)
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp ->
    case Parser a -> ByteString -> Maybe (a, ByteString)
forall a. Parser a -> ByteString -> Maybe (a, ByteString)
runParser Parser a
par ByteString
inp of
      Maybe (a, ByteString)
Nothing -> Maybe ((ByteString, a), ByteString)
forall a. Maybe a
Nothing
      Just (a
x, ByteString
more) ->
        let n :: Int
n = ByteString -> Int
length ByteString
more
         in ((ByteString, a), ByteString)
-> Maybe ((ByteString, a), ByteString)
forall a. a -> Maybe a
Just ((Int -> ByteString -> ByteString
BS.take Int
n ByteString
inp, a
x), ByteString
more)


  -- |
  -- Accept whatever input remains.
  --
  {-# INLINE takeByteString #-}
  takeByteString :: Parser ByteString
  takeByteString :: Parser ByteString
takeByteString = (ByteString -> Maybe (ByteString, ByteString)) -> Parser ByteString
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp -> (ByteString, ByteString) -> Maybe (ByteString, ByteString)
forall a. a -> Maybe a
Just (ByteString
inp, ByteString
forall a. Monoid a => a
mempty)


  -- |
  -- Accepts end of input and fails if we are not there yet.
  --
  {-# INLINE endOfInput #-}
  endOfInput :: Parser ()
  endOfInput :: Parser ()
endOfInput = (ByteString -> Maybe ((), ByteString)) -> Parser ()
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \case
    ByteString
inp | ByteString -> Bool
null ByteString
inp  -> ((), ByteString) -> Maybe ((), ByteString)
forall a. a -> Maybe a
Just ((), ByteString
inp)
    ByteString
_otherwise      -> Maybe ((), ByteString)
forall a. Maybe a
Nothing


  -- |
  -- Returns whether we are at the end of the input yet.
  --
  {-# INLINE atEnd #-}
  atEnd :: Parser Bool
  atEnd :: Parser Bool
atEnd = (ByteString -> Maybe (Bool, ByteString)) -> Parser Bool
forall a. (ByteString -> Maybe (a, ByteString)) -> Parser a
Parser \ByteString
inp -> (Bool, ByteString) -> Maybe (Bool, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Bool
null ByteString
inp, ByteString
inp)


-- vim:set ft=haskell sw=2 ts=2 et: