e4b5588327
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.
141 lines
3.6 KiB
JavaScript
141 lines
3.6 KiB
JavaScript
describe("compiler pass |removeProxyRules|", function() {
|
|
var pass = PEG.compiler.passes.transform.removeProxyRules;
|
|
|
|
function proxyGrammar(rule) {
|
|
return [rule, 'proxy = proxied', 'proxied = "a"'].join("\n");
|
|
}
|
|
|
|
function expressionDetails(details) {
|
|
return {
|
|
rules: [
|
|
{ type: "rule", name: "start", expression: details },
|
|
{ type: "rule", name: "proxied" }
|
|
]
|
|
};
|
|
}
|
|
|
|
var defaultOptions = { allowedStartRules: ["start"] },
|
|
proxiedRefDetails = { type: "rule_ref", name: "proxied" },
|
|
simpleDetails = expressionDetails({ expression: proxiedRefDetails });
|
|
|
|
it("removes proxy rule from a rule", function() {
|
|
expect(pass).toChangeAST(proxyGrammar('start = proxy'), defaultOptions, {
|
|
rules: [
|
|
{ type: "rule", name: "start", expression: proxiedRefDetails },
|
|
{ type: "rule", name: "proxied" }
|
|
]
|
|
});
|
|
});
|
|
|
|
it("removes proxy rule from a named", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start "start" = proxy'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a choice", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy / "a" / "b"'),
|
|
defaultOptions,
|
|
expressionDetails({ alternatives: [proxiedRefDetails, {}, {}] })
|
|
);
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = "a" / "b" / proxy'),
|
|
defaultOptions,
|
|
expressionDetails({ alternatives: [{}, {}, proxiedRefDetails] })
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from an action", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy { }'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a sequence", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy "a" "b"'),
|
|
defaultOptions,
|
|
expressionDetails({ elements: [proxiedRefDetails, {}, {}] })
|
|
);
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = "a" "b" proxy'),
|
|
defaultOptions,
|
|
expressionDetails({ elements: [{}, {}, proxiedRefDetails] })
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a labeled", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = label:proxy'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a text", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = $proxy'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a simple and", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = &proxy'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a simple not", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = &proxy'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from an optional", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy?'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a zero or more", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy*'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("removes proxy rule from a one or more", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy+'),
|
|
defaultOptions,
|
|
simpleDetails
|
|
);
|
|
});
|
|
|
|
it("doesn't remove a proxy rule listed in |allowedStartRules|", function() {
|
|
expect(pass).toChangeAST(
|
|
proxyGrammar('start = proxy'),
|
|
{ allowedStartRules: ["proxy"] },
|
|
{
|
|
rules: [
|
|
{ name: "proxy" },
|
|
{ name: "proxied" }
|
|
]
|
|
}
|
|
);
|
|
});
|
|
});
|