From 11166911dc8a801aef43cfaa360fbeabaa0a9bde Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Tue, 19 Jun 2012 11:18:51 -0500 Subject: [PATCH 1/2] Recognise that PEG.js-generated parsers are in fact generated --- lib/linguist/blob_helper.rb | 36 +- test/fixtures/javascript/parser.js | 2963 ++++++++++++++++++++++++++++ test/test_blob.rb | 8 +- 3 files changed, 2996 insertions(+), 11 deletions(-) create mode 100644 test/fixtures/javascript/parser.js diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 29c9bdcf..0cee4d20 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -255,17 +255,16 @@ module Linguist # Includes: # - XCode project XML files # - Minified JavaScript + # - Compiled CoffeeScript + # - PEG.js-generated parsers # # Please add additional test coverage to # `test/test_blob.rb#test_generated` if you make any changes. # # Return true or false def generated? - if xcode_project_file? || generated_net_docfile? - true - elsif generated_coffeescript? || minified_javascript? - true - elsif name == 'Gemfile.lock' + if name == 'Gemfile.lock' || minified_javascript? || compiled_coffeescript? || + xcode_project_file? || generated_net_docfile? || generated_parser? true else false @@ -293,17 +292,36 @@ module Linguist average_line_length > 100 end - # Internal: Is the blob JS generated by CoffeeScript? + # Internal: Is the blob of JS a parser generated by PEG.js? + # + # Requires Blob#data + # + # PEG.js-generated parsers are not meant to be consumed by humans. + # + # Return true or false + def generated_parser? + return false unless extname == '.js' + + # PEG.js-generated parsers include a comment near the top of the file + # that marks them as such. + if lines[0..4].join('') =~ /^(?:[^\/]|\/[^\*])*\/\*(?:[^\*]|\*[^\/])*Generated by PEG.js/ + return true + end + + false + end + + # Internal: Is the blob of JS generated by CoffeeScript? # # Requires Blob#data # # CoffeScript is meant to output JS that would be difficult to # tell if it was generated or not. Look for a number of patterns - # outputed by the CS compiler. + # output by the CS compiler. # # Return true or false - def generated_coffeescript? - return unless extname == '.js' + def compiled_coffeescript? + return false unless extname == '.js' # CoffeeScript generated by > 1.2 include a comment on the first line if lines[0] =~ /^\/\/ Generated by / diff --git a/test/fixtures/javascript/parser.js b/test/fixtures/javascript/parser.js new file mode 100644 index 00000000..d6950361 --- /dev/null +++ b/test/fixtures/javascript/parser.js @@ -0,0 +1,2963 @@ +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_nonBraceCharacters(); + } + while (result2 !== null) { + result1.push(result2); + result2 = parse_braced(); + if (result2 === null) { + result2 = parse_nonBraceCharacters(); + } + } + 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", + parts: partsConverted, + // FIXME: Get the raw text from the input directly. + rawText: rawText, + inverted: inverted === "^", + ignoreCase: flags === "i" + }; + })(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; +})(); diff --git a/test/test_blob.rb b/test/test_blob.rb index 1d17e60d..8d46da91 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -183,9 +183,13 @@ class TestBlob < Test::Unit::TestCase assert blob("javascript/jquery-1.6.1.min.js").generated? assert blob("javascript/jquery-1.4.2.min.js").generated? - # CoffeScript JS + # CoffeeScript-generated JS + # TODO - # These examples are to basic to tell + # PEG.js-generated parsers + assert blob("javascript/parser.js").generated? + + # These examples are too basic to tell assert !blob("javascript/empty.js").generated? assert !blob("javascript/hello.js").generated? From 93d0611b4e9f5430ea6828d1e6912d42944e5617 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Tue, 19 Jun 2012 11:30:39 -0500 Subject: [PATCH 2/2] accidental hard tabs --- test/test_blob.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_blob.rb b/test/test_blob.rb index 8d46da91..483a03a0 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -184,10 +184,10 @@ class TestBlob < Test::Unit::TestCase assert blob("javascript/jquery-1.4.2.min.js").generated? # CoffeeScript-generated JS - # TODO + # TODO - # PEG.js-generated parsers - assert blob("javascript/parser.js").generated? + # PEG.js-generated parsers + assert blob("javascript/parser.js").generated? # These examples are too basic to tell assert !blob("javascript/empty.js").generated?