forked from raphaelhuefner/ace-mode-solidity
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathastTraversal.js
71 lines (64 loc) · 1.49 KB
/
astTraversal.js
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
class AstTraversal {
constructor(ast) {
this.ast = ast;
this.stack = [];
this.callbacks = {};
}
on(type, callback) {
if (! this.callbacks[type]) {
this.callbacks[type] = [];
}
this.callbacks[type].push(callback);
}
_applyCallbacks(node) {
for (const callbackId of [node.type, '*']) {
if (this.callbacks[callbackId]) {
for (const cb of this.callbacks[callbackId]) {
const result = cb(node, this.stack, this.ast);
if (false === result) {
return;
}
}
}
}
}
traverse(ast) {
// if (null === ast) {
// return;
// }
if (Array.isArray(ast)) {
let i = 0;
for (const node of ast) {
this.stack.push({levelType:'listIndex', id:i});
this.traverse(node);
this.stack.pop();
i++;
}
return;
}
if ('object' === typeof ast) {
if (!ast || ! ast.type) { // Not a node, i.e. `loc` or `value:{}` or similar.
return;
}
this._applyCallbacks(ast);
this.stack.push({levelType:'nodeType', id:ast.type});
for (const field of Object.keys(ast)) {
// if ('loc' === field) {
// continue;
// }
this.stack.push({levelType:'fieldName', id:field});
this.traverse(ast[field]);
this.stack.pop();
}
this.stack.pop();
return;
}
}
start() {
this.traverse(this.ast);
}
getAst() {
return this.ast;
}
}
module.exports = AstTraversal;