@ -3,92 +3,133 @@
const util = require ( "../util" ) ;
const _ _slice = Array . prototype . slice ;
// Simple AST node visitor builder.
const visitor = {
build ( functions ) {
// Abstract syntax tree visitor for PEG.js
class ASTVisitor {
function visit ( node ) {
// Will traverse the node, strictly assuming the visitor can handle the node type.
visit ( node ) {
return functions [ node . type ] . apply ( null , arguments ) ;
const args = _ _slice . call ( arguments , 0 ) ;
}
return this [ node . type ] . apply ( this , args ) ;
}
// Simple AST node visitor builder for PEG.js
static build ( functions ) {
const visitor = new ASTVisitor ( ) ;
util . extend ( visitor , functions ) ;
return visitor . visit . bind ( visitor ) ;
}
}
module . exports = ASTVisitor ;
const visitNop = util . noop ;
// Helper's to create visitor's for use with the ASTVisitor class
const on = ASTVisitor . for = {
function visitExpression ( node ) {
// Visit a node that is defined as a property on another node
property ( name ) {
return function visitProperty ( node ) {
const extraArgs = _ _slice . call ( arguments , 1 ) ;
const value = node [ name ] ;
visit . apply ( null , [ node . expression ] . concat ( extraArgs ) ) ;
if ( extraArgs . length )
}
this . visit . apply ( this , [ value ] . concat ( extraArgs ) ) ;
function visitChildren ( children , extraArgs ) {
else
const args = [ void 0 ] . concat ( extraArgs ) ;
const cb = extraArgs . length
? function withArgs ( child ) {
this . visit ( value ) ;
args [ 0 ] = child ;
visit . apply ( null , args ) ;
} ;
} ,
// Visit an array of nodes that are defined as a property on another node
children ( name ) {
return function visitProperty ( node ) {
const args = _ _slice . call ( arguments , 0 ) ;
const children = node [ name ] ;
const visitor = this ;
const cb = args . length < 2
? function withoutArgs ( child ) {
visitor . visit ( child ) ;
}
: function withoutArgs ( child ) {
: function with Args( child ) {
visit ( child ) ;
args [ 0 ] = child ;
visitor . visit . apply ( visitor , args ) ;
} ;
children . forEach ( cb ) ;
}
} ;
const DEFAULT _FUNCTIONS = {
grammar ( node ) {
} ,
const extraArgs = _ _slice . call ( arguments , 1 ) ;
} ;
if ( node . initializer ) {
// Build the default ast visitor functions
visit . apply ( null , [ node . initializer ] . concat ( extraArgs ) ) ;
const visitNop = util . noop ;
const visitExpression = on . property ( "expression" ) ;
}
const DEFAULT _FUNCTIONS = {
node . rules . forEach ( rule => {
visit . apply ( null , [ rule ] . concat ( extraArgs ) ) ;
} ) ;
} ,
initializer : visitNop ,
rule : visitExpression ,
named : visitExpression ,
choice : util . createVisitor ( "alternatives" , visitChildren ) ,
action : visitExpression ,
sequence : util . createVisitor ( "elements" , visitChildren ) ,
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
} ;
grammar ( node ) {
util . extend ( functions , DEFAULT _FUNCTIONS ) ;
const extraArgs = _ _slice . call ( arguments , 1 ) ;
return visit ;
if ( node . initializer ) {
this . visit . apply ( this , [ node . initializer ] . concat ( extraArgs ) ) ;
}
node . rules . forEach ( rule => {
this . visit . apply ( this , [ rule ] . concat ( extraArgs ) ) ;
} ) ;
} ,
initializer : visitNop ,
rule : visitExpression ,
named : visitExpression ,
choice : on . children ( "alternatives" ) ,
action : visitExpression ,
sequence : on . children ( "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 ,
}
} ;
module . exports = visitor ;
util . each ( DEFAULT _FUNCTIONS , ( fn , name ) => {
ASTVisitor . prototype [ name ] = fn ;
} ) ;