/* JSON parser based on the grammar described at http://json.org/. */ /* ===== Syntactical Elements ===== */ start = _ object:object { return object; } object = "{" _ "}" _ { return {}; } / "{" _ members:members "}" _ { return members; } members = head:pair tail:("," _ pair)* { var result = {}; result[head[0]] = head[1]; for (var i = 0; i < tail.length; i++) { result[tail[i][2][0]] = tail[i][2][1]; } return result; } pair = name:string ":" _ value:value { return [name, value]; } array = "[" _ "]" _ { return []; } / "[" _ elements:elements "]" _ { return elements; } elements = head:value tail:("," _ value)* { var result = [head]; for (var i = 0; i < tail.length; i++) { result.push(tail[i][2]); } return result; } value = string / number / object / array / "true" _ { return true; } / "false" _ { return false; } // FIXME: We can't return null here because that would mean parse failure. / "null" _ { return "null"; } /* ===== Lexical Elements ===== */ string "string" = '"' '"' _ { return ""; } / '"' chars:chars '"' _ { return chars; } chars = chars:char+ { return chars.join(""); } char // In the original JSON grammar: "any-Unicode-character-except-"-or-\-or-control-character" = [^"\\\0-\x1F\x7f] / '\\"' { return '"'; } / "\\\\" { return "\\"; } / "\\/" { return "/"; } / "\\b" { return "\b"; } / "\\f" { return "\f"; } / "\\n" { return "\n"; } / "\\r" { return "\r"; } / "\\t" { return "\t"; } / "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit { return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); } number "number" = int_:int frac:frac exp:exp _ { return parseFloat(int_ + frac + exp); } / int_:int frac:frac _ { return parseFloat(int_ + frac); } / int_:int exp:exp _ { return parseFloat(int_ + exp); } / int_:int _ { return parseFloat(int_); } int = digit19:digit19 digits:digits { return digit19 + digits; } / digit:digit / "-" digit19:digit19 digits:digits { return "-" + digit19 + digits; } / "-" digit:digit { return "-" + digit; } frac = "." digits:digits { return "." + digits; } exp = e:e digits:digits { return e + digits; } digits = digits:digit+ { return digits.join(""); } e = e:[eE] sign:[+-]? { return e + sign; } /* * The following rules are not present in the original JSON gramar, but they are * assumed to exist implicitly. * * FIXME: Define them according to ECMA-262, 5th ed. */ digit = [0-9] digit19 = [1-9] hexDigit = [0-9a-fA-F] /* ===== Whitespace ===== */ _ "whitespace" = whitespace* // Whitespace is undefined in the original JSON grammar, so I assume a simple // conventional definition consistent with ECMA-262, 5th ed. whitespace = [ \t\n\r]