-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtraverser.ts
55 lines (46 loc) · 1.31 KB
/
traverser.ts
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
import { NodeTypes, RootNode, ChildNode, CallExpressionNode } from "./ast";
type ParentNode = RootNode | CallExpressionNode | undefined;
type MethodFn = (node: RootNode | ChildNode, parent: ParentNode) => void;
interface VisitorOption {
enter: MethodFn;
exit?: MethodFn;
}
interface Visitor {
Program?: VisitorOption;
CallExpression?: VisitorOption;
NumberLiteral?: VisitorOption;
StringLiteral?: VisitorOption;
}
export function traverser(rootNode: RootNode, visitor: Visitor) {
// 1. 深度优先遍历
// 2. visitor
function traverseArray(array: ChildNode[], parent: ParentNode) {
array.forEach((node) => {
traverseNode(node, parent);
});
}
function traverseNode(node: ChildNode | RootNode, parent?: ParentNode) {
const visitorObj = visitor[node.type];
// enter
if (visitorObj) {
visitorObj.enter(node, parent);
}
switch (node.type) {
case NodeTypes.NumberLiteral:
// console.log("number", node);
// traverseNode(node)
break;
case NodeTypes.CallExpression:
traverseArray(node.params, node);
break;
case NodeTypes.Program:
traverseArray(node.body, node);
break;
}
// exit
if (visitorObj && visitorObj.exit) {
visitorObj.exit(node, parent);
}
}
traverseNode(rootNode);
}