+ parseUser :: Parser Char IRCUser
+ parseUser = parseNick
+ >>= \nick->optional (pToken '!' >>| parseUsr)
+ >>= \muser->optional (pToken '@' >>| parseHost)
+ >>= \mhost->pure {IRCUser
+ | irc_nick=nick, irc_user=muser, irc_host=mhost}
+
+ parseUsr :: Parser Char String
+ parseUsr = toString <$> pSome (pNoneOf [' ', '@':illegal])
+
+ parseNick :: Parser Char String
+ parseNick = pAlpha
+ >>= \c ->pMany (pAlpha <|> pDigit <|> pOneOf (fromString "-[]\\`^{}"))
+ >>= \cs->pure (toString [c:cs])
+
+ parseHost :: Parser Char String
+ parseHost = jon "." <$> (pSepBy parseName (pToken '.'))
+ >>= \s->optional (pToken '.') >>= pure o maybe s (\p->s+++toString s)
+ where
+ parseName :: Parser Char String
+ parseName = toString <$> pSome (pAlpha <|> pDigit <|> pOneOf ['-', '/'])
+
+//Parse Cmd
+parseCmd :: [Char] -> Either Error IRCCommand
+parseCmd cs = fst $ gIRCParse{|*|} $ argfun $ split " " $ toString cs
+ where
+ argfun :: [String] -> [String]
+ argfun [] = []
+ argfun [x:xs]
+ # x = trim x
+ | x.[0] == ':' = [jon " " $ [x % (1, size x):map rtrim xs]]
+ | otherwise = [x:argfun xs]
+
+//Reply
+parseReply :: Parser Char IRCNumReply
+parseReply = spaceParser
+ >>| (pMany (pToken '0') >>| pSome pDigit <* spaceParser)
+ >>= \rep->(toString <$> pSome (pNoneOf [' ':illegal]) <* spaceParser)
+ >>= \rec->(toString <$> pSome (pNoneOf illegal))
+ >>= \msg->pure {IRCNumReply
+ | irc_reply = fromInt $ toInt $ toString rep
+ , irc_recipient = rec
+ , irc_message = msg % (if (msg.[0] == ':') 1 0, size msg)
+ }
+ <* pToken '\r' <* pToken '\n'
+ where
+ spaceParser :: Parser Char [Char]
+ spaceParser = pMany $ pToken ' '
+
+//Common parsers
+pNoneOf :: [a] -> Parser a a | Eq a
+pNoneOf l = pSatisfy (not o flip isMember l)
+
+illegal :: [Char]
+illegal = ['\x00','\r','\n']
+
+instance toString IRCNumReply where
+ toString m = lpad (toString $ toInt m.irc_reply) 3 '0' <+ " " <+
+ m.irc_recipient <+ " " <+ concat (gIRCPrint{|*|} m.irc_message)
+instance toString IRCMessage where
+ toString m = maybe "" (\s->either ((<+) ":") id s <+ " ") m.irc_prefix
+ <+ either toString toString m.irc_command
+instance toString IRCUser where
+ toString m = m.irc_nick <+ maybe "" ((<+) "!") m.irc_user
+ <+ maybe "" ((<+) "@") m.irc_host
+instance toString IRCCommand where
+ toString m = jon " " (gIRCPrint{|*|} m) +++ "\r\n"