Skip to content

Instantly share code, notes, and snippets.

@kkung
Created January 19, 2011 04:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kkung/785709 to your computer and use it in GitHub Desktop.
Save kkung/785709 to your computer and use it in GitHub Desktop.
poor irc packet parser in scala
import scala.util.parsing.combinator._
class IrcParser extends RegexParsers {
/*
RFC1459 2.3.1 Message format in 'pseudo' BNF
<message> ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
<prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
<command> ::= <letter> { <letter> } | <number> <number> <number>
<SPACE> ::= ' ' { ' ' }
<params> ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
<middle> ::= <Any *non-empty* sequence of octets not including SPACE
or NUL or CR or LF, the first of which may not be ':'>
<trailing> ::= <Any, possibly *empty*, sequence of octets not including
NUL or CR or LF>
<crlf> ::= CR LF
*/
abstract class Packet
case class Command(name: String) extends Packet
case class Param(value: String) extends Packet
case class ServerName(name: String) extends Packet
case class Nickname(name: String) extends Packet
case class UserMask(mask: String) extends Packet
case class Message(prefix: String, command: Command, params: Param) extends Packet
override def skipWhitespace = false;
def uniletter:Parser[String] = regex("""\p{L}""".r);
def number:Parser[Any] = regex("[0-9]".r);
def crlf : Parser[Any] = regex("""\r\n""".r);
def special:Parser[Any] = regex("""[-\[\]\\`^\{\}]""".r);
def space:Parser[String] = regex("""[ ]{1,}""".r);
def trailing:Parser[String] = regex("""[^\r\n]+""".r);
def middle:Parser[String] = regex("""[^:][^\s\r\n]+""".r);
def servername:Parser[ServerName] = regex("""[a-zA-Z0-9.\-]+""".r) ^^ (ServerName(_));
def nick:Parser[Nickname] = regex("""(\p{L}|[0-9]|[-\[\]\\`^\{\}])+""".r) ^^ (Nickname(_));
def user:Parser[UserMask] = regex("""\S+""".r) ^^ (UserMask(_));
def prefix:Parser[Any] = (servername | nick ) ~ opt( '!' ~ user ) ~ opt( '@' ~ servername );
def message:Parser[Message] = opt(':' ~ prefix ~ space) ~ command ~ params ~ crlf ^^ {
case pfx ~ cmd ~ ps ~ crlf => pfx match {
case Some(pfx) => new Message(pfx.toString, cmd, ps)
case _ => new Message(null, cmd, ps)
}
}
def command:Parser[Command] = regex("""[a-zA-Z]+""".r) ^^ (Command(_)) | regex("""[0-9]{3}""".r) ^^ (Command(_));
def params:Parser[Param] = space ~ opt( ':' ~ trailing | middle ~ params ) ^^ {
case x ~ p => p match {
case Some(z) => z match {
case ':' ~ z1 => new Param(z1.toString)
case z1 ~ z2 =>
new Param( (if ( z1 != null ) z1.toString else null ) + (if ( z2 != null ) z2.toString else null ))
case _ => null
}
case None => null
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment