ee8c121676
Labeled expressions lead to more maintainable code and also will allow certain optimizations (we can ignore results of expressions not passed to the actions). This does not speed up the benchmark suite execution statistically significantly on V8. Detailed results (benchmark suite totals): --------------------------------- Test # Before After --------------------------------- 1 28.43 kB/s 28.46 kB/s 2 28.38 kB/s 28.56 kB/s 3 28.22 kB/s 28.58 kB/s 4 28.76 kB/s 28.55 kB/s 5 28.57 kB/s 28.48 kB/s --------------------------------- Average 28.47 kB/s 28.53 kB/s --------------------------------- Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.55 Safari/533.4
121 lines
2.9 KiB
JavaScript
121 lines
2.9 KiB
JavaScript
/* 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]
|