diff --git a/spec/compiler/passes/report-left-recursion.spec.js b/spec/compiler/passes/report-left-recursion.spec.js new file mode 100644 index 0000000..79c6dce --- /dev/null +++ b/spec/compiler/passes/report-left-recursion.spec.js @@ -0,0 +1,88 @@ +describe("compiler pass |reportLeftRecursion|", function() { + var pass = PEG.compiler.passes.reportLeftRecursion; + + beforeEach(function() { + this.addMatchers({ + toReportLeftRecursionIn: function(grammar) { + var ast = PEG.parser.parse(grammar); + + try { + this.actual(ast); + + this.message = function() { + return "Expected the pass to report left recursion for grammar " + + jasmine.pp(grammar) + ", " + + "but it didn't."; + }; + + return false; + } catch (e) { + if (this.isNot) { + this.message = function() { + return "Expected the pass not to report left recursion for grammar " + + jasmine.pp(grammar) + ", " + + "but it did."; + }; + } else { + this.message = function() { + return "Expected the pass to report left recursion for grammar " + + jasmine.pp(grammar) + ", " + + "but it reported an error with message " + + jasmine.pp(e.message) + "."; + }; + } + + return e.message === 'Left recursion detected for rule \"start\".'; + } + } + }); + }); + + it("reports left recursion inside a rule", function() { + expect(pass).toReportLeftRecursionIn('start = start'); + }); + + it("reports left recursion inside a choice", function() { + expect(pass).toReportLeftRecursionIn('start = start / "a" / "b"'); + expect(pass).toReportLeftRecursionIn('start = "a" / "b" / start'); + }); + + it("reports left recursion inside a sequence", function() { + expect(pass).toReportLeftRecursionIn('start = start "a" "b"'); + }); + + it("reports left recursion inside a labeled", function() { + expect(pass).toReportLeftRecursionIn('start = label:start'); + }); + + it("reports left recursion inside a simple and", function() { + expect(pass).toReportLeftRecursionIn('start = &start'); + }); + + it("reports left recursion inside a simple not", function() { + expect(pass).toReportLeftRecursionIn('start = &start'); + }); + + it("reports left recursion inside an optional", function() { + expect(pass).toReportLeftRecursionIn('start = start?'); + }); + + it("reports left recursion inside a zero or more", function() { + expect(pass).toReportLeftRecursionIn('start = start*'); + }); + + it("reports left recursion inside a one or more", function() { + expect(pass).toReportLeftRecursionIn('start = start+'); + }); + + it("reports left recursion inside an action", function() { + expect(pass).toReportLeftRecursionIn('start = start { }'); + }); + + it("reports indirect left recursion", function() { + expect(pass).toReportLeftRecursionIn([ + 'start = stop', + 'stop = start' + ].join("\n")); + }); +}); diff --git a/spec/index.html b/spec/index.html index 7b0679f..e5b200a 100644 --- a/spec/index.html +++ b/spec/index.html @@ -9,6 +9,7 @@ + - diff --git a/test/run b/test/run index 9121eae..43e4789 100755 --- a/test/run +++ b/test/run @@ -75,7 +75,6 @@ QUnit.done(function(details) { [ "helpers.js", - "compiler/passes/report-left-recursion-test.js", "compiler/passes/remove-proxy-rules-test.js", "compiler/passes/compute-var-names-test.js", "compiler/passes/compute-params-test.js"