163
|
1 from .astnodes import *
|
|
2
|
|
3 class Visitor:
|
215
|
4 """
|
|
5 Visitor that can visit all nodes in the AST
|
|
6 and run pre and post functions.
|
|
7 """
|
|
8 def visit(self, node, f_pre=None, f_post=None):
|
|
9 self.f_pre = f_pre
|
|
10 self.f_post = f_post
|
|
11 self.do(node)
|
|
12
|
|
13 def do(self, node):
|
163
|
14 # Run visitor:
|
215
|
15 if self.f_pre:
|
|
16 self.f_pre(node)
|
|
17
|
163
|
18 # Descent into subnodes:
|
|
19 if type(node) is Package:
|
215
|
20 for decl in node.declarations:
|
|
21 self.do(decl)
|
163
|
22 elif type(node) is Function:
|
215
|
23 for s in node.declarations:
|
|
24 self.do(s)
|
|
25 self.do(node.body)
|
163
|
26 elif type(node) is CompoundStatement:
|
|
27 for s in node.statements:
|
215
|
28 self.do(s)
|
163
|
29 elif type(node) is IfStatement:
|
215
|
30 self.do(node.condition)
|
|
31 self.do(node.truestatement)
|
|
32 self.do(node.falsestatement)
|
167
|
33 elif type(node) is FunctionCall:
|
|
34 for arg in node.args:
|
215
|
35 self.do(arg)
|
163
|
36 elif type(node) is Assignment:
|
215
|
37 self.do(node.lval)
|
|
38 self.do(node.rval)
|
163
|
39 elif type(node) is ReturnStatement:
|
215
|
40 self.do(node.expr)
|
163
|
41 elif type(node) is Binop:
|
215
|
42 self.do(node.a)
|
|
43 self.do(node.b)
|
166
|
44 elif type(node) is Constant:
|
215
|
45 self.do(node.value)
|
166
|
46 elif type(node) in [EmptyStatement, VariableUse, Variable, Literal, FunctionType]:
|
163
|
47 # Those nodes do not have child nodes.
|
|
48 pass
|
176
|
49 elif type(node) is WhileStatement:
|
215
|
50 self.do(node.condition)
|
|
51 self.do(node.statement)
|
163
|
52 else:
|
215
|
53 raise Exception('Could not visit "{0}"'.format(node))
|
163
|
54
|
215
|
55 # run post function
|
|
56 if self.f_post:
|
|
57 self.f_post(node)
|
|
58
|