5 -- |This is an auxiliary parser utilities for parsing things related
8 -- In general you don't have to use this module directly.
9 module Network.HTTP.Lucu.Parser.Http
29 import Control.Applicative
31 import Data.Ascii (Ascii)
32 import qualified Data.Ascii as A
33 import Data.Attoparsec.Char8 as P hiding (scan)
34 import qualified Data.Attoparsec.FastSet as FS
35 import qualified Data.ByteString.Char8 as BS
36 import Network.HTTP.Lucu.Parser
37 import Prelude.Unicode
39 -- |@'isCtl' c@ returns 'False' iff @0x20 <= c < 0x7F@.
47 -- |@'isText'@ is equivalent to @'not' '.' 'isCtl'@
52 -- |@'isSeparator' c@ returns 'True' iff c is one of the HTTP
54 isSeparator ∷ Char → Bool
55 {-# INLINE isSeparator #-}
56 isSeparator = flip FS.memberChar set
59 set = FS.charClass "()<>@,;:\\\"/[]?={}\x20\x09"
61 -- |@'isChar' c@ returns 'True' iff @c <= 0x7f@.
66 -- |@'isToken' c@ is equivalent to @not ('isCtl' c '||' 'isSeparator'
69 {-# INLINE isToken #-}
70 isToken c = (¬) (isCtl c ∨ isSeparator c)
72 -- |@'listOf' p@ is similar to @'sepBy' p ('char' \',\')@ but it
73 -- allows any occurrences of 'lws' before and after each tokens.
74 listOf ∷ Parser a → Parser [a]
75 {-# INLINEABLE listOf #-}
78 p `sepBy` do skipMany lws
84 -- |'token' is almost the same as @'takeWhile1' 'isToken'@
87 token = (A.unsafeFromByteString <$> takeWhile1 isToken)
91 -- |The CRLF: 0x0D 0x0A.
94 crlf = (string "\x0D\x0A" *> return ())
101 sp = char '\x20' *> return ()
103 -- |HTTP LWS: crlf? (sp | ht)+
105 {-# INLINEABLE lws #-}
106 lws = (option () crlf *> void (takeWhile1 isSPHT))
110 -- |Returns 'True' for SP and HT.
112 {-# INLINE isSPHT #-}
117 -- |@'separators'@ is almost the same as @'takeWhile1' 'isSeparator'@.
118 separators ∷ Parser Ascii
119 {-# INLINE separators #-}
120 separators = (A.unsafeFromByteString <$> takeWhile1 isSeparator)
124 -- |'quotedStr' accepts a string surrounded by double quotation
125 -- marks. Quotes can be escaped by backslashes.
126 quotedStr ∷ Parser Ascii
127 {-# INLINEABLE quotedStr #-}
128 quotedStr = do void $ char '"'
129 xs ← P.many (qdtext <|> quotedPair)
131 return $ A.unsafeFromByteString $ BS.pack xs
136 {-# INLINE qdtext #-}
137 qdtext = satisfy (\c → c ≢ '"' ∧ (¬) (isCtl c))
141 quotedPair ∷ Parser Char
142 {-# INLINE quotedPair #-}
143 quotedPair = (char '\\' *> satisfy isChar)
147 -- |'qvalue' accepts a so-called qvalue.
148 qvalue ∷ Parser Double
149 {-# INLINEABLE qvalue #-}
150 qvalue = ( do x ← char '0'
160 ys ← atMost 3 (char '0')