From 1279e87766d7c91557bd4a4be97373998e86311a Mon Sep 17 00:00:00 2001 From: David Majda Date: Mon, 16 Aug 2010 21:20:37 +0200 Subject: [PATCH] Simplify utility functions structure + do not export them as part of the PEG object --- src/checks.js | 8 +-- src/emitter.js | 32 ++++----- src/parser.js | 128 ++++++++++++++++++------------------ src/parser.pegjs | 14 ++-- src/passes.js | 2 +- src/utils.js | 147 ++++++++++++++++++------------------------ test/compiler-test.js | 72 ++------------------- 7 files changed, 157 insertions(+), 246 deletions(-) diff --git a/src/checks.js b/src/checks.js index 96c4ad1..a07abe2 100644 --- a/src/checks.js +++ b/src/checks.js @@ -13,9 +13,7 @@ PEG.compiler.checks = [ function checkExpression(node) { check(node.expression); } function checkSubnodes(propertyName) { - return function(node) { - PEG.ArrayUtils.each(node[propertyName], check); - }; + return function(node) { each(node[propertyName], check); }; } var checkFunctions = { @@ -81,7 +79,7 @@ PEG.compiler.checks = [ choice: function(node, appliedRules) { - PEG.ArrayUtils.each(node.alternatives, function(alternative) { + each(node.alternatives, function(alternative) { check(alternative, appliedRules); }); }, @@ -105,7 +103,7 @@ PEG.compiler.checks = [ rule_ref: function(node, appliedRules) { - if (PEG.ArrayUtils.contains(appliedRules, node.name)) { + if (contains(appliedRules, node.name)) { throw new PEG.GrammarError( "Left recursion detected for rule \"" + node.name + "\"." ); diff --git a/src/emitter.js b/src/emitter.js index 8bc6ba0..cfe34f0 100644 --- a/src/emitter.js +++ b/src/emitter.js @@ -32,7 +32,7 @@ PEG.compiler.emitter = function(ast) { */ function formatCode() { function interpolateVariablesInParts(parts) { - return PEG.ArrayUtils.map(parts, function(part) { + return map(parts, function(part) { return part.replace( /\$\{([a-zA-Z_][a-zA-Z0-9_]*)(\|([a-zA-Z_][a-zA-Z0-9_]*))?\}/g, function(match, name, dummy, filter) { @@ -43,7 +43,7 @@ PEG.compiler.emitter = function(ast) { if (filter !== undefined && filter != "") { // JavaScript engines differ here. if (filter === "string") { - return PEG.StringUtils.quote(value); + return quote(value); } else { throw new Error("Unrecognized filter: \"" + filter + "\"."); } @@ -56,13 +56,13 @@ PEG.compiler.emitter = function(ast) { } function indentMultilineParts(parts) { - return PEG.ArrayUtils.map(parts, function(part) { + return map(parts, function(part) { if (!/\n/.test(part)) { return part; } var firstLineWhitespacePrefix = part.match(/^\s*/)[0]; var lines = part.split("\n"); var linesIndented = [lines[0]].concat( - PEG.ArrayUtils.map(lines.slice(1), function(line) { + map(lines.slice(1), function(line) { return firstLineWhitespacePrefix + line; }) ); @@ -118,8 +118,8 @@ PEG.compiler.emitter = function(ast) { " var rightmostMatchFailuresExpected = [];", " var cache = {};", " ", - /* This needs to be in sync with PEG.StringUtils.quote. */ - " function quoteString(s) {", + /* 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,", @@ -136,8 +136,8 @@ PEG.compiler.emitter = function(ast) { " + '\"';", " }", " ", - /* This needs to be in sync with PEG.ArrayUtils.contains. */ - " function arrayContains(array, value) {", + /* This needs to be in sync with |contains| in utils.js. */ + " function contains(array, value) {", " /*", " * Stupid IE does not have Array.prototype.indexOf, otherwise this", " * function would be a one-liner.", @@ -161,7 +161,7 @@ PEG.compiler.emitter = function(ast) { " rightmostMatchFailuresExpected = [];", " }", " ", - " if (!arrayContains(rightmostMatchFailuresExpected, failure)) {", + " if (!contains(rightmostMatchFailuresExpected, failure)) {", " rightmostMatchFailuresExpected.push(failure);", " }", " }", @@ -186,7 +186,7 @@ PEG.compiler.emitter = function(ast) { " var expected = buildExpected(rightmostMatchFailuresExpected);", " var actualPos = Math.max(pos, rightmostMatchFailuresPos);", " var actual = actualPos < input.length", - " ? quoteString(input.charAt(actualPos))", + " ? quote(input.charAt(actualPos))", " : 'end of input';", " ", " return 'Expected ' + expected + ' but ' + actual + ' found.';", @@ -404,7 +404,7 @@ PEG.compiler.emitter = function(ast) { sequence: function(node, resultVar) { var savedPosVar = UID.next("savedPos"); - var elementResultVars = PEG.ArrayUtils.map(node.elements, function() { + var elementResultVars = map(node.elements, function() { return UID.next("result") }); @@ -647,7 +647,7 @@ PEG.compiler.emitter = function(ast) { "} else {", " var ${resultVar} = null;", " if (context.reportMatchFailures) {", - " matchFailed(quoteString(${value|string}));", + " matchFailed(quote(${value|string}));", " }", "}", { @@ -677,12 +677,12 @@ PEG.compiler.emitter = function(ast) { if (node.parts.length > 0) { var regexp = "/^[" + (node.inverted ? "^" : "") - + PEG.ArrayUtils.map(node.parts, function(part) { + + map(node.parts, function(part) { return part instanceof Array - ? PEG.RegExpUtils.quoteForClass(part[0]) + ? quoteForRegexpClass(part[0]) + "-" - + PEG.RegExpUtils.quoteForClass(part[1]) - : PEG.RegExpUtils.quoteForClass(part); + + quoteForRegexpClass(part[1]) + : quoteForRegexpClass(part); }).join("") + "]/"; } else { diff --git a/src/parser.js b/src/parser.js index b5e7c1c..84f2042 100644 --- a/src/parser.js +++ b/src/parser.js @@ -14,7 +14,7 @@ PEG.parser = (function(){ var rightmostMatchFailuresExpected = []; var cache = {}; - function quoteString(s) { + 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, @@ -31,7 +31,7 @@ PEG.parser = (function(){ + '"'; } - function arrayContains(array, value) { + function contains(array, value) { /* * Stupid IE does not have Array.prototype.indexOf, otherwise this * function would be a one-liner. @@ -55,7 +55,7 @@ PEG.parser = (function(){ rightmostMatchFailuresExpected = []; } - if (!arrayContains(rightmostMatchFailuresExpected, failure)) { + if (!contains(rightmostMatchFailuresExpected, failure)) { rightmostMatchFailuresExpected.push(failure); } } @@ -102,7 +102,7 @@ PEG.parser = (function(){ var result0 = result1 !== null ? (function(initializer, rules) { var rulesConverted = {}; - PEG.ArrayUtils.each(rules, function(rule) { rulesConverted[rule.name] = rule; }); + each(rules, function(rule) { rulesConverted[rule.name] = rule; }); return { type: "grammar", @@ -186,7 +186,7 @@ PEG.parser = (function(){ } else { var result8 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("")); + matchFailed(quote("")); } } if (result8 !== null) { @@ -301,7 +301,7 @@ PEG.parser = (function(){ var result0 = result1 !== null ? (function(head, tail) { if (tail.length > 0) { - var alternatives = [head].concat(PEG.ArrayUtils.map( + var alternatives = [head].concat(map( tail, function(element) { return element[1]; } )); @@ -718,7 +718,7 @@ PEG.parser = (function(){ } else { var result18 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("")); + matchFailed(quote("")); } } if (result18 !== null) { @@ -887,7 +887,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("{")); + matchFailed(quote("{")); } } if (result2 !== null) { @@ -924,7 +924,7 @@ PEG.parser = (function(){ } else { var result4 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("}")); + matchFailed(quote("}")); } } if (result4 !== null) { @@ -1032,7 +1032,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("=")); + matchFailed(quote("=")); } } if (result2 !== null) { @@ -1076,7 +1076,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString(":")); + matchFailed(quote(":")); } } if (result2 !== null) { @@ -1120,7 +1120,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString(";")); + matchFailed(quote(";")); } } if (result2 !== null) { @@ -1164,7 +1164,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("/")); + matchFailed(quote("/")); } } if (result2 !== null) { @@ -1208,7 +1208,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("&")); + matchFailed(quote("&")); } } if (result2 !== null) { @@ -1252,7 +1252,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("!")); + matchFailed(quote("!")); } } if (result2 !== null) { @@ -1296,7 +1296,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("?")); + matchFailed(quote("?")); } } if (result2 !== null) { @@ -1340,7 +1340,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("*")); + matchFailed(quote("*")); } } if (result2 !== null) { @@ -1384,7 +1384,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("+")); + matchFailed(quote("+")); } } if (result2 !== null) { @@ -1428,7 +1428,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("(")); + matchFailed(quote("(")); } } if (result2 !== null) { @@ -1472,7 +1472,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString(")")); + matchFailed(quote(")")); } } if (result2 !== null) { @@ -1516,7 +1516,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString(".")); + matchFailed(quote(".")); } } if (result2 !== null) { @@ -1565,7 +1565,7 @@ PEG.parser = (function(){ } else { var result11 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("_")); + matchFailed(quote("_")); } } if (result11 !== null) { @@ -1577,7 +1577,7 @@ PEG.parser = (function(){ } else { var result10 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("$")); + matchFailed(quote("$")); } } if (result10 !== null) { @@ -1603,7 +1603,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("_")); + matchFailed(quote("_")); } } if (result7 !== null) { @@ -1615,7 +1615,7 @@ PEG.parser = (function(){ } else { var result6 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("$")); + matchFailed(quote("$")); } } if (result6 !== null) { @@ -1642,7 +1642,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("_")); + matchFailed(quote("_")); } } if (result7 !== null) { @@ -1654,7 +1654,7 @@ PEG.parser = (function(){ } else { var result6 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("$")); + matchFailed(quote("$")); } } if (result6 !== null) { @@ -1764,7 +1764,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\"")); + matchFailed(quote("\"")); } } if (result2 !== null) { @@ -1781,7 +1781,7 @@ PEG.parser = (function(){ } else { var result4 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\"")); + matchFailed(quote("\"")); } } if (result4 !== null) { @@ -1880,7 +1880,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\"")); + matchFailed(quote("\"")); } } if (result7 !== null) { @@ -1892,7 +1892,7 @@ PEG.parser = (function(){ } else { var result6 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\")); + matchFailed(quote("\\")); } } if (result6 !== null) { @@ -1962,7 +1962,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("'")); + matchFailed(quote("'")); } } if (result2 !== null) { @@ -1979,7 +1979,7 @@ PEG.parser = (function(){ } else { var result4 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("'")); + matchFailed(quote("'")); } } if (result4 !== null) { @@ -2078,7 +2078,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("'")); + matchFailed(quote("'")); } } if (result7 !== null) { @@ -2090,7 +2090,7 @@ PEG.parser = (function(){ } else { var result6 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\")); + matchFailed(quote("\\")); } } if (result6 !== null) { @@ -2161,7 +2161,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("[")); + matchFailed(quote("[")); } } if (result2 !== null) { @@ -2171,7 +2171,7 @@ PEG.parser = (function(){ } else { var result10 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("^")); + matchFailed(quote("^")); } } var result3 = result10 !== null ? result10 : ''; @@ -2209,7 +2209,7 @@ PEG.parser = (function(){ } else { var result5 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("]")); + matchFailed(quote("]")); } } if (result5 !== null) { @@ -2238,14 +2238,10 @@ PEG.parser = (function(){ } var result0 = result1 !== null ? (function(inverted, parts) { - partsConverted = PEG.ArrayUtils.map(parts, function(part) { - return part.data; - }); + partsConverted = map(parts, function(part) { return part.data; }); rawText = "[" + inverted - + PEG.ArrayUtils.map(parts, function(part) { - return part.rawText; - }).join("") + + map(parts, function(part) { return part.rawText; }).join("") + "]"; return { @@ -2287,7 +2283,7 @@ PEG.parser = (function(){ } else { var result3 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("-")); + matchFailed(quote("-")); } } if (result3 !== null) { @@ -2346,7 +2342,7 @@ PEG.parser = (function(){ return { data: char_, // FIXME: Get the raw text from the input directly. - rawText: PEG.RegExpUtils.quoteForClass(char_) + rawText: quoteForRegexpClass(char_) }; })(result1) : null; @@ -2429,7 +2425,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("]")); + matchFailed(quote("]")); } } if (result7 !== null) { @@ -2441,7 +2437,7 @@ PEG.parser = (function(){ } else { var result6 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\")); + matchFailed(quote("\\")); } } if (result6 !== null) { @@ -2511,7 +2507,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\")); + matchFailed(quote("\\")); } } if (result2 !== null) { @@ -2528,7 +2524,7 @@ PEG.parser = (function(){ } else { var result8 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("x")); + matchFailed(quote("x")); } } if (result8 !== null) { @@ -2540,7 +2536,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("u")); + matchFailed(quote("u")); } } if (result7 !== null) { @@ -2623,7 +2619,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\0")); + matchFailed(quote("\\0")); } } if (result2 !== null) { @@ -2677,7 +2673,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\x")); + matchFailed(quote("\\x")); } } if (result2 !== null) { @@ -2729,7 +2725,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\u")); + matchFailed(quote("\\u")); } } if (result2 !== null) { @@ -2793,7 +2789,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\\")); + matchFailed(quote("\\")); } } if (result2 !== null) { @@ -3067,7 +3063,7 @@ PEG.parser = (function(){ } else { var result1 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("//")); + matchFailed(quote("//")); } } if (result1 !== null) { @@ -3175,7 +3171,7 @@ PEG.parser = (function(){ } else { var result1 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("/*")); + matchFailed(quote("/*")); } } if (result1 !== null) { @@ -3190,7 +3186,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("*/")); + matchFailed(quote("*/")); } } context.reportMatchFailures = savedReportMatchFailuresVar0; @@ -3232,7 +3228,7 @@ PEG.parser = (function(){ } else { var result7 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("*/")); + matchFailed(quote("*/")); } } context.reportMatchFailures = savedReportMatchFailuresVar0; @@ -3270,7 +3266,7 @@ PEG.parser = (function(){ } else { var result3 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("*/")); + matchFailed(quote("*/")); } } if (result3 !== null) { @@ -3313,7 +3309,7 @@ PEG.parser = (function(){ } else { var result5 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\n")); + matchFailed(quote("\n")); } } if (result5 !== null) { @@ -3325,7 +3321,7 @@ PEG.parser = (function(){ } else { var result4 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\r\n")); + matchFailed(quote("\r\n")); } } if (result4 !== null) { @@ -3337,7 +3333,7 @@ PEG.parser = (function(){ } else { var result3 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\r")); + matchFailed(quote("\r")); } } if (result3 !== null) { @@ -3349,7 +3345,7 @@ PEG.parser = (function(){ } else { var result2 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\u2028")); + matchFailed(quote("\u2028")); } } if (result2 !== null) { @@ -3361,7 +3357,7 @@ PEG.parser = (function(){ } else { var result1 = null; if (context.reportMatchFailures) { - matchFailed(quoteString("\u2029")); + matchFailed(quote("\u2029")); } } if (result1 !== null) { @@ -3462,7 +3458,7 @@ PEG.parser = (function(){ var expected = buildExpected(rightmostMatchFailuresExpected); var actualPos = Math.max(pos, rightmostMatchFailuresPos); var actual = actualPos < input.length - ? quoteString(input.charAt(actualPos)) + ? quote(input.charAt(actualPos)) : 'end of input'; return 'Expected ' + expected + ' but ' + actual + ' found.'; diff --git a/src/parser.pegjs b/src/parser.pegjs index 2f6cbf8..2c4ea12 100644 --- a/src/parser.pegjs +++ b/src/parser.pegjs @@ -1,7 +1,7 @@ grammar = __ initializer:initializer? rules:rule+ { var rulesConverted = {}; - PEG.ArrayUtils.each(rules, function(rule) { rulesConverted[rule.name] = rule; }); + each(rules, function(rule) { rulesConverted[rule.name] = rule; }); return { type: "grammar", @@ -35,7 +35,7 @@ expression choice = head:sequence tail:(slash sequence)* { if (tail.length > 0) { - var alternatives = [head].concat(PEG.ArrayUtils.map( + var alternatives = [head].concat(map( tail, function(element) { return element[1]; } )); @@ -232,14 +232,10 @@ simpleSingleQuotedCharacter class "character class" = "[" inverted:"^"? parts:(classCharacterRange / classCharacter)* "]" __ { - partsConverted = PEG.ArrayUtils.map(parts, function(part) { - return part.data; - }); + partsConverted = map(parts, function(part) { return part.data; }); rawText = "[" + inverted - + PEG.ArrayUtils.map(parts, function(part) { - return part.rawText; - }).join("") + + map(parts, function(part) { return part.rawText; }).join("") + "]"; return { @@ -271,7 +267,7 @@ classCharacter return { data: char_, // FIXME: Get the raw text from the input directly. - rawText: PEG.RegExpUtils.quoteForClass(char_) + rawText: quoteForRegexpClass(char_) }; } diff --git a/src/passes.js b/src/passes.js index 8a8b53b..ff5efc0 100644 --- a/src/passes.js +++ b/src/passes.js @@ -22,7 +22,7 @@ PEG.compiler.passes = [ function replaceInSubnodes(propertyName) { return function(node, from, to) { - PEG.ArrayUtils.each(node[propertyName], function(node) { + each(node[propertyName], function(node) { replace(node, from, to); }); }; diff --git a/src/utils.js b/src/utils.js index 001437e..9c80d82 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,94 +1,75 @@ -/* ===== PEG.ArrayUtils ===== */ - -/* Array manipulation utility functions. */ - -PEG.ArrayUtils = { +/* + * The code needs to be in sync with the code template in the compilation + * function for "action" nodes. + */ +function contains(array, value) { /* - * The code needs to be in sync with the code template in the compilation - * function for "action" nodes. + * Stupid IE does not have Array.prototype.indexOf, otherwise this function + * would be a one-liner. */ - contains: function(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; - } + var length = array.length; + for (var i = 0; i < length; i++) { + if (array[i] === value) { + return true; } - return false; - }, - - each: function(array, callback) { - var length = array.length; - for (var i = 0; i < length; i++) { - callback(array[i]); - } - }, - - map: function(array, callback) { - var result = []; - var length = array.length; - for (var i = 0; i < length; i++) { - result[i] = callback(array[i]); - } - return result; } -}; - -/* ===== PEG.StringUtils ===== */ - -/* String manipulation utility functions. */ + return false; +} -PEG.StringUtils = { - /* - * 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 th code template in the compilation - * function for "action" nodes. - */ - quote: function(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. - */ - return '"' + s - .replace(/\\/g, '\\\\') // backslash - .replace(/"/g, '\\"') // closing quote character - .replace(/\r/g, '\\r') // carriage return - .replace(/\u2028/g, '\\u2028') // line separator - .replace(/\u2029/g, '\\u2029') // paragraph separator - .replace(/\n/g, '\\n') // line feed - + '"'; +function each(array, callback) { + var length = array.length; + for (var i = 0; i < length; i++) { + callback(array[i]); } +} -}; - -/* ===== PEG.RegExpUtils ===== */ - -/* RegExp manipulation utility functions. */ +function map(array, callback) { + var result = []; + var length = array.length; + for (var i = 0; i < length; i++) { + result[i] = callback(array[i]); + } + return result; +} -PEG.RegExpUtils = { +/* + * 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 th code template in the compilation + * function for "action" nodes. + */ +function quote(s) { /* - * Escapes characters inside the string so that it can be used as a list of - * characters in a character class of a regular expression. + * 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. */ - quoteForClass: function(s) { - /* Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1. */ - return s - .replace(/\\/g, '\\\\') // backslash - .replace(/\0/g, '\\0') // null, IE needs this - .replace(/\//g, '\\/') // closing slash - .replace(/]/g, '\\]') // closing bracket - .replace(/-/g, '\\-') // dash - .replace(/\r/g, '\\r') // carriage return - .replace(/\u2028/g, '\\u2028') // line separator - .replace(/\u2029/g, '\\u2029') // paragraph separator - .replace(/\n/g, '\\n') // line feed - } + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\r/g, '\\r') // carriage return + .replace(/\u2028/g, '\\u2028') // line separator + .replace(/\u2029/g, '\\u2029') // paragraph separator + .replace(/\n/g, '\\n') // line feed + + '"'; }; + +/* + * 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. */ + return s + .replace(/\\/g, '\\\\') // backslash + .replace(/\0/g, '\\0') // null, IE needs this + .replace(/\//g, '\\/') // closing slash + .replace(/]/g, '\\]') // closing bracket + .replace(/-/g, '\\-') // dash + .replace(/\r/g, '\\r') // carriage return + .replace(/\u2028/g, '\\u2028') // line separator + .replace(/\u2029/g, '\\u2029') // paragraph separator + .replace(/\n/g, '\\n') // line feed +} diff --git a/test/compiler-test.js b/test/compiler-test.js index e63dfe5..09cffc2 100644 --- a/test/compiler-test.js +++ b/test/compiler-test.js @@ -57,66 +57,6 @@ global.doesNotParseWithPos = function(parser, input, line, column) { ); }; -/* ===== PEG.ArrayUtils ===== */ - -module("PEG.ArrayUtils"); - -test("contains", function() { - ok(!PEG.ArrayUtils.contains([], 42)); - - ok(PEG.ArrayUtils.contains([1, 2, 3], 1)); - ok(PEG.ArrayUtils.contains([1, 2, 3], 2)); - ok(PEG.ArrayUtils.contains([1, 2, 3], 3)); - ok(!PEG.ArrayUtils.contains([1, 2, 3], 42)); - ok(!PEG.ArrayUtils.contains([1, 2, 3], "2")); // Does it use |===|? -}); - -test("each", function() { - var sum; - function increment(x) { sum += x; } - - sum = 0; - PEG.ArrayUtils.each([], increment); - strictEqual(sum, 0); - - sum = 0; - PEG.ArrayUtils.each([1, 2, 3], increment); - strictEqual(sum, 6); -}); - -test("map", function() { - function square(x) { return x * x; } - - deepEqual(PEG.ArrayUtils.map([], square), []); - deepEqual(PEG.ArrayUtils.map([1, 2, 3], square), [1, 4, 9]); -}); - -/* ===== PEG.StringUtils ===== */ - -module("PEG.StringUtils"); - -test("quote", function() { - strictEqual(PEG.StringUtils.quote(""), '""'); - strictEqual(PEG.StringUtils.quote("abcd"), '"abcd"'); - strictEqual( - PEG.StringUtils.quote("\"\\\r\u2028\u2029\n\"\\\r\u2028\u2029\n"), - '"\\\"\\\\\\r\\u2028\\u2029\\n\\\"\\\\\\r\\u2028\\u2029\\n"' - ); -}); - -/* ===== PEG.RegExpUtils ===== */ - -module("PEG.RegExpUtils"); - -test("quoteForClass", function() { - strictEqual(PEG.RegExpUtils.quoteForClass(""), ''); - strictEqual(PEG.RegExpUtils.quoteForClass("abcd"), 'abcd'); - strictEqual( - PEG.RegExpUtils.quoteForClass("\\\0/]-\r\u2028\u2029\n\\\0/]-\r\u2028\u2029\n"), - '\\\\\\0\\/\\]\\-\\r\\u2028\\u2029\\n\\\\\\0\\/\\]\\-\\r\\u2028\\u2029\\n' - ); -}); - /* ===== PEG ===== */ module("PEG"); @@ -144,13 +84,13 @@ test("buildParser reports missing referenced rules", function() { 'start = missing { }' ]; - PEG.ArrayUtils.each(grammars, function(grammar) { + for (var i = 0; i < grammars.length; i++) { throws( - function() { PEG.buildParser(grammar); }, + function() { PEG.buildParser(grammars[i]); }, PEG.GrammarError, { message: "Referenced rule \"missing\" does not exist." } ); - }); + } }); test("buildParser reports left recursion", function() { @@ -172,13 +112,13 @@ test("buildParser reports left recursion", function() { 'start = stop; stop = start' ]; - PEG.ArrayUtils.each(grammars, function(grammar) { + for (var i = 0; i < grammars.length; i++) { throws( - function() { PEG.buildParser(grammar); }, + function() { PEG.buildParser(grammars[i]); }, PEG.GrammarError, { message: "Left recursion detected for rule \"start\"." } ); - }); + } }); test("buildParser allows custom start rule", function() {