pegjs/lib/compiler/visitor.js

98 lines
2.3 KiB
JavaScript
Raw Normal View History

"use strict";
2016-09-17 16:28:28 +02:00
// Simple AST node visitor builder.
const visitor = {
build( functions ) {
function visit( node ) {
return functions[ node.type ].apply( null, arguments );
}
function visitNop() {
// Do nothing.
}
function visitExpression( node ) {
const extraArgs = Array.prototype.slice.call( arguments, 1 );
2017-10-26 11:20:29 +02:00
visit.apply( null, [ node.expression ].concat( extraArgs ) );
}
function visitChildren( property ) {
return function visitProperty( node ) {
const extraArgs = Array.prototype.slice.call( arguments, 1 );
node[ property ].forEach( child => {
2017-10-26 11:20:29 +02:00
visit.apply( null, [ child ].concat( extraArgs ) );
} );
};
}
const DEFAULT_FUNCTIONS = {
grammar( node ) {
const extraArgs = Array.prototype.slice.call( arguments, 1 );
if ( node.initializer ) {
2017-10-26 11:20:29 +02:00
visit.apply( null, [ node.initializer ].concat( extraArgs ) );
}
node.rules.forEach( rule => {
2017-10-26 11:20:29 +02:00
visit.apply( null, [ rule ].concat( extraArgs ) );
} );
},
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,
class: visitNop,
any: visitNop
};
Object.keys( DEFAULT_FUNCTIONS ).forEach( type => {
if ( ! Object.prototype.hasOwnProperty.call( functions, type ) ) {
functions[ type ] = DEFAULT_FUNCTIONS[ type ];
}
} );
return visit;
}
};
module.exports = visitor;