2015-06-08 20:21:19 +02:00
|
|
|
"use strict";
|
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
let chai = require("chai");
|
|
|
|
let helpers = require("./helpers");
|
2016-12-16 13:21:48 +01:00
|
|
|
let pass = require("../../../../lib/compiler/passes/report-infinite-recursion");
|
2016-09-08 13:29:06 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
chai.use(helpers);
|
|
|
|
|
|
|
|
let expect = chai.expect;
|
|
|
|
|
2016-07-29 18:06:16 +02:00
|
|
|
describe("compiler pass |reportInfiniteRecursion|", function() {
|
2014-06-07 09:11:00 +02:00
|
|
|
it("reports direct left recursion", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = start", {
|
2016-09-22 05:25:09 +02:00
|
|
|
message: "Possible infinite loop when parsing (left recursion: start -> start).",
|
2015-04-06 10:34:07 +02:00
|
|
|
location: {
|
2016-09-22 05:25:09 +02:00
|
|
|
start: { offset: 8, line: 1, column: 9 },
|
|
|
|
end: { offset: 13, line: 1, column: 14 }
|
2015-04-06 10:34:07 +02:00
|
|
|
}
|
2012-04-30 13:42:13 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("reports indirect left recursion", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError([
|
2016-09-21 15:06:56 +02:00
|
|
|
"start = stop",
|
2016-09-22 09:25:31 +02:00
|
|
|
"stop = start"
|
2014-06-07 09:11:00 +02:00
|
|
|
].join("\n"), {
|
2016-09-22 05:25:09 +02:00
|
|
|
message: "Possible infinite loop when parsing (left recursion: start -> stop -> start).",
|
2015-04-06 10:34:07 +02:00
|
|
|
location: {
|
2016-09-22 09:25:31 +02:00
|
|
|
start: { offset: 20, line: 2, column: 8 },
|
|
|
|
end: { offset: 25, line: 2, column: 13 }
|
2015-04-06 10:34:07 +02:00
|
|
|
}
|
2014-06-07 09:11:00 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("in sequences", function() {
|
2015-03-31 19:02:59 +02:00
|
|
|
it("reports left recursion if all preceding elements match empty string", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = '' '' '' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("doesn't report left recursion if some preceding element doesn't match empty string", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.not.reportError("start = 'a' '' '' start");
|
|
|
|
expect(pass).to.not.reportError("start = '' 'a' '' start");
|
|
|
|
expect(pass).to.not.reportError("start = '' '' 'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
});
|
|
|
|
|
2016-09-17 16:28:28 +02:00
|
|
|
// Regression test for #359.
|
2015-08-17 10:58:37 +02:00
|
|
|
it("reports left recursion when rule reference is wrapped in an expression", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = '' start?");
|
2015-08-17 10:58:37 +02:00
|
|
|
});
|
|
|
|
|
2015-09-04 17:35:37 +02:00
|
|
|
it("computes expressions that always consume input on success correctly", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError([
|
2016-09-21 15:06:56 +02:00
|
|
|
"start = a start",
|
|
|
|
"a 'a' = ''"
|
|
|
|
].join("\n"));
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.not.reportError([
|
2016-09-21 15:06:56 +02:00
|
|
|
"start = a start",
|
|
|
|
"a 'a' = 'a'"
|
|
|
|
].join("\n"));
|
2015-08-03 16:56:57 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ('' / 'a' / 'b') start");
|
|
|
|
expect(pass).to.reportError("start = ('a' / '' / 'b') start");
|
|
|
|
expect(pass).to.reportError("start = ('a' / 'b' / '') start");
|
|
|
|
expect(pass).to.not.reportError("start = ('a' / 'b' / 'c') start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ('' { }) start");
|
|
|
|
expect(pass).to.not.reportError("start = ('a' { }) start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ('' '' '') start");
|
|
|
|
expect(pass).to.not.reportError("start = ('a' '' '') start");
|
|
|
|
expect(pass).to.not.reportError("start = ('' 'a' '') start");
|
|
|
|
expect(pass).to.not.reportError("start = ('' '' 'a') start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = a:'' start");
|
|
|
|
expect(pass).to.not.reportError("start = a:'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = $'' start");
|
|
|
|
expect(pass).to.not.reportError("start = $'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = &'' start");
|
|
|
|
expect(pass).to.reportError("start = &'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = !'' start");
|
|
|
|
expect(pass).to.reportError("start = !'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ''? start");
|
|
|
|
expect(pass).to.reportError("start = 'a'? start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ''* start");
|
|
|
|
expect(pass).to.reportError("start = 'a'* start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ''+ start");
|
|
|
|
expect(pass).to.not.reportError("start = 'a'+ start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = ('') start");
|
|
|
|
expect(pass).to.not.reportError("start = ('a') start");
|
2016-03-11 16:18:29 +01:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = &{ } start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = !{ } start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError([
|
2016-09-21 15:06:56 +02:00
|
|
|
"start = a start",
|
|
|
|
"a = ''"
|
|
|
|
].join("\n"));
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.not.reportError([
|
2016-09-21 15:06:56 +02:00
|
|
|
"start = a start",
|
|
|
|
"a = 'a'"
|
|
|
|
].join("\n"));
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.reportError("start = '' start");
|
|
|
|
expect(pass).to.not.reportError("start = 'a' start");
|
2015-03-31 19:02:59 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.not.reportError("start = [a-d] start");
|
2014-06-07 09:11:00 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(pass).to.not.reportError("start = . start");
|
2014-06-07 09:11:00 +02:00
|
|
|
});
|
2012-04-30 13:42:13 +02:00
|
|
|
});
|
|
|
|
});
|