1 -- |Yet another parser combinator. This is mostly a subset of Parsec
2 -- but there are some differences:
4 -- * This parser works on ByteString instead of String.
6 -- * Backtracking is the only possible behavior so there is no \"try\"
9 -- * On success, the remaining string is returned as well as the
12 -- * You can choose whether to treat reaching EOF (trying to eat one
13 -- more letter at the end of string) a fatal error or to treat it a
14 -- normal failure. If a fatal error occurs, the entire parsing
15 -- process immediately fails without trying any backtracks. The
16 -- default behavior is to treat EOF fatal.
18 -- In general, you don't have to use this module directly.
19 module Network.HTTP.Lucu.Parser
53 import Control.Monad.State
54 import qualified Data.ByteString.Lazy.Char8 as B
55 import Data.ByteString.Lazy.Char8 (ByteString)
57 -- |@Parser a@ is obviously a parser which parses and returns @a@.
58 data Parser a = Parser {
59 runParser :: State ParserState (ParserResult a)
62 type ParserState = (ByteString, IsEOFFatal)
64 type IsEOFFatal = Bool
66 data ParserResult a = Success a
67 | IllegalInput -- 受理出來ない入力があった
68 | ReachedEOF -- 限界を越えて讀まうとした
72 -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b
73 instance Monad Parser where
74 p >>= f = Parser $ do saved@(_, isEOFFatal) <- get -- 失敗した時の爲に状態を保存
77 Success a -> runParser (f a)
78 IllegalInput -> do put saved -- 状態を復歸
80 ReachedEOF -> do unless isEOFFatal
83 return = Parser . return . Success
84 fail _ = Parser $ return IllegalInput
86 -- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(result,
88 parse :: Parser a -> ByteString -> (ParserResult a, ByteString)
89 parse p input = let (result, (input', _)) = runState (runParser p) (input, True)
93 -- |@'parseStr' p str@ packs @str@ and parses it.
94 parseStr :: Parser a -> String -> (ParserResult a, ByteString)
95 parseStr p input = parse p $ B.pack input
98 anyChar :: Parser Char
99 anyChar = Parser $ do (input, isEOFFatal) <- get
103 do let c = B.head input
104 put (B.tail input, isEOFFatal)
109 eof = Parser $ do (input, _) <- get
115 -- |@'allowEOF' p@ makes @p@ treat reaching EOF a normal failure.
116 allowEOF :: Parser a -> Parser a
117 allowEOF f = Parser $ do (input, isEOFFatal) <- get
120 result <- runParser f
123 put (input', isEOFFatal)
128 satisfy :: (Char -> Bool) -> Parser Char
129 satisfy f = do c <- anyChar
130 unless (f c) (fail "")
134 char :: Char -> Parser Char
135 char c = satisfy (== c)
138 string :: String -> Parser String
139 string str = do mapM_ char str
145 -- |This is the backtracking alternation. There is no non-backtracking
147 (<|>) :: Parser a -> Parser a -> Parser a
148 f <|> g = Parser $ do saved@(_, isEOFFatal) <- get -- 状態を保存
149 result <- runParser f
151 Success a -> return $ Success a
152 IllegalInput -> do put saved -- 状態を復歸
154 ReachedEOF -> if isEOFFatal then
161 oneOf :: [Char] -> Parser Char
162 oneOf = foldl (<|>) (fail "") . map char
165 notFollowedBy :: Parser a -> Parser ()
166 notFollowedBy p = p >>= fail "" <|> return ()
170 digit = do c <- anyChar
171 if c >= '0' && c <= '9' then
177 hexDigit :: Parser Char
178 hexDigit = do c <- anyChar
179 if (c >= '0' && c <= '9') ||
180 (c >= 'a' && c <= 'f') ||
181 (c >= 'A' && c <= 'F') then
187 many :: Parser a -> Parser [a]
195 many1 :: Parser a -> Parser [a]
196 many1 p = do ret <- many p
202 manyTill :: Parser a -> Parser end -> Parser [a]
203 manyTill p end = many $ do x <- p
208 many1Till :: Parser a -> Parser end -> Parser [a]
209 many1Till p end = many1 $ do x <- p
214 count :: Int -> Parser a -> Parser [a]
215 count 0 _ = return []
216 count n p = do x <- p
221 option :: a -> Parser a -> Parser a
222 option def p = p <|> return def
225 sepBy :: Parser a -> Parser sep -> Parser [a]
226 sepBy p sep = sepBy1 p sep <|> return []
229 sepBy1 :: Parser a -> Parser sep -> Parser [a]
230 sepBy1 p sep = do x <- p
231 xs <- many $ sep >> p
243 crlf :: Parser String
244 crlf = string "\x0d\x0a"