pegjs/lib/compiler/passes/remove-proxy-rules.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

76 lines
1.9 KiB
JavaScript

var utils = require("../../utils");
/*
* Removes proxy rules -- that is, rules that only delegate to other rule.
*/
module.exports = function(ast) {
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) {
utils.each(node[propertyName], function(subnode) {
replace(subnode, from, to);
});
};
}
var replace = utils.buildNodeVisitor({
grammar: replaceInSubnodes("rules"),
rule: replaceInExpression,
named: replaceInExpression,
choice: replaceInSubnodes("alternatives"),
sequence: replaceInSubnodes("elements"),
labeled: replaceInExpression,
text: replaceInExpression,
simple_and: replaceInExpression,
simple_not: replaceInExpression,
semantic_and: nop,
semantic_not: nop,
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,
"class": nop,
any: nop
});
replace(ast, from, to);
}
var indices = [];
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;
}
indices.push(i);
}
});
indices.reverse();
utils.each(indices, function(index) {
ast.rules.splice(index, 1);
});
};