diff --git a/lib/compiler.js b/lib/compiler.js index 84865b0..678fd3c 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -56,6 +56,24 @@ PEG.buildParser = function(grammar, startRule) { /* Array manipulation utility functions. */ PEG.ArrayUtils = { + /* + * The code needs to be in sync with a code template in + * PEG.Grammar.Action.prototype.compile. + */ + 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; + } + } + return false; + }, + each: function(array, callback) { var length = array.length; for (var i = 0; i < length; i++) { @@ -289,7 +307,7 @@ PEG.Grammar.extendNodes("checkNoLeftRecursion", { RuleRef: function(grammar, appliedRules) { - if (appliedRules.indexOf(this._name) !== -1) { + if (PEG.ArrayUtils.contains(appliedRules, this._name)) { throw new PEG.Grammar.GrammarError("Left recursion detected for rule \"" + this._name + "\"."); } grammar[this._name].checkNoLeftRecursion(grammar, appliedRules); @@ -443,13 +461,28 @@ PEG.Compiler = { " + '\"';", " },", " ", + /* This needs to be in sync with PEG.ArrayUtils.contains. */ + " _arrayContains: 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;", + " }", + " }", + " return false;", + " },", + " ", " _matchFailed: function(failure) {", " if (this._pos > this._rightmostMatchFailuresPos) {", " this._rightmostMatchFailuresPos = this._pos;", " this._rightmostMatchFailuresExpected = [];", " }", " ", - " if (this._rightmostMatchFailuresExpected.indexOf(failure) === -1) {", + " if (!this._arrayContains(this._rightmostMatchFailuresExpected, failure)) {", " this._rightmostMatchFailuresExpected.push(failure);", " }", " },", diff --git a/lib/metagrammar.js b/lib/metagrammar.js index 4a2a051..53f9095 100644 --- a/lib/metagrammar.js +++ b/lib/metagrammar.js @@ -19,13 +19,27 @@ PEG.grammarParser = (function(){ + '"'; }, + _arrayContains: 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; + } + } + return false; + }, + _matchFailed: function(failure) { if (this._pos > this._rightmostMatchFailuresPos) { this._rightmostMatchFailuresPos = this._pos; this._rightmostMatchFailuresExpected = []; } - if (this._rightmostMatchFailuresExpected.indexOf(failure) === -1) { + if (!this._arrayContains(this._rightmostMatchFailuresExpected, failure)) { this._rightmostMatchFailuresExpected.push(failure); } }, diff --git a/test/compiler-test.js b/test/compiler-test.js index c4c9b7f..cd7fbd7 100644 --- a/test/compiler-test.js +++ b/test/compiler-test.js @@ -61,6 +61,16 @@ global.doesNotParseWithPos = function(parser, input, line, column) { 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; }