Created
December 4, 2014 11:59
-
-
Save triplefox/d6560bb694a06a138ce8 to your computer and use it in GitHub Desktop.
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 com.ludamix.ds; | |
class Deli | |
{ | |
/* | |
Deli - "Better than your usual hashmap" | |
A syntax that maps text data to lists of numbers and strings by declaration, | |
vs. by position and context as in most textual formats. | |
Deli data is primarily intended as a human-editable source format and an efficient means | |
of describing deeply nested structures. It does not aim for reproducability after processing. | |
Syntax: | |
Linebreak-delimited. | |
Lines starting with @ describe enumerated schema keys of integers: | |
"@<name>(=value),<name>(=value)..." | |
@wall, floor, start, end // 0, 1, 2, 3 | |
@GREEN_KEY=100, RED_KEY, BLUE_KEY // 100, 101, 102... | |
Lines starting with a number or name describe data. | |
"<key>.<key>...=<type><data> | |
message.0=$hello | |
message.1=$goodbye | |
Data types: | |
$ - string | |
# - number | |
@ - schema key | |
Tricks: | |
A schema can refer to a previously declared schema. | |
@red, green, blue, scarlet=red // scarlet = 0 | |
A schema actually contains an array of integers, making this valid: | |
@nested=0.0.0 | |
nested=$i am in 0.0.0 | |
Likewise: | |
@nested=0.0.0 | |
nested=@nested // [[[[0,0,0]]]] - a way to store an integer array | |
You can mix in schema keys with indexes in an arbitrary way: | |
patch.0.part.1.envelope.0.attack=#0.3 | |
*/ | |
public static function parse(s : String) { | |
var r /*result*/ : Array<Dynamic> = []; | |
var m /*mapping of name to enumerated idx*/ = new Map<String, Array<Int>>(); | |
var li : Int = 0; | |
var flat /*flatten schema keys*/ = function(ka : Array<String>, l : String) : Array<Int> | |
{ | |
var kia = new Array<Int>(); | |
for (n in 0...ka.length) | |
{ | |
if (ka[n].length == 0) throw 'line $li: contains extraneous ".": $l'; | |
var idx = Std.parseInt(ka[n]); | |
if (idx == null) { /*fallback to schema search if it can't parse an int*/ | |
if (m.exists(ka[n])) { for (j in m.get(ka[n])) kia.push(j); } /*concat*/ | |
else throw 'line $li: key not found "${ka[n]}": $l'; | |
} | |
else kia.push(idx); /*concat*/ | |
} | |
return kia; | |
} | |
for (l /*line*/ in s.split("\n")) { li += 1; | |
if (l.charAt(0) == "@") | |
{ | |
var idx /*enumeration start point*/ : Dynamic = 0; | |
var i /*enumeration counter*/ : Int = 0; | |
var sa /*schema array*/ = l.substr(1).split(","); | |
for(sc in sa) { | |
var eq = sc.split("="); eq[0] = StringTools.trim(eq[0]); | |
if (eq.length == 1) { m.set(eq[0], [i + idx]); } /*ordinary incrementing enum*/ | |
else { /*fancy traversal*/ | |
var kia /*key index array*/ = flat(eq[1].split("."), sc); | |
idx = kia[0]; i = 0; /*reset the counter to start incrementing from the indicated base*/ | |
m.set(eq[0], kia); | |
} | |
i += 1; | |
} | |
} | |
else | |
{ | |
var i0 = l.indexOf("="); | |
var kia /*key index array*/ = flat(l.substr(0, i0).split("."), l); | |
var cur = r; | |
for (n in 0...kia.length) | |
{ | |
var idx = kia[n]; | |
if (n < kia.length - 1) /*all but the last entry needs to populate a new array*/ | |
{ | |
if (cur[idx] == null) { cur[idx] = []; } cur = cur[idx]; | |
} | |
else /*set data*/ { var v = l.substr(i0 + 2); var t = l.charAt(i0 + 1); | |
switch(t) | |
{ | |
case '@': /*use enum value*/ v = StringTools.trim(v); | |
if (m.exists(v)) { cur[idx] = m.get(v); | |
/*reduce single enums to ints*/ if (cur[idx].length == 1) cur[idx] = cur[idx][0]; } | |
else throw 'line $li: key not found "$v": $l'; | |
case '$': /*use string value*/ cur[idx] = v; | |
case '#': /*use number value*/ cur[idx] = Std.parseFloat(v); | |
} | |
} | |
} | |
} | |
} | |
return {m/*mapping*/:m,d/*data*/:r}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment