module Scanner
( Scanner
, Result (..)
, scan
, scanOnly
, scanLazy
, scanWith
, anyWord8
, anyChar8
, word8
, char8
, take
, takeWhile
, takeWhileChar8
, string
, skipWhile
, skipSpace
, lookAhead
, lookAheadChar8
, foldlWhile
, foldlWhile1
, satisfy
, satisfyMaybe
, decimal
)
where
import Scanner.Internal
import Prelude hiding (take, takeWhile)
import Data.Word
import qualified Data.Char as Char
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as Lazy (ByteString)
import qualified Data.ByteString.Lazy as Lazy.ByteString
import Control.Monad
import GHC.Base (unsafeChr)
scanOnly :: Scanner a -> ByteString -> Either String a
scanOnly :: Scanner a -> ByteString -> Either String a
scanOnly s :: Scanner a
s bs :: ByteString
bs = Result a -> Either String a
forall b. Result b -> Either String b
go (Scanner a -> ByteString -> Result a
forall r. Scanner r -> ByteString -> Result r
scan Scanner a
s ByteString
bs)
where
go :: Result b -> Either String b
go res :: Result b
res = case Result b
res of
Done _ r :: b
r -> b -> Either String b
forall a b. b -> Either a b
Right b
r
Fail _ err :: String
err -> String -> Either String b
forall a b. a -> Either a b
Left String
err
More more :: ByteString -> Result b
more -> Result b -> Either String b
go (ByteString -> Result b
more ByteString
ByteString.empty)
scanLazy :: Scanner a -> Lazy.ByteString -> Either String a
scanLazy :: Scanner a -> ByteString -> Either String a
scanLazy s :: Scanner a
s lbs :: ByteString
lbs = (ByteString -> Result a) -> [ByteString] -> Either String a
forall b.
(ByteString -> Result b) -> [ByteString] -> Either String b
go (Scanner a -> ByteString -> Result a
forall r. Scanner r -> ByteString -> Result r
scan Scanner a
s) (ByteString -> [ByteString]
Lazy.ByteString.toChunks ByteString
lbs)
where
go :: (ByteString -> Result b) -> [ByteString] -> Either String b
go more :: ByteString -> Result b
more chunks :: [ByteString]
chunks =
let (chunk :: ByteString
chunk, chunks' :: [ByteString]
chunks') = case [ByteString]
chunks of
[] -> (ByteString
ByteString.empty, [])
(c:cs) -> (ByteString
c, [ByteString]
cs)
in case ByteString -> Result b
more ByteString
chunk of
Done _ r :: b
r -> b -> Either String b
forall a b. b -> Either a b
Right b
r
Fail _ err :: String
err -> String -> Either String b
forall a b. a -> Either a b
Left String
err
More more' :: ByteString -> Result b
more' -> (ByteString -> Result b) -> [ByteString] -> Either String b
go ByteString -> Result b
more' [ByteString]
chunks'
scanWith :: Monad m => m ByteString -> Scanner a -> ByteString -> m (Result a)
scanWith :: m ByteString -> Scanner a -> ByteString -> m (Result a)
scanWith more :: m ByteString
more s :: Scanner a
s input :: ByteString
input = ByteString -> (ByteString -> Result a) -> m (Result a)
forall r. ByteString -> (ByteString -> Result r) -> m (Result r)
go ByteString
input (Scanner a -> ByteString -> Result a
forall r. Scanner r -> ByteString -> Result r
scan Scanner a
s)
where
go :: ByteString -> (ByteString -> Result r) -> m (Result r)
go bs :: ByteString
bs next :: ByteString -> Result r
next = case ByteString -> Result r
next ByteString
bs of
More next' :: ByteString -> Result r
next' -> do
ByteString
bs' <- m ByteString
more
ByteString -> (ByteString -> Result r) -> m (Result r)
go ByteString
bs' ByteString -> Result r
next'
res :: Result r
res -> Result r -> m (Result r)
forall (m :: * -> *) a. Monad m => a -> m a
return Result r
res
{-# INLINE anyChar8 #-}
anyChar8 :: Scanner Char
anyChar8 :: Scanner Char
anyChar8 = Word8 -> Char
w2c (Word8 -> Char) -> Scanner Word8 -> Scanner Char
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Scanner Word8
anyWord8
{-# INLINE word8 #-}
word8 :: Word8 -> Scanner ()
word8 :: Word8 -> Scanner ()
word8 w :: Word8
w = do
Word8
w' <- Scanner Word8
anyWord8
Bool -> Scanner () -> Scanner ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Word8
w' Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
w) (Scanner () -> Scanner ()) -> Scanner () -> Scanner ()
forall a b. (a -> b) -> a -> b
$
String -> Scanner ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail "unexpected word"
{-# INLINE char8 #-}
char8 :: Char -> Scanner ()
char8 :: Char -> Scanner ()
char8 = Word8 -> Scanner ()
word8 (Word8 -> Scanner ()) -> (Char -> Word8) -> Char -> Scanner ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Word8
c2w
{-# INLINE takeWhileChar8 #-}
takeWhileChar8 :: (Char -> Bool) -> Scanner ByteString
takeWhileChar8 :: (Char -> Bool) -> Scanner ByteString
takeWhileChar8 p :: Char -> Bool
p = (Word8 -> Bool) -> Scanner ByteString
takeWhile (Char -> Bool
p (Char -> Bool) -> (Word8 -> Char) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Char
w2c)
{-# INLINE lookAheadChar8 #-}
lookAheadChar8 :: Scanner (Maybe Char)
lookAheadChar8 :: Scanner (Maybe Char)
lookAheadChar8 = (Word8 -> Char) -> Maybe Word8 -> Maybe Char
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word8 -> Char
w2c (Maybe Word8 -> Maybe Char)
-> Scanner (Maybe Word8) -> Scanner (Maybe Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Scanner (Maybe Word8)
lookAhead
{-# INLINE skipWhile #-}
skipWhile :: (Word8 -> Bool) -> Scanner ()
skipWhile :: (Word8 -> Bool) -> Scanner ()
skipWhile = Scanner ByteString -> Scanner ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Scanner ByteString -> Scanner ())
-> ((Word8 -> Bool) -> Scanner ByteString)
-> (Word8 -> Bool)
-> Scanner ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool) -> Scanner ByteString
takeWhile
{-# INLINE skipSpace #-}
skipSpace :: Scanner ()
skipSpace :: Scanner ()
skipSpace = (Word8 -> Bool) -> Scanner ()
skipWhile Word8 -> Bool
isSpaceWord8
{-# INLINE isSpaceWord8 #-}
isSpaceWord8 :: Word8 -> Bool
isSpaceWord8 :: Word8 -> Bool
isSpaceWord8 w :: Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 32 Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= 13
{-# INLINE w2c #-}
w2c :: Word8 -> Char
w2c :: Word8 -> Char
w2c = Int -> Char
unsafeChr (Int -> Char) -> (Word8 -> Int) -> Word8 -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE c2w #-}
c2w :: Char -> Word8
c2w :: Char -> Word8
c2w = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
Char.ord