2012-04-30 13:42:13 +02:00
|
|
|
describe("compiler pass |reportLeftRecursion|", function() {
|
2013-01-13 11:17:44 +01:00
|
|
|
var pass = PEG.compiler.passes.check.reportLeftRecursion;
|
2012-04-30 13:42:13 +02:00
|
|
|
|
2014-06-07 09:11:00 +02:00
|
|
|
it("reports direct left recursion", function() {
|
|
|
|
expect(pass).toReportError('start = start', {
|
|
|
|
message: 'Left recursion detected for rule \"start\".'
|
2012-04-30 13:42:13 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("reports indirect left recursion", function() {
|
2014-06-07 09:11:00 +02:00
|
|
|
expect(pass).toReportError([
|
2012-04-30 13:42:13 +02:00
|
|
|
'start = stop',
|
|
|
|
'stop = start'
|
2014-06-07 09:11:00 +02:00
|
|
|
].join("\n"), {
|
|
|
|
message: 'Left recursion detected for rule \"start\".'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("in sequences", function() {
|
2015-03-31 19:02:59 +02:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
|
|
|
|
it("computes empty string matching correctly", function() {
|
|
|
|
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).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');
|
2014-06-07 09:11:00 +02:00
|
|
|
|
2015-03-31 19:02:59 +02:00
|
|
|
expect(pass).not.toReportError('start = "." start');
|
2014-06-07 09:11:00 +02:00
|
|
|
});
|
2012-04-30 13:42:13 +02:00
|
|
|
});
|
|
|
|
});
|