module Network.HTTP.Lucu.Parser.Http
( isCtl
, isText
, isSeparator
, isChar
, isToken
, isSPHT
, listOf
, crlf
, sp
, lws
, token
, separators
, quotedStr
, qvalue
)
where
import Control.Applicative
import Control.Monad
import Data.Ascii (Ascii)
import qualified Data.Ascii as A
import Data.Attoparsec.Char8
import qualified Data.ByteString.Char8 as BS
import Network.HTTP.Lucu.Parser
import Prelude.Unicode
isCtl ∷ Char → Bool
isCtl c
| c ≤ '\x1f' = True
| c > '\x7f' = True
| otherwise = False
isText ∷ Char → Bool
isText = (¬) ∘ isCtl
isSeparator ∷ Char → Bool
isSeparator = inClass "()<>@,;:\\\"/[]?={}\x20\x09"
isChar ∷ Char → Bool
isChar = (≤ '\x7F')
isToken ∷ Char → Bool
isToken c = (¬) (isCtl c ∨ isSeparator c)
listOf ∷ Parser a → Parser [a]
listOf p
= do skipMany lws
p `sepBy` do skipMany lws
void $ char ','
skipMany lws
<?>
"listOf"
token ∷ Parser Ascii
token = (A.unsafeFromByteString <$> takeWhile1 isToken)
<?>
"token"
crlf ∷ Parser ()
crlf = (string "\x0D\x0A" *> return ())
<?>
"crlf"
sp ∷ Parser ()
sp = char '\x20' *> return ()
lws ∷ Parser ()
lws = (option () crlf *> void (takeWhile1 isSPHT))
<?>
"lws"
isSPHT ∷ Char → Bool
isSPHT '\x20' = True
isSPHT '\x09' = True
isSPHT _ = False
separators ∷ Parser Ascii
separators = (A.unsafeFromByteString <$> takeWhile1 isSeparator)
<?>
"separators"
quotedStr ∷ Parser Ascii
quotedStr = do void $ char '"'
xs ← many (qdtext <|> quotedPair)
void $ char '"'
return ∘ A.unsafeFromByteString $ BS.pack xs
<?>
"quotedStr"
where
qdtext ∷ Parser Char
qdtext = satisfy (\c → c ≢ '"' ∧ (¬) (isCtl c))
<?>
"qdtext"
quotedPair ∷ Parser Char
quotedPair = (char '\\' *> satisfy isChar)
<?>
"quotedPair"
qvalue ∷ Parser Double
qvalue = ( do x ← char '0'
xs ← option "" $
do y ← char '.'
ys ← atMost 3 digit
return (y:ys)
return $ read (x:xs)
<|>
do x ← char '1'
xs ← option "" $
do y ← char '.'
ys ← atMost 3 (char '0')
return (y:ys)
return $ read (x:xs)
)
<?>
"qvalue"