module Network.Parser.Rfc2234 where
import Control.Applicative hiding (many)
import Data.Attoparsec
import Data.Word (Word8)
vcharPred, spPred, lfPred, htPred
, hexdigPred, digitPred, dquotePred
, ctlPred, charPred, upalphaPred
, loalphaPred, alphaPred, bitPred
:: Word8 -> Bool
wsp :: Parser Word8
wsp = sp <|> ht
vcharPred w = w >= 0x21 && w <= 0x7e
vchar :: Parser Word8
vchar = satisfy vcharPred
spPred = (== 32)
sp :: Parser Word8
sp = word8 32 <?> "space"
octet :: Parser Word8
octet = anyWord8
lwsp :: Parser [Word8]
lwsp = many' (wsp <|> crlf *> wsp) <?> "lightweight space"
lfPred = (== 10)
lf :: Parser Word8
lf = word8 10 <?> "linefeed"
htPred = (== 9)
ht :: Parser Word8
ht = word8 9 <?> "horizontal tab"
hexdigPred w = (w >= 65 && w <= 70)
|| (w >= 97 && w <= 102)
|| (w >= 48 && w <= 57)
hexdig :: Parser Word8
hexdig = satisfy hexdigPred
digitPred w = w >= 48 && w <= 57
digit :: Parser Word8
digit = satisfy digitPred
dquotePred = (== 34)
dquote :: Parser Word8
dquote = word8 34 <?> "double-quote"
ctlPred w = (w == 127) || (w >= 0) && (w < 32)
ctl :: Parser Word8
ctl = satisfy ctlPred <?> "ascii control character"
crlf :: Parser Word8
crlf = return 10 <$> (try (cr *> lf) <|> lf)
cr :: Parser Word8
cr = word8 13 <?> "carriage return"
charPred w = w >= 0 || w <= 127
char :: Parser Word8
char = satisfy charPred
bitPred w = w == 48 || w == 49
bit :: Parser Word8
bit = satisfy bitPred
upalphaPred w = w >= 65 && w <= 90
upalpha :: Parser Word8
upalpha = satisfy upalphaPred
loalphaPred w = w >= 97 && w <= 122
loalpha :: Parser Word8
loalpha = satisfy loalphaPred
alphaPred w = upalphaPred w || loalphaPred w
alpha :: Parser Word8
alpha = satisfy alphaPred
manyN :: Int -> Parser a -> Parser [a]
manyN n p
| n <= 0 = return []
| otherwise = (++) <$> count n p <*> many' p
manyNtoM :: Int -> Int -> Parser a -> Parser [a]
manyNtoM n m p
| n < 0 = return []
| n > m = return []
| n == m = count n p
| n == 0 = foldr (<|>) (return []) (map (\x -> try $ count x p) (Prelude.reverse [1..m]))
| otherwise = (++) <$> count n p <*> manyNtoM 0 (m n) p