X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FParser.hs;h=c36655b4fc81f65c2fab16da81ecaef21a3c25f6;hp=c43dfa7616d758bd2d5776c803cc435a56f0fd22;hb=30fcb38426696db8b80d322196cc594431e30407;hpb=175e14b3b144537644e65ca76f1fca5c56fd44e9 diff --git a/Network/HTTP/Lucu/Parser.hs b/Network/HTTP/Lucu/Parser.hs index c43dfa7..c36655b 100644 --- a/Network/HTTP/Lucu/Parser.hs +++ b/Network/HTTP/Lucu/Parser.hs @@ -1,33 +1,51 @@ +-- |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 @@ -36,6 +54,7 @@ import Control.Monad.State 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) } @@ -58,21 +77,20 @@ instance Monad Parser where 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 @@ -94,7 +112,7 @@ eof = Parser $ do (input, _) <- get 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) @@ -124,6 +142,8 @@ string str = do mapM_ char str 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