Showing the changes to sys/src/cmd/python/Demo/parser/unparse.py (1 of 3706 files). Show all
Unified · Split
| @@ -0,0 +1,519 @@ | |||
| 1 | "Usage: unparse.py <path to source file>" | ||
| 2 | import sys | ||
| 3 | import _ast | ||
| 4 | import cStringIO | ||
| 5 | import os | ||
| 6 | |||
| 7 | class 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 | for deco in t.decorators: | ||
| 227 | self.fill("@") | ||
| 228 | self.dispatch(deco) | ||
| 229 | self.fill("def "+t.name + "(") | ||
| 230 | self.dispatch(t.args) | ||
| 231 | self.write(")") | ||
| 232 | self.enter() | ||
| 233 | self.dispatch(t.body) | ||
| 234 | self.leave() | ||
| 235 | |||
| 236 | def _For(self, t): | ||
| 237 | self.fill("for ") | ||
| 238 | self.dispatch(t.target) | ||
| 239 | self.write(" in ") | ||
| 240 | self.dispatch(t.iter) | ||
| 241 | self.enter() | ||
| 242 | self.dispatch(t.body) | ||
| 243 | self.leave() | ||
| 244 | if t.orelse: | ||
| 245 | self.fill("else") | ||
| 246 | self.enter() | ||
| 247 | self.dispatch(t.orelse) | ||
| 248 | self.leave | ||
| 249 | |||
| 250 | def _If(self, t): | ||
| 251 | self.fill("if ") | ||
| 252 | self.dispatch(t.test) | ||
| 253 | self.enter() | ||
| 254 | # XXX elif? | ||
| 255 | self.dispatch(t.body) | ||
| 256 | self.leave() | ||
| 257 | if t.orelse: | ||
| 258 | self.fill("else") | ||
| 259 | self.enter() | ||
| 260 | self.dispatch(t.orelse) | ||
| 261 | self.leave() | ||
| 262 | |||
| 263 | def _While(self, t): | ||
| 264 | self.fill("while ") | ||
| 265 | self.dispatch(t.test) | ||
| 266 | self.enter() | ||
| 267 | self.dispatch(t.body) | ||
| 268 | self.leave() | ||
| 269 | if t.orelse: | ||
| 270 | self.fill("else") | ||
| 271 | self.enter() | ||
| 272 | self.dispatch(t.orelse) | ||
| 273 | self.leave | ||
| 274 | |||
| 275 | def _With(self, t): | ||
| 276 | self.fill("with ") | ||
| 277 | self.dispatch(t.context_expr) | ||
| 278 | if t.optional_vars: | ||
| 279 | self.write(" as ") | ||
| 280 | self.dispatch(t.optional_vars) | ||
| 281 | self.enter() | ||
| 282 | self.dispatch(t.body) | ||
| 283 | self.leave() | ||
| 284 | |||
| 285 | # expr | ||
| 286 | def _Str(self, tree): | ||
| 287 | self.write(repr(tree.s)) | ||
| 288 | |||
| 289 | def _Name(self, t): | ||
| 290 | self.write(t.id) | ||
| 291 | |||
| 292 | def _Repr(self, t): | ||
| 293 | self.write("`") | ||
| 294 | self.dispatch(t.value) | ||
| 295 | self.write("`") | ||
| 296 | |||
| 297 | def _Num(self, t): | ||
| 298 | self.write(repr(t.n)) | ||
| 299 | |||
| 300 | def _List(self, t): | ||
| 301 | self.write("[") | ||
| 302 | for e in t.elts: | ||
| 303 | self.dispatch(e) | ||
| 304 | self.write(", ") | ||
| 305 | self.write("]") | ||
| 306 | |||
| 307 | def _ListComp(self, t): | ||
| 308 | self.write("[") | ||
| 309 | self.dispatch(t.elt) | ||
| 310 | for gen in t.generators: | ||
| 311 | self.dispatch(gen) | ||
| 312 | self.write("]") | ||
| 313 | |||
| 314 | def _GeneratorExp(self, t): | ||
| 315 | self.write("(") | ||
| 316 | self.dispatch(t.elt) | ||
| 317 | for gen in t.generators: | ||
| 318 | self.dispatch(gen) | ||
| 319 | self.write(")") | ||
| 320 | |||
| 321 | def _comprehension(self, t): | ||
| 322 | self.write(" for ") | ||
| 323 | self.dispatch(t.target) | ||
| 324 | self.write(" in ") | ||
| 325 | self.dispatch(t.iter) | ||
| 326 | for if_clause in t.ifs: | ||
| 327 | self.write(" if ") | ||
| 328 | self.dispatch(if_clause) | ||
| 329 | |||
| 330 | def _IfExp(self, t): | ||
| 331 | self.dispatch(t.body) | ||
| 332 | self.write(" if ") | ||
| 333 | self.dispatch(t.test) | ||
| 334 | if t.orelse: | ||
| 335 | self.write(" else ") | ||
| 336 | self.dispatch(t.orelse) | ||
| 337 | |||
| 338 | def _Dict(self, t): | ||
| 339 | self.write("{") | ||
| 340 | for k,v in zip(t.keys, t.values): | ||
| 341 | self.dispatch(k) | ||
| 342 | self.write(" : ") | ||
| 343 | self.dispatch(v) | ||
| 344 | self.write(", ") | ||
| 345 | self.write("}") | ||
| 346 | |||
| 347 | def _Tuple(self, t): | ||
| 348 | if not t.elts: | ||
| 349 | self.write("()") | ||
| 350 | return | ||
| 351 | self.write("(") | ||
| 352 | for e in t.elts: | ||
| 353 | self.dispatch(e) | ||
| 354 | self.write(", ") | ||
| 355 | self.write(")") | ||
| 356 | |||
| 357 | unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} | ||
| 358 | def _UnaryOp(self, t): | ||
| 359 | self.write(self.unop[t.op.__class__.__name__]) | ||
| 360 | self.write("(") | ||
| 361 | self.dispatch(t.operand) | ||
| 362 | self.write(")") | ||
| 363 | |||
| 364 | binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%", | ||
| 365 | "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&", | ||
| 366 | "FloorDiv":"//", "Pow": "**"} | ||
| 367 | def _BinOp(self, t): | ||
| 368 | self.write("(") | ||
| 369 | self.dispatch(t.left) | ||
| 370 | self.write(")" + self.binop[t.op.__class__.__name__] + "(") | ||
| 371 | self.dispatch(t.right) | ||
| 372 | self.write(")") | ||
| 373 | |||
| 374 | cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=", | ||
| 375 | "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"} | ||
| 376 | def _Compare(self, t): | ||
| 377 | self.write("(") | ||
| 378 | self.dispatch(t.left) | ||
| 379 | for o, e in zip(t.ops, t.comparators): | ||
| 380 | self.write(") " +self.cmpops[o.__class__.__name__] + " (") | ||
| 381 | self.dispatch(e) | ||
| 382 | self.write(")") | ||
| 383 | |||
| 384 | boolops = {_ast.And: 'and', _ast.Or: 'or'} | ||
| 385 | def _BoolOp(self, t): | ||
| 386 | self.write("(") | ||
| 387 | self.dispatch(t.values[0]) | ||
| 388 | for v in t.values[1:]: | ||
| 389 | self.write(" %s " % self.boolops[t.op.__class__]) | ||
| 390 | self.dispatch(v) | ||
| 391 | self.write(")") | ||
| 392 | |||
| 393 | def _Attribute(self,t): | ||
| 394 | self.dispatch(t.value) | ||
| 395 | self.write(".") | ||
| 396 | self.write(t.attr) | ||
| 397 | |||
| 398 | def _Call(self, t): | ||
| 399 | self.dispatch(t.func) | ||
| 400 | self.write("(") | ||
| 401 | comma = False | ||
| 402 | for e in t.args: | ||
| 403 | if comma: self.write(", ") | ||
| 404 | else: comma = True | ||
| 405 | self.dispatch(e) | ||
| 406 | for e in t.keywords: | ||
| 407 | if comma: self.write(", ") | ||
| 408 | else: comma = True | ||
| 409 | self.dispatch(e) | ||
| 410 | if t.starargs: | ||
| 411 | if comma: self.write(", ") | ||
| 412 | else: comma = True | ||
| 413 | self.write("*") | ||
| 414 | self.dispatch(t.starargs) | ||
| 415 | if t.kwargs: | ||
| 416 | if comma: self.write(", ") | ||
| 417 | else: comma = True | ||
| 418 | self.write("**") | ||
| 419 | self.dispatch(t.kwargs) | ||
| 420 | self.write(")") | ||
| 421 | |||
| 422 | def _Subscript(self, t): | ||
| 423 | self.dispatch(t.value) | ||
| 424 | self.write("[") | ||
| 425 | self.dispatch(t.slice) | ||
| 426 | self.write("]") | ||
| 427 | |||
| 428 | # slice | ||
| 429 | def _Ellipsis(self, t): | ||
| 430 | self.write("...") | ||
| 431 | |||
| 432 | def _Index(self, t): | ||
| 433 | self.dispatch(t.value) | ||
| 434 | |||
| 435 | def _Slice(self, t): | ||
| 436 | if t.lower: | ||
| 437 | self.dispatch(t.lower) | ||
| 438 | self.write(":") | ||
| 439 | if t.upper: | ||
| 440 | self.dispatch(t.upper) | ||
| 441 | if t.step: | ||
| 442 | self.write(":") | ||
| 443 | self.dispatch(t.step) | ||
| 444 | |||
| 445 | def _ExtSlice(self, t): | ||
| 446 | for i, d in enumerate(t.dims): | ||
| 447 | if i != 0: | ||
| 448 | self.write(': ') | ||
| 449 | self.dispatch(d) | ||
| 450 | |||
| 451 | # others | ||
| 452 | def _arguments(self, t): | ||
| 453 | first = True | ||
| 454 | nonDef = len(t.args)-len(t.defaults) | ||
| 455 | for a in t.args[0:nonDef]: | ||
| 456 | if first:first = False | ||
| 457 | else: self.write(", ") | ||
| 458 | self.dispatch(a) | ||
| 459 | for a,d in zip(t.args[nonDef:], t.defaults): | ||
| 460 | if first:first = False | ||
| 461 | else: self.write(", ") | ||
| 462 | self.dispatch(a), | ||
| 463 | self.write("=") | ||
| 464 | self.dispatch(d) | ||
| 465 | if t.vararg: | ||
| 466 | if first:first = False | ||
| 467 | else: self.write(", ") | ||
| 468 | self.write("*"+t.vararg) | ||
| 469 | if t.kwarg: | ||
| 470 | if first:first = False | ||
| 471 | else: self.write(", ") | ||
| 472 | self.write("**"+t.kwarg) | ||
| 473 | |||
| 474 | def _keyword(self, t): | ||
| 475 | self.write(t.arg) | ||
| 476 | self.write("=") | ||
| 477 | self.dispatch(t.value) | ||
| 478 | |||
| 479 | def _Lambda(self, t): | ||
| 480 | self.write("lambda ") | ||
| 481 | self.dispatch(t.args) | ||
| 482 | self.write(": ") | ||
| 483 | self.dispatch(t.body) | ||
| 484 | |||
| 485 | def roundtrip(filename, output=sys.stdout): | ||
| 486 | source = open(filename).read() | ||
| 487 | tree = compile(source, filename, "exec", 0x400) | ||
| 488 | Unparser(tree, output) | ||
| 489 | |||
| 490 | |||
| 491 | |||
| 492 | def testdir(a): | ||
| 493 | try: | ||
| 494 | names = [n for n in os.listdir(a) if n.endswith('.py')] | ||
| 495 | except OSError: | ||
| 496 | print >> sys.stderr, "Directory not readable: %s" % a | ||
| 497 | else: | ||
| 498 | for n in names: | ||
| 499 | fullname = os.path.join(a, n) | ||
| 500 | if os.path.isfile(fullname): | ||
| 501 | output = cStringIO.StringIO() | ||
| 502 | print 'Testing %s' % fullname | ||
| 503 | try: | ||
| 504 | roundtrip(fullname, output) | ||
| 505 | except Exception, e: | ||
| 506 | print ' Failed to compile, exception is %s' % repr(e) | ||
| 507 | elif os.path.isdir(fullname): | ||
| 508 | testdir(fullname) | ||
| 509 | |||
| 510 | def main(args): | ||
| 511 | if args[0] == '--testdir': | ||
| 512 | for a in args[1:]: | ||
| 513 | testdir(a) | ||
| 514 | else: | ||
| 515 | for a in args: | ||
| 516 | roundtrip(a) | ||
| 517 | |||
| 518 | if __name__=='__main__': | ||
| 519 | main(sys.argv[1:]) | ||