Add compiler optimization: Remove proxy rules

This shouldn't have measurable effect on the benchmarks as there are no
proxy rules in the grammars the benchamrk uses. However the effect on
generated parsers' speed should be positive generally.
redux
David Majda 15 years ago
parent 33a1a7c1e9
commit 90ed4712e9

@ -372,6 +372,82 @@ PEG.Compiler = {
}
],
/*
* Optimalization passes made on the grammar AST before compilation. Each pass
* is a function that is passed the AST and start rule and returns a new AST
* and start rule. The AST can be modified in-place by the pass. The passes
* are run in sequence in order of their definition.
*/
_passes: [
/*
* Removes proxy rules -- that is, rules that only delegate to other rule.
*/
function(ast, startRule) {
function isProxyRule(node) {
return node.type === "rule" && node.expression.type === "rule_ref";
}
function replaceRuleRefs(ast, from, to) {
function nop() {}
function replaceInExpression(node, from, to) {
replace(node.expression, from, to);
}
function replaceInSubnodes(propertyName) {
return function(node, from, to) {
PEG.ArrayUtils.each(node[propertyName], function(node) {
replace(node, from, to);
});
};
}
var replaceFunctions = {
rule: replaceInExpression,
choice: replaceInSubnodes("alternatives"),
sequence: replaceInSubnodes("elements"),
and_predicate: replaceInExpression,
not_predicate: replaceInExpression,
optional: replaceInExpression,
zero_or_more: replaceInExpression,
one_or_more: replaceInExpression,
action: replaceInExpression,
rule_ref:
function(node, from, to) {
if (node.name === from) {
node.name = to;
}
},
literal: nop,
any: nop,
"class": nop
};
function replace(node, from, to) {
replaceFunctions[node.type](node, from, to);
}
for (var rule in ast) {
replace(ast[rule], from, to);
}
}
for (var rule in ast) {
if (isProxyRule(ast[rule])) {
replaceRuleRefs(ast, ast[rule].name, ast[rule].expression.name);
if (rule === startRule) {
startRule = ast[rule].expression.name;
}
delete ast[rule];
}
}
return [ast, startRule];
}
],
_compileFunctions: {
rule: function(node) {
var resultVar = PEG.Compiler.generateUniqueIdentifier("result");
@ -787,6 +863,12 @@ PEG.Compiler = {
this._checks[i](ast, startRule);
}
for (var i = 0; i < this._passes.length; i++) {
var newAstNadStartRule = this._passes[i](ast, startRule);
ast = newAstNadStartRule[0];
startRule = newAstNadStartRule[1];
}
var parseFunctionDefinitions = [];
for (var rule in ast) {
parseFunctionDefinitions.push(this.compileNode(ast[rule]));

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save