pegjs/spec/unit/compiler/passes/report-infinite-loops.spec.js
David Majda 0c39f1cf86 Fix labels leaking to outer scope
Labels in expressions like "(a:"a")" or "(a:"a" b:"b" c:"c")" were
visible to the outside despite being wrapped in parens. This commit
makes them invisible, as they should be.

Note this required introduction of a new "group" AST node, whose purpose
is purely to provide label scope isolation. This was necessary because
"label" and "sequence" nodes don't (and can't!) provide this isolation
themselves.

Part of a fix of #396.
2016-03-11 16:42:03 +01:00

96 lines
2.9 KiB
JavaScript

/* global PEG */
"use strict";
describe("compiler pass |reportInfiniteLoops|", function() {
var pass = PEG.compiler.passes.check.reportInfiniteLoops;
it("reports infinite loops for zero_or_more", function() {
expect(pass).toReportError('start = ("")*', {
message: "Possible infinite loop detected.",
location: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 13, line: 1, column: 14 }
}
});
});
it("reports infinite loops for one_or_more", function() {
expect(pass).toReportError('start = ("")+', {
message: "Possible infinite loop detected.",
location: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 13, line: 1, column: 14 }
}
});
});
it("computes expressions that always consume input on success correctly", function() {
expect(pass).toReportError([
'start = a*',
'a "a" = ""'
].join('\n'));
expect(pass).not.toReportError([
'start = a*',
'a "a" = "a"'
].join('\n'));
expect(pass).toReportError('start = ("" / "a" / "b")*');
expect(pass).toReportError('start = ("a" / "" / "b")*');
expect(pass).toReportError('start = ("a" / "b" / "")*');
expect(pass).not.toReportError('start = ("a" / "b" / "c")*');
expect(pass).toReportError('start = ("" { })*');
expect(pass).not.toReportError('start = ("a" { })*');
expect(pass).toReportError('start = ("" "" "")*');
expect(pass).not.toReportError('start = ("a" "" "")*');
expect(pass).not.toReportError('start = ("" "a" "")*');
expect(pass).not.toReportError('start = ("" "" "a")*');
expect(pass).toReportError('start = (a:"")*');
expect(pass).not.toReportError('start = (a:"a")*');
expect(pass).toReportError('start = ($"")*');
expect(pass).not.toReportError('start = ($"a")*');
expect(pass).toReportError('start = (&"")*');
expect(pass).toReportError('start = (&"a")*');
expect(pass).toReportError('start = (!"")*');
expect(pass).toReportError('start = (!"a")*');
expect(pass).toReportError('start = (""?)*');
expect(pass).toReportError('start = ("a"?)*');
expect(pass).toReportError('start = (""*)*');
expect(pass).toReportError('start = ("a"*)*');
expect(pass).toReportError('start = (""+)*');
expect(pass).not.toReportError('start = ("a"+)*');
expect(pass).toReportError('start = ("")*');
expect(pass).not.toReportError('start = ("a")*');
expect(pass).toReportError('start = (&{ })*');
expect(pass).toReportError('start = (!{ })*');
expect(pass).toReportError([
'start = a*',
'a = ""'
].join('\n'));
expect(pass).not.toReportError([
'start = a*',
'a = "a"'
].join('\n'));
expect(pass).toReportError('start = ""*');
expect(pass).not.toReportError('start = "a"*');
expect(pass).not.toReportError('start = [a-d]*');
expect(pass).not.toReportError('start = .*');
});
});