Created
February 18, 2014 22:19
-
-
Save nadako/9081608 to your computer and use it in GitHub Desktop.
Using haxe macros as syntax-tolerant, position-aware json parser
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 haxe.macro.Context; | |
import haxe.macro.Expr; | |
using haxe.macro.ExprTools; | |
class Main | |
{ | |
inline static var QUOTED_FIELD_PREFIX = "@$__hx__"; | |
static function main() | |
{ | |
var e = parseFile("test.json"); | |
validateExpr(e); | |
trace(extractValue(e)); | |
} | |
static function parseFile(path:String):Expr | |
{ | |
var content = sys.io.File.getContent(path); | |
var pos = Context.makePosition({min: 0, max: 0, file: path}); | |
return Context.parseInlineString(content, pos); | |
} | |
static function validateExpr(e:Expr):Void | |
{ | |
switch (e.expr) | |
{ | |
case EConst(CInt(_) | CFloat(_) | CString(_) | CIdent("true" | "false" | "null")): // constants | |
case EBlock([]): // empty object | |
case EObjectDecl(fields): for (f in fields) validateExpr(f.expr); | |
case EArrayDecl(exprs): for (e in exprs) validateExpr(e); | |
default: | |
throw new Error("Invalid JSON expression: " + e.toString(), e.pos); | |
} | |
} | |
static function extractValue(e:Expr):Dynamic | |
{ | |
switch (e.expr) | |
{ | |
case EConst(c): | |
switch (c) | |
{ | |
case CInt(s): | |
var i = Std.parseInt(s); | |
return (i != null) ? i : Std.parseFloat(s); // if the number exceeds standard int return as float | |
case CFloat(s): | |
return Std.parseFloat(s); | |
case CString(s): | |
return s; | |
case CIdent("null"): | |
return null; | |
case CIdent("true"): | |
return true; | |
case CIdent("false"): | |
return false; | |
default: | |
} | |
case EBlock([]): | |
return {}; | |
case EObjectDecl(fields): | |
var object = {}; | |
for (field in fields) | |
Reflect.setField(object, unquoteField(field.field), extractValue(field.expr)); | |
return object; | |
case EArrayDecl(exprs): | |
return [for (e in exprs) extractValue(e)]; | |
default: | |
} | |
throw new Error("Invalid JSON expression: " + e.toString(), e.pos); | |
} | |
// see https://github.com/HaxeFoundation/haxe/issues/2642 | |
static function unquoteField(name:String):String | |
{ | |
return (name.indexOf(QUOTED_FIELD_PREFIX) == 0) ? name.substr(QUOTED_FIELD_PREFIX.length) : name; | |
} | |
} |
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
/* some comment */ | |
{ | |
"a.b": { | |
key: // look at me, unquoted object key (also, line comment) | |
[ | |
1, | |
"s", | |
null, | |
false, | |
true, | |
20.5 | |
] | |
} | |
} |
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
-cp src | |
--macro Main.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment