-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtraverser.ts
49 lines (43 loc) · 1.19 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
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
}
export interface Visitor {
Program?: VisitorOption
CallExpression?: VisitorOption
NumberLiteral?: VisitorOption
StringLiteral?: VisitorOption
}
export function traverser(rootNode: RootNode, visitor: Visitor) {
// 深度优先搜索
function traverseArray(array: ChildNode[], parent: ParentNode) {
array.forEach((node) => {
traverseNode(node, parent)
})
}
function traverseNode(node: ChildNode | RootNode, parent?: ParentNode) {
const methods = visitor[node.type]
// enter
if (methods) {
methods.enter(node, parent)
}
switch (node.type) {
case NodeTypes.NumberLiteral:
break
case NodeTypes.CallExpression:
traverseArray(node.params, node)
break
case NodeTypes.Program:
traverseArray(node.body, node)
break
}
// exit
if (methods && methods.exit) {
methods.exit(node, parent)
}
}
traverseNode(rootNode)
}