+-- |Yet another parser combinator. This is mostly a subset of Parsec
+-- but there are some differences:
+--
+-- * This parser works on ByteString instead of String.
+--
+-- * Backtracking is the only possible behavior so there is no \"try\"
+-- action.
+--
+-- * On success, the remaining string is returned as well as the
+-- parser result.
+--
+-- * You can treat reaching EOF (trying to eat one more letter at the
+-- end of string) a fatal error or a normal failure. If a fatal
+-- error occurs, the entire parsing process immediately fails
+-- without trying any backtracks. The default behavior is to treat
+-- EOF fatal.
+--
+-- In general, you don't have to use this module directly.
module Network.HTTP.Lucu.Parser
- ( Parser(..)
+ ( Parser
, ParserResult(..)
- , parse -- Parser a -> ByteString -> (ParserResult a, ByteString)
- , parseStr -- Parser a -> String -> (ParserResult a, ByteString)
-
- , anyChar -- Parser Char
- , eof -- Parser ()
- , allowEOF -- Parser a -> Parser a
- , satisfy -- (Char -> Bool) -> Parser Char
- , char -- Char -> Parser Char
- , string -- String -> Parser String
- , (<|>) -- Parser a -> Parser a -> Parser a
- , oneOf -- [Char] -> Parser Char
- , digit -- Parser Char
- , hexDigit -- Parser Char
- , notFollowedBy -- Parser a -> Parser ()
- , many -- Parser a -> Parser [a]
- , many1 -- Parser a -> Parser [a]
- , manyTill -- Parser a -> Parser end -> Parser [a]
- , many1Till -- Parser a -> Parser end -> Parser [a]
- , count -- Int -> Parser a -> Parser [a]
- , option -- a -> Parser a -> Parser a
- , sepBy -- Parser a -> Parser sep -> Parser [a]
- , sepBy1 -- Parser a -> Parser sep -> Parser [a]
-
- , sp -- Parser Char
- , ht -- Parser Char
- , crlf -- Parser String
+ , parse
+ , parseStr
+
+ , anyChar
+ , eof
+ , allowEOF
+ , satisfy
+ , char
+ , string
+ , (<|>)
+ , oneOf
+ , digit
+ , hexDigit
+ , notFollowedBy
+ , many
+ , many1
+ , manyTill
+ , many1Till
+ , count
+ , option
+ , sepBy
+ , sepBy1
+
+ , sp
+ , ht
+ , crlf
)
where
import qualified Data.ByteString.Lazy.Char8 as B
import Data.ByteString.Lazy.Char8 (ByteString)
+-- |@Parser a@ is obviously a parser which parses and returns @a@.
data Parser a = Parser {
runParser :: State ParserState (ParserResult a)
}
Success a -> runParser (f a)
IllegalInput -> do put saved -- 状態を復歸
return IllegalInput
- ReachedEOF -> if isEOFFatal then
- return ReachedEOF
- else
- do put saved
- return IllegalInput
+ ReachedEOF -> do unless isEOFFatal
+ $ put saved -- 状態を復歸
+ return ReachedEOF
return = Parser . return . Success
fail _ = Parser $ return IllegalInput
-
+-- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(result,
+-- remaining)@.
parse :: Parser a -> ByteString -> (ParserResult a, ByteString)
parse p input = let (result, (input', _)) = runState (runParser p) (input, True)
in
(result, input')
-
+-- |@'parseStr' p str@ packs @str@ and parses it.
parseStr :: Parser a -> String -> (ParserResult a, ByteString)
parseStr p input = parse p $ B.pack input
else
return IllegalInput
-
+-- |@'allowEOF' p@ makes @p@ treat reaching EOF a normal failure.
allowEOF :: Parser a -> Parser a
allowEOF f = Parser $ do (input, isEOFFatal) <- get
put (input, False)
infixr 0 <|>
+-- |This is the backtracking alternation. There is no non-backtracking
+-- equivalent.
(<|>) :: Parser a -> Parser a -> Parser a
f <|> g = Parser $ do saved@(_, isEOFFatal) <- get -- 状態を保存
result <- runParser f