2015-06-08 20:21:19 +02:00
|
|
|
"use strict";
|
|
|
|
|
2016-09-17 16:28:28 +02:00
|
|
|
// Simple AST node visitor builder.
|
2016-09-08 16:04:36 +02:00
|
|
|
let visitor = {
|
2014-05-08 14:51:17 +02:00
|
|
|
build: function(functions) {
|
2014-06-04 07:23:34 +02:00
|
|
|
function visit(node) {
|
2014-05-08 11:48:56 +02:00
|
|
|
return functions[node.type].apply(null, arguments);
|
2014-06-04 07:23:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function visitNop() { }
|
|
|
|
|
|
|
|
function visitExpression(node) {
|
2016-09-08 16:04:36 +02:00
|
|
|
let extraArgs = Array.prototype.slice.call(arguments, 1);
|
2014-06-04 07:23:34 +02:00
|
|
|
|
|
|
|
visit.apply(null, [node.expression].concat(extraArgs));
|
|
|
|
}
|
|
|
|
|
|
|
|
function visitChildren(property) {
|
|
|
|
return function(node) {
|
2016-09-08 16:04:36 +02:00
|
|
|
let extraArgs = Array.prototype.slice.call(arguments, 1);
|
2014-06-04 07:23:34 +02:00
|
|
|
|
2016-09-09 13:27:24 +02:00
|
|
|
node[property].forEach(child => {
|
2014-06-04 07:23:34 +02:00
|
|
|
visit.apply(null, [child].concat(extraArgs));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-09-08 16:04:36 +02:00
|
|
|
const DEFAULT_FUNCTIONS = {
|
2016-10-04 11:00:25 +02:00
|
|
|
grammar: function(node) {
|
|
|
|
let extraArgs = Array.prototype.slice.call(arguments, 1);
|
2014-06-04 07:23:34 +02:00
|
|
|
|
2016-10-04 11:00:25 +02:00
|
|
|
if (node.initializer) {
|
|
|
|
visit.apply(null, [node.initializer].concat(extraArgs));
|
|
|
|
}
|
2014-06-04 07:23:34 +02:00
|
|
|
|
2016-10-04 11:00:25 +02:00
|
|
|
node.rules.forEach(rule => {
|
|
|
|
visit.apply(null, [rule].concat(extraArgs));
|
|
|
|
});
|
|
|
|
},
|
2014-06-04 07:23:34 +02:00
|
|
|
|
2016-10-04 11:00:25 +02:00
|
|
|
initializer: visitNop,
|
|
|
|
rule: visitExpression,
|
|
|
|
named: visitExpression,
|
|
|
|
choice: visitChildren("alternatives"),
|
|
|
|
action: visitExpression,
|
|
|
|
sequence: visitChildren("elements"),
|
|
|
|
labeled: visitExpression,
|
|
|
|
text: visitExpression,
|
|
|
|
simple_and: visitExpression,
|
|
|
|
simple_not: visitExpression,
|
|
|
|
optional: visitExpression,
|
|
|
|
zero_or_more: visitExpression,
|
|
|
|
one_or_more: visitExpression,
|
|
|
|
group: visitExpression,
|
|
|
|
semantic_and: visitNop,
|
|
|
|
semantic_not: visitNop,
|
|
|
|
rule_ref: visitNop,
|
|
|
|
literal: visitNop,
|
2016-10-04 16:25:54 +02:00
|
|
|
class: visitNop,
|
2016-10-04 11:00:25 +02:00
|
|
|
any: visitNop
|
|
|
|
};
|
2014-06-04 07:23:34 +02:00
|
|
|
|
2016-09-14 13:53:23 +02:00
|
|
|
Object.keys(DEFAULT_FUNCTIONS).forEach(type => {
|
|
|
|
if (!functions.hasOwnProperty(type)) {
|
|
|
|
functions[type] = DEFAULT_FUNCTIONS[type];
|
|
|
|
}
|
|
|
|
});
|
2014-06-04 07:23:34 +02:00
|
|
|
|
|
|
|
return visit;
|
2014-05-08 11:48:56 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = visitor;
|