You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pegjs/spec/unit/compiler/passes/report-infinite-recursion.s...

116 lines
4.0 KiB
JavaScript

"use strict";
let peg = require("../../../../lib/peg");
describe("compiler pass |reportInfiniteRecursion|", function() {
let pass = peg.compiler.passes.check.reportInfiniteRecursion;
it("reports direct left recursion", function() {
expect(pass).toReportError("start = start", {
message: "Possible infinite loop when parsing (left recursion: start -> start).",
location: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 13, line: 1, column: 14 }
}
});
});
it("reports indirect left recursion", function() {
expect(pass).toReportError([
"start = stop",
"stop = start"
].join("\n"), {
message: "Possible infinite loop when parsing (left recursion: start -> stop -> start).",
location: {
start: { offset: 20, line: 2, column: 8 },
end: { offset: 25, line: 2, column: 13 }
}
});
});
describe("in sequences", function() {
it("reports left recursion if all preceding elements match empty string", function() {
expect(pass).toReportError("start = '' '' '' start");
});
it("doesn't report left recursion if some preceding element doesn't match empty string", function() {
expect(pass).not.toReportError("start = 'a' '' '' start");
expect(pass).not.toReportError("start = '' 'a' '' start");
expect(pass).not.toReportError("start = '' '' 'a' start");
});
// Regression test for #359.
it("reports left recursion when rule reference is wrapped in an expression", function() {
expect(pass).toReportError("start = '' start?");
});
it("computes expressions that always consume input on success correctly", function() {
expect(pass).toReportError([
"start = a start",
"a 'a' = ''"
].join("\n"));
expect(pass).not.toReportError([
"start = a start",
"a 'a' = 'a'"
].join("\n"));
expect(pass).toReportError("start = ('' / 'a' / 'b') start");
expect(pass).toReportError("start = ('a' / '' / 'b') start");
expect(pass).toReportError("start = ('a' / 'b' / '') start");
expect(pass).not.toReportError("start = ('a' / 'b' / 'c') start");
expect(pass).toReportError("start = ('' { }) start");
expect(pass).not.toReportError("start = ('a' { }) start");
expect(pass).toReportError("start = ('' '' '') start");
expect(pass).not.toReportError("start = ('a' '' '') start");
expect(pass).not.toReportError("start = ('' 'a' '') start");
expect(pass).not.toReportError("start = ('' '' 'a') start");
expect(pass).toReportError("start = a:'' start");
expect(pass).not.toReportError("start = a:'a' start");
expect(pass).toReportError("start = $'' start");
expect(pass).not.toReportError("start = $'a' start");
expect(pass).toReportError("start = &'' start");
expect(pass).toReportError("start = &'a' start");
expect(pass).toReportError("start = !'' start");
expect(pass).toReportError("start = !'a' start");
expect(pass).toReportError("start = ''? start");
expect(pass).toReportError("start = 'a'? start");
expect(pass).toReportError("start = ''* start");
expect(pass).toReportError("start = 'a'* start");
expect(pass).toReportError("start = ''+ start");
expect(pass).not.toReportError("start = 'a'+ start");
expect(pass).toReportError("start = ('') start");
expect(pass).not.toReportError("start = ('a') start");
expect(pass).toReportError("start = &{ } start");
expect(pass).toReportError("start = !{ } start");
expect(pass).toReportError([
"start = a start",
"a = ''"
].join("\n"));
expect(pass).not.toReportError([
"start = a start",
"a = 'a'"
].join("\n"));
expect(pass).toReportError("start = '' start");
expect(pass).not.toReportError("start = 'a' start");
expect(pass).not.toReportError("start = [a-d] start");
expect(pass).not.toReportError("start = . start");
});
});
});