bdf91b5941
This is purely a mechanical change, not taking advantage of block scope of "let" and "const". Minimizing variable scope will come in the next commit. In general, "var" is converted into "let" and "const" is used only for immutable variables of permanent character (generally spelled in ALL_CAPS). Using it for any immutable variable regardless on its permanence would feel confusing. Any code which is not transpiled and needs to run in ES6 environment (examples, code in grammars embedded in specs, ...) is kept unchanged. This is also true for code generated by PEG.js. See #442.
116 lines
4 KiB
JavaScript
116 lines
4 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: 21, line: 2, column: 9 },
|
|
end: { offset: 26, line: 2, column: 14 }
|
|
}
|
|
});
|
|
});
|
|
|
|
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');
|
|
});
|
|
});
|
|
});
|