source: trunk/essentials/dev-lang/python/Demo/parser/unparse.py@ 3398

Last change on this file since 3398 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 13.4 KB
Line 
1"Usage: unparse.py <path to source file>"
2import sys
3import _ast
4import cStringIO
5import os
6
7class Unparser:
8 """Methods in this class recursively traverse an AST and
9 output source code for the abstract syntax; original formatting
10 is disregarged. """
11
12 def __init__(self, tree, file = sys.stdout):
13 """Unparser(tree, file=sys.stdout) -> None.
14 Print the source for tree to file."""
15 self.f = file
16 self._indent = 0
17 self.dispatch(tree)
18 print >>self.f,""
19 self.f.flush()
20
21 def fill(self, text = ""):
22 "Indent a piece of text, according to the current indentation level"
23 self.f.write("\n"+" "*self._indent + text)
24
25 def write(self, text):
26 "Append a piece of text to the current line."
27 self.f.write(text)
28
29 def enter(self):
30 "Print ':', and increase the indentation."
31 self.write(":")
32 self._indent += 1
33
34 def leave(self):
35 "Decrease the indentation level."
36 self._indent -= 1
37
38 def dispatch(self, tree):
39 "Dispatcher function, dispatching tree type T to method _T."
40 if isinstance(tree, list):
41 for t in tree:
42 self.dispatch(t)
43 return
44 meth = getattr(self, "_"+tree.__class__.__name__)
45 meth(tree)
46
47
48 ############### Unparsing methods ######################
49 # There should be one method per concrete grammar type #
50 # Constructors should be grouped by sum type. Ideally, #
51 # this would follow the order in the grammar, but #
52 # currently doesn't. #
53 ########################################################
54
55 def _Module(self, tree):
56 for stmt in tree.body:
57 self.dispatch(stmt)
58
59 # stmt
60 def _Expr(self, tree):
61 self.fill()
62 self.dispatch(tree.value)
63
64 def _Import(self, t):
65 self.fill("import ")
66 first = True
67 for a in t.names:
68 if first:
69 first = False
70 else:
71 self.write(", ")
72 self.write(a.name)
73 if a.asname:
74 self.write(" as "+a.asname)
75
76 def _ImportFrom(self, t):
77 self.fill("from ")
78 self.write(t.module)
79 self.write(" import ")
80 for i, a in enumerate(t.names):
81 if i == 0:
82 self.write(", ")
83 self.write(a.name)
84 if a.asname:
85 self.write(" as "+a.asname)
86 # XXX(jpe) what is level for?
87
88 def _Assign(self, t):
89 self.fill()
90 for target in t.targets:
91 self.dispatch(target)
92 self.write(" = ")
93 self.dispatch(t.value)
94
95 def _AugAssign(self, t):
96 self.fill()
97 self.dispatch(t.target)
98 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
99 self.dispatch(t.value)
100
101 def _Return(self, t):
102 self.fill("return ")
103 if t.value:
104 self.dispatch(t.value)
105
106 def _Pass(self, t):
107 self.fill("pass")
108
109 def _Break(self, t):
110 self.fill("break")
111
112 def _Continue(self, t):
113 self.fill("continue")
114
115 def _Delete(self, t):
116 self.fill("del ")
117 self.dispatch(t.targets)
118
119 def _Assert(self, t):
120 self.fill("assert ")
121 self.dispatch(t.test)
122 if t.msg:
123 self.write(", ")
124 self.dispatch(t.msg)
125
126 def _Exec(self, t):
127 self.fill("exec ")
128 self.dispatch(t.body)
129 if t.globals:
130 self.write(" in ")
131 self.dispatch(t.globals)
132 if t.locals:
133 self.write(", ")
134 self.dispatch(t.locals)
135
136 def _Print(self, t):
137 self.fill("print ")
138 do_comma = False
139 if t.dest:
140 self.write(">>")
141 self.dispatch(t.dest)
142 do_comma = True
143 for e in t.values:
144 if do_comma:self.write(", ")
145 else:do_comma=True
146 self.dispatch(e)
147 if not t.nl:
148 self.write(",")
149
150 def _Global(self, t):
151 self.fill("global")
152 for i, n in enumerate(t.names):
153 if i != 0:
154 self.write(",")
155 self.write(" " + n)
156
157 def _Yield(self, t):
158 self.fill("yield")
159 if t.value:
160 self.write(" (")
161 self.dispatch(t.value)
162 self.write(")")
163
164 def _Raise(self, t):
165 self.fill('raise ')
166 if t.type:
167 self.dispatch(t.type)
168 if t.inst:
169 self.write(", ")
170 self.dispatch(t.inst)
171 if t.tback:
172 self.write(", ")
173 self.dispatch(t.tback)
174
175 def _TryExcept(self, t):
176 self.fill("try")
177 self.enter()
178 self.dispatch(t.body)
179 self.leave()
180
181 for ex in t.handlers:
182 self.dispatch(ex)
183 if t.orelse:
184 self.fill("else")
185 self.enter()
186 self.dispatch(t.orelse)
187 self.leave()
188
189 def _TryFinally(self, t):
190 self.fill("try")
191 self.enter()
192 self.dispatch(t.body)
193 self.leave()
194
195 self.fill("finally")
196 self.enter()
197 self.dispatch(t.finalbody)
198 self.leave()
199
200 def _excepthandler(self, t):
201 self.fill("except ")
202 if t.type:
203 self.dispatch(t.type)
204 if t.name:
205 self.write(", ")
206 self.dispatch(t.name)
207 self.enter()
208 self.dispatch(t.body)
209 self.leave()
210
211 def _ClassDef(self, t):
212 self.write("\n")
213 self.fill("class "+t.name)
214 if t.bases:
215 self.write("(")
216 for a in t.bases:
217 self.dispatch(a)
218 self.write(", ")
219 self.write(")")
220 self.enter()
221 self.dispatch(t.body)
222 self.leave()
223
224 def _FunctionDef(self, t):
225 self.write("\n")
226 self.fill("def "+t.name + "(")
227 self.dispatch(t.args)
228 self.write(")")
229 self.enter()
230 self.dispatch(t.body)
231 self.leave()
232
233 def _For(self, t):
234 self.fill("for ")
235 self.dispatch(t.target)