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
34 import qualified Data.ByteString.Char8 as BS
35 import Network.HTTP.Lucu.Parser
36 import Prelude.Unicode
38 -- |@'isCtl' c@ returns 'False' iff @0x20 <= c < 0x7F@.
46 -- |@'isText'@ is equivalent to @'not' '.' 'isCtl'@
51 -- |@'isSeparator' c@ returns 'True' iff c is one of the HTTP
53 isSeparator ∷ Char → Bool
54 {-# INLINE isSeparator #-}
55 isSeparator = inClass "()<>@,;:\\\"/[]?={}\x20\x09"
57 -- |@'isChar' c@ returns 'True' iff @c <= 0x7f@.
62 -- |@'isToken' c@ is equivalent to @not ('isCtl' c '||' 'isSeparator'
65 {-# INLINE isToken #-}
66 isToken c = (¬) (isCtl c ∨ isSeparator c)
68 -- |@'listOf' p@ is similar to @'sepBy' p ('char' \',\')@ but it
69 -- allows any occurrences of 'lws' before and after each tokens.
70 listOf ∷ Parser a → Parser [a]
71 {-# INLINEABLE listOf #-}
74 p `sepBy` do skipMany lws
80 -- |'token' is almost the same as @'takeWhile1' 'isToken'@
83 token = (A.unsafeFromByteString <$> takeWhile1 isToken)
87 -- |The CRLF: 0x0D 0x0A.
90 crlf = (string "\x0D\x0A" *> return ())
97 sp = char '\x20' *> return ()
99 -- |HTTP LWS: crlf? (sp | ht)+
101 {-# INLINEABLE lws #-}
102 lws = (option () crlf *> void (takeWhile1 isSPHT))
106 -- |Returns 'True' for SP and HT.
108 {-# INLINE isSPHT #-}
113 -- |@'separators'@ is almost the same as @'takeWhile1' 'isSeparator'@.
114 separators ∷ Parser Ascii
115 {-# INLINE separators #-}
116 separators = (A.unsafeFromByteString <$> takeWhile1 isSeparator)
120 -- |'quotedStr' accepts a string surrounded by double quotation
121 -- marks. Quotes can be escaped by backslashes.
122 quotedStr ∷ Parser Ascii
123 {-# INLINEABLE quotedStr #-}
124 quotedStr = do void $ char '"'
125 xs ← many (qdtext <|> quotedPair)
127 return ∘ A.unsafeFromByteString $ BS.pack xs
132 {-# INLINE qdtext #-}
133 qdtext = satisfy (\c → c ≢ '"' ∧ (¬) (isCtl c))
137 quotedPair ∷ Parser Char
138 {-# INLINE quotedPair #-}
139 quotedPair = (char '\\' *> satisfy isChar)
143 -- |'qvalue' accepts a so-called qvalue.
144 qvalue ∷ Parser Double
145 {-# INLINEABLE qvalue #-}
146 qvalue = ( do x ← char '0'
156 ys ← atMost 3 (char '0')