+parsePrefix :: Parser Char (Maybe (Either IRCUser String))
+parsePrefix = optional (pToken ':' >>| parseEither parseUser parseHost) <* pToken ' '
+
+generic gIRCParse a :: [String] -> (Either [Error] a, [String])
+gIRCParse{|UNIT|} a = (Right UNIT, a)
+gIRCParse{|String|} [a:as] = (Right a, as)
+gIRCParse{|String|} [] = (Left ["Expected a string"], [])
+gIRCParse{|Int|} [a:as] = (Right $ toInt a, as)
+gIRCParse{|Int|} [] = (Left ["Expected an integer"], [])
+gIRCParse{|EITHER|} lp rp as = case lp as of
+ (Right a, rest) = (Right $ LEFT a, rest)
+ (Left e1, rest) = case rp as of
+ (Right a, rest) = (Right $ RIGHT a, rest)
+ (Left e2, rest) = (Left $ e1 ++ e2, [])
+gIRCParse{|OBJECT|} p as = case p as of
+ (Right e, rest) = (Right $ OBJECT e, rest)
+ (Left e, rest) = (Left e, [])
+gIRCParse{|CONS of d|} p [] = (Left ["Expected a cmd constructor: " +++ d.gcd_name], [])
+gIRCParse{|CONS of d|} p [a:as]
+| a <> d.gcd_name = (Left ["Wrong constructor. expected: " +++ d.gcd_name +++ ", got: " +++ a], [])
+= case p as of
+ (Right a, rest) = (Right $ CONS a, rest)
+ (Left e, rest) = (Left e, [])
+gIRCParse{|PAIR|} pl pr as = case pl as of
+ (Right a1, rest) = case pr rest of
+ (Right a2, rest) = (Right $ PAIR a1 a2, rest)
+ (Left e, rest) = (Left e, [])
+ (Left e, rest) = (Left e, [])
+gIRCParse{|[]|} pl as = plist pl as
+where
+ plist pl as = case pl as of
+ (Right e, rest) = case plist pl rest of
+ (Right es, rest) = (Right [e:es], rest)
+ (Left e, rest) = (Left e, [])
+ (Left e, rest) = (Right [], as)
+gIRCParse{|Maybe|} pm as = case pm as of
+ (Right a, rest) = (Right $ Just a, rest)
+ (Left e, rest) = (Right Nothing, as)
+
+derive gIRCParse (,), (,,), IRCCommand
+
+parseCmd :: [Char] -> Either [Error] IRCCommand
+parseCmd cs = fst $ gIRCParse{|*|} $ argfun $ 'Text'.split " " $ toString cs
+//= parse cmdParser $ argfun $ 'Text'.split " " $ toString cs