pulsar/vendor/pegjs.js

4529 lines
131 KiB
JavaScript

/*
* PEG.js 0.7.0
*
* http://pegjs.majda.cz/
*
* Copyright (c) 2010-2012 David Majda
* Licensend under the MIT license.
*/
var PEG = (function(undefined) {
var PEG = {
/* PEG.js version (uses semantic versioning). */
VERSION: "0.7.0",
/*
* Generates a parser from a specified grammar and returns it.
*
* The grammar must be a string in the format described by the metagramar in
* the parser.pegjs file.
*
* Throws |PEG.parser.SyntaxError| if the grammar contains a syntax error or
* |PEG.GrammarError| if it contains a semantic error. Note that not all
* errors are detected during the generation and some may protrude to the
* generated parser and cause its malfunction.
*/
buildParser: function(grammar, options) {
return PEG.compiler.compile(PEG.parser.parse(grammar), options);
}
};
/* Thrown when the grammar contains an error. */
PEG.GrammarError = function(message) {
this.name = "PEG.GrammarError";
this.message = message;
};
PEG.GrammarError.prototype = Error.prototype;
/* Like Python's |range|, but without |step|. */
function range(start, stop) {
if (stop === undefined) {
stop = start;
start = 0;
}
var result = new Array(Math.max(0, stop - start));
for (var i = 0, j = start; j < stop; i++, j++) {
result[i] = j;
}
return result;
}
function find(array, callback) {
var length = array.length;
for (var i = 0; i < length; i++) {
if (callback(array[i])) {
return array[i];
}
}
}
function contains(array, value) {
/*
* Stupid IE does not have Array.prototype.indexOf, otherwise this function
* would be a one-liner.
*/
var length = array.length;
for (var i = 0; i < length; i++) {
if (array[i] === value) {
return true;
}
}
return false;
}
function each(array, callback) {
var length = array.length;
for (var i = 0; i < length; i++) {
callback(array[i], i);
}
}
function map(array, callback) {
var result = [];
var length = array.length;
for (var i = 0; i < length; i++) {
result[i] = callback(array[i], i);
}
return result;
}
function pluck(array, key) {
return map(array, function (e) { return e[key]; });
}
function keys(object) {
var result = [];
for (var key in object) {
result.push(key);
}
return result;
}
function values(object) {
var result = [];
for (var key in object) {
result.push(object[key]);
}
return result;
}
/*
* Returns a string padded on the left to a desired length with a character.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
function padLeft(input, padding, length) {
var result = input;
var padLength = length - input.length;
for (var i = 0; i < padLength; i++) {
result = padding + result;
}
return result;
}
/*
* Returns an escape sequence for given character. Uses \x for characters <=
* 0xFF to save space, \u for the rest.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
function escape(ch) {
var charCode = ch.charCodeAt(0);
var escapeChar;
var length;
if (charCode <= 0xFF) {
escapeChar = 'x';
length = 2;
} else {
escapeChar = 'u';
length = 4;
}
return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
}
/*
* Surrounds the string with quotes and escapes characters inside so that the
* result is a valid JavaScript string.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
function quote(s) {
/*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
* literal except for the closing quote character, backslash, carriage return,
* line separator, paragraph separator, and line feed. Any character may
* appear in the form of an escape sequence.
*
* For portability, we also escape escape all control and non-ASCII
* characters. Note that "\0" and "\v" escape sequences are not used because
* JSHint does not like the first and IE the second.
*/
return '"' + s
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // closing quote character
.replace(/\x08/g, '\\b') // backspace
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
+ '"';
}
/*
* Escapes characters inside the string so that it can be used as a list of
* characters in a character class of a regular expression.
*/
function quoteForRegexpClass(s) {
/*
* Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
*
* For portability, we also escape escape all control and non-ASCII
* characters.
*/
return s
.replace(/\\/g, '\\\\') // backslash
.replace(/\//g, '\\/') // closing slash
.replace(/\]/g, '\\]') // closing bracket
.replace(/-/g, '\\-') // dash
.replace(/\0/g, '\\0') // null
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\v/g, '\\x0B') // vertical tab
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x01-\x08\x0E-\x1F\x80-\uFFFF]/g, escape);
}
/*
* Builds a node visitor -- a function which takes a node and any number of
* other parameters, calls an appropriate function according to the node type,
* passes it all its parameters and returns its value. The functions for various
* node types are passed in a parameter to |buildNodeVisitor| as a hash.
*/
function buildNodeVisitor(functions) {
return function(node) {
return functions[node.type].apply(null, arguments);
};
}
function findRuleByName(ast, name) {
return find(ast.rules, function(r) { return r.name === name; });
}
PEG.parser = (function(){
/*
* Generated by PEG.js 0.7.0.
*
* http://pegjs.majda.cz/
*/
function quote(s) {
/*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
* string literal except for the closing quote character, backslash,
* carriage return, line separator, paragraph separator, and line feed.
* Any character may appear in the form of an escape sequence.
*
* For portability, we also escape escape all control and non-ASCII
* characters. Note that "\0" and "\v" escape sequences are not used
* because JSHint does not like the first and IE the second.
*/
return '"' + s
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // closing quote character
.replace(/\x08/g, '\\b') // backspace
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
+ '"';
}
var result = {
/*
* Parses the input with a generated parser. If the parsing is successfull,
* returns a value explicitly or implicitly specified by the grammar from
* which the parser was generated (see |PEG.buildParser|). If the parsing is
* unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
*/
parse: function(input, startRule) {
var parseFunctions = {
"grammar": parse_grammar,
"initializer": parse_initializer,
"rule": parse_rule,
"choice": parse_choice,
"sequence": parse_sequence,
"labeled": parse_labeled,
"prefixed": parse_prefixed,
"suffixed": parse_suffixed,
"primary": parse_primary,
"action": parse_action,
"braced": parse_braced,
"nonBraceCharacters": parse_nonBraceCharacters,
"nonBraceCharacter": parse_nonBraceCharacter,
"equals": parse_equals,
"colon": parse_colon,
"semicolon": parse_semicolon,
"slash": parse_slash,
"and": parse_and,
"not": parse_not,
"question": parse_question,
"star": parse_star,
"plus": parse_plus,
"lparen": parse_lparen,
"rparen": parse_rparen,
"dot": parse_dot,
"identifier": parse_identifier,
"literal": parse_literal,
"string": parse_string,
"doubleQuotedString": parse_doubleQuotedString,
"doubleQuotedCharacter": parse_doubleQuotedCharacter,
"simpleDoubleQuotedCharacter": parse_simpleDoubleQuotedCharacter,
"singleQuotedString": parse_singleQuotedString,
"singleQuotedCharacter": parse_singleQuotedCharacter,
"simpleSingleQuotedCharacter": parse_simpleSingleQuotedCharacter,
"class": parse_class,
"classCharacterRange": parse_classCharacterRange,
"classCharacter": parse_classCharacter,
"bracketDelimitedCharacter": parse_bracketDelimitedCharacter,
"simpleBracketDelimitedCharacter": parse_simpleBracketDelimitedCharacter,
"simpleEscapeSequence": parse_simpleEscapeSequence,
"zeroEscapeSequence": parse_zeroEscapeSequence,
"hexEscapeSequence": parse_hexEscapeSequence,
"unicodeEscapeSequence": parse_unicodeEscapeSequence,
"eolEscapeSequence": parse_eolEscapeSequence,
"digit": parse_digit,
"hexDigit": parse_hexDigit,
"letter": parse_letter,
"lowerCaseLetter": parse_lowerCaseLetter,
"upperCaseLetter": parse_upperCaseLetter,
"__": parse___,
"comment": parse_comment,
"singleLineComment": parse_singleLineComment,
"multiLineComment": parse_multiLineComment,
"eol": parse_eol,
"eolChar": parse_eolChar,
"whitespace": parse_whitespace
};
if (startRule !== undefined) {
if (parseFunctions[startRule] === undefined) {
throw new Error("Invalid rule name: " + quote(startRule) + ".");
}
} else {
startRule = "grammar";
}
var pos = 0;
var reportFailures = 0;
var rightmostFailuresPos = 0;
var rightmostFailuresExpected = [];
function padLeft(input, padding, length) {
var result = input;
var padLength = length - input.length;
for (var i = 0; i < padLength; i++) {
result = padding + result;
}
return result;
}
function escape(ch) {
var charCode = ch.charCodeAt(0);
var escapeChar;
var length;
if (charCode <= 0xFF) {
escapeChar = 'x';
length = 2;
} else {
escapeChar = 'u';
length = 4;
}
return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
}
function matchFailed(failure) {
if (pos < rightmostFailuresPos) {
return;
}
if (pos > rightmostFailuresPos) {
rightmostFailuresPos = pos;
rightmostFailuresExpected = [];
}
rightmostFailuresExpected.push(failure);
}
function parse_grammar() {
var result0, result1, result2, result3;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse___();
if (result0 !== null) {
result1 = parse_initializer();
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result3 = parse_rule();
if (result3 !== null) {
result2 = [];
while (result3 !== null) {
result2.push(result3);
result3 = parse_rule();
}
} else {
result2 = null;
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, initializer, rules) {
return {
type: "grammar",
initializer: initializer !== "" ? initializer : null,
rules: rules,
startRule: rules[0].name
};
})(pos0, result0[1], result0[2]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_initializer() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_action();
if (result0 !== null) {
result1 = parse_semicolon();
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, code) {
return {
type: "initializer",
code: code
};
})(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_rule() {
var result0, result1, result2, result3, result4;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_identifier();
if (result0 !== null) {
result1 = parse_string();
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result2 = parse_equals();
if (result2 !== null) {
result3 = parse_choice();
if (result3 !== null) {
result4 = parse_semicolon();
result4 = result4 !== null ? result4 : "";
if (result4 !== null) {
result0 = [result0, result1, result2, result3, result4];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, name, displayName, expression) {
return {
type: "rule",
name: name,
displayName: displayName !== "" ? displayName : null,
expression: expression
};
})(pos0, result0[0], result0[1], result0[3]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_choice() {
var result0, result1, result2, result3;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
result0 = parse_sequence();
if (result0 !== null) {
result1 = [];
pos2 = pos;
result2 = parse_slash();
if (result2 !== null) {
result3 = parse_sequence();
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos2;
}
} else {
result2 = null;
pos = pos2;
}
while (result2 !== null) {
result1.push(result2);
pos2 = pos;
result2 = parse_slash();
if (result2 !== null) {
result3 = parse_sequence();
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos2;
}
} else {
result2 = null;
pos = pos2;
}
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, head, tail) {
if (tail.length > 0) {
var alternatives = [head].concat(map(
tail,
function(element) { return element[1]; }
));
return {
type: "choice",
alternatives: alternatives
};
} else {
return head;
}
})(pos0, result0[0], result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_sequence() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = [];
result1 = parse_labeled();
while (result1 !== null) {
result0.push(result1);
result1 = parse_labeled();
}
if (result0 !== null) {
result1 = parse_action();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, elements, code) {
var expression = elements.length !== 1
? {
type: "sequence",
elements: elements
}
: elements[0];
return {
type: "action",
expression: expression,
code: code
};
})(pos0, result0[0], result0[1]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
result0 = [];
result1 = parse_labeled();
while (result1 !== null) {
result0.push(result1);
result1 = parse_labeled();
}
if (result0 !== null) {
result0 = (function(offset, elements) {
return elements.length !== 1
? {
type: "sequence",
elements: elements
}
: elements[0];
})(pos0, result0);
}
if (result0 === null) {
pos = pos0;
}
}
return result0;
}
function parse_labeled() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_identifier();
if (result0 !== null) {
result1 = parse_colon();
if (result1 !== null) {
result2 = parse_prefixed();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, label, expression) {
return {
type: "labeled",
label: label,
expression: expression
};
})(pos0, result0[0], result0[2]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
result0 = parse_prefixed();
}
return result0;
}
function parse_prefixed() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_and();
if (result0 !== null) {
result1 = parse_action();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, code) {
return {
type: "semantic_and",
code: code
};
})(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_and();
if (result0 !== null) {
result1 = parse_suffixed();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) {
return {
type: "simple_and",
expression: expression
};
})(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_not();
if (result0 !== null) {
result1 = parse_action();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, code) {
return {
type: "semantic_not",
code: code
};
})(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_not();
if (result0 !== null) {
result1 = parse_suffixed();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) {
return {
type: "simple_not",
expression: expression
};
})(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
result0 = parse_suffixed();
}
}
}
}
return result0;
}
function parse_suffixed() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_primary();
if (result0 !== null) {
result1 = parse_question();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) {
return {
type: "optional",
expression: expression
};
})(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_primary();
if (result0 !== null) {
result1 = parse_star();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) {
return {
type: "zero_or_more",
expression: expression
};
})(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_primary();
if (result0 !== null) {
result1 = parse_plus();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) {
return {
type: "one_or_more",
expression: expression
};
})(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
result0 = parse_primary();
}
}
}
return result0;
}
function parse_primary() {
var result0, result1, result2;
var pos0, pos1, pos2, pos3;
pos0 = pos;
pos1 = pos;
result0 = parse_identifier();
if (result0 !== null) {
pos2 = pos;
reportFailures++;
pos3 = pos;
result1 = parse_string();
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result2 = parse_equals();
if (result2 !== null) {
result1 = [result1, result2];
} else {
result1 = null;
pos = pos3;
}
} else {
result1 = null;
pos = pos3;
}
reportFailures--;
if (result1 === null) {
result1 = "";
} else {
result1 = null;
pos = pos2;
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, name) {
return {
type: "rule_ref",
name: name
};
})(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
result0 = parse_literal();
if (result0 === null) {
pos0 = pos;
result0 = parse_dot();
if (result0 !== null) {
result0 = (function(offset) { return { type: "any" }; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
result0 = parse_class();
if (result0 === null) {
pos0 = pos;
pos1 = pos;
result0 = parse_lparen();
if (result0 !== null) {
result1 = parse_choice();
if (result1 !== null) {
result2 = parse_rparen();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, expression) { return expression; })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
}
}
}
}
return result0;
}
function parse_action() {
var result0, result1;
var pos0, pos1;
reportFailures++;
pos0 = pos;
pos1 = pos;
result0 = parse_braced();
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, braced) { return braced.substr(1, braced.length - 2); })(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("action");
}
return result0;
}
function parse_braced() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 123) {
result0 = "{";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"{\"");
}
}
if (result0 !== null) {
result1 = [];
result2 = parse_braced();
if (result2 === null) {
result2 = parse_nonBraceCharacter();
}
while (result2 !== null) {
result1.push(result2);
result2 = parse_braced();
if (result2 === null) {
result2 = parse_nonBraceCharacter();
}
}
if (result1 !== null) {
if (input.charCodeAt(pos) === 125) {
result2 = "}";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"}\"");
}
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, parts) {
return "{" + parts.join("") + "}";
})(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_nonBraceCharacters() {
var result0, result1;
var pos0;
pos0 = pos;
result1 = parse_nonBraceCharacter();
if (result1 !== null) {
result0 = [];
while (result1 !== null) {
result0.push(result1);
result1 = parse_nonBraceCharacter();
}
} else {
result0 = null;
}
if (result0 !== null) {
result0 = (function(offset, chars) { return chars.join(""); })(pos0, result0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_nonBraceCharacter() {
var result0;
if (/^[^{}]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[^{}]");
}
}
return result0;
}
function parse_equals() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 61) {
result0 = "=";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"=\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "="; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_colon() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 58) {
result0 = ":";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\":\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return ":"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_semicolon() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 59) {
result0 = ";";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\";\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return ";"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_slash() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 47) {
result0 = "/";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"/\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "/"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_and() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 38) {
result0 = "&";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"&\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "&"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_not() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 33) {
result0 = "!";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"!\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "!"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_question() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 63) {
result0 = "?";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"?\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "?"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_star() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 42) {
result0 = "*";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"*\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "*"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_plus() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 43) {
result0 = "+";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"+\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "+"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_lparen() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 40) {
result0 = "(";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"(\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "("; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_rparen() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 41) {
result0 = ")";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\")\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return ")"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_dot() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 46) {
result0 = ".";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\".\"");
}
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "."; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_identifier() {
var result0, result1, result2;
var pos0, pos1;
reportFailures++;
pos0 = pos;
pos1 = pos;
result0 = parse_letter();
if (result0 === null) {
if (input.charCodeAt(pos) === 95) {
result0 = "_";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"_\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 36) {
result0 = "$";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"$\"");
}
}
}
}
if (result0 !== null) {
result1 = [];
result2 = parse_letter();
if (result2 === null) {
result2 = parse_digit();
if (result2 === null) {
if (input.charCodeAt(pos) === 95) {
result2 = "_";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"_\"");
}
}
if (result2 === null) {
if (input.charCodeAt(pos) === 36) {
result2 = "$";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"$\"");
}
}
}
}
}
while (result2 !== null) {
result1.push(result2);
result2 = parse_letter();
if (result2 === null) {
result2 = parse_digit();
if (result2 === null) {
if (input.charCodeAt(pos) === 95) {
result2 = "_";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"_\"");
}
}
if (result2 === null) {
if (input.charCodeAt(pos) === 36) {
result2 = "$";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"$\"");
}
}
}
}
}
}
if (result1 !== null) {
result2 = parse___();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, head, tail) {
return head + tail.join("");
})(pos0, result0[0], result0[1]);
}
if (result0 === null) {
pos = pos0;
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("identifier");
}
return result0;
}
function parse_literal() {
var result0, result1, result2;
var pos0, pos1;
reportFailures++;
pos0 = pos;
pos1 = pos;
result0 = parse_doubleQuotedString();
if (result0 === null) {
result0 = parse_singleQuotedString();
}
if (result0 !== null) {
if (input.charCodeAt(pos) === 105) {
result1 = "i";
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("\"i\"");
}
}
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result2 = parse___();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, value, flags) {
return {
type: "literal",
value: value,
ignoreCase: flags === "i"
};
})(pos0, result0[0], result0[1]);
}
if (result0 === null) {
pos = pos0;
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("literal");
}
return result0;
}
function parse_string() {
var result0, result1;
var pos0, pos1;
reportFailures++;
pos0 = pos;
pos1 = pos;
result0 = parse_doubleQuotedString();
if (result0 === null) {
result0 = parse_singleQuotedString();
}
if (result0 !== null) {
result1 = parse___();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, string) { return string; })(pos0, result0[0]);
}
if (result0 === null) {
pos = pos0;
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("string");
}
return result0;
}
function parse_doubleQuotedString() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 34) {
result0 = "\"";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\"\"");
}
}
if (result0 !== null) {
result1 = [];
result2 = parse_doubleQuotedCharacter();
while (result2 !== null) {
result1.push(result2);
result2 = parse_doubleQuotedCharacter();
}
if (result1 !== null) {
if (input.charCodeAt(pos) === 34) {
result2 = "\"";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"\\\"\"");
}
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, chars) { return chars.join(""); })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_doubleQuotedCharacter() {
var result0;
result0 = parse_simpleDoubleQuotedCharacter();
if (result0 === null) {
result0 = parse_simpleEscapeSequence();
if (result0 === null) {
result0 = parse_zeroEscapeSequence();
if (result0 === null) {
result0 = parse_hexEscapeSequence();
if (result0 === null) {
result0 = parse_unicodeEscapeSequence();
if (result0 === null) {
result0 = parse_eolEscapeSequence();
}
}
}
}
}
return result0;
}
function parse_simpleDoubleQuotedCharacter() {
var result0, result1;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
pos2 = pos;
reportFailures++;
if (input.charCodeAt(pos) === 34) {
result0 = "\"";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\"\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 92) {
result0 = "\\";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\\"");
}
}
if (result0 === null) {
result0 = parse_eolChar();
}
}
reportFailures--;
if (result0 === null) {
result0 = "";
} else {
result0 = null;
pos = pos2;
}
if (result0 !== null) {
if (input.length > pos) {
result1 = input.charAt(pos);
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, char_) { return char_; })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_singleQuotedString() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 39) {
result0 = "'";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"'\"");
}
}
if (result0 !== null) {
result1 = [];
result2 = parse_singleQuotedCharacter();
while (result2 !== null) {
result1.push(result2);
result2 = parse_singleQuotedCharacter();
}
if (result1 !== null) {
if (input.charCodeAt(pos) === 39) {
result2 = "'";
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"'\"");
}
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, chars) { return chars.join(""); })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_singleQuotedCharacter() {
var result0;
result0 = parse_simpleSingleQuotedCharacter();
if (result0 === null) {
result0 = parse_simpleEscapeSequence();
if (result0 === null) {
result0 = parse_zeroEscapeSequence();
if (result0 === null) {
result0 = parse_hexEscapeSequence();
if (result0 === null) {
result0 = parse_unicodeEscapeSequence();
if (result0 === null) {
result0 = parse_eolEscapeSequence();
}
}
}
}
}
return result0;
}
function parse_simpleSingleQuotedCharacter() {
var result0, result1;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
pos2 = pos;
reportFailures++;
if (input.charCodeAt(pos) === 39) {
result0 = "'";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"'\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 92) {
result0 = "\\";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\\"");
}
}
if (result0 === null) {
result0 = parse_eolChar();
}
}
reportFailures--;
if (result0 === null) {
result0 = "";
} else {
result0 = null;
pos = pos2;
}
if (result0 !== null) {
if (input.length > pos) {
result1 = input.charAt(pos);
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, char_) { return char_; })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_class() {
var result0, result1, result2, result3, result4, result5;
var pos0, pos1;
reportFailures++;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 91) {
result0 = "[";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"[\"");
}
}
if (result0 !== null) {
if (input.charCodeAt(pos) === 94) {
result1 = "^";
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("\"^\"");
}
}
result1 = result1 !== null ? result1 : "";
if (result1 !== null) {
result2 = [];
result3 = parse_classCharacterRange();
if (result3 === null) {
result3 = parse_classCharacter();
}
while (result3 !== null) {
result2.push(result3);
result3 = parse_classCharacterRange();
if (result3 === null) {
result3 = parse_classCharacter();
}
}
if (result2 !== null) {
if (input.charCodeAt(pos) === 93) {
result3 = "]";
pos++;
} else {
result3 = null;
if (reportFailures === 0) {
matchFailed("\"]\"");
}
}
if (result3 !== null) {
if (input.charCodeAt(pos) === 105) {
result4 = "i";
pos++;
} else {
result4 = null;
if (reportFailures === 0) {
matchFailed("\"i\"");
}
}
result4 = result4 !== null ? result4 : "";
if (result4 !== null) {
result5 = parse___();
if (result5 !== null) {
result0 = [result0, result1, result2, result3, result4, result5];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, inverted, parts, flags) {
var partsConverted = map(parts, function(part) { return part.data; });
var rawText = "["
+ inverted
+ map(parts, function(part) { return part.rawText; }).join("")
+ "]"
+ flags;
return {
type: "class",
inverted: inverted === "^",
ignoreCase: flags === "i",
parts: partsConverted,
// FIXME: Get the raw text from the input directly.
rawText: rawText
};
})(pos0, result0[1], result0[2], result0[4]);
}
if (result0 === null) {
pos = pos0;
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("character class");
}
return result0;
}
function parse_classCharacterRange() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
result0 = parse_classCharacter();
if (result0 !== null) {
if (input.charCodeAt(pos) === 45) {
result1 = "-";
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("\"-\"");
}
}
if (result1 !== null) {
result2 = parse_classCharacter();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, begin, end) {
if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) {
throw new this.SyntaxError(
"Invalid character range: " + begin.rawText + "-" + end.rawText + "."
);
}
return {
data: [begin.data, end.data],
// FIXME: Get the raw text from the input directly.
rawText: begin.rawText + "-" + end.rawText
};
})(pos0, result0[0], result0[2]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_classCharacter() {
var result0;
var pos0;
pos0 = pos;
result0 = parse_bracketDelimitedCharacter();
if (result0 !== null) {
result0 = (function(offset, char_) {
return {
data: char_,
// FIXME: Get the raw text from the input directly.
rawText: quoteForRegexpClass(char_)
};
})(pos0, result0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_bracketDelimitedCharacter() {
var result0;
result0 = parse_simpleBracketDelimitedCharacter();
if (result0 === null) {
result0 = parse_simpleEscapeSequence();
if (result0 === null) {
result0 = parse_zeroEscapeSequence();
if (result0 === null) {
result0 = parse_hexEscapeSequence();
if (result0 === null) {
result0 = parse_unicodeEscapeSequence();
if (result0 === null) {
result0 = parse_eolEscapeSequence();
}
}
}
}
}
return result0;
}
function parse_simpleBracketDelimitedCharacter() {
var result0, result1;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
pos2 = pos;
reportFailures++;
if (input.charCodeAt(pos) === 93) {
result0 = "]";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"]\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 92) {
result0 = "\\";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\\"");
}
}
if (result0 === null) {
result0 = parse_eolChar();
}
}
reportFailures--;
if (result0 === null) {
result0 = "";
} else {
result0 = null;
pos = pos2;
}
if (result0 !== null) {
if (input.length > pos) {
result1 = input.charAt(pos);
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, char_) { return char_; })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_simpleEscapeSequence() {
var result0, result1, result2;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 92) {
result0 = "\\";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\\"");
}
}
if (result0 !== null) {
pos2 = pos;
reportFailures++;
result1 = parse_digit();
if (result1 === null) {
if (input.charCodeAt(pos) === 120) {
result1 = "x";
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("\"x\"");
}
}
if (result1 === null) {
if (input.charCodeAt(pos) === 117) {
result1 = "u";
pos++;
} else {
result1 = null;
if (reportFailures === 0) {
matchFailed("\"u\"");
}
}
if (result1 === null) {
result1 = parse_eolChar();
}
}
}
reportFailures--;
if (result1 === null) {
result1 = "";
} else {
result1 = null;
pos = pos2;
}
if (result1 !== null) {
if (input.length > pos) {
result2 = input.charAt(pos);
pos++;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, char_) {
return char_
.replace("b", "\b")
.replace("f", "\f")
.replace("n", "\n")
.replace("r", "\r")
.replace("t", "\t")
.replace("v", "\x0B"); // IE does not recognize "\v".
})(pos0, result0[2]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_zeroEscapeSequence() {
var result0, result1;
var pos0, pos1, pos2;
pos0 = pos;
pos1 = pos;
if (input.substr(pos, 2) === "\\0") {
result0 = "\\0";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\0\"");
}
}
if (result0 !== null) {
pos2 = pos;
reportFailures++;
result1 = parse_digit();
reportFailures--;
if (result1 === null) {
result1 = "";
} else {
result1 = null;
pos = pos2;
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset) { return "\x00"; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_hexEscapeSequence() {
var result0, result1, result2;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.substr(pos, 2) === "\\x") {
result0 = "\\x";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\x\"");
}
}
if (result0 !== null) {
result1 = parse_hexDigit();
if (result1 !== null) {
result2 = parse_hexDigit();
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, h1, h2) {
return String.fromCharCode(parseInt(h1 + h2, 16));
})(pos0, result0[1], result0[2]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_unicodeEscapeSequence() {
var result0, result1, result2, result3, result4;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.substr(pos, 2) === "\\u") {
result0 = "\\u";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\u\"");
}
}
if (result0 !== null) {
result1 = parse_hexDigit();
if (result1 !== null) {
result2 = parse_hexDigit();
if (result2 !== null) {
result3 = parse_hexDigit();
if (result3 !== null) {
result4 = parse_hexDigit();
if (result4 !== null) {
result0 = [result0, result1, result2, result3, result4];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, h1, h2, h3, h4) {
return String.fromCharCode(parseInt(h1 + h2 + h3 + h4, 16));
})(pos0, result0[1], result0[2], result0[3], result0[4]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_eolEscapeSequence() {
var result0, result1;
var pos0, pos1;
pos0 = pos;
pos1 = pos;
if (input.charCodeAt(pos) === 92) {
result0 = "\\";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\\\\"");
}
}
if (result0 !== null) {
result1 = parse_eol();
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos1;
}
} else {
result0 = null;
pos = pos1;
}
if (result0 !== null) {
result0 = (function(offset, eol) { return eol; })(pos0, result0[1]);
}
if (result0 === null) {
pos = pos0;
}
return result0;
}
function parse_digit() {
var result0;
if (/^[0-9]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[0-9]");
}
}
return result0;
}
function parse_hexDigit() {
var result0;
if (/^[0-9a-fA-F]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[0-9a-fA-F]");
}
}
return result0;
}
function parse_letter() {
var result0;
result0 = parse_lowerCaseLetter();
if (result0 === null) {
result0 = parse_upperCaseLetter();
}
return result0;
}
function parse_lowerCaseLetter() {
var result0;
if (/^[a-z]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[a-z]");
}
}
return result0;
}
function parse_upperCaseLetter() {
var result0;
if (/^[A-Z]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[A-Z]");
}
}
return result0;
}
function parse___() {
var result0, result1;
result0 = [];
result1 = parse_whitespace();
if (result1 === null) {
result1 = parse_eol();
if (result1 === null) {
result1 = parse_comment();
}
}
while (result1 !== null) {
result0.push(result1);
result1 = parse_whitespace();
if (result1 === null) {
result1 = parse_eol();
if (result1 === null) {
result1 = parse_comment();
}
}
}
return result0;
}
function parse_comment() {
var result0;
reportFailures++;
result0 = parse_singleLineComment();
if (result0 === null) {
result0 = parse_multiLineComment();
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("comment");
}
return result0;
}
function parse_singleLineComment() {
var result0, result1, result2, result3;
var pos0, pos1, pos2;
pos0 = pos;
if (input.substr(pos, 2) === "//") {
result0 = "//";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"//\"");
}
}
if (result0 !== null) {
result1 = [];
pos1 = pos;
pos2 = pos;
reportFailures++;
result2 = parse_eolChar();
reportFailures--;
if (result2 === null) {
result2 = "";
} else {
result2 = null;
pos = pos2;
}
if (result2 !== null) {
if (input.length > pos) {
result3 = input.charAt(pos);
pos++;
} else {
result3 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos1;
}
} else {
result2 = null;
pos = pos1;
}
while (result2 !== null) {
result1.push(result2);
pos1 = pos;
pos2 = pos;
reportFailures++;
result2 = parse_eolChar();
reportFailures--;
if (result2 === null) {
result2 = "";
} else {
result2 = null;
pos = pos2;
}
if (result2 !== null) {
if (input.length > pos) {
result3 = input.charAt(pos);
pos++;
} else {
result3 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos1;
}
} else {
result2 = null;
pos = pos1;
}
}
if (result1 !== null) {
result0 = [result0, result1];
} else {
result0 = null;
pos = pos0;
}
} else {
result0 = null;
pos = pos0;
}
return result0;
}
function parse_multiLineComment() {
var result0, result1, result2, result3;
var pos0, pos1, pos2;
pos0 = pos;
if (input.substr(pos, 2) === "/*") {
result0 = "/*";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"/*\"");
}
}
if (result0 !== null) {
result1 = [];
pos1 = pos;
pos2 = pos;
reportFailures++;
if (input.substr(pos, 2) === "*/") {
result2 = "*/";
pos += 2;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"*/\"");
}
}
reportFailures--;
if (result2 === null) {
result2 = "";
} else {
result2 = null;
pos = pos2;
}
if (result2 !== null) {
if (input.length > pos) {
result3 = input.charAt(pos);
pos++;
} else {
result3 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos1;
}
} else {
result2 = null;
pos = pos1;
}
while (result2 !== null) {
result1.push(result2);
pos1 = pos;
pos2 = pos;
reportFailures++;
if (input.substr(pos, 2) === "*/") {
result2 = "*/";
pos += 2;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"*/\"");
}
}
reportFailures--;
if (result2 === null) {
result2 = "";
} else {
result2 = null;
pos = pos2;
}
if (result2 !== null) {
if (input.length > pos) {
result3 = input.charAt(pos);
pos++;
} else {
result3 = null;
if (reportFailures === 0) {
matchFailed("any character");
}
}
if (result3 !== null) {
result2 = [result2, result3];
} else {
result2 = null;
pos = pos1;
}
} else {
result2 = null;
pos = pos1;
}
}
if (result1 !== null) {
if (input.substr(pos, 2) === "*/") {
result2 = "*/";
pos += 2;
} else {
result2 = null;
if (reportFailures === 0) {
matchFailed("\"*/\"");
}
}
if (result2 !== null) {
result0 = [result0, result1, result2];
} else {
result0 = null;
pos = pos0;
}
} else {
result0 = null;
pos = pos0;
}
} else {
result0 = null;
pos = pos0;
}
return result0;
}
function parse_eol() {
var result0;
reportFailures++;
if (input.charCodeAt(pos) === 10) {
result0 = "\n";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\n\"");
}
}
if (result0 === null) {
if (input.substr(pos, 2) === "\r\n") {
result0 = "\r\n";
pos += 2;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\r\\n\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 13) {
result0 = "\r";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\r\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 8232) {
result0 = "\u2028";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\u2028\"");
}
}
if (result0 === null) {
if (input.charCodeAt(pos) === 8233) {
result0 = "\u2029";
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("\"\\u2029\"");
}
}
}
}
}
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("end of line");
}
return result0;
}
function parse_eolChar() {
var result0;
if (/^[\n\r\u2028\u2029]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[\\n\\r\\u2028\\u2029]");
}
}
return result0;
}
function parse_whitespace() {
var result0;
reportFailures++;
if (/^[ \t\x0B\f\xA0\uFEFF\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]/.test(input.charAt(pos))) {
result0 = input.charAt(pos);
pos++;
} else {
result0 = null;
if (reportFailures === 0) {
matchFailed("[ \\t\\x0B\\f\\xA0\\uFEFF\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000]");
}
}
reportFailures--;
if (reportFailures === 0 && result0 === null) {
matchFailed("whitespace");
}
return result0;
}
function cleanupExpected(expected) {
expected.sort();
var lastExpected = null;
var cleanExpected = [];
for (var i = 0; i < expected.length; i++) {
if (expected[i] !== lastExpected) {
cleanExpected.push(expected[i]);
lastExpected = expected[i];
}
}
return cleanExpected;
}
function computeErrorPosition() {
/*
* The first idea was to use |String.split| to break the input up to the
* error position along newlines and derive the line and column from
* there. However IE's |split| implementation is so broken that it was
* enough to prevent it.
*/
var line = 1;
var column = 1;
var seenCR = false;
for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
var ch = input.charAt(i);
if (ch === "\n") {
if (!seenCR) { line++; }
column = 1;
seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
line++;
column = 1;
seenCR = true;
} else {
column++;
seenCR = false;
}
}
return { line: line, column: column };
}
var result = parseFunctions[startRule]();
/*
* The parser is now in one of the following three states:
*
* 1. The parser successfully parsed the whole input.
*
* - |result !== null|
* - |pos === input.length|
* - |rightmostFailuresExpected| may or may not contain something
*
* 2. The parser successfully parsed only a part of the input.
*
* - |result !== null|
* - |pos < input.length|
* - |rightmostFailuresExpected| may or may not contain something
*
* 3. The parser did not successfully parse any part of the input.
*
* - |result === null|
* - |pos === 0|
* - |rightmostFailuresExpected| contains at least one failure
*
* All code following this comment (including called functions) must
* handle these states.
*/
if (result === null || pos !== input.length) {
var offset = Math.max(pos, rightmostFailuresPos);
var found = offset < input.length ? input.charAt(offset) : null;
var errorPosition = computeErrorPosition();
throw new this.SyntaxError(
cleanupExpected(rightmostFailuresExpected),
found,
offset,
errorPosition.line,
errorPosition.column
);
}
return result;
},
/* Returns the parser source code. */
toSource: function() { return this._source; }
};
/* Thrown when a parser encounters a syntax error. */
result.SyntaxError = function(expected, found, offset, line, column) {
function buildMessage(expected, found) {
var expectedHumanized, foundHumanized;
switch (expected.length) {
case 0:
expectedHumanized = "end of input";
break;
case 1:
expectedHumanized = expected[0];
break;
default:
expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
+ " or "
+ expected[expected.length - 1];
}
foundHumanized = found ? quote(found) : "end of input";
return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
}
this.name = "SyntaxError";
this.expected = expected;
this.found = found;
this.message = buildMessage(expected, found);
this.offset = offset;
this.line = line;
this.column = column;
};
result.SyntaxError.prototype = Error.prototype;
return result;
})();
PEG.compiler = {
/*
* Names of passes that will get run during the compilation (in the specified
* order).
*/
appliedPassNames: [
"reportMissingRules",
"reportLeftRecursion",
"removeProxyRules",
"computeVarNames",
"computeParams"
],
/*
* Generates a parser from a specified grammar AST. Throws |PEG.GrammarError|
* if the AST contains a semantic error. Note that not all errors are detected
* during the generation and some may protrude to the generated parser and
* cause its malfunction.
*/
compile: function(ast, options) {
var that = this;
each(this.appliedPassNames, function(passName) {
that.passes[passName](ast);
});
var source = this.emitter(ast, options);
var result = eval(source);
result._source = source;
return result;
}
};
/*
* Compiler passes.
*
* Each pass is a function that is passed the AST. It can perform checks on it
* or modify it as needed. If the pass encounters a semantic error, it throws
* |PEG.GrammarError|.
*/
PEG.compiler.passes = {
/* Checks that all referenced rules exist. */
reportMissingRules: function(ast) {
function nop() {}
function checkExpression(node) { check(node.expression); }
function checkSubnodes(propertyName) {
return function(node) { each(node[propertyName], check); };
}
var check = buildNodeVisitor({
grammar: checkSubnodes("rules"),
rule: checkExpression,
choice: checkSubnodes("alternatives"),
sequence: checkSubnodes("elements"),
labeled: checkExpression,
simple_and: checkExpression,
simple_not: checkExpression,
semantic_and: nop,
semantic_not: nop,
optional: checkExpression,
zero_or_more: checkExpression,
one_or_more: checkExpression,
action: checkExpression,
rule_ref:
function(node) {
if (!findRuleByName(ast, node.name)) {
throw new PEG.GrammarError(
"Referenced rule \"" + node.name + "\" does not exist."
);
}
},
literal: nop,
any: nop,
"class": nop
});
check(ast);
},
/* Checks that no left recursion is present. */
reportLeftRecursion: function(ast) {
function nop() {}
function checkExpression(node, appliedRules) {
check(node.expression, appliedRules);
}
function checkSubnodes(propertyName) {
return function(node, appliedRules) {
each(node[propertyName], function(subnode) {
check(subnode, appliedRules);
});
};
}
var check = buildNodeVisitor({
grammar: checkSubnodes("rules"),
rule:
function(node, appliedRules) {
check(node.expression, appliedRules.concat(node.name));
},
choice: checkSubnodes("alternatives"),
sequence:
function(node, appliedRules) {
if (node.elements.length > 0) {
check(node.elements[0], appliedRules);
}
},
labeled: checkExpression,
simple_and: checkExpression,
simple_not: checkExpression,
semantic_and: nop,
semantic_not: nop,
optional: checkExpression,
zero_or_more: checkExpression,
one_or_more: checkExpression,
action: checkExpression,
rule_ref:
function(node, appliedRules) {
if (contains(appliedRules, node.name)) {
throw new PEG.GrammarError(
"Left recursion detected for rule \"" + node.name + "\"."
);
}
check(findRuleByName(ast, node.name), appliedRules);
},
literal: nop,
any: nop,
"class": nop
});
check(ast, []);
},
/*
* Removes proxy rules -- that is, rules that only delegate to other rule.
*/
removeProxyRules: function(ast) {
function isProxyRule(node) {
return node.type === "rule" && node.expression.type === "rule_ref";
}
function replaceRuleRefs(ast, from, to) {
function nop() {}
function replaceInExpression(node, from, to) {
replace(node.expression, from, to);
}
function replaceInSubnodes(propertyName) {
return function(node, from, to) {
each(node[propertyName], function(subnode) {
replace(subnode, from, to);
});
};
}
var replace = buildNodeVisitor({
grammar: replaceInSubnodes("rules"),
rule: replaceInExpression,
choice: replaceInSubnodes("alternatives"),
sequence: replaceInSubnodes("elements"),
labeled: replaceInExpression,
simple_and: replaceInExpression,
simple_not: replaceInExpression,
semantic_and: nop,
semantic_not: nop,
optional: replaceInExpression,
zero_or_more: replaceInExpression,
one_or_more: replaceInExpression,
action: replaceInExpression,
rule_ref:
function(node, from, to) {
if (node.name === from) {
node.name = to;
}
},
literal: nop,
any: nop,
"class": nop
});
replace(ast, from, to);
}
var indices = [];
each(ast.rules, function(rule, i) {
if (isProxyRule(rule)) {
replaceRuleRefs(ast, rule.name, rule.expression.name);
if (rule.name === ast.startRule) {
ast.startRule = rule.expression.name;
}
indices.push(i);
}
});
indices.reverse();
each(indices, function(index) {
ast.rules.splice(index, 1);
});
},
/*
* Computes names of variables used for storing match results and parse
* positions in generated code. These variables are organized as two stacks.
* The following will hold after running this pass:
*
* * All nodes except "grammar" and "rule" nodes will have a |resultVar|
* property. It will contain a name of the variable that will store a
* match result of the expression represented by the node in generated
* code.
*
* * Some nodes will have a |posVar| property. It will contain a name of the
* variable that will store a parse position in generated code.
*
* * All "rule" nodes will contain |resultVars| and |posVars| properties.
* They will contain a list of values of |resultVar| and |posVar|
* properties used in rule's subnodes. (This is useful to declare
* variables in generated code.)
*/
computeVarNames: function(ast) {
function resultVar(index) { return "result" + index; }
function posVar(index) { return "pos" + index; }
function computeLeaf(node, index) {
node.resultVar = resultVar(index.result);
return { result: 0, pos: 0 };
}
function computeFromExpression(delta) {
return function(node, index) {
var depth = compute(
node.expression,
{
result: index.result + delta.result,
pos: index.pos + delta.pos
}
);
node.resultVar = resultVar(index.result);
if (delta.pos !== 0) {
node.posVar = posVar(index.pos);
}
return {
result: depth.result + delta.result,
pos: depth.pos + delta.pos
};
};
}
var compute = buildNodeVisitor({
grammar:
function(node, index) {
each(node.rules, function(node) {
compute(node, index);
});
},
rule:
function(node, index) {
var depth = compute(node.expression, index);
node.resultVar = resultVar(index.result);
node.resultVars = map(range(depth.result + 1), resultVar);
node.posVars = map(range(depth.pos), posVar);
},
choice:
function(node, index) {
var depths = map(node.alternatives, function(alternative) {
return compute(alternative, index);
});
node.resultVar = resultVar(index.result);
return {
result: Math.max.apply(null, pluck(depths, "result")),
pos: Math.max.apply(null, pluck(depths, "pos"))
};
},
sequence:
function(node, index) {
var depths = map(node.elements, function(element, i) {
return compute(
element,
{ result: index.result + i, pos: index.pos + 1 }
);
});
node.resultVar = resultVar(index.result);
node.posVar = posVar(index.pos);
return {
result:
node.elements.length > 0
? Math.max.apply(
null,
map(depths, function(d, i) { return i + d.result; })
)
: 0,
pos:
node.elements.length > 0
? 1 + Math.max.apply(null, pluck(depths, "pos"))
: 1
};
},
labeled: computeFromExpression({ result: 0, pos: 0 }),
simple_and: computeFromExpression({ result: 0, pos: 1 }),
simple_not: computeFromExpression({ result: 0, pos: 1 }),
semantic_and: computeLeaf,
semantic_not: computeLeaf,
optional: computeFromExpression({ result: 0, pos: 0 }),
zero_or_more: computeFromExpression({ result: 1, pos: 0 }),
one_or_more: computeFromExpression({ result: 1, pos: 0 }),
action: computeFromExpression({ result: 0, pos: 1 }),
rule_ref: computeLeaf,
literal: computeLeaf,
any: computeLeaf,
"class": computeLeaf
});
compute(ast, { result: 0, pos: 0 });
},
/*
* This pass walks through the AST and tracks what labels are visible at each
* point. For "action", "semantic_and" and "semantic_or" nodes it computes
* parameter names and values for the function used in generated code. (In the
* emitter, user's code is wrapped into a function that is immediately
* executed. Its parameter names correspond to visible labels and its
* parameter values to their captured values). Implicitly, this pass defines
* scoping rules for labels.
*
* After running this pass, all "action", "semantic_and" and "semantic_or"
* nodes will have a |params| property containing an object mapping parameter
* names to the expressions that will be used as their values.
*/
computeParams: function(ast) {
var envs = [];
function scoped(f) {
envs.push({});
f();
envs.pop();
}
function nop() {}
function computeForScopedExpression(node) {
scoped(function() { compute(node.expression); });
}
function computeParams(node) {
var env = envs[envs.length - 1], params = {}, name;
for (name in env) {
params[name] = env[name];
}
node.params = params;
}
var compute = buildNodeVisitor({
grammar:
function(node) {
each(node.rules, compute);
},
rule: computeForScopedExpression,
choice:
function(node) {
scoped(function() { each(node.alternatives, compute); });
},
sequence:
function(node) {
var env = envs[envs.length - 1], name;
function fixup(name) {
each(pluck(node.elements, "resultVar"), function(resultVar, i) {
if ((new RegExp("^" + resultVar + "(\\[\\d+\\])*$")).test(env[name])) {
env[name] = node.resultVar + "[" + i + "]"
+ env[name].substr(resultVar.length);
}
});
}
each(node.elements, compute);
for (name in env) {
fixup(name);
}
},
labeled:
function(node) {
envs[envs.length - 1][node.label] = node.resultVar;
scoped(function() { compute(node.expression); });
},
simple_and: computeForScopedExpression,
simple_not: computeForScopedExpression,
semantic_and: computeParams,
semantic_not: computeParams,
optional: computeForScopedExpression,
zero_or_more: computeForScopedExpression,
one_or_more: computeForScopedExpression,
action:
function(node) {
scoped(function() {
compute(node.expression);
computeParams(node);
});
},
rule_ref: nop,
literal: nop,
any: nop,
"class": nop
});
compute(ast);
}
};
/* Emits the generated code for the AST. */
PEG.compiler.emitter = function(ast, options) {
options = options || {};
if (options.cache === undefined) {
options.cache = false;
}
if (options.trackLineAndColumn === undefined) {
options.trackLineAndColumn = false;
}
/*
* Codie 1.1.0
*
* https://github.com/dmajda/codie
*
* Copyright (c) 2011-2012 David Majda
* Licensend under the MIT license.
*/
var Codie = (function(undefined) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
/*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
* string literal except for the closing quote character, backslash,
* carriage return, line separator, paragraph separator, and line feed.
* Any character may appear in the form of an escape sequence.
*
* For portability, we also escape escape all control and non-ASCII
* characters. Note that "\0" and "\v" escape sequences are not used
* because JSHint does not like the first and IE the second.
*/
return s
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // closing double quote
.replace(/\x08/g, '\\b') // backspace
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
function push(s) { return '__p.push(' + s + ');'; }
function pushRaw(template, length, state) {
function unindent(code, level, unindentFirst) {
return code.replace(
new RegExp('^.{' + level +'}', "gm"),
function(str, offset) {
if (offset === 0) {
return unindentFirst ? '' : str;
} else {
return "";
}
}
);
}
var escaped = stringEscape(unindent(
template.substring(0, length),
state.indentLevel(),
state.atBOL
));
return escaped.length > 0 ? push('"' + escaped + '"') : '';
}
var Codie = {
/* Codie version (uses semantic versioning). */
VERSION: "1.1.0",
/*
* Specifies by how many characters do #if/#else and #for unindent their
* content in the generated code.
*/
indentStep: 2,
/* Description of #-commands. Extend to define your own commands. */
commands: {
"if": {
params: /^(.*)$/,
compile: function(state, prefix, params) {
return ['if(' + params[0] + '){', []];
},
stackOp: "push"
},
"else": {
params: /^$/,
compile: function(state) {
var stack = state.commandStack,
insideElse = stack[stack.length - 1] === "else",
insideIf = stack[stack.length - 1] === "if";
if (insideElse) { throw new Error("Multiple #elses."); }
if (!insideIf) { throw new Error("Using #else outside of #if."); }
return ['}else{', []];
},
stackOp: "replace"
},
"for": {
params: /^([a-zA-Z_][a-zA-Z0-9_]*)[ \t]+in[ \t]+(.*)$/,
init: function(state) {
state.forCurrLevel = 0; // current level of #for loop nesting
state.forMaxLevel = 0; // maximum level of #for loop nesting
},
compile: function(state, prefix, params) {
var c = '__c' + state.forCurrLevel, // __c for "collection"
l = '__l' + state.forCurrLevel, // __l for "length"
i = '__i' + state.forCurrLevel; // __i for "index"
state.forCurrLevel++;
if (state.forMaxLevel < state.forCurrLevel) {
state.forMaxLevel = state.forCurrLevel;
}
return [
c + '=' + params[1] + ';'
+ l + '=' + c + '.length;'
+ 'for(' + i + '=0;' + i + '<' + l + ';' + i + '++){'
+ params[0] + '=' + c + '[' + i + '];',
[params[0], c, l, i]
];
},
exit: function(state) { state.forCurrLevel--; },
stackOp: "push"
},
"end": {
params: /^$/,
compile: function(state) {
var stack = state.commandStack, exit;
if (stack.length === 0) { throw new Error("Too many #ends."); }
exit = Codie.commands[stack[stack.length - 1]].exit;
if (exit) { exit(state); }
return ['}', []];
},
stackOp: "pop"
},
"block": {
params: /^(.*)$/,
compile: function(state, prefix, params) {
var x = '__x', // __x for "prefix",
n = '__n', // __n for "lines"
l = '__l', // __l for "length"
i = '__i'; // __i for "index"
/*
* Originally, the generated code used |String.prototype.replace|, but
* it is buggy in certain versions of V8 so it was rewritten. See the
* tests for details.
*/
return [
x + '="' + stringEscape(prefix.substring(state.indentLevel())) + '";'
+ n + '=(' + params[0] + ').toString().split("\\n");'
+ l + '=' + n + '.length;'
+ 'for(' + i + '=0;' + i + '<' + l + ';' + i + '++){'
+ n + '[' + i +']=' + x + '+' + n + '[' + i + ']+"\\n";'
+ '}'
+ push(n + '.join("")'),
[x, n, l, i]
];
},
stackOp: "nop"
}
},
/*
* Compiles a template into a function. When called, this function will
* execute the template in the context of an object passed in a parameter and
* return the result.
*/
template: function(template) {
var stackOps = {
push: function(stack, name) { stack.push(name); },
replace: function(stack, name) { stack[stack.length - 1] = name; },
pop: function(stack) { stack.pop(); },
nop: function() { }
};
function compileExpr(state, expr) {
state.atBOL = false;
return [push(expr), []];
}
function compileCommand(state, prefix, name, params) {
var command, match, result;
command = Codie.commands[name];
if (!command) { throw new Error("Unknown command: #" + name + "."); }
match = command.params.exec(params);
if (match === null) {
throw new Error(
"Invalid params for command #" + name + ": " + params + "."
);
}
result = command.compile(state, prefix, match.slice(1));
stackOps[command.stackOp](state.commandStack, name);
state.atBOL = true;
return result;
}
var state = { // compilation state
commandStack: [], // stack of commands as they were nested
atBOL: true, // is the next character to process at BOL?
indentLevel: function() {
return Codie.indentStep * this.commandStack.length;
}
},
code = '', // generated template function code
vars = ['__p=[]'], // variables used by generated code
name, match, result, i;
/* Initialize state. */
for (name in Codie.commands) {
if (Codie.commands[name].init) { Codie.commands[name].init(state); }
}
/* Compile the template. */
while ((match = /^([ \t]*)#([a-zA-Z_][a-zA-Z0-9_]*)(?:[ \t]+([^ \t\n][^\n]*))?[ \t]*(?:\n|$)|#\{([^}]*)\}/m.exec(template)) !== null) {
code += pushRaw(template, match.index, state);
result = match[2] !== undefined && match[2] !== ""
? compileCommand(state, match[1], match[2], match[3] || "") // #-command
: compileExpr(state, match[4]); // #{...}
code += result[0];
vars = vars.concat(result[1]);
template = template.substring(match.index + match[0].length);
}
code += pushRaw(template, template.length, state);
/* Check the final state. */
if (state.commandStack.length > 0) { throw new Error("Missing #end."); }
/* Sanitize the list of variables used by commands. */
vars.sort();
for (i = 0; i < vars.length; i++) {
if (vars[i] === vars[i - 1]) { vars.splice(i--, 1); }
}
/* Create the resulting function. */
return new Function("__v", [
'__v=__v||{};',
'var ' + vars.join(',') + ';',
'with(__v){',
code,
'return __p.join("").replace(/^\\n+|\\n+$/g,"");};'
].join(''));
}
};
return Codie;
})();
var templates = (function() {
var name,
templates = {},
sources = {
grammar: [
'(function(){',
' /*',
' * Generated by PEG.js 0.7.0.',
' *',
' * http://pegjs.majda.cz/',
' */',
' ',
/* This needs to be in sync with |quote| in utils.js. */
' function quote(s) {',
' /*',
' * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a',
' * string literal except for the closing quote character, backslash,',
' * carriage return, line separator, paragraph separator, and line feed.',
' * Any character may appear in the form of an escape sequence.',
' *',
' * For portability, we also escape escape all control and non-ASCII',
' * characters. Note that "\\0" and "\\v" escape sequences are not used',
' * because JSHint does not like the first and IE the second.',
' */',
' return \'"\' + s',
' .replace(/\\\\/g, \'\\\\\\\\\') // backslash',
' .replace(/"/g, \'\\\\"\') // closing quote character',
' .replace(/\\x08/g, \'\\\\b\') // backspace',
' .replace(/\\t/g, \'\\\\t\') // horizontal tab',
' .replace(/\\n/g, \'\\\\n\') // line feed',
' .replace(/\\f/g, \'\\\\f\') // form feed',
' .replace(/\\r/g, \'\\\\r\') // carriage return',
' .replace(/[\\x00-\\x07\\x0B\\x0E-\\x1F\\x80-\\uFFFF]/g, escape)',
' + \'"\';',
' }',
' ',
' var result = {',
' /*',
' * Parses the input with a generated parser. If the parsing is successfull,',
' * returns a value explicitly or implicitly specified by the grammar from',
' * which the parser was generated (see |PEG.buildParser|). If the parsing is',
' * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.',
' */',
' parse: function(input, startRule) {',
' var parseFunctions = {',
' #for rule in node.rules',
' #{string(rule.name) + ": parse_" + rule.name + (rule !== node.rules[node.rules.length - 1] ? "," : "")}',
' #end',
' };',
' ',
' if (startRule !== undefined) {',
' if (parseFunctions[startRule] === undefined) {',
' throw new Error("Invalid rule name: " + quote(startRule) + ".");',
' }',
' } else {',
' startRule = #{string(node.startRule)};',
' }',
' ',
' #{posInit("pos")};',
' var reportFailures = 0;', // 0 = report, anything > 0 = do not report
' #{posInit("rightmostFailuresPos")};',
' var rightmostFailuresExpected = [];',
' #if options.cache',
' var cache = {};',
' #end',
' ',
/* This needs to be in sync with |padLeft| in utils.js. */
' function padLeft(input, padding, length) {',
' var result = input;',
' ',
' var padLength = length - input.length;',
' for (var i = 0; i < padLength; i++) {',
' result = padding + result;',
' }',
' ',
' return result;',
' }',
' ',
/* This needs to be in sync with |escape| in utils.js. */
' function escape(ch) {',
' var charCode = ch.charCodeAt(0);',
' var escapeChar;',
' var length;',
' ',
' if (charCode <= 0xFF) {',
' escapeChar = \'x\';',
' length = 2;',
' } else {',
' escapeChar = \'u\';',
' length = 4;',
' }',
' ',
' return \'\\\\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), \'0\', length);',
' }',
' ',
' #if options.trackLineAndColumn',
' function clone(object) {',
' var result = {};',
' for (var key in object) {',
' result[key] = object[key];',
' }',
' return result;',
' }',
' ',
' function advance(pos, n) {',
' var endOffset = pos.offset + n;',
' ',
' for (var offset = pos.offset; offset < endOffset; offset++) {',
' var ch = input.charAt(offset);',
' if (ch === "\\n") {',
' if (!pos.seenCR) { pos.line++; }',
' pos.column = 1;',
' pos.seenCR = false;',
' } else if (ch === "\\r" || ch === "\\u2028" || ch === "\\u2029") {',
' pos.line++;',
' pos.column = 1;',
' pos.seenCR = true;',
' } else {',
' pos.column++;',
' pos.seenCR = false;',
' }',
' }',
' ',
' pos.offset += n;',
' }',
' ',
' #end',
' function matchFailed(failure) {',
' if (#{posOffset("pos")} < #{posOffset("rightmostFailuresPos")}) {',
' return;',
' }',
' ',
' if (#{posOffset("pos")} > #{posOffset("rightmostFailuresPos")}) {',
' rightmostFailuresPos = #{posClone("pos")};',
' rightmostFailuresExpected = [];',
' }',
' ',
' rightmostFailuresExpected.push(failure);',
' }',
' ',
' #for rule in node.rules',
' #block emit(rule)',
' ',
' #end',
' ',
' function cleanupExpected(expected) {',
' expected.sort();',
' ',
' var lastExpected = null;',
' var cleanExpected = [];',
' for (var i = 0; i < expected.length; i++) {',
' if (expected[i] !== lastExpected) {',
' cleanExpected.push(expected[i]);',
' lastExpected = expected[i];',
' }',
' }',
' return cleanExpected;',
' }',
' ',
' #if !options.trackLineAndColumn',
' function computeErrorPosition() {',
' /*',
' * The first idea was to use |String.split| to break the input up to the',
' * error position along newlines and derive the line and column from',
' * there. However IE\'s |split| implementation is so broken that it was',
' * enough to prevent it.',
' */',
' ',
' var line = 1;',
' var column = 1;',
' var seenCR = false;',
' ',
' for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {',
' var ch = input.charAt(i);',
' if (ch === "\\n") {',
' if (!seenCR) { line++; }',
' column = 1;',
' seenCR = false;',
' } else if (ch === "\\r" || ch === "\\u2028" || ch === "\\u2029") {',
' line++;',
' column = 1;',
' seenCR = true;',
' } else {',
' column++;',
' seenCR = false;',
' }',
' }',
' ',
' return { line: line, column: column };',
' }',
' #end',
' ',
' #if node.initializer',
' #block emit(node.initializer)',
' #end',
' ',
' var result = parseFunctions[startRule]();',
' ',
' /*',
' * The parser is now in one of the following three states:',
' *',
' * 1. The parser successfully parsed the whole input.',
' *',
' * - |result !== null|',
' * - |#{posOffset("pos")} === input.length|',
' * - |rightmostFailuresExpected| may or may not contain something',
' *',
' * 2. The parser successfully parsed only a part of the input.',
' *',
' * - |result !== null|',
' * - |#{posOffset("pos")} < input.length|',
' * - |rightmostFailuresExpected| may or may not contain something',
' *',
' * 3. The parser did not successfully parse any part of the input.',
' *',
' * - |result === null|',
' * - |#{posOffset("pos")} === 0|',
' * - |rightmostFailuresExpected| contains at least one failure',
' *',
' * All code following this comment (including called functions) must',
' * handle these states.',
' */',
' if (result === null || #{posOffset("pos")} !== input.length) {',
' var offset = Math.max(#{posOffset("pos")}, #{posOffset("rightmostFailuresPos")});',
' var found = offset < input.length ? input.charAt(offset) : null;',
' #if options.trackLineAndColumn',
' var errorPosition = #{posOffset("pos")} > #{posOffset("rightmostFailuresPos")} ? pos : rightmostFailuresPos;',
' #else',
' var errorPosition = computeErrorPosition();',
' #end',
' ',
' throw new this.SyntaxError(',
' cleanupExpected(rightmostFailuresExpected),',
' found,',
' offset,',
' errorPosition.line,',
' errorPosition.column',
' );',
' }',
' ',
' return result;',
' },',
' ',
' /* Returns the parser source code. */',
' toSource: function() { return this._source; }',
' };',
' ',
' /* Thrown when a parser encounters a syntax error. */',
' ',
' result.SyntaxError = function(expected, found, offset, line, column) {',
' function buildMessage(expected, found) {',
' var expectedHumanized, foundHumanized;',
' ',
' switch (expected.length) {',
' case 0:',
' expectedHumanized = "end of input";',
' break;',
' case 1:',
' expectedHumanized = expected[0];',
' break;',
' default:',
' expectedHumanized = expected.slice(0, expected.length - 1).join(", ")',
' + " or "',
' + expected[expected.length - 1];',
' }',
' ',
' foundHumanized = found ? quote(found) : "end of input";',
' ',
' return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";',
' }',
' ',
' this.name = "SyntaxError";',
' this.expected = expected;',
' this.found = found;',
' this.message = buildMessage(expected, found);',
' this.offset = offset;',
' this.line = line;',
' this.column = column;',
' };',
' ',
' result.SyntaxError.prototype = Error.prototype;',
' ',
' return result;',
'})()'
],
rule: [
'function parse_#{node.name}() {',
' #if options.cache',
' var cacheKey = "#{node.name}@" + #{posOffset("pos")};',
' var cachedResult = cache[cacheKey];',
' if (cachedResult) {',
' pos = #{posClone("cachedResult.nextPos")};',
' return cachedResult.result;',
' }',
' ',
' #end',
' #if node.resultVars.length > 0',
' var #{node.resultVars.join(", ")};',
' #end',
' #if node.posVars.length > 0',
' var #{node.posVars.join(", ")};',
' #end',
' ',
' #if node.displayName !== null',
' reportFailures++;',
' #end',
' #block emit(node.expression)',
' #if node.displayName !== null',
' reportFailures--;',
' if (reportFailures === 0 && #{node.resultVar} === null) {',
' matchFailed(#{string(node.displayName)});',
' }',
' #end',
' #if options.cache',
' ',
' cache[cacheKey] = {',
' nextPos: #{posClone("pos")},',
' result: #{node.resultVar}',
' };',
' #end',
' return #{node.resultVar};',
'}'
],
choice: [
'#block emit(alternative)',
'#block nextAlternativesCode'
],
"choice.next": [
'if (#{node.resultVar} === null) {',
' #block code',
'}'
],
sequence: [
'#{posSave(node)};',
'#block code'
],
"sequence.iteration": [
'#block emit(element)',
'if (#{element.resultVar} !== null) {',
' #block code',
'} else {',
' #{node.resultVar} = null;',
' #{posRestore(node)};',
'}'
],
"sequence.inner": [
'#{node.resultVar} = [#{pluck(node.elements, "resultVar").join(", ")}];'
],
simple_and: [
'#{posSave(node)};',
'reportFailures++;',
'#block emit(node.expression)',
'reportFailures--;',
'if (#{node.resultVar} !== null) {',
' #{node.resultVar} = "";',
' #{posRestore(node)};',
'} else {',
' #{node.resultVar} = null;',
'}'
],
simple_not: [
'#{posSave(node)};',
'reportFailures++;',
'#block emit(node.expression)',
'reportFailures--;',
'if (#{node.resultVar} === null) {',
' #{node.resultVar} = "";',
'} else {',
' #{node.resultVar} = null;',
' #{posRestore(node)};',
'}'
],
semantic_and: [
'#{node.resultVar} = (function(#{(options.trackLineAndColumn ? ["offset", "line", "column"] : ["offset"]).concat(keys(node.params)).join(", ")}) {#{node.code}})(#{(options.trackLineAndColumn ? ["pos.offset", "pos.line", "pos.column"] : ["pos"]).concat(values(node.params)).join(", ")}) ? "" : null;'
],
semantic_not: [
'#{node.resultVar} = (function(#{(options.trackLineAndColumn ? ["offset", "line", "column"] : ["offset"]).concat(keys(node.params)).join(", ")}) {#{node.code}})(#{(options.trackLineAndColumn ? ["pos.offset", "pos.line", "pos.column"] : ["pos"]).concat(values(node.params)).join(", ")}) ? null : "";'
],
optional: [
'#block emit(node.expression)',
'#{node.resultVar} = #{node.resultVar} !== null ? #{node.resultVar} : "";'
],
zero_or_more: [
'#{node.resultVar} = [];',
'#block emit(node.expression)',
'while (#{node.expression.resultVar} !== null) {',
' #{node.resultVar}.push(#{node.expression.resultVar});',
' #block emit(node.expression)',
'}'
],
one_or_more: [
'#block emit(node.expression)',
'if (#{node.expression.resultVar} !== null) {',
' #{node.resultVar} = [];',
' while (#{node.expression.resultVar} !== null) {',
' #{node.resultVar}.push(#{node.expression.resultVar});',
' #block emit(node.expression)',
' }',
'} else {',
' #{node.resultVar} = null;',
'}'
],
action: [
'#{posSave(node)};',
'#block emit(node.expression)',
'if (#{node.resultVar} !== null) {',
' #{node.resultVar} = (function(#{(options.trackLineAndColumn ? ["offset", "line", "column"] : ["offset"]).concat(keys(node.params)).join(", ")}) {#{node.code}})(#{(options.trackLineAndColumn ? [node.posVar + ".offset", node.posVar + ".line", node.posVar + ".column"] : [node.posVar]).concat(values(node.params)).join(", ")});',
'}',
'if (#{node.resultVar} === null) {',
' #{posRestore(node)};',
'}'
],
rule_ref: [
'#{node.resultVar} = parse_#{node.name}();'
],
literal: [
'#if node.value.length === 0',
' #{node.resultVar} = "";',
'#else',
' #if !node.ignoreCase',
' #if node.value.length === 1',
' if (input.charCodeAt(#{posOffset("pos")}) === #{node.value.charCodeAt(0)}) {',
' #else',
' if (input.substr(#{posOffset("pos")}, #{node.value.length}) === #{string(node.value)}) {',
' #end',
' #else',
/*
* One-char literals are not optimized when case-insensitive
* matching is enabled. This is because there is no simple way to
* lowercase a character code that works for character outside ASCII
* letters. Moreover, |toLowerCase| can change string length,
* meaning the result of lowercasing a character can be more
* characters.
*/
' if (input.substr(#{posOffset("pos")}, #{node.value.length}).toLowerCase() === #{string(node.value.toLowerCase())}) {',
' #end',
' #if !node.ignoreCase',
' #{node.resultVar} = #{string(node.value)};',
' #else',
' #{node.resultVar} = input.substr(#{posOffset("pos")}, #{node.value.length});',
' #end',
' #{posAdvance(node.value.length)};',
' } else {',
' #{node.resultVar} = null;',
' if (reportFailures === 0) {',
' matchFailed(#{string(string(node.value))});',
' }',
' }',
'#end'
],
any: [
'if (input.length > #{posOffset("pos")}) {',
' #{node.resultVar} = input.charAt(#{posOffset("pos")});',
' #{posAdvance(1)};',
'} else {',
' #{node.resultVar} = null;',
' if (reportFailures === 0) {',
' matchFailed("any character");',
' }',
'}'
],
"class": [
'if (#{regexp}.test(input.charAt(#{posOffset("pos")}))) {',
' #{node.resultVar} = input.charAt(#{posOffset("pos")});',
' #{posAdvance(1)};',
'} else {',
' #{node.resultVar} = null;',
' if (reportFailures === 0) {',
' matchFailed(#{string(node.rawText)});',
' }',
'}'
]
};
for (name in sources) {
templates[name] = Codie.template(sources[name].join('\n'));
}
return templates;
})();
function fill(name, vars) {
vars.string = quote;
vars.pluck = pluck;
vars.keys = keys;
vars.values = values;
vars.emit = emit;
vars.options = options;
/* Position-handling macros */
if (options.trackLineAndColumn) {
vars.posInit = function(name) {
return "var "
+ name
+ " = "
+ "{ offset: 0, line: 1, column: 1, seenCR: false }";
};
vars.posClone = function(name) { return "clone(" + name + ")"; };
vars.posOffset = function(name) { return name + ".offset"; };
vars.posAdvance = function(n) { return "advance(pos, " + n + ")"; };
} else {
vars.posInit = function(name) { return "var " + name + " = 0"; };
vars.posClone = function(name) { return name; };
vars.posOffset = function(name) { return name; };
vars.posAdvance = function(n) {
return n === 1 ? "pos++" : "pos += " + n;
};
}
vars.posSave = function(node) {
return node.posVar + " = " + vars.posClone("pos");
};
vars.posRestore = function(node) {
return "pos" + " = " + vars.posClone(node.posVar);
};
return templates[name](vars);
}
function emitSimple(name) {
return function(node) { return fill(name, { node: node }); };
}
var emit = buildNodeVisitor({
grammar: emitSimple("grammar"),
initializer: function(node) { return node.code; },
rule: emitSimple("rule"),
/*
* The contract for all code fragments generated by the following functions
* is as follows.
*
* The code fragment tries to match a part of the input starting with the
* position indicated in |pos|. That position may point past the end of the
* input.
*
* * If the code fragment matches the input, it advances |pos| to point to
* the first chracter following the matched part of the input and sets
* variable with a name stored in |node.resultVar| to an appropriate
* value. This value is always non-|null|.
*
* * If the code fragment does not match the input, it returns with |pos|
* set to the original value and it sets a variable with a name stored in
* |node.resultVar| to |null|.
*
* The code can use variables with names stored in |resultVar| and |posVar|
* properties of the current node's subnodes. It can't use any other
* variables.
*/
choice: function(node) {
var code, nextAlternativesCode;
for (var i = node.alternatives.length - 1; i >= 0; i--) {
nextAlternativesCode = i !== node.alternatives.length - 1
? fill("choice.next", { node: node, code: code })
: '';
code = fill("choice", {
alternative: node.alternatives[i],
nextAlternativesCode: nextAlternativesCode
});
}
return code;
},
sequence: function(node) {
var code = fill("sequence.inner", { node: node });
for (var i = node.elements.length - 1; i >= 0; i--) {
code = fill("sequence.iteration", {
node: node,
element: node.elements[i],
code: code
});
}
return fill("sequence", { node: node, code: code });
},
labeled: function(node) { return emit(node.expression); },
simple_and: emitSimple("simple_and"),
simple_not: emitSimple("simple_not"),
semantic_and: emitSimple("semantic_and"),
semantic_not: emitSimple("semantic_not"),
optional: emitSimple("optional"),
zero_or_more: emitSimple("zero_or_more"),
one_or_more: emitSimple("one_or_more"),
action: emitSimple("action"),
rule_ref: emitSimple("rule_ref"),
literal: emitSimple("literal"),
any: emitSimple("any"),
"class": function(node) {
var regexp;
if (node.parts.length > 0) {
regexp = '/^['
+ (node.inverted ? '^' : '')
+ map(node.parts, function(part) {
return part instanceof Array
? quoteForRegexpClass(part[0])
+ '-'
+ quoteForRegexpClass(part[1])
: quoteForRegexpClass(part);
}).join('')
+ ']/' + (node.ignoreCase ? 'i' : '');
} else {
/*
* Stupid IE considers regexps /[]/ and /[^]/ syntactically invalid, so
* we translate them into euqivalents it can handle.
*/
regexp = node.inverted ? '/^[\\S\\s]/' : '/^(?!)/';
}
return fill("class", { node: node, regexp: regexp });
}
});
return emit(ast);
};
return PEG;
})();
if (typeof module !== "undefined") {
module.exports = PEG;
}