Created
February 24, 2014 00:08
-
-
Save oakwhiz/9179290 to your computer and use it in GitHub Desktop.
VMF (Valve Map Format) Hammer save file parser written in Scala using parser combinators.
This file contains hidden or 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.RegexParsers | |
object Main { | |
val testdata = """versioninfo | |
{ | |
"editorversion" "400" | |
"editorbuild" "5704" | |
"mapversion" "3656" | |
"formatversion" "100" | |
"prefab" "0" | |
} | |
visgroups | |
{ | |
visgroup | |
{ | |
"name" "Global" | |
"visgroupid" "43" | |
"color" "215 212 165" | |
visgroup | |
{ | |
"name" "Geo" | |
"visgroupid" "44" | |
"color" "186 211 144" | |
visgroup | |
{ | |
"name" "Main" | |
"visgroupid" "45" | |
"color" "173 82 107" | |
visgroup | |
{ | |
"name" "railing" | |
"visgroupid" "29" | |
"color" "143 204 173" | |
} | |
} | |
} | |
visgroup | |
{ | |
"name" "Models" | |
"visgroupid" "47" | |
"color" "88 249 190" | |
visgroup | |
{ | |
"name" "prop_static" | |
"visgroupid" "46" | |
"color" "103 244 101" | |
} | |
visgroup | |
{ | |
"name" "prop_physics" | |
"visgroupid" "50" | |
"color" "195 224 113" | |
} | |
} | |
visgroup | |
{ | |
"name" "Lighting_Effects" | |
"visgroupid" "57" | |
"color" "230 159 204" | |
visgroup | |
{ | |
"name" "sprites" | |
"visgroupid" "60" | |
"color" "141 146 155" | |
} | |
visgroup | |
{ | |
"name" "instances" | |
"visgroupid" "75" | |
"color" "162 123 104" | |
} | |
visgroup | |
{ | |
"name" "lights_local" | |
"visgroupid" "77" | |
"color" "112 97 118" | |
} | |
} | |
} | |
visgroup | |
{ | |
"name" "DNC" | |
"visgroupid" "42" | |
"color" "170 227 176" | |
visgroup | |
{ | |
"name" "_fixtextures" | |
"visgroupid" "37" | |
"color" "203 152 201" | |
} | |
visgroup | |
{ | |
"name" "_oldoutdoorstreetlights" | |
"visgroupid" "36" | |
"color" "80 97 150" | |
} | |
visgroup | |
{ | |
"name" "_oldoutdoorbuildinglights" | |
"visgroupid" "35" | |
"color" "95 220 125" | |
} | |
visgroup | |
{ | |
"name" "_oldoutdoorlights" | |
"visgroupid" "34" | |
"color" "82 139 88" | |
} | |
visgroup | |
{ | |
"name" "ExitGreenLights" | |
"visgroupid" "21" | |
"color" "43 209 1" | |
} | |
visgroup | |
{ | |
"name" "_temp" | |
"visgroupid" "38" | |
"color" "166 159 220" | |
} | |
} | |
visgroup | |
{ | |
"name" "-art_removal" | |
"visgroupid" "51" | |
"color" "115 112 113" | |
} | |
visgroup | |
{ | |
"name" "junk" | |
"visgroupid" "10" | |
"color" "190 215 132" | |
} | |
visgroup | |
{ | |
"name" "shrubbery" | |
"visgroupid" "11" | |
"color" "219 184 217" | |
} | |
} | |
viewsettings | |
{ | |
"bSnapToGrid" "1" | |
"bShowGrid" "1" | |
"bShowLogicalGrid" "0" | |
"nGridSpacing" "64" | |
"bShow3DGrid" "0" | |
}""" | |
def main(args: Array[String]) { | |
println("Testing the parser:") | |
println(VMFParser(testdata)) | |
} | |
} | |
case class VMFDocument(cl: Seq[VMFClass]) | |
class VMFProperty | |
case class VMFClass(n: String, m: Seq[VMFProperty]) extends VMFProperty | |
class VMFTuple extends VMFProperty | |
case class VMFTupleGeneric(n: String, m: String) extends VMFTuple | |
object VMFParser extends RegexParsers { | |
import language.postfixOps | |
def crlf = """\r?\n""".r //CRLF or LF | |
def ows = """[^\S\r\n]*""".r //optional whitespace | |
def owscrlf = ows ~ crlf //optional whitespace followed by CRLF | |
def cname = """[^\s{]+""".r //at least 1 of anything except whitespace or a { | |
def value = """[^\"]*""".r //anything except a " | |
def valuetuple: Parser[VMFTuple] = (ows ~> '"' ~> value <~ '"' <~ ows) ~ ('"' ~> value <~ '"' <~ owscrlf) ^^ { | |
case n ~ m => VMFTupleGeneric(n,m) | |
} | |
def property: Parser[VMFProperty] = (valuetuple | clazz) | |
def propertylist: Parser[List[VMFProperty]] = property* | |
//def propertylist: Parser[List[VMFProperty]] = log(repsep(valuetuple | clazz,crlf))("property list") | |
def clazz: Parser[VMFClass] = (ows ~> cname <~ owscrlf) ~ | |
(ows ~> "{" ~> owscrlf ~> | |
propertylist <~ | |
ows <~ "}" <~ (owscrlf | "$".r)) ^^ { | |
case n ~ m => VMFClass(n,m) | |
} | |
def document: Parser[VMFDocument] = (clazz*) ^^ { | |
case x => VMFDocument(x) | |
} | |
override def skipWhitespace = false | |
def apply(input: String): VMFDocument = parseAll(document, input) match { | |
case Success(result, _) => result | |
case failure: NoSuccess => scala.sys.error(failure.msg) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment