Fix too eager proxy rules removal

Fixes GH-137.
redux
David Majda 11 years ago
parent 5d00815b41
commit 3981433984

@ -3,7 +3,7 @@ var utils = require("../../utils");
/*
* Removes proxy rules -- that is, rules that only delegate to other rule.
*/
module.exports = function(ast) {
module.exports = function(ast, options) {
function isProxyRule(node) {
return node.type === "rule" && node.expression.type === "rule_ref";
}
@ -55,15 +55,17 @@ module.exports = function(ast) {
replace(ast, from, to);
}
var indices = [];
var indices = [],
allowedStartRules = options.allowedStartRules !== undefined
? options.allowedStartRules
: [ast.startRule];
utils.each(ast.rules, function(rule, i) {
if (isProxyRule(rule)) {
replaceRuleRefs(ast, rule.name, rule.expression.name);
if (rule.name === ast.startRule) {
ast.startRule = rule.expression.name;
if (!utils.contains(allowedStartRules, rule.name)) {
indices.push(i);
}
indices.push(i);
}
});

@ -19,8 +19,8 @@ describe("compiler pass |removeProxyRules|", function() {
it("removes proxy rule from a rule", function() {
expect(pass).toChangeAST(proxyGrammar('start = proxy'), {
startRule: "proxied",
rules: [
rules: [
{ type: "rule", name: "start", expression: proxiedRefDetails },
{ type: "rule", name: "proxied" }
]
});
@ -86,4 +86,17 @@ describe("compiler pass |removeProxyRules|", function() {
it("removes proxy rule from a one or more", function() {
expect(pass).toChangeAST(proxyGrammar('start = proxy+'), 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" }
]
}
);
});
});

@ -4,7 +4,7 @@ if (typeof module !== "undefined") {
beforeEach(function() {
this.addMatchers({
toChangeAST: function(grammar, details) {
toChangeAST: function(grammar) {
function matchDetails(value, details) {
function isArray(value) {
return Object.prototype.toString.apply(value) === "[object Array]";
@ -40,12 +40,15 @@ beforeEach(function() {
}
}
var ast = PEG.parser.parse(grammar);
var options = arguments.length > 2 ? arguments[1] : {},
details = arguments[arguments.length - 1],
ast = PEG.parser.parse(grammar);
this.actual(ast);
this.actual(ast, options);
this.message = function() {
return "Expected the pass "
+ "with options " + jasmine.pp(options) + " "
+ (this.isNot ? "not " : "")
+ "to change the AST " + jasmine.pp(ast) + " "
+ "to match " + jasmine.pp(details) + ", "

Loading…
Cancel
Save