/* * 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; }