diff --git a/examples/json.pegjs b/examples/json.pegjs new file mode 100644 index 0000000..d607fe1 --- /dev/null +++ b/examples/json.pegjs @@ -0,0 +1,104 @@ +/* JSON parser based on the grammar described at http://json.org/. */ + +/* ===== Syntactical Elements ===== */ + +start: _ object { return $2; } + +object + : "{" _ "}" _ { return {}; } + / "{" _ members "}" _ { return $3; } + +members: pair ("," _ pair)* { + var result = {}; + result[$1[0]] = $1[1]; + for (var i = 0; i < $2.length; i++) { + result[$2[i][2][0]] = $2[i][2][1]; + } + return result; +} + +pair: string ":" _ value { return [$1, $4]; } + +array + : "[" _ "]" _ { return []; } + / "[" _ elements "]" _ { return $3; } + +elements: value ("," _ value)* { + var result = [$1]; + for (var i = 0; i < $2.length; i++) { + result.push($2[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 '"' _ { return $2; } + +chars: char+ { return $1.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" hexDigit hexDigit hexDigit hexDigit { + return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5)); + } + +number "number" + : int frac exp _ { return parseFloat($1 + $2 + $3); } + / int frac _ { return parseFloat($1 + $2); } + / int exp _ { return parseFloat($1 + $2); } + / int _ { return parseFloat($1); } + +int + : digit19 digits { return $1 + $2; } + / digit + / "-" digit19 digits { return $1 + $2 + $3; } + / "-" digit { return $1 + $2; } + +frac: "." digits { return $1 + $2; } + +exp: e digits { return $1 + $2; } + +digits: digit+ { return $1.join(""); } + +e: [eE] [+-]? { return $1 + $2; } + +/* + * The following rules are not present in the original JSON gramar, but they are + * assumed to exist implicitly. + */ + +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. +whitespace: [ \t\n\r]