-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathTrees.js
More file actions
140 lines (129 loc) · 4.26 KB
/
Trees.js
File metadata and controls
140 lines (129 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
import Token from '../Token.js';
import ErrorNode from './ErrorNode.js';
import TerminalNode from './TerminalNode.js';
import RuleNode from './RuleNode.js';
import escapeWhitespace from "../utils/escapeWhitespace.js";
/** A set of utility routines useful for all kinds of ANTLR trees. */
let 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 = escapeWhitespace(s, false);
let 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 RuleNode) {
let context = t.ruleContext;
let altNumber = context.getAltNumber();
// use let value of ATN.INVALID_ALT_NUMBER to avoid circular dependency
if ( altNumber != 0 ) {
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
let 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) {
let 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) {
let 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 RuleNode)) {
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;
}
}
export default Trees;