module Network.IRC.Parser (
decode
, prefix
, serverPrefix
, nicknamePrefix
, command
, parameter
, message
, crlf
, spaces
, tokenize
, takeUntil
, parseMessage
) where
import Network.IRC.Base
import Control.Monad
import Text.ParserCombinators.Parsec hiding (spaces)
decode :: String
-> Maybe Message
decode = (either (const Nothing) Just) . (parse message "")
parseMessage :: String -> Maybe Message
parseMessage = decode
takeUntil :: String -> CharParser st String
takeUntil s = anyChar `manyTill` (lookAhead (oneOf s))
tokenize :: CharParser st a -> CharParser st a
tokenize p = p >>= \x -> spaces >> return x
spaces :: CharParser st ()
spaces = skipMany1 (oneOf " \t\b")
prefix :: CharParser st Prefix
prefix = char ':' >> (try nicknamePrefix <|> serverPrefix)
serverPrefix :: CharParser st Prefix
serverPrefix = takeUntil " " >>= return . Server
nicknamePrefix :: CharParser st Prefix
nicknamePrefix = do
n <- takeUntil " .!@\r\n"
p <- option False (char '.' >> return True)
when p (fail "")
u <- optionMaybe $ char '!' >> takeUntil " @\r\n"
s <- optionMaybe $ char '@' >> takeUntil " \r\n"
return $ NickName n u s
command :: CharParser st Command
command = (many1 upper)
<|> do x <- digit
y <- digit
z <- digit
return [x,y,z]
parameter :: CharParser st Parameter
parameter = (char ':' >> takeUntil "\r\n")
<|> (takeUntil " \r\n")
crlf :: CharParser st ()
crlf = (char '\r' >> optional (char '\n'))
<|> (char '\n' >> return () )
message :: CharParser st Message
message = do
p <- optionMaybe $ tokenize prefix
c <- command
ps <- many (spaces >> parameter)
crlf >> eof
return $ Message p c ps