Created
September 5, 2014 16:47
-
-
Save kafecho/a42263cce99765b9a0aa to your computer and use it in GitHub Desktop.
Initial work on Scala parser combinators for reading sdp (session description protocol) files.
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
package org.kafecho.learning.parser | |
import scala.util.parsing.combinator.RegexParsers | |
import java.net.URI | |
sealed trait SdpValue | |
sealed trait Username | |
case class UserLogin(login: String) extends Username | |
case object UserIdsNotSupported extends Username | |
sealed trait Media | |
case object Audio extends Media | |
case object Video extends Media | |
case object Text extends Media | |
case object Application extends Media | |
sealed trait Attribute | |
case class BinaryAttribute(value: String) extends Attribute | |
case class KeyValueAttribute(key: String, value: String) extends Attribute | |
case class ProtocolVersion(version: Long) extends SdpValue | |
case class Origin(username: Username, sessionId: Long, sessionVersion: Long, netType: String, addrType: String, unicastAddress: Option[String]) extends SdpValue | |
case class SessionName(name: String) extends SdpValue | |
case class Information(information: String) extends SdpValue | |
case class Protocol(protocol: String) | |
case class MediaField(media: Media, port: Long, protocol: Protocol, payloadType: Long) | |
/** Prototype parser for the Session Description Protocol. | |
* See http://tools.ietf.org/html/rfc4566.html#page-39 | |
* Also see http://www.regular-expressions.info/posixbrackets.html for some help on regexes. | |
*/ | |
class SdpParser extends RegexParsers { | |
def nonWsString: Parser[String] = """\p{Graph}+""".r | |
def number: Parser[Long] = """\p{Digit}+""".r ^^ { _.toLong } | |
def text: Parser[String] = """\p{Print}+""".r | |
def username: Parser[Username] = ("-" | nonWsString) ^^ { | |
case "-" => UserIdsNotSupported | |
case s: String => UserLogin(s) | |
} | |
def netType: Parser[String] = "IN" | |
def addrType: Parser[String] = "IP4|IP6".r | |
def media: Parser[Media] = ("video" | "audio" | "text" | "application") ^^ { | |
case "video" => Video | |
case "audio" => Audio | |
case "text" => Text | |
case "application" => Application | |
} | |
val token = """( \x21 | [\x23-\x27]|[\x2A-\x2B]|[\x2D-\x2E]|[\x30-\x39]|[\x41-\x5A]|[\x5E-\x7E])+""".r | |
def protocolVersionField: Parser[ProtocolVersion] = "v=" ~ number ^^ { case _ ~ n => ProtocolVersion(n) } | |
def originField: Parser[Origin] = ("o=" ~ username ~ number ~ number ~ netType ~ addrType ~ opt(nonWsString)) ^^ { | |
case _ ~ username ~ sessionId ~ sessionVersion ~ netType ~ addrType ~ unicastAddress => | |
Origin(username, sessionId, sessionVersion, netType, addrType, unicastAddress) | |
} | |
def sessionNameField: Parser[SessionName] = ("s=" ~ text) ^^ { case _ ~ text => SessionName(text) } | |
def informationField: Parser[Information] = ("i=" ~ text) ^^ { case _ ~ text => Information(text) } | |
def uriField : Parser[URI] = ("u=" ~ text) ^^ { case _ ~ s => new URI(s)} | |
def protocol : Parser[Protocol] = ("""RTP/AVP""" | "udp") ^^ { s => Protocol(s) } | |
def mediaField : Parser[MediaField] = ("m=" ~ media ~ number ~ protocol ~ number) ^^ { case _ ~ media ~ port ~ protocol ~ payloadType => | |
MediaField(media, port, protocol, payloadType) | |
} | |
def keyValueAttribute : Parser[Attribute]= ( token ~ ":" ~ nonWsString ) ^^ { case key ~ ":" ~ value => KeyValueAttribute(key, value)} | |
def binaryAttribute: Parser[Attribute]= nonWsString ^^ { s => BinaryAttribute(s)} | |
def attributeField : Parser[List[Attribute]] = "a=" ~ rep(keyValueAttribute | binaryAttribute) ^^ { case _ ~ l => l } | |
def mediaDescriptions: Parser[Any] = rep(mediaField ~ rep (attributeField)) | |
} | |
object SdpParser extends App{ | |
val src = """ | |
m=audio 49170 RTP/AVP 0 | |
m=audio 49170 RTP/AVP 0 | |
a=rtpmap:99 h263-1998/90000""" | |
val parser = new SdpParser | |
val parseResult = parser.parseAll(parser.mediaDescriptions, src) | |
println (parseResult) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment