, char
, string
, (<|>)
+ , choice
, oneOf
, digit
, hexDigit
where
import Control.Monad.State.Strict
-import Data.ByteString.Base (LazyByteString)
-import Data.ByteString.Lazy ()
-import qualified Data.ByteString.Lazy.Char8 as B
+import qualified Data.ByteString.Lazy as Lazy (ByteString)
+import qualified Data.ByteString.Lazy.Char8 as B hiding (ByteString)
-- |@'Parser' a@ is obviously a parser which parses and returns @a@.
newtype Parser a = Parser {
data ParserState
= PST {
- pstInput :: LazyByteString
+ pstInput :: Lazy.ByteString
, pstIsEOFFatal :: !Bool
}
deriving (Eq, Show)
failP :: Parser a
failP = fail undefined
--- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(result,
--- remaining)@.
-parse :: Parser a -> LazyByteString -> (# ParserResult a, LazyByteString #)
+-- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(# result,
+-- remaining #)@.
+parse :: Parser a -> Lazy.ByteString -> (# ParserResult a, Lazy.ByteString #)
parse p input -- input は lazy である必要有り。
= p `seq`
let (result, state') = runState (runParser p) (PST input True)
result `seq` (# result, pstInput state' #) -- pstInput state' も lazy である必要有り。
-- |@'parseStr' p str@ packs @str@ and parses it.
-parseStr :: Parser a -> String -> (# ParserResult a, LazyByteString #)
+parseStr :: Parser a -> String -> (# ParserResult a, Lazy.ByteString #)
parseStr p input
= p `seq` -- input は lazy である必要有り。
parse p (B.pack input)
satisfy :: (Char -> Bool) -> Parser Char
satisfy f = f `seq`
do c <- anyChar
- if f c then
+ if f $! c then
return c
else
failP
(<|>) :: Parser a -> Parser a -> Parser a
f <|> g
= f `seq` g `seq`
- Parser $! do saved <- get -- 状態を保存
+ Parser $! do saved <- get -- 状態を保存
result <- runParser f
case result of
Success a -> return $! Success a
runParser g
+choice :: [Parser a] -> Parser a
+choice = foldl (<|>) failP
+
+
oneOf :: [Char] -> Parser Char
oneOf = foldl (<|>) failP . map char
notFollowedBy :: Parser a -> Parser ()
-notFollowedBy p = p `seq`
- (p >> failP) <|> return ()
+notFollowedBy p
+ = p `seq`
+ Parser $! do saved <- get -- 状態を保存
+ result <- runParser p
+ case result of
+ Success _ -> do put saved -- 状態を復歸
+ return IllegalInput
+ IllegalInput -> do put saved -- 状態を復歸
+ return $! Success ()
+ ReachedEOF -> do put saved -- 状態を復歸
+ return $! Success ()
digit :: Parser Char