Created
January 19, 2011 04:57
-
-
Save kkung/785709 to your computer and use it in GitHub Desktop.
poor irc packet parser in scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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