forked from jasder/antlr
refactored Trees to be a plain object to avoid "this" invocation
This commit is contained in:
parent
af45a02d1e
commit
66c652142c
|
@ -11,132 +11,129 @@ const {RuleContext} = require('./../RuleContext');
|
|||
const {ATN: {INVALID_ALT_NUMBER}} = require('./../atn/ATN');
|
||||
|
||||
/** A set of utility routines useful for all kinds of ANTLR trees. */
|
||||
function Trees() {
|
||||
const Trees = {
|
||||
/**
|
||||
* Print out a whole tree in LISP form. {@link //getNodeText} is used on the
|
||||
* node payloads to get the text for the nodes. Detect
|
||||
* parse trees and extract data appropriately.
|
||||
*/
|
||||
toStringTree: function(tree, ruleNames, recog) {
|
||||
ruleNames = ruleNames || null;
|
||||
recog = recog || null;
|
||||
if(recog!==null) {
|
||||
ruleNames = recog.ruleNames;
|
||||
}
|
||||
let s = Trees.getNodeText(tree, ruleNames);
|
||||
s = Utils.escapeWhitespace(s, false);
|
||||
const c = tree.getChildCount();
|
||||
if(c===0) {
|
||||
return s;
|
||||
}
|
||||
let res = "(" + s + ' ';
|
||||
if(c>0) {
|
||||
s = Trees.toStringTree(tree.getChild(0), ruleNames);
|
||||
res = res.concat(s);
|
||||
}
|
||||
for(let i=1;i<c;i++) {
|
||||
s = Trees.toStringTree(tree.getChild(i), ruleNames);
|
||||
res = res.concat(' ' + s);
|
||||
}
|
||||
res = res.concat(")");
|
||||
return res;
|
||||
},
|
||||
|
||||
getNodeText: function(t, ruleNames, recog) {
|
||||
ruleNames = ruleNames || null;
|
||||
recog = recog || null;
|
||||
if(recog!==null) {
|
||||
ruleNames = recog.ruleNames;
|
||||
}
|
||||
if(ruleNames!==null) {
|
||||
if (t instanceof RuleContext) {
|
||||
const altNumber = t.getAltNumber();
|
||||
if ( altNumber!=INVALID_ALT_NUMBER ) {
|
||||
return ruleNames[t.ruleIndex]+":"+altNumber;
|
||||
}
|
||||
return ruleNames[t.ruleIndex];
|
||||
} else if ( t instanceof ErrorNode) {
|
||||
return t.toString();
|
||||
} else if(t instanceof TerminalNode) {
|
||||
if(t.symbol!==null) {
|
||||
return t.symbol.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no recog for rule names
|
||||
const payload = t.getPayload();
|
||||
if (payload instanceof Token ) {
|
||||
return payload.text;
|
||||
}
|
||||
return t.getPayload().toString();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return ordered list of all children of this node
|
||||
*/
|
||||
getChildren: function(t) {
|
||||
const list = [];
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
list.push(t.getChild(i));
|
||||
}
|
||||
return list;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a list of all ancestors of this node. The first node of
|
||||
* list is the root and the last is the parent of this node.
|
||||
*/
|
||||
getAncestors: function(t) {
|
||||
let ancestors = [];
|
||||
t = t.getParent();
|
||||
while(t!==null) {
|
||||
ancestors = [t].concat(ancestors);
|
||||
t = t.getParent();
|
||||
}
|
||||
return ancestors;
|
||||
},
|
||||
|
||||
findAllTokenNodes: function(t, ttype) {
|
||||
return Trees.findAllNodes(t, ttype, true);
|
||||
},
|
||||
|
||||
findAllRuleNodes: function(t, ruleIndex) {
|
||||
return Trees.findAllNodes(t, ruleIndex, false);
|
||||
},
|
||||
|
||||
findAllNodes: function(t, index, findTokens) {
|
||||
const nodes = [];
|
||||
Trees._findAllNodes(t, index, findTokens, nodes);
|
||||
return nodes;
|
||||
},
|
||||
|
||||
_findAllNodes: function(t, index, findTokens, nodes) {
|
||||
// check this node (the root) first
|
||||
if(findTokens && (t instanceof TerminalNode)) {
|
||||
if(t.symbol.type===index) {
|
||||
nodes.push(t);
|
||||
}
|
||||
} else if(!findTokens && (t instanceof ParserRuleContext)) {
|
||||
if(t.ruleIndex===index) {
|
||||
nodes.push(t);
|
||||
}
|
||||
}
|
||||
// check children
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
Trees._findAllNodes(t.getChild(i), index, findTokens, nodes);
|
||||
}
|
||||
},
|
||||
|
||||
descendants: function(t) {
|
||||
let nodes = [t];
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
nodes = nodes.concat(Trees.descendants(t.getChild(i)));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out a whole tree in LISP form. {@link //getNodeText} is used on the
|
||||
* node payloads to get the text for the nodes. Detect
|
||||
* parse trees and extract data appropriately.
|
||||
*/
|
||||
Trees.toStringTree = function(tree, ruleNames, recog) {
|
||||
ruleNames = ruleNames || null;
|
||||
recog = recog || null;
|
||||
if(recog!==null) {
|
||||
ruleNames = recog.ruleNames;
|
||||
}
|
||||
let s = Trees.getNodeText(tree, ruleNames);
|
||||
s = Utils.escapeWhitespace(s, false);
|
||||
const c = tree.getChildCount();
|
||||
if(c===0) {
|
||||
return s;
|
||||
}
|
||||
let res = "(" + s + ' ';
|
||||
if(c>0) {
|
||||
s = Trees.toStringTree(tree.getChild(0), ruleNames);
|
||||
res = res.concat(s);
|
||||
}
|
||||
for(let i=1;i<c;i++) {
|
||||
s = Trees.toStringTree(tree.getChild(i), ruleNames);
|
||||
res = res.concat(' ' + s);
|
||||
}
|
||||
res = res.concat(")");
|
||||
return res;
|
||||
};
|
||||
|
||||
Trees.getNodeText = function(t, ruleNames, recog) {
|
||||
ruleNames = ruleNames || null;
|
||||
recog = recog || null;
|
||||
if(recog!==null) {
|
||||
ruleNames = recog.ruleNames;
|
||||
}
|
||||
if(ruleNames!==null) {
|
||||
if (t instanceof RuleContext) {
|
||||
const altNumber = t.getAltNumber();
|
||||
if ( altNumber!=INVALID_ALT_NUMBER ) {
|
||||
return ruleNames[t.ruleIndex]+":"+altNumber;
|
||||
}
|
||||
return ruleNames[t.ruleIndex];
|
||||
} else if ( t instanceof ErrorNode) {
|
||||
return t.toString();
|
||||
} else if(t instanceof TerminalNode) {
|
||||
if(t.symbol!==null) {
|
||||
return t.symbol.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no recog for rule names
|
||||
const payload = t.getPayload();
|
||||
if (payload instanceof Token ) {
|
||||
return payload.text;
|
||||
}
|
||||
return t.getPayload().toString();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return ordered list of all children of this node
|
||||
*/
|
||||
Trees.getChildren = function(t) {
|
||||
const list = [];
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
list.push(t.getChild(i));
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a list of all ancestors of this node. The first node of
|
||||
* list is the root and the last is the parent of this node.
|
||||
*/
|
||||
Trees.getAncestors = function(t) {
|
||||
let ancestors = [];
|
||||
t = t.getParent();
|
||||
while(t!==null) {
|
||||
ancestors = [t].concat(ancestors);
|
||||
t = t.getParent();
|
||||
}
|
||||
return ancestors;
|
||||
};
|
||||
|
||||
Trees.findAllTokenNodes = function(t, ttype) {
|
||||
return Trees.findAllNodes(t, ttype, true);
|
||||
};
|
||||
|
||||
Trees.findAllRuleNodes = function(t, ruleIndex) {
|
||||
return Trees.findAllNodes(t, ruleIndex, false);
|
||||
};
|
||||
|
||||
Trees.findAllNodes = function(t, index, findTokens) {
|
||||
const nodes = [];
|
||||
Trees._findAllNodes(t, index, findTokens, nodes);
|
||||
return nodes;
|
||||
};
|
||||
|
||||
Trees._findAllNodes = function(t, index, findTokens, nodes) {
|
||||
// check this node (the root) first
|
||||
if(findTokens && (t instanceof TerminalNode)) {
|
||||
if(t.symbol.type===index) {
|
||||
nodes.push(t);
|
||||
}
|
||||
} else if(!findTokens && (t instanceof ParserRuleContext)) {
|
||||
if(t.ruleIndex===index) {
|
||||
nodes.push(t);
|
||||
}
|
||||
}
|
||||
// check children
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
Trees._findAllNodes(t.getChild(i), index, findTokens, nodes);
|
||||
}
|
||||
};
|
||||
|
||||
Trees.descendants = function(t) {
|
||||
let nodes = [t];
|
||||
for(let i=0;i<t.getChildCount();i++) {
|
||||
nodes = nodes.concat(Trees.descendants(t.getChild(i)));
|
||||
}
|
||||
return nodes;
|
||||
};
|
||||
|
||||
|
||||
exports.Trees = Trees;
|
||||
module.exports = {Trees};
|
||||
|
|
Loading…
Reference in New Issue