pegjs/spec/compiler/passes/report-left-recursion.spec.js
David Majda 5e146fce38 Text nodes: Implement text nodes
Implement a new syntax to extract matched strings from expressions. For
example, instead of:

  identifier = first:[a-zA-Z_] rest:[a-zA-Z0-9_]* { return first + rest.join(""); }

you can now just write:

  identifier = $([a-zA-Z_] [a-zA-Z0-9_]*)

This is useful mostly for "lexical" rules at the bottom of many
grammars.

Note that structured match results are still built for the expressions
prefixed by "$", they are just ignored. I plan to optimize this later
(sometime after the code generator rewrite).
2012-12-02 17:05:13 +01:00

97 lines
3 KiB
JavaScript

describe("compiler pass |reportLeftRecursion|", function() {
var pass = PEG.compiler.passes.reportLeftRecursion;
beforeEach(function() {
this.addMatchers({
toReportLeftRecursionIn: function(grammar) {
var ast = PEG.parser.parse(grammar);
try {
this.actual(ast);
this.message = function() {
return "Expected the pass to report left recursion for grammar "
+ jasmine.pp(grammar) + ", "
+ "but it didn't.";
};
return false;
} catch (e) {
if (this.isNot) {
this.message = function() {
return "Expected the pass not to report left recursion for grammar "
+ jasmine.pp(grammar) + ", "
+ "but it did.";
};
} else {
this.message = function() {
return "Expected the pass to report left recursion for grammar "
+ jasmine.pp(grammar) + ", "
+ "but it reported an error with message "
+ jasmine.pp(e.message) + ".";
};
}
return e.message === 'Left recursion detected for rule \"start\".';
}
}
});
});
it("reports left recursion inside a rule", function() {
expect(pass).toReportLeftRecursionIn('start = start');
});
it("reports left recursion inside a named", function() {
expect(pass).toReportLeftRecursionIn('start "start" = start');
});
it("reports left recursion inside a choice", function() {
expect(pass).toReportLeftRecursionIn('start = start / "a" / "b"');
expect(pass).toReportLeftRecursionIn('start = "a" / "b" / start');
});
it("reports left recursion inside an action", function() {
expect(pass).toReportLeftRecursionIn('start = start { }');
});
it("reports left recursion inside a sequence", function() {
expect(pass).toReportLeftRecursionIn('start = start "a" "b"');
});
it("reports left recursion inside a labeled", function() {
expect(pass).toReportLeftRecursionIn('start = label:start');
});
it("reports left recursion inside a text", function() {
expect(pass).toReportLeftRecursionIn('start = $start');
});
it("reports left recursion inside a simple and", function() {
expect(pass).toReportLeftRecursionIn('start = &start');
});
it("reports left recursion inside a simple not", function() {
expect(pass).toReportLeftRecursionIn('start = &start');
});
it("reports left recursion inside an optional", function() {
expect(pass).toReportLeftRecursionIn('start = start?');
});
it("reports left recursion inside a zero or more", function() {
expect(pass).toReportLeftRecursionIn('start = start*');
});
it("reports left recursion inside a one or more", function() {
expect(pass).toReportLeftRecursionIn('start = start+');
});
it("reports indirect left recursion", function() {
expect(pass).toReportLeftRecursionIn([
'start = stop',
'stop = start'
].join("\n"));
});
});