pegjs/spec/compiler/passes/report-missing-rules.spec.js
David Majda e4b5588327 Plugin API: Split compiler passes into stages
The compiler passes are now split into three stages:

  * check -- passes that check for various error conditions

  * transform -- passes that transform the AST (e.g. to perform
    optimizations)

  * generate -- passes that are related to code generation

Splitting the passes into stages is important for plugins. For example,
if a plugin wants to add a new optimization pass, it can add it at the
end of the "transform" stage without any knowledge about other passes it
contains. Similarly, if it wants to generate something else than the
default code generator does from the AST, it can just replace all passes
in the "generate" stage by its own one(s).

More generally, the stages make it possible to write plugins that do not
depend on names and actions of specific passes (which I consider
internal and subject of change), just on the definition of stages (which
I consider a public API with to which semver rules apply).

Implements part of GH-106.
2013-01-13 19:08:06 +01:00

91 lines
3 KiB
JavaScript

describe("compiler pass |reportMissingRules|", function() {
var pass = PEG.compiler.passes.check.reportMissingRules;
beforeEach(function() {
this.addMatchers({
toReportMissingRuleIn: function(grammar) {
var ast = PEG.parser.parse(grammar);
try {
this.actual(ast);
this.message = function() {
return "Expected the pass to report a missing rule 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 a missing rule for grammar "
+ jasmine.pp(grammar) + ", "
+ "but it did.";
};
} else {
this.message = function() {
return "Expected the pass to report a missing rule for grammar "
+ jasmine.pp(grammar) + ", "
+ "but it reported an error with message "
+ jasmine.pp(e.message) + ".";
};
}
return e.message === 'Referenced rule "missing" does not exist.';
}
}
});
});
it("reports missing rule referenced from a rule", function() {
expect(pass).toReportMissingRuleIn('start = missing');
});
it("reports missing rule referenced from a named", function() {
expect(pass).toReportMissingRuleIn('start "start" = missing');
});
it("reports missing rule referenced from a choice", function() {
expect(pass).toReportMissingRuleIn('start = missing / "a" / "b"');
expect(pass).toReportMissingRuleIn('start = "a" / "b" / missing');
});
it("reports missing rule referenced from an action", function() {
expect(pass).toReportMissingRuleIn('start = missing { }');
});
it("reports missing rule referenced from a sequence", function() {
expect(pass).toReportMissingRuleIn('start = missing "a" "b"');
expect(pass).toReportMissingRuleIn('start = "a" "b" missing');
});
it("reports missing rule referenced from a labeled", function() {
expect(pass).toReportMissingRuleIn('start = label:missing');
});
it("reports missing rule referenced from a text", function() {
expect(pass).toReportMissingRuleIn('start = $missing');
});
it("reports missing rule referenced from a simple and", function() {
expect(pass).toReportMissingRuleIn('start = &missing');
});
it("reports missing rule referenced from a simple not", function() {
expect(pass).toReportMissingRuleIn('start = &missing');
});
it("reports missing rule referenced from an optional", function() {
expect(pass).toReportMissingRuleIn('start = missing?');
});
it("reports missing rule referenced from a zero or more", function() {
expect(pass).toReportMissingRuleIn('start = missing*');
});
it("reports missing rule referenced from a one or more", function() {
expect(pass).toReportMissingRuleIn('start = missing+');
});
});