| 1 | """Parse tree transformation module.
 | 
| 2 | 
 | 
| 3 | Transforms Python source code into an abstract syntax tree (AST)
 | 
| 4 | defined in the ast module.
 | 
| 5 | 
 | 
| 6 | The simplest ways to invoke this module are via parse and parseFile.
 | 
| 7 | parse(buf) -> AST
 | 
| 8 | parseFile(path) -> AST
 | 
| 9 | """
 | 
| 10 | 
 | 
| 11 | # Original version written by Greg Stein (gstein@lyra.org)
 | 
| 12 | #                         and Bill Tutt (rassilon@lima.mudlib.org)
 | 
| 13 | # February 1997.
 | 
| 14 | #
 | 
| 15 | # Modifications and improvements for Python 2.0 by Jeremy Hylton and
 | 
| 16 | # Mark Hammond
 | 
| 17 | #
 | 
| 18 | # Some fixes to try to have correct line number on almost all nodes
 | 
| 19 | # (except Module, Discard and Stmt) added by Sylvain Thenault
 | 
| 20 | #
 | 
| 21 | # Portions of this file are:
 | 
| 22 | # Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
 | 
| 23 | #
 | 
| 24 | # This module is provided under a BSD-ish license. See
 | 
| 25 | #   http://www.opensource.org/licenses/bsd-license.html
 | 
| 26 | # and replace OWNER, ORGANIZATION, and YEAR as appropriate.
 | 
| 27 | 
 | 
| 28 | from .ast import *
 | 
| 29 | from .consts import CO_VARARGS, CO_VARKEYWORDS
 | 
| 30 | from .consts import OP_ASSIGN, OP_DELETE, OP_APPLY
 | 
| 31 | 
 | 
| 32 | from ..pytree import type_repr
 | 
| 33 | from pgen2 import token
 | 
| 34 | 
 | 
| 35 | 
 | 
| 36 | symbol = None
 | 
| 37 | 
 | 
| 38 | def Init(sym):
 | 
| 39 |   """Replacement for the stdlib symbol module.
 | 
| 40 | 
 | 
| 41 |   Args:
 | 
| 42 |     sym: module
 | 
| 43 | 
 | 
| 44 |   The stdlib module is generated from pgen.c's output data.  pgen2 derives it
 | 
| 45 |   from the grammar directly.
 | 
| 46 | 
 | 
| 47 |   """
 | 
| 48 |   global symbol
 | 
| 49 |   symbol = sym
 | 
| 50 |   _InitGlobals()
 | 
| 51 | 
 | 
| 52 | 
 | 
| 53 | # Various constants
 | 
| 54 | _doc_nodes = []
 | 
| 55 | _legal_node_types = []
 | 
| 56 | _assign_types = []
 | 
| 57 | # NOTE: This is somewhat duplicated in pytree.py as type_repr.
 | 
| 58 | _names = {}
 | 
| 59 | 
 | 
| 60 | def _InitGlobals():
 | 
| 61 |   _doc_nodes.extend([
 | 
| 62 |     symbol.expr_stmt,
 | 
| 63 |     symbol.testlist,
 | 
| 64 |     symbol.testlist_safe,
 | 
| 65 |     symbol.test,
 | 
| 66 |     symbol.or_test,
 | 
| 67 |     symbol.and_test,
 | 
| 68 |     symbol.not_test,
 | 
| 69 |     symbol.comparison,
 | 
| 70 |     symbol.expr,
 | 
| 71 |     symbol.xor_expr,
 | 
| 72 |     symbol.and_expr,
 | 
| 73 |     symbol.shift_expr,
 | 
| 74 |     symbol.arith_expr,
 | 
| 75 |     symbol.term,
 | 
| 76 |     symbol.factor,
 | 
| 77 |     symbol.power,
 | 
| 78 |     ])
 | 
| 79 | 
 | 
| 80 |   _legal_node_types.extend([
 | 
| 81 |     symbol.funcdef,
 | 
| 82 |     symbol.classdef,
 | 
| 83 |     symbol.stmt,
 | 
| 84 |     symbol.small_stmt,
 | 
| 85 |     symbol.flow_stmt,
 | 
| 86 |     symbol.simple_stmt,
 | 
| 87 |     symbol.compound_stmt,
 | 
| 88 |     symbol.expr_stmt,
 | 
| 89 |     symbol.print_stmt,
 | 
| 90 |     symbol.del_stmt,
 | 
| 91 |     symbol.pass_stmt,
 | 
| 92 |     symbol.break_stmt,
 | 
| 93 |     symbol.continue_stmt,
 | 
| 94 |     symbol.return_stmt,
 | 
| 95 |     symbol.raise_stmt,
 | 
| 96 |     symbol.import_stmt,
 | 
| 97 |     symbol.global_stmt,
 | 
| 98 |     symbol.exec_stmt,
 | 
| 99 |     symbol.assert_stmt,
 | 
| 100 |     symbol.if_stmt,
 | 
| 101 |     symbol.while_stmt,
 | 
| 102 |     symbol.for_stmt,
 | 
| 103 |     symbol.try_stmt,
 | 
| 104 |     symbol.with_stmt,
 | 
| 105 |     symbol.suite,
 | 
| 106 |     symbol.testlist,
 | 
| 107 |     symbol.testlist_safe,
 | 
| 108 |     symbol.test,
 | 
| 109 |     symbol.and_test,
 | 
| 110 |     symbol.not_test,
 | 
| 111 |     symbol.comparison,
 | 
| 112 |     symbol.exprlist,
 | 
| 113 |     symbol.expr,
 | 
| 114 |     symbol.xor_expr,
 | 
| 115 |     symbol.and_expr,
 | 
| 116 |     symbol.shift_expr,
 | 
| 117 |     symbol.arith_expr,
 | 
| 118 |     symbol.term,
 | 
| 119 |     symbol.factor,
 | 
| 120 |     symbol.power,
 | 
| 121 |     symbol.atom,
 | 
| 122 |     ])
 | 
| 123 | 
 | 
| 124 |   if hasattr(symbol, 'yield_stmt'):
 | 
| 125 |     _legal_node_types.append(symbol.yield_stmt)
 | 
| 126 |   if hasattr(symbol, 'yield_expr'):
 | 
| 127 |     _legal_node_types.append(symbol.yield_expr)
 | 
| 128 | 
 | 
| 129 |   _assign_types.extend([
 | 
| 130 |     symbol.test,
 | 
| 131 |     symbol.or_test,
 | 
| 132 |     symbol.and_test,
 | 
| 133 |     symbol.not_test,
 | 
| 134 |     symbol.comparison,
 | 
| 135 |     symbol.expr,
 | 
| 136 |     symbol.xor_expr,
 | 
| 137 |     symbol.and_expr,
 | 
| 138 |     symbol.shift_expr,
 | 
| 139 |     symbol.arith_expr,
 | 
| 140 |     symbol.term,
 | 
| 141 |     symbol.factor,
 | 
| 142 |     ])
 | 
| 143 | 
 | 
| 144 |   # Do this first because NT_OFFSET (non-terminal offset) conflicts with
 | 
| 145 |   # file_input.
 | 
| 146 |   for k, v in token.tok_name.items():
 | 
| 147 |       _names[k] = v
 | 
| 148 |   for k, v in symbol.number2symbol.items():
 | 
| 149 |       _names[k] = v
 | 
| 150 | 
 | 
| 151 | 
 | 
| 152 | # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
 | 
| 153 | #             | 'in' | 'not' 'in' | 'is' | 'is' 'not'
 | 
| 154 | _cmp_types = {
 | 
| 155 |     token.LESS : '<',
 | 
| 156 |     token.GREATER : '>',
 | 
| 157 |     token.EQEQUAL : '==',
 | 
| 158 |     token.EQUAL : '==',
 | 
| 159 |     token.LESSEQUAL : '<=',
 | 
| 160 |     token.GREATEREQUAL : '>=',
 | 
| 161 |     token.NOTEQUAL : '!=',
 | 
| 162 |     }
 | 
| 163 | 
 | 
| 164 | 
 | 
| 165 | class WalkerError(StandardError):
 | 
| 166 |     pass
 | 
| 167 | 
 | 
| 168 | 
 | 
| 169 | def asList(nodes):
 | 
| 170 |     l = []
 | 
| 171 |     for item in nodes:
 | 
| 172 |         if hasattr(item, "asList"):
 | 
| 173 |             l.append(item.asList())
 | 
| 174 |         else:
 | 
| 175 |             if type(item) is type( (None, None) ):
 | 
| 176 |                 l.append(tuple(asList(item)))
 | 
| 177 |             elif type(item) is type( [] ):
 | 
| 178 |                 l.append(asList(item))
 | 
| 179 |             else:
 | 
| 180 |                 l.append(item)
 | 
| 181 |     return l
 | 
| 182 | 
 | 
| 183 | def extractLineNo(ast):
 | 
| 184 |     if not isinstance(ast[1], tuple):
 | 
| 185 |         # get a terminal node
 | 
| 186 |         return ast[2]
 | 
| 187 |     for child in ast[1:]:
 | 
| 188 |         if isinstance(child, tuple):
 | 
| 189 |             lineno = extractLineNo(child)
 | 
| 190 |             if lineno is not None:
 | 
| 191 |                 return lineno
 | 
| 192 | 
 | 
| 193 | def Node(*args):
 | 
| 194 |     kind = args[0]
 | 
| 195 |     if kind in nodes:
 | 
| 196 |         try:
 | 
| 197 |             return nodes[kind](*args[1:])
 | 
| 198 |         except TypeError:
 | 
| 199 |             print(nodes[kind], len(args), args)
 | 
| 200 |             raise
 | 
| 201 |     else:
 | 
| 202 |         raise WalkerError, "Can't find appropriate Node type: %s" % str(args)
 | 
| 203 |         #return apply(ast.Node, args)
 | 
| 204 | 
 | 
| 205 | class Transformer(object):
 | 
| 206 |     """Transform a parse tree into an AST."""
 | 
| 207 | 
 | 
| 208 |     def __init__(self):
 | 
| 209 |         self._dispatch = {}
 | 
| 210 |         for value, name in symbol.number2symbol.items():
 | 
| 211 |             if hasattr(self, name):
 | 
| 212 |                 self._dispatch[value] = getattr(self, name)
 | 
| 213 |         self._dispatch[token.NEWLINE] = self.com_NEWLINE
 | 
| 214 |         self._atom_dispatch = {token.LPAR: self.atom_lpar,
 | 
| 215 |                                token.LSQB: self.atom_lsqb,
 | 
| 216 |                                token.LBRACE: self.atom_lbrace,
 | 
| 217 |                                token.BACKQUOTE: self.atom_backquote,
 | 
| 218 |                                token.NUMBER: self.atom_number,
 | 
| 219 |                                token.STRING: self.atom_string,
 | 
| 220 |                                token.NAME: self.atom_name,
 | 
| 221 |                                }
 | 
| 222 |         self.encoding = None
 | 
| 223 | 
 | 
| 224 |     def transform(self, node):
 | 
| 225 |         ### emit a line-number node?
 | 
| 226 |         n = node[0]
 | 
| 227 | 
 | 
| 228 |         if n == symbol.encoding_decl:
 | 
| 229 |             self.encoding = node[2]
 | 
| 230 |             node = node[1]
 | 
| 231 |             n = node[0]
 | 
| 232 | 
 | 
| 233 |         if n == symbol.single_input:
 | 
| 234 |             return self.single_input(node[1:])
 | 
| 235 |         if n == symbol.file_input:
 | 
| 236 |             return self.file_input(node[1:])
 | 
| 237 |         if n == symbol.eval_input:
 | 
| 238 |             return self.eval_input(node[1:])
 | 
| 239 |         if n == symbol.lambdef:
 | 
| 240 |             return self.lambdef(node[1:])
 | 
| 241 |         if n == symbol.funcdef:
 | 
| 242 |             return self.funcdef(node[1:])
 | 
| 243 |         if n == symbol.classdef:
 | 
| 244 |             return self.classdef(node[1:])
 | 
| 245 | 
 | 
| 246 |         raise WalkerError('unexpected node type %r' % type_repr(n))
 | 
| 247 | 
 | 
| 248 |     # --------------------------------------------------------------
 | 
| 249 |     #
 | 
| 250 |     # PRIVATE METHODS
 | 
| 251 |     #
 | 
| 252 | 
 | 
| 253 |     def single_input(self, node):
 | 
| 254 |         ### do we want to do anything about being "interactive" ?
 | 
| 255 | 
 | 
| 256 |         # NEWLINE | simple_stmt | compound_stmt NEWLINE
 | 
| 257 |         n = node[0][0]
 | 
| 258 |         if n != token.NEWLINE:
 | 
| 259 |             return self.com_stmt(node[0])
 | 
| 260 | 
 | 
| 261 |         return Pass()
 | 
| 262 | 
 | 
| 263 |     def file_input(self, nodelist):
 | 
| 264 |         doc = self.get_docstring(nodelist, symbol.file_input)
 | 
| 265 |         if doc is not None:
 | 
| 266 |             i = 1
 | 
| 267 |         else:
 | 
| 268 |             i = 0
 | 
| 269 |         stmts = []
 | 
| 270 |         for node in nodelist[i:]:
 | 
| 271 |             if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
 | 
| 272 |                 self.com_append_stmt(stmts, node)
 | 
| 273 |         return Module(doc, Stmt(stmts))
 | 
| 274 | 
 | 
| 275 |     def eval_input(self, nodelist):
 | 
| 276 |         # from the built-in function input()
 | 
| 277 |         ### is this sufficient?
 | 
| 278 |         return Expression(self.com_node(nodelist[0]))
 | 
| 279 | 
 | 
| 280 |     def decorator_name(self, nodelist):
 | 
| 281 |         listlen = len(nodelist)
 | 
| 282 |         assert listlen >= 1 and listlen % 2 == 1
 | 
| 283 | 
 | 
| 284 |         item = self.atom_name(nodelist)
 | 
| 285 |         i = 1
 | 
| 286 |         while i < listlen:
 | 
| 287 |             assert nodelist[i][0] == token.DOT
 | 
| 288 |             assert nodelist[i + 1][0] == token.NAME
 | 
| 289 |             item = Getattr(item, nodelist[i + 1][1])
 | 
| 290 |             i += 2
 | 
| 291 | 
 | 
| 292 |         return item
 | 
| 293 | 
 | 
| 294 |     def decorator(self, nodelist):
 | 
| 295 |         # '@' dotted_name [ '(' [arglist] ')' ]
 | 
| 296 |         assert len(nodelist) in (3, 5, 6)
 | 
| 297 |         assert nodelist[0][0] == token.AT
 | 
| 298 |         assert nodelist[-1][0] == token.NEWLINE
 | 
| 299 | 
 | 
| 300 |         assert nodelist[1][0] == symbol.dotted_name
 | 
| 301 |         funcname = self.decorator_name(nodelist[1][1:])
 | 
| 302 | 
 | 
| 303 |         if len(nodelist) > 3:
 | 
| 304 |             assert nodelist[2][0] == token.LPAR
 | 
| 305 |             expr = self.com_call_function(funcname, nodelist[3])
 | 
| 306 |         else:
 | 
| 307 |             expr = funcname
 | 
| 308 | 
 | 
| 309 |         return expr
 | 
| 310 | 
 | 
| 311 |     def decorators(self, nodelist):
 | 
| 312 |         # decorators: decorator ([NEWLINE] decorator)* NEWLINE
 | 
| 313 |         items = []
 | 
| 314 |         for dec_nodelist in nodelist:
 | 
| 315 |             assert dec_nodelist[0] == symbol.decorator
 | 
| 316 |             items.append(self.decorator(dec_nodelist[1:]))
 | 
| 317 |         return Decorators(items)
 | 
| 318 | 
 | 
| 319 |     def decorated(self, nodelist):
 | 
| 320 |         assert nodelist[0][0] == symbol.decorators
 | 
| 321 |         if nodelist[1][0] == symbol.funcdef:
 | 
| 322 |             n = [nodelist[0]] + list(nodelist[1][1:])
 | 
| 323 |             return self.funcdef(n)
 | 
| 324 |         elif nodelist[1][0] == symbol.classdef:
 | 
| 325 |             decorators = self.decorators(nodelist[0][1:])
 | 
| 326 |             cls = self.classdef(nodelist[1][1:])
 | 
| 327 |             cls.decorators = decorators
 | 
| 328 |             return cls
 | 
| 329 |         raise WalkerError()
 | 
| 330 | 
 | 
| 331 |     def funcdef(self, nodelist):
 | 
| 332 |         #                    -6   -5    -4         -3  -2    -1
 | 
| 333 |         # funcdef: [decorators] 'def' NAME parameters ':' suite
 | 
| 334 |         # parameters: '(' [varargslist] ')'
 | 
| 335 | 
 | 
| 336 |         if len(nodelist) == 6:
 | 
| 337 |             assert nodelist[0][0] == symbol.decorators
 | 
| 338 |             decorators = self.decorators(nodelist[0][1:])
 | 
| 339 |         else:
 | 
| 340 |             assert len(nodelist) == 5
 | 
| 341 |             decorators = None
 | 
| 342 | 
 | 
| 343 |         lineno = nodelist[-4][2]
 | 
| 344 |         name = nodelist[-4][1]
 | 
| 345 |         args = nodelist[-3][2]
 | 
| 346 | 
 | 
| 347 |         if args[0] == symbol.varargslist:
 | 
| 348 |             names, defaults, flags = self.com_arglist(args[1:])
 | 
| 349 |         else:
 | 
| 350 |             names = defaults = ()
 | 
| 351 |             flags = 0
 | 
| 352 |         doc = self.get_docstring(nodelist[-1])
 | 
| 353 | 
 | 
| 354 |         # code for function
 | 
| 355 |         code = self.com_node(nodelist[-1])
 | 
| 356 | 
 | 
| 357 |         if doc is not None:
 | 
| 358 |             assert isinstance(code, Stmt)
 | 
| 359 |             assert isinstance(code.nodes[0], Discard)
 | 
| 360 |             del code.nodes[0]
 | 
| 361 |         return Function(decorators, name, names, defaults, flags, doc, code,
 | 
| 362 |                      lineno=lineno)
 | 
| 363 | 
 | 
| 364 |     def lambdef(self, nodelist):
 | 
| 365 |         # lambdef: 'lambda' [varargslist] ':' test
 | 
| 366 |         if nodelist[2][0] == symbol.varargslist:
 | 
| 367 |             names, defaults, flags = self.com_arglist(nodelist[2][1:])
 | 
| 368 |         else:
 | 
| 369 |             names = defaults = ()
 | 
| 370 |             flags = 0
 | 
| 371 | 
 | 
| 372 |         # code for lambda
 | 
| 373 |         code = self.com_node(nodelist[-1])
 | 
| 374 | 
 | 
| 375 |         return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
 | 
| 376 |     old_lambdef = lambdef
 | 
| 377 | 
 | 
| 378 |     def classdef(self, nodelist):
 | 
| 379 |         # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
 | 
| 380 | 
 | 
| 381 |         name = nodelist[1][1]
 | 
| 382 |         doc = self.get_docstring(nodelist[-1])
 | 
| 383 |         if nodelist[2][0] == token.COLON:
 | 
| 384 |             bases = []
 | 
| 385 |         elif nodelist[3][0] == token.RPAR:
 | 
| 386 |             bases = []
 | 
| 387 |         else:
 | 
| 388 |             bases = self.com_bases(nodelist[3])
 | 
| 389 | 
 | 
| 390 |         # code for class
 | 
| 391 |         code = self.com_node(nodelist[-1])
 | 
| 392 | 
 | 
| 393 |         if doc is not None:
 | 
| 394 |             assert isinstance(code, Stmt)
 | 
| 395 |             assert isinstance(code.nodes[0], Discard)
 | 
| 396 |             del code.nodes[0]
 | 
| 397 | 
 | 
| 398 |         return Class(name, bases, doc, code, lineno=nodelist[1][2])
 | 
| 399 | 
 | 
| 400 |     def stmt(self, nodelist):
 | 
| 401 |         return self.com_stmt(nodelist[0])
 | 
| 402 | 
 | 
| 403 |     small_stmt = stmt
 | 
| 404 |     flow_stmt = stmt
 | 
| 405 |     compound_stmt = stmt
 | 
| 406 | 
 | 
| 407 |     def simple_stmt(self, nodelist):
 | 
| 408 |         # small_stmt (';' small_stmt)* [';'] NEWLINE
 | 
| 409 |         stmts = []
 | 
| 410 |         for i in range(0, len(nodelist), 2):
 | 
| 411 |             self.com_append_stmt(stmts, nodelist[i])
 | 
| 412 |         return Stmt(stmts)
 | 
| 413 | 
 | 
| 414 |     def parameters(self, nodelist):
 | 
| 415 |         raise WalkerError
 | 
| 416 | 
 | 
| 417 |     def varargslist(self, nodelist):
 | 
| 418 |         raise WalkerError
 | 
| 419 | 
 | 
| 420 |     def fpdef(self, nodelist):
 | 
| 421 |         raise WalkerError
 | 
| 422 | 
 | 
| 423 |     def fplist(self, nodelist):
 | 
| 424 |         raise WalkerError
 | 
| 425 | 
 | 
| 426 |     def dotted_name(self, nodelist):
 | 
| 427 |         raise WalkerError
 | 
| 428 | 
 | 
| 429 |     def comp_op(self, nodelist):
 | 
| 430 |         raise WalkerError
 | 
| 431 | 
 | 
| 432 |     def trailer(self, nodelist):
 | 
| 433 |         raise WalkerError
 | 
| 434 | 
 | 
| 435 |     def sliceop(self, nodelist):
 | 
| 436 |         raise WalkerError
 | 
| 437 | 
 | 
| 438 |     def argument(self, nodelist):
 | 
| 439 |         raise WalkerError
 | 
| 440 | 
 | 
| 441 |     # --------------------------------------------------------------
 | 
| 442 |     #
 | 
| 443 |     # STATEMENT NODES  (invoked by com_node())
 | 
| 444 |     #
 | 
| 445 | 
 | 
| 446 |     def expr_stmt(self, nodelist):
 | 
| 447 |         # augassign testlist | testlist ('=' testlist)*
 | 
| 448 |         en = nodelist[-1]
 | 
| 449 |         exprNode = self.lookup_node(en)(en[1:])
 | 
| 450 |         if len(nodelist) == 1:
 | 
| 451 |             return Discard(exprNode, lineno=exprNode.lineno)
 | 
| 452 |         if nodelist[1][0] == token.EQUAL:
 | 
| 453 |             nodesl = []
 | 
| 454 |             for i in range(0, len(nodelist) - 2, 2):
 | 
| 455 |                 nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
 | 
| 456 |             return Assign(nodesl, exprNode, lineno=nodelist[1][2])
 | 
| 457 |         else:
 | 
| 458 |             lval = self.com_augassign(nodelist[0])
 | 
| 459 |             op = self.com_augassign_op(nodelist[1])
 | 
| 460 |             return AugAssign(lval, op[1], exprNode, lineno=op[2])
 | 
| 461 |         raise WalkerError, "can't get here"
 | 
| 462 | 
 | 
| 463 |     def print_stmt(self, nodelist):
 | 
| 464 |         # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
 | 
| 465 |         items = []
 | 
| 466 |         if len(nodelist) == 1:
 | 
| 467 |             start = 1
 | 
| 468 |             dest = None
 | 
| 469 |         elif nodelist[1][0] == token.RIGHTSHIFT:
 | 
| 470 |             assert len(nodelist) == 3 \
 | 
| 471 |                    or nodelist[3][0] == token.COMMA
 | 
| 472 |             dest = self.com_node(nodelist[2])
 | 
| 473 |             start = 4
 | 
| 474 |         else:
 | 
| 475 |             dest = None
 | 
| 476 |             start = 1
 | 
| 477 |         for i in range(start, len(nodelist), 2):
 | 
| 478 |             items.append(self.com_node(nodelist[i]))
 | 
| 479 |         if nodelist[-1][0] == token.COMMA:
 | 
| 480 |             return Print(items, dest, lineno=nodelist[0][2])
 | 
| 481 |         return Printnl(items, dest, lineno=nodelist[0][2])
 | 
| 482 | 
 | 
| 483 |     def del_stmt(self, nodelist):
 | 
| 484 |         return self.com_assign(nodelist[1], OP_DELETE)
 | 
| 485 | 
 | 
| 486 |     def pass_stmt(self, nodelist):
 | 
| 487 |         return Pass(lineno=nodelist[0][2])
 | 
| 488 | 
 | 
| 489 |     def break_stmt(self, nodelist):
 | 
| 490 |         return Break(lineno=nodelist[0][2])
 | 
| 491 | 
 | 
| 492 |     def continue_stmt(self, nodelist):
 | 
| 493 |         return Continue(lineno=nodelist[0][2])
 | 
| 494 | 
 | 
| 495 |     def return_stmt(self, nodelist):
 | 
| 496 |         # return: [testlist]
 | 
| 497 |         if len(nodelist) < 2:
 | 
| 498 |             return Return(Const(None), lineno=nodelist[0][2])
 | 
| 499 |         return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
 | 
| 500 | 
 | 
| 501 |     def yield_stmt(self, nodelist):
 | 
| 502 |         expr = self.com_node(nodelist[0])
 | 
| 503 |         return Discard(expr, lineno=expr.lineno)
 | 
| 504 | 
 | 
| 505 |     def yield_expr(self, nodelist):
 | 
| 506 |         if len(nodelist) > 1:
 | 
| 507 |             value = self.com_node(nodelist[1])
 | 
| 508 |         else:
 | 
| 509 |             value = Const(None)
 | 
| 510 |         return Yield(value, lineno=nodelist[0][2])
 | 
| 511 | 
 | 
| 512 |     def raise_stmt(self, nodelist):
 | 
| 513 |         # raise: [test [',' test [',' test]]]
 | 
| 514 |         if len(nodelist) > 5:
 | 
| 515 |             expr3 = self.com_node(nodelist[5])
 | 
| 516 |         else:
 | 
| 517 |             expr3 = None
 | 
| 518 |         if len(nodelist) > 3:
 | 
| 519 |             expr2 = self.com_node(nodelist[3])
 | 
| 520 |         else:
 | 
| 521 |             expr2 = None
 | 
| 522 |         if len(nodelist) > 1:
 | 
| 523 |             expr1 = self.com_node(nodelist[1])
 | 
| 524 |         else:
 | 
| 525 |             expr1 = None
 | 
| 526 |         return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
 | 
| 527 | 
 | 
| 528 |     def import_stmt(self, nodelist):
 | 
| 529 |         # import_stmt: import_name | import_from
 | 
| 530 |         assert len(nodelist) == 1
 | 
| 531 |         return self.com_node(nodelist[0])
 | 
| 532 | 
 | 
| 533 |     def import_name(self, nodelist):
 | 
| 534 |         # import_name: 'import' dotted_as_names
 | 
| 535 |         return Import(self.com_dotted_as_names(nodelist[1]),
 | 
| 536 |                       lineno=nodelist[0][2])
 | 
| 537 | 
 | 
| 538 |     def import_from(self, nodelist):
 | 
| 539 |         # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
 | 
| 540 |         #    '(' import_as_names ')' | import_as_names)
 | 
| 541 |         assert nodelist[0][1] == 'from'
 | 
| 542 |         idx = 1
 | 
| 543 |         while nodelist[idx][1] == '.':
 | 
| 544 |             idx += 1
 | 
| 545 |         level = idx - 1
 | 
| 546 |         if nodelist[idx][0] == symbol.dotted_name:
 | 
| 547 |             fromname = self.com_dotted_name(nodelist[idx])
 | 
| 548 |             idx += 1
 | 
| 549 |         else:
 | 
| 550 |             fromname = ""
 | 
| 551 |         assert nodelist[idx][1] == 'import'
 | 
| 552 |         if nodelist[idx + 1][0] == token.STAR:
 | 
| 553 |             return From(fromname, [('*', None)], level,
 | 
| 554 |                         lineno=nodelist[0][2])
 | 
| 555 |         else:
 | 
| 556 |             node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
 | 
| 557 |             return From(fromname, self.com_import_as_names(node), level,
 | 
| 558 |                         lineno=nodelist[0][2])
 | 
| 559 | 
 | 
| 560 |     def global_stmt(self, nodelist):
 | 
| 561 |         # global: NAME (',' NAME)*
 | 
| 562 |         names = []
 | 
| 563 |         for i in range(1, len(nodelist), 2):
 | 
| 564 |             names.append(nodelist[i][1])
 | 
| 565 |         return Global(names, lineno=nodelist[0][2])
 | 
| 566 | 
 | 
| 567 |     def exec_stmt(self, nodelist):
 | 
| 568 |         # exec_stmt: 'exec' expr ['in' expr [',' expr]]
 | 
| 569 |         expr1 = self.com_node(nodelist[1])
 | 
| 570 |         if len(nodelist) >= 4:
 | 
| 571 |             expr2 = self.com_node(nodelist[3])
 | 
| 572 |             if len(nodelist) >= 6:
 | 
| 573 |                 expr3 = self.com_node(nodelist[5])
 | 
| 574 |             else:
 | 
| 575 |                 expr3 = None
 | 
| 576 |         else:
 | 
| 577 |             expr2 = expr3 = None
 | 
| 578 | 
 | 
| 579 |         return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
 | 
| 580 | 
 | 
| 581 |     def assert_stmt(self, nodelist):
 | 
| 582 |         # 'assert': test, [',' test]
 | 
| 583 |         expr1 = self.com_node(nodelist[1])
 | 
| 584 |         if (len(nodelist) == 4):
 | 
| 585 |             expr2 = self.com_node(nodelist[3])
 | 
| 586 |         else:
 | 
| 587 |             expr2 = None
 | 
| 588 |         return Assert(expr1, expr2, lineno=nodelist[0][2])
 | 
| 589 | 
 | 
| 590 |     def if_stmt(self, nodelist):
 | 
| 591 |         # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
 | 
| 592 |         tests = []
 | 
| 593 |         for i in range(0, len(nodelist) - 3, 4):
 | 
| 594 |             testNode = self.com_node(nodelist[i + 1])
 | 
| 595 |             suiteNode = self.com_node(nodelist[i + 3])
 | 
| 596 |             tests.append((testNode, suiteNode))
 | 
| 597 | 
 | 
| 598 |         if len(nodelist) % 4 == 3:
 | 
| 599 |             elseNode = self.com_node(nodelist[-1])
 | 
| 600 | ##      elseNode.lineno = nodelist[-1][1][2]
 | 
| 601 |         else:
 | 
| 602 |             elseNode = None
 | 
| 603 |         return If(tests, elseNode, lineno=nodelist[0][2])
 | 
| 604 | 
 | 
| 605 |     def while_stmt(self, nodelist):
 | 
| 606 |         # 'while' test ':' suite ['else' ':' suite]
 | 
| 607 | 
 | 
| 608 |         testNode = self.com_node(nodelist[1])
 | 
| 609 |         bodyNode = self.com_node(nodelist[3])
 | 
| 610 | 
 | 
| 611 |         if len(nodelist) > 4:
 | 
| 612 |             elseNode = self.com_node(nodelist[6])
 | 
| 613 |         else:
 | 
| 614 |             elseNode = None
 | 
| 615 | 
 | 
| 616 |         return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
 | 
| 617 | 
 | 
| 618 |     def for_stmt(self, nodelist):
 | 
| 619 |         # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
 | 
| 620 | 
 | 
| 621 |         assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
 | 
| 622 |         listNode = self.com_node(nodelist[3])
 | 
| 623 |         bodyNode = self.com_node(nodelist[5])
 | 
| 624 | 
 | 
| 625 |         if len(nodelist) > 8:
 | 
| 626 |             elseNode = self.com_node(nodelist[8])
 | 
| 627 |         else:
 | 
| 628 |             elseNode = None
 | 
| 629 | 
 | 
| 630 |         return For(assignNode, listNode, bodyNode, elseNode,
 | 
| 631 |                    lineno=nodelist[0][2])
 | 
| 632 | 
 | 
| 633 |     def try_stmt(self, nodelist):
 | 
| 634 |         return self.com_try_except_finally(nodelist)
 | 
| 635 | 
 | 
| 636 |     def with_stmt(self, nodelist):
 | 
| 637 |         return self.com_with(nodelist)
 | 
| 638 | 
 | 
| 639 |     def with_var(self, nodelist):
 | 
| 640 |         return self.com_with_var(nodelist)
 | 
| 641 | 
 | 
| 642 |     def suite(self, nodelist):
 | 
| 643 |         # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
 | 
| 644 |         if len(nodelist) == 1:
 | 
| 645 |             return self.com_stmt(nodelist[0])
 | 
| 646 | 
 | 
| 647 |         stmts = []
 | 
| 648 |         for node in nodelist:
 | 
| 649 |             if node[0] == symbol.stmt:
 | 
| 650 |                 self.com_append_stmt(stmts, node)
 | 
| 651 |         return Stmt(stmts)
 | 
| 652 | 
 | 
| 653 |     # --------------------------------------------------------------
 | 
| 654 |     #
 | 
| 655 |     # EXPRESSION NODES  (invoked by com_node())
 | 
| 656 |     #
 | 
| 657 | 
 | 
| 658 |     def testlist(self, nodelist):
 | 
| 659 |         # testlist: expr (',' expr)* [',']
 | 
| 660 |         # testlist_safe: test [(',' test)+ [',']]
 | 
| 661 |         # exprlist: expr (',' expr)* [',']
 | 
| 662 |         return self.com_binary(Tuple, nodelist)
 | 
| 663 | 
 | 
| 664 |     testlist_safe = testlist # XXX
 | 
| 665 |     testlist1 = testlist
 | 
| 666 |     exprlist = testlist
 | 
| 667 | 
 | 
| 668 |     def testlist_comp(self, nodelist):
 | 
| 669 |         # test ( comp_for | (',' test)* [','] )
 | 
| 670 |         assert nodelist[0][0] == symbol.test
 | 
| 671 |         if len(nodelist) == 2 and nodelist[1][0] == symbol.comp_for:
 | 
| 672 |             test = self.com_node(nodelist[0])
 | 
| 673 |             return self.com_generator_expression(test, nodelist[1])
 | 
| 674 |         return self.testlist(nodelist)
 | 
| 675 | 
 | 
| 676 |     def test(self, nodelist):
 | 
| 677 |         # or_test ['if' or_test 'else' test] | lambdef
 | 
| 678 |         if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
 | 
| 679 |             return self.lambdef(nodelist[0])
 | 
| 680 |         then = self.com_node(nodelist[0])
 | 
| 681 |         if len(nodelist) > 1:
 | 
| 682 |             assert len(nodelist) == 5
 | 
| 683 |             assert nodelist[1][1] == 'if'
 | 
| 684 |             assert nodelist[3][1] == 'else'
 | 
| 685 |             test = self.com_node(nodelist[2])
 | 
| 686 |             else_ = self.com_node(nodelist[4])
 | 
| 687 |             return IfExp(test, then, else_, lineno=nodelist[1][2])
 | 
| 688 |         return then
 | 
| 689 | 
 | 
| 690 |     def or_test(self, nodelist):
 | 
| 691 |         # and_test ('or' and_test)* | lambdef
 | 
| 692 |         if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
 | 
| 693 |             return self.lambdef(nodelist[0])
 | 
| 694 |         return self.com_binary(Or, nodelist)
 | 
| 695 |     old_test = or_test
 | 
| 696 | 
 | 
| 697 |     def and_test(self, nodelist):
 | 
| 698 |         # not_test ('and' not_test)*
 | 
| 699 |         return self.com_binary(And, nodelist)
 | 
| 700 | 
 | 
| 701 |     def not_test(self, nodelist):
 | 
| 702 |         # 'not' not_test | comparison
 | 
| 703 |         result = self.com_node(nodelist[-1])
 | 
| 704 |         if len(nodelist) == 2:
 | 
| 705 |             return Not(result, lineno=nodelist[0][2])
 | 
| 706 |         return result
 | 
| 707 | 
 | 
| 708 |     def comparison(self, nodelist):
 | 
| 709 |         # comparison: expr (comp_op expr)*
 | 
| 710 |         node = self.com_node(nodelist[0])
 | 
| 711 |         if len(nodelist) == 1:
 | 
| 712 |             return node
 | 
| 713 | 
 | 
| 714 |         results = []
 | 
| 715 |         for i in range(2, len(nodelist), 2):
 | 
| 716 |             nl = nodelist[i-1]
 | 
| 717 | 
 | 
| 718 |             # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
 | 
| 719 |             #          | 'in' | 'not' 'in' | 'is' | 'is' 'not'
 | 
| 720 |             n = nl[1]
 | 
| 721 |             if n[0] == token.NAME:
 | 
| 722 |                 type = n[1]
 | 
| 723 |                 if len(nl) == 3:
 | 
| 724 |                     if type == 'not':
 | 
| 725 |                         type = 'not in'
 | 
| 726 |                     else:
 | 
| 727 |                         type = 'is not'
 | 
| 728 |             else:
 | 
| 729 |                 type = _cmp_types[n[0]]
 | 
| 730 | 
 | 
| 731 |             lineno = nl[1][2]
 | 
| 732 |             results.append((type, self.com_node(nodelist[i])))
 | 
| 733 | 
 | 
| 734 |         # we need a special "compare" node so that we can distinguish
 | 
| 735 |         #   3 < x < 5   from    (3 < x) < 5
 | 
| 736 |         # the two have very different semantics and results (note that the
 | 
| 737 |         # latter form is always true)
 | 
| 738 | 
 | 
| 739 |         return Compare(node, results, lineno=lineno)
 | 
| 740 | 
 | 
| 741 |     def expr(self, nodelist):
 | 
| 742 |         # xor_expr ('|' xor_expr)*
 | 
| 743 |         return self.com_binary(Bitor, nodelist)
 | 
| 744 | 
 | 
| 745 |     def xor_expr(self, nodelist):
 | 
| 746 |         # xor_expr ('^' xor_expr)*
 | 
| 747 |         return self.com_binary(Bitxor, nodelist)
 | 
| 748 | 
 | 
| 749 |     def and_expr(self, nodelist):
 | 
| 750 |         # xor_expr ('&' xor_expr)*
 | 
| 751 |         return self.com_binary(Bitand, nodelist)
 | 
| 752 | 
 | 
| 753 |     def shift_expr(self, nodelist):
 | 
| 754 |         # shift_expr ('<<'|'>>' shift_expr)*
 | 
| 755 |         node = self.com_node(nodelist[0])
 | 
| 756 |         for i in range(2, len(nodelist), 2):
 | 
| 757 |             right = self.com_node(nodelist[i])
 | 
| 758 |             if nodelist[i-1][0] == token.LEFTSHIFT:
 | 
| 759 |                 node = LeftShift([node, right], lineno=nodelist[1][2])
 | 
| 760 |             elif nodelist[i-1][0] == token.RIGHTSHIFT:
 | 
| 761 |                 node = RightShift([node, right], lineno=nodelist[1][2])
 | 
| 762 |             else:
 | 
| 763 |                 raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
 | 
| 764 |         return node
 | 
| 765 | 
 | 
| 766 |     def arith_expr(self, nodelist):
 | 
| 767 |         node = self.com_node(nodelist[0])
 | 
| 768 |         for i in range(2, len(nodelist), 2):
 | 
| 769 |             right = self.com_node(nodelist[i])
 | 
| 770 |             if nodelist[i-1][0] == token.PLUS:
 | 
| 771 |                 node = Add([node, right], lineno=nodelist[1][2])
 | 
| 772 |             elif nodelist[i-1][0] == token.MINUS:
 | 
| 773 |                 node = Sub([node, right], lineno=nodelist[1][2])
 | 
| 774 |             else:
 | 
| 775 |                 raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
 | 
| 776 |         return node
 | 
| 777 | 
 | 
| 778 |     def term(self, nodelist):
 | 
| 779 |         node = self.com_node(nodelist[0])
 | 
| 780 |         for i in range(2, len(nodelist), 2):
 | 
| 781 |             right = self.com_node(nodelist[i])
 | 
| 782 |             t = nodelist[i-1][0]
 | 
| 783 |             if t == token.STAR:
 | 
| 784 |                 node = Mul([node, right])
 | 
| 785 |             elif t == token.SLASH:
 | 
| 786 |                 node = Div([node, right])
 | 
| 787 |             elif t == token.PERCENT:
 | 
| 788 |                 node = Mod([node, right])
 | 
| 789 |             elif t == token.DOUBLESLASH:
 | 
| 790 |                 node = FloorDiv([node, right])
 | 
| 791 |             else:
 | 
| 792 |                 raise ValueError, "unexpected token: %s" % t
 | 
| 793 |             node.lineno = nodelist[1][2]
 | 
| 794 |         return node
 | 
| 795 | 
 | 
| 796 |     def factor(self, nodelist):
 | 
| 797 |         elt = nodelist[0]
 | 
| 798 |         t = elt[0]
 | 
| 799 |         node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
 | 
| 800 |         # need to handle (unary op)constant here...
 | 
| 801 |         if t == token.PLUS:
 | 
| 802 |             return UnaryAdd(node, lineno=elt[2])
 | 
| 803 |         elif t == token.MINUS:
 | 
| 804 |             return UnarySub(node, lineno=elt[2])
 | 
| 805 |         elif t == token.TILDE:
 | 
| 806 |             node = Invert(node, lineno=elt[2])
 | 
| 807 |         return node
 | 
| 808 | 
 | 
| 809 |     def power(self, nodelist):
 | 
| 810 |         # power: atom trailer* ['**' factor]
 | 
| 811 |         node = self.com_node(nodelist[0])
 | 
| 812 |         for i in range(1, len(nodelist)):
 | 
| 813 |             elt = nodelist[i]
 | 
| 814 |             if elt[0] == token.DOUBLESTAR:
 | 
| 815 |                 return Power([node, self.com_node(nodelist[i+1])],
 | 
| 816 |                              lineno=elt[2])
 | 
| 817 | 
 | 
| 818 |             node = self.com_apply_trailer(node, elt)
 | 
| 819 | 
 | 
| 820 |         return node
 | 
| 821 | 
 | 
| 822 |     def atom(self, nodelist):
 | 
| 823 |         return self._atom_dispatch[nodelist[0][0]](nodelist)
 | 
| 824 | 
 | 
| 825 |     def atom_lpar(self, nodelist):
 | 
| 826 |         if nodelist[1][0] == token.RPAR:
 | 
| 827 |             return Tuple((), lineno=nodelist[0][2])
 | 
| 828 |         return self.com_node(nodelist[1])
 | 
| 829 | 
 | 
| 830 |     def atom_lsqb(self, nodelist):
 | 
| 831 |         if nodelist[1][0] == token.RSQB:
 | 
| 832 |             return List((), lineno=nodelist[0][2])
 | 
| 833 |         return self.com_list_constructor(nodelist[1])
 | 
| 834 | 
 | 
| 835 |     def atom_lbrace(self, nodelist):
 | 
| 836 |         if nodelist[1][0] == token.RBRACE:
 | 
| 837 |             return Dict((), lineno=nodelist[0][2])
 | 
| 838 |         return self.com_dictorsetmaker(nodelist[1])
 | 
| 839 | 
 | 
| 840 |     def atom_backquote(self, nodelist):
 | 
| 841 |         return Backquote(self.com_node(nodelist[1]))
 | 
| 842 | 
 | 
| 843 |     def atom_number(self, nodelist):
 | 
| 844 |         ### need to verify this matches compile.c
 | 
| 845 |         k = eval(nodelist[0][1])
 | 
| 846 |         return Const(k, lineno=nodelist[0][2])
 | 
| 847 | 
 | 
| 848 |     def decode_literal(self, lit):
 | 
| 849 |         if self.encoding:
 | 
| 850 |             # this is particularly fragile & a bit of a
 | 
| 851 |             # hack... changes in compile.c:parsestr and
 | 
| 852 |             # tokenizer.c must be reflected here.
 | 
| 853 |             if self.encoding not in ['utf-8', 'iso-8859-1']:
 | 
| 854 |                 lit = unicode(lit, 'utf-8').encode(self.encoding)
 | 
| 855 |             return eval("# coding: %s\n%s" % (self.encoding, lit))
 | 
| 856 |         else:
 | 
| 857 |             return eval(lit)
 | 
| 858 | 
 | 
| 859 |     def atom_string(self, nodelist):
 | 
| 860 |         k = ''
 | 
| 861 |         for node in nodelist:
 | 
| 862 |             k += self.decode_literal(node[1])
 | 
| 863 |         return Const(k, lineno=nodelist[0][2])
 | 
| 864 | 
 | 
| 865 |     def atom_name(self, nodelist):
 | 
| 866 |         return Name(nodelist[0][1], lineno=nodelist[0][2])
 | 
| 867 | 
 | 
| 868 |     # --------------------------------------------------------------
 | 
| 869 |     #
 | 
| 870 |     # INTERNAL PARSING UTILITIES
 | 
| 871 |     #
 | 
| 872 | 
 | 
| 873 |     # The use of com_node() introduces a lot of extra stack frames,
 | 
| 874 |     # enough to cause a stack overflow compiling test.test_parser with
 | 
| 875 |     # the standard interpreter recursionlimit.  The com_node() is a
 | 
| 876 |     # convenience function that hides the dispatch details, but comes
 | 
| 877 |     # at a very high cost.  It is more efficient to dispatch directly
 | 
| 878 |     # in the callers.  In these cases, use lookup_node() and call the
 | 
| 879 |     # dispatched node directly.
 | 
| 880 | 
 | 
| 881 |     def lookup_node(self, node):
 | 
| 882 |         return self._dispatch[node[0]]
 | 
| 883 | 
 | 
| 884 |     def com_node(self, node):
 | 
| 885 |         # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
 | 
| 886 |         #       break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
 | 
| 887 |         #       and compound_stmt.
 | 
| 888 |         #       We'll just dispatch them.
 | 
| 889 |         return self._dispatch[node[0]](node[1:])
 | 
| 890 | 
 | 
| 891 |     def com_NEWLINE(self, *args):
 | 
| 892 |         # A ';' at the end of a line can make a NEWLINE token appear
 | 
| 893 |         # here, Render it harmless. (genc discards ('discard',
 | 
| 894 |         # ('const', xxxx)) Nodes)
 | 
| 895 |         return Discard(Const(None))
 | 
| 896 | 
 | 
| 897 |     def com_arglist(self, nodelist):
 | 
| 898 |         # varargslist:
 | 
| 899 |         #     (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
 | 
| 900 |         #   | fpdef ['=' test] (',' fpdef ['=' test])* [',']
 | 
| 901 |         # fpdef: NAME | '(' fplist ')'
 | 
| 902 |         # fplist: fpdef (',' fpdef)* [',']
 | 
| 903 |         names = []
 | 
| 904 |         defaults = []
 | 
| 905 |         flags = 0
 | 
| 906 | 
 | 
| 907 |         i = 0
 | 
| 908 |         while i < len(nodelist):
 | 
| 909 |             node = nodelist[i]
 | 
| 910 |             if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
 | 
| 911 |                 if node[0] == token.STAR:
 | 
| 912 |                     node = nodelist[i+1]
 | 
| 913 |                     if node[0] == token.NAME:
 | 
| 914 |                         names.append(node[1])
 | 
| 915 |                         flags = flags | CO_VARARGS
 | 
| 916 |                         i = i + 3
 | 
| 917 | 
 | 
| 918 |                 if i < len(nodelist):
 | 
| 919 |                     # should be DOUBLESTAR
 | 
| 920 |                     t = nodelist[i][0]
 | 
| 921 |                     if t == token.DOUBLESTAR:
 | 
| 922 |                         node = nodelist[i+1]
 | 
| 923 |                     else:
 | 
| 924 |                         raise ValueError, "unexpected token: %s" % t
 | 
| 925 |                     names.append(node[1])
 | 
| 926 |                     flags = flags | CO_VARKEYWORDS
 | 
| 927 | 
 | 
| 928 |                 break
 | 
| 929 | 
 | 
| 930 |             # fpdef: NAME | '(' fplist ')'
 | 
| 931 |             names.append(self.com_fpdef(node))
 | 
| 932 | 
 | 
| 933 |             i = i + 1
 | 
| 934 |             if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
 | 
| 935 |                 defaults.append(self.com_node(nodelist[i + 1]))
 | 
| 936 |                 i = i + 2
 | 
| 937 |             elif len(defaults):
 | 
| 938 |                 # we have already seen an argument with default, but here
 | 
| 939 |                 # came one without
 | 
| 940 |                 raise SyntaxError, "non-default argument follows default argument"
 | 
| 941 | 
 | 
| 942 |             # skip the comma
 | 
| 943 |             i = i + 1
 | 
| 944 | 
 | 
| 945 |         return names, defaults, flags
 | 
| 946 | 
 | 
| 947 |     def com_fpdef(self, node):
 | 
| 948 |         # fpdef: NAME | '(' fplist ')'
 | 
| 949 |         if node[1][0] == token.LPAR:
 | 
| 950 |             return self.com_fplist(node[2])
 | 
| 951 |         return node[1][1]
 | 
| 952 | 
 | 
| 953 |     def com_fplist(self, node):
 | 
| 954 |         # fplist: fpdef (',' fpdef)* [',']
 | 
| 955 |         if len(node) == 2:
 | 
| 956 |             return self.com_fpdef(node[1])
 | 
| 957 |         list = []
 | 
| 958 |         for i in range(1, len(node), 2):
 | 
| 959 |             list.append(self.com_fpdef(node[i]))
 | 
| 960 |         return tuple(list)
 | 
| 961 | 
 | 
| 962 |     def com_dotted_name(self, node):
 | 
| 963 |         # String together the dotted names and return the string
 | 
| 964 |         name = ""
 | 
| 965 |         for n in node:
 | 
| 966 |             if type(n) == type(()) and n[0] == 1:
 | 
| 967 |                 name = name + n[1] + '.'
 | 
| 968 |         return name[:-1]
 | 
| 969 | 
 | 
| 970 |     def com_dotted_as_name(self, node):
 | 
| 971 |         assert node[0] == symbol.dotted_as_name
 | 
| 972 |         node = node[1:]
 | 
| 973 |         dot = self.com_dotted_name(node[0][1:])
 | 
| 974 |         if len(node) == 1:
 | 
| 975 |             return dot, None
 | 
| 976 |         assert node[1][1] == 'as'
 | 
| 977 |         assert node[2][0] == token.NAME
 | 
| 978 |         return dot, node[2][1]
 | 
| 979 | 
 | 
| 980 |     def com_dotted_as_names(self, node):
 | 
| 981 |         assert node[0] == symbol.dotted_as_names
 | 
| 982 |         node = node[1:]
 | 
| 983 |         names = [self.com_dotted_as_name(node[0])]
 | 
| 984 |         for i in range(2, len(node), 2):
 | 
| 985 |             names.append(self.com_dotted_as_name(node[i]))
 | 
| 986 |         return names
 | 
| 987 | 
 | 
| 988 |     def com_import_as_name(self, node):
 | 
| 989 |         assert node[0] == symbol.import_as_name
 | 
| 990 |         node = node[1:]
 | 
| 991 |         assert node[0][0] == token.NAME
 | 
| 992 |         if len(node) == 1:
 | 
| 993 |             return node[0][1], None
 | 
| 994 |         assert node[1][1] == 'as', node
 | 
| 995 |         assert node[2][0] == token.NAME
 | 
| 996 |         return node[0][1], node[2][1]
 | 
| 997 | 
 | 
| 998 |     def com_import_as_names(self, node):
 | 
| 999 |         assert node[0] == symbol.import_as_names
 | 
| 1000 |         node = node[1:]
 | 
| 1001 |         names = [self.com_import_as_name(node[0])]
 | 
| 1002 |         for i in range(2, len(node), 2):
 | 
| 1003 |             names.append(self.com_import_as_name(node[i]))
 | 
| 1004 |         return names
 | 
| 1005 | 
 | 
| 1006 |     def com_bases(self, node):
 | 
| 1007 |         bases = []
 | 
| 1008 |         for i in range(1, len(node), 2):
 | 
| 1009 |             bases.append(self.com_node(node[i]))
 | 
| 1010 |         return bases
 | 
| 1011 | 
 | 
| 1012 |     def com_try_except_finally(self, nodelist):
 | 
| 1013 |         # ('try' ':' suite
 | 
| 1014 |         #  ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite]
 | 
| 1015 |         #   | 'finally' ':' suite))
 | 
| 1016 | 
 | 
| 1017 |         if nodelist[3][0] == token.NAME:
 | 
| 1018 |             # first clause is a finally clause: only try-finally
 | 
| 1019 |             return TryFinally(self.com_node(nodelist[2]),
 | 
| 1020 |                               self.com_node(nodelist[5]),
 | 
| 1021 |                               lineno=nodelist[0][2])
 | 
| 1022 | 
 | 
| 1023 |         #tryexcept:  [TryNode, [except_clauses], elseNode)]
 | 
| 1024 |         clauses = []
 | 
| 1025 |         elseNode = None
 | 
| 1026 |         finallyNode = None
 | 
| 1027 |         for i in range(3, len(nodelist), 3):
 | 
| 1028 |             node = nodelist[i]
 | 
| 1029 |             if node[0] == symbol.except_clause:
 | 
| 1030 |                 # except_clause: 'except' [expr [(',' | 'as') expr]] */
 | 
| 1031 |                 if len(node) > 2:
 | 
| 1032 |                     expr1 = self.com_node(node[2])
 | 
| 1033 |                     if len(node) > 4:
 | 
| 1034 |                         expr2 = self.com_assign(node[4], OP_ASSIGN)
 | 
| 1035 |                     else:
 | 
| 1036 |                         expr2 = None
 | 
| 1037 |                 else:
 | 
| 1038 |                     expr1 = expr2 = None
 | 
| 1039 |                 clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
 | 
| 1040 | 
 | 
| 1041 |             if node[0] == token.NAME:
 | 
| 1042 |                 if node[1] == 'else':
 | 
| 1043 |                     elseNode = self.com_node(nodelist[i+2])
 | 
| 1044 |                 elif node[1] == 'finally':
 | 
| 1045 |                     finallyNode = self.com_node(nodelist[i+2])
 | 
| 1046 |         try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
 | 
| 1047 |                                lineno=nodelist[0][2])
 | 
| 1048 |         if finallyNode:
 | 
| 1049 |             return TryFinally(try_except, finallyNode, lineno=nodelist[0][2])
 | 
| 1050 |         else:
 | 
| 1051 |             return try_except
 | 
| 1052 | 
 | 
| 1053 |     def com_with(self, nodelist):
 | 
| 1054 |         # with_stmt: 'with' with_item (',' with_item)* ':' suite
 | 
| 1055 |         body = self.com_node(nodelist[-1])
 | 
| 1056 |         for i in range(len(nodelist) - 3, 0, -2):
 | 
| 1057 |             ret = self.com_with_item(nodelist[i], body, nodelist[0][2])
 | 
| 1058 |             if i == 1:
 | 
| 1059 |                 return ret
 | 
| 1060 |             body = ret
 | 
| 1061 | 
 | 
| 1062 |     def com_with_item(self, nodelist, body, lineno):
 | 
| 1063 |         # with_item: test ['as' expr]
 | 
| 1064 |         if len(nodelist) == 4:
 | 
| 1065 |             var = self.com_assign(nodelist[3], OP_ASSIGN)
 | 
| 1066 |         else:
 | 
| 1067 |             var = None
 | 
| 1068 |         expr = self.com_node(nodelist[1])
 | 
| 1069 |         return With(expr, var, body, lineno=lineno)
 | 
| 1070 | 
 | 
| 1071 |     def com_augassign_op(self, node):
 | 
| 1072 |         assert node[0] == symbol.augassign
 | 
| 1073 |         return node[1]
 | 
| 1074 | 
 | 
| 1075 |     def com_augassign(self, node):
 | 
| 1076 |         """Return node suitable for lvalue of augmented assignment
 | 
| 1077 | 
 | 
| 1078 |         Names, slices, and attributes are the only allowable nodes.
 | 
| 1079 |         """
 | 
| 1080 |         l = self.com_node(node)
 | 
| 1081 |         if l.__class__ in (Name, Slice, Subscript, Getattr):
 | 
| 1082 |             return l
 | 
| 1083 |         raise SyntaxError, "can't assign to %s" % l.__class__.__name__
 | 
| 1084 | 
 | 
| 1085 |     def com_assign(self, node, assigning):
 | 
| 1086 |         # return a node suitable for use as an "lvalue"
 | 
| 1087 |         # loop to avoid trivial recursion
 | 
| 1088 |         while 1:
 | 
| 1089 |             t = node[0]
 | 
| 1090 |             if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_comp):
 | 
| 1091 |                 if len(node) > 2:
 | 
| 1092 |                     return self.com_assign_tuple(node, assigning)
 | 
| 1093 |                 node = node[1]
 | 
| 1094 |             elif t in _assign_types:
 | 
| 1095 |                 if len(node) > 2:
 | 
| 1096 |                     raise SyntaxError, "can't assign to operator"
 | 
| 1097 |                 node = node[1]
 | 
| 1098 |             elif t == symbol.power:
 | 
| 1099 |                 if node[1][0] != symbol.atom:
 | 
| 1100 |                     raise SyntaxError, "can't assign to operator"
 | 
| 1101 |                 if len(node) > 2:
 | 
| 1102 |                     primary = self.com_node(node[1])
 | 
| 1103 |                     for i in range(2, len(node)-1):
 | 
| 1104 |                         ch = node[i]
 | 
| 1105 |                         if ch[0] == token.DOUBLESTAR:
 | 
| 1106 |                             raise SyntaxError, "can't assign to operator"
 | 
| 1107 |                         primary = self.com_apply_trailer(primary, ch)
 | 
| 1108 |                     return self.com_assign_trailer(primary, node[-1],
 | 
| 1109 |                                                    assigning)
 | 
| 1110 |                 node = node[1]
 | 
| 1111 |             elif t == symbol.atom:
 | 
| 1112 |                 t = node[1][0]
 | 
| 1113 |                 if t == token.LPAR:
 | 
| 1114 |                     node = node[2]
 | 
| 1115 |                     if node[0] == token.RPAR:
 | 
| 1116 |                         raise SyntaxError, "can't assign to ()"
 | 
| 1117 |                 elif t == token.LSQB:
 | 
| 1118 |                     node = node[2]
 | 
| 1119 |                     if node[0] == token.RSQB:
 | 
| 1120 |                         raise SyntaxError, "can't assign to []"
 | 
| 1121 |                     return self.com_assign_list(node, assigning)
 | 
| 1122 |                 elif t == token.NAME:
 | 
| 1123 |                     return self.com_assign_name(node[1], assigning)
 | 
| 1124 |                 else:
 | 
| 1125 |                     raise SyntaxError, "can't assign to literal"
 | 
| 1126 |             else:
 | 
| 1127 |                 raise SyntaxError, "bad assignment (%s)" % t
 | 
| 1128 | 
 | 
| 1129 |     def com_assign_tuple(self, node, assigning):
 | 
| 1130 |         assigns = []
 | 
| 1131 |         for i in range(1, len(node), 2):
 | 
| 1132 |             assigns.append(self.com_assign(node[i], assigning))
 | 
| 1133 |         return AssTuple(assigns, lineno=extractLineNo(node))
 | 
| 1134 | 
 | 
| 1135 |     def com_assign_list(self, node, assigning):
 | 
| 1136 |         assigns = []
 | 
| 1137 |         for i in range(1, len(node), 2):
 | 
| 1138 |             if i + 1 < len(node):
 | 
| 1139 |                 if node[i + 1][0] == symbol.list_for:
 | 
| 1140 |                     raise SyntaxError, "can't assign to list comprehension"
 | 
| 1141 |                 assert node[i + 1][0] == token.COMMA, node[i + 1]
 | 
| 1142 |             assigns.append(self.com_assign(node[i], assigning))
 | 
| 1143 |         return AssList(assigns, lineno=extractLineNo(node))
 | 
| 1144 | 
 | 
| 1145 |     def com_assign_name(self, node, assigning):
 | 
| 1146 |         return AssName(node[1], assigning, lineno=node[2])
 | 
| 1147 | 
 | 
| 1148 |     def com_assign_trailer(self, primary, node, assigning):
 | 
| 1149 |         t = node[1][0]
 | 
| 1150 |         if t == token.DOT:
 | 
| 1151 |             return self.com_assign_attr(primary, node[2], assigning)
 | 
| 1152 |         if t == token.LSQB:
 | 
| 1153 |             return self.com_subscriptlist(primary, node[2], assigning)
 | 
| 1154 |         if t == token.LPAR:
 | 
| 1155 |             raise SyntaxError, "can't assign to function call"
 | 
| 1156 |         raise SyntaxError, "unknown trailer type: %s" % t
 | 
| 1157 | 
 | 
| 1158 |     def com_assign_attr(self, primary, node, assigning):
 | 
| 1159 |         return AssAttr(primary, node[1], assigning, lineno=node[-1])
 | 
| 1160 | 
 | 
| 1161 |     def com_binary(self, constructor, nodelist):
 | 
| 1162 |         "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
 | 
| 1163 |         l = len(nodelist)
 | 
| 1164 |         if l == 1:
 | 
| 1165 |             n = nodelist[0]
 | 
| 1166 |             return self.lookup_node(n)(n[1:])
 | 
| 1167 |         items = []
 | 
| 1168 |         for i in range(0, l, 2):
 | 
| 1169 |             n = nodelist[i]
 | 
| 1170 |             items.append(self.lookup_node(n)(n[1:]))
 | 
| 1171 |         return constructor(items, lineno=extractLineNo(nodelist))
 | 
| 1172 | 
 | 
| 1173 |     def com_stmt(self, node):
 | 
| 1174 |         result = self.lookup_node(node)(node[1:])
 | 
| 1175 |         assert result is not None
 | 
| 1176 |         if isinstance(result, Stmt):
 | 
| 1177 |             return result
 | 
| 1178 |         return Stmt([result])
 | 
| 1179 | 
 | 
| 1180 |     def com_append_stmt(self, stmts, node):
 | 
| 1181 |         result = self.lookup_node(node)(node[1:])
 | 
| 1182 |         assert result is not None
 | 
| 1183 |         if isinstance(result, Stmt):
 | 
| 1184 |             stmts.extend(result.nodes)
 | 
| 1185 |         else:
 | 
| 1186 |             stmts.append(result)
 | 
| 1187 | 
 | 
| 1188 |     def com_list_constructor(self, nodelist):
 | 
| 1189 |         # listmaker: test ( list_for | (',' test)* [','] )
 | 
| 1190 |         values = []
 | 
| 1191 |         for i in range(1, len(nodelist)):
 | 
| 1192 |             if nodelist[i][0] == symbol.list_for:
 | 
| 1193 |                 assert len(nodelist[i:]) == 1
 | 
| 1194 |                 return self.com_list_comprehension(values[0],
 | 
| 1195 |                                                    nodelist[i])
 | 
| 1196 |             elif nodelist[i][0] == token.COMMA:
 | 
| 1197 |                 continue
 | 
| 1198 |             values.append(self.com_node(nodelist[i]))
 | 
| 1199 |         return List(values, lineno=values[0].lineno)
 | 
| 1200 | 
 | 
| 1201 |     def com_list_comprehension(self, expr, node):
 | 
| 1202 |         return self.com_comprehension(expr, None, node, 'list')
 | 
| 1203 | 
 | 
| 1204 |     def com_comprehension(self, expr1, expr2, node, type):
 | 
| 1205 |         # list_iter: list_for | list_if
 | 
| 1206 |         # list_for: 'for' exprlist 'in' testlist [list_iter]
 | 
| 1207 |         # list_if: 'if' test [list_iter]
 | 
| 1208 | 
 | 
| 1209 |         # XXX should raise SyntaxError for assignment
 | 
| 1210 |         # XXX(avassalotti) Set and dict comprehensions should have generator
 | 
| 1211 |         #                  semantics. In other words, they shouldn't leak
 | 
| 1212 |         #                  variables outside of the comprehension's scope.
 | 
| 1213 | 
 | 
| 1214 |         lineno = node[1][2]
 | 
| 1215 |         fors = []
 | 
| 1216 |         while node:
 | 
| 1217 |             t = node[1][1]
 | 
| 1218 |             if t == 'for':
 | 
| 1219 |                 assignNode = self.com_assign(node[2], OP_ASSIGN)
 | 
| 1220 |                 compNode = self.com_node(node[4])
 | 
| 1221 |                 newfor = ListCompFor(assignNode, compNode, [])
 | 
| 1222 |                 newfor.lineno = node[1][2]
 | 
| 1223 |                 fors.append(newfor)
 | 
| 1224 |                 if len(node) == 5:
 | 
| 1225 |                     node = None
 | 
| 1226 |                 elif type == 'list':
 | 
| 1227 |                     node = self.com_list_iter(node[5])
 | 
| 1228 |                 else:
 | 
| 1229 |                     node = self.com_comp_iter(node[5])
 | 
| 1230 |             elif t == 'if':
 | 
| 1231 |                 test = self.com_node(node[2])
 | 
| 1232 |                 newif = ListCompIf(test, lineno=node[1][2])
 | 
| 1233 |                 newfor.ifs.append(newif)
 | 
| 1234 |                 if len(node) == 3:
 | 
| 1235 |                     node = None
 | 
| 1236 |                 elif type == 'list':
 | 
| 1237 |                     node = self.com_list_iter(node[3])
 | 
| 1238 |                 else:
 | 
| 1239 |                     node = self.com_comp_iter(node[3])
 | 
| 1240 |             else:
 | 
| 1241 |                 raise SyntaxError, \
 | 
| 1242 |                       ("unexpected comprehension element: %s %d"
 | 
| 1243 |                        % (node, lineno))
 | 
| 1244 |         if type == 'list':
 | 
| 1245 |             return ListComp(expr1, fors, lineno=lineno)
 | 
| 1246 |         elif type == 'set':
 | 
| 1247 |             return SetComp(expr1, fors, lineno=lineno)
 | 
| 1248 |         elif type == 'dict':
 | 
| 1249 |             return DictComp(expr1, expr2, fors, lineno=lineno)
 | 
| 1250 |         else:
 | 
| 1251 |             raise ValueError("unexpected comprehension type: " + repr(type))
 | 
| 1252 | 
 | 
| 1253 |     def com_list_iter(self, node):
 | 
| 1254 |         assert node[0] == symbol.list_iter
 | 
| 1255 |         return node[1]
 | 
| 1256 | 
 | 
| 1257 |     def com_comp_iter(self, node):
 | 
| 1258 |         assert node[0] == symbol.comp_iter
 | 
| 1259 |         return node[1]
 | 
| 1260 | 
 | 
| 1261 |     def com_generator_expression(self, expr, node):
 | 
| 1262 |         # comp_iter: comp_for | comp_if
 | 
| 1263 |         # comp_for: 'for' exprlist 'in' test [comp_iter]
 | 
| 1264 |         # comp_if: 'if' test [comp_iter]
 | 
| 1265 | 
 | 
| 1266 |         lineno = node[1][2]
 | 
| 1267 |         fors = []
 | 
| 1268 |         while node:
 | 
| 1269 |             t = node[1][1]
 | 
| 1270 |             if t == 'for':
 | 
| 1271 |                 assignNode = self.com_assign(node[2], OP_ASSIGN)
 | 
| 1272 |                 genNode = self.com_node(node[4])
 | 
| 1273 |                 newfor = GenExprFor(assignNode, genNode, [],
 | 
| 1274 |                                     lineno=node[1][2])
 | 
| 1275 |                 fors.append(newfor)
 | 
| 1276 |                 if (len(node)) == 5:
 | 
| 1277 |                     node = None
 | 
| 1278 |                 else:
 | 
| 1279 |                     node = self.com_comp_iter(node[5])
 | 
| 1280 |             elif t == 'if':
 | 
| 1281 |                 test = self.com_node(node[2])
 | 
| 1282 |                 newif = GenExprIf(test, lineno=node[1][2])
 | 
| 1283 |                 newfor.ifs.append(newif)
 | 
| 1284 |                 if len(node) == 3:
 | 
| 1285 |                     node = None
 | 
| 1286 |                 else:
 | 
| 1287 |                     node = self.com_comp_iter(node[3])
 | 
| 1288 |             else:
 | 
| 1289 |                 raise SyntaxError, \
 | 
| 1290 |                         ("unexpected generator expression element: %s %d"
 | 
| 1291 |                          % (node, lineno))
 | 
| 1292 |         fors[0].is_outmost = True
 | 
| 1293 |         return GenExpr(GenExprInner(expr, fors), lineno=lineno)
 | 
| 1294 | 
 | 
| 1295 |     def com_dictorsetmaker(self, nodelist):
 | 
| 1296 |         # dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
 | 
| 1297 |         #                   (test (comp_for | (',' test)* [','])) )
 | 
| 1298 |         assert nodelist[0] == symbol.dictorsetmaker
 | 
| 1299 |         nodelist = nodelist[1:]
 | 
| 1300 |         if len(nodelist) == 1 or nodelist[1][0] == token.COMMA:
 | 
| 1301 |             # set literal
 | 
| 1302 |             items = []
 | 
| 1303 |             for i in range(0, len(nodelist), 2):
 | 
| 1304 |                 items.append(self.com_node(nodelist[i]))
 | 
| 1305 |             return Set(items, lineno=items[0].lineno)
 | 
| 1306 |         elif nodelist[1][0] == symbol.comp_for:
 | 
| 1307 |             # set comprehension
 | 
| 1308 |             expr = self.com_node(nodelist[0])
 | 
| 1309 |             return self.com_comprehension(expr, None, nodelist[1], 'set')
 | 
| 1310 |         elif len(nodelist) > 3 and nodelist[3][0] == symbol.comp_for:
 | 
| 1311 |             # dict comprehension
 | 
| 1312 |             assert nodelist[1][0] == token.COLON
 | 
| 1313 |             key = self.com_node(nodelist[0])
 | 
| 1314 |             value = self.com_node(nodelist[2])
 | 
| 1315 |             return self.com_comprehension(key, value, nodelist[3], 'dict')
 | 
| 1316 |         else:
 | 
| 1317 |             # dict literal
 | 
| 1318 |             items = []
 | 
| 1319 |             for i in range(0, len(nodelist), 4):
 | 
| 1320 |                 items.append((self.com_node(nodelist[i]),
 | 
| 1321 |                               self.com_node(nodelist[i+2])))
 | 
| 1322 |             return Dict(items, lineno=items[0][0].lineno)
 | 
| 1323 | 
 | 
| 1324 |     def com_apply_trailer(self, primaryNode, nodelist):
 | 
| 1325 |         t = nodelist[1][0]
 | 
| 1326 |         if t == token.LPAR:
 | 
| 1327 |             return self.com_call_function(primaryNode, nodelist[2])
 | 
| 1328 |         if t == token.DOT:
 | 
| 1329 |             return self.com_select_member(primaryNode, nodelist[2])
 | 
| 1330 |         if t == token.LSQB:
 | 
| 1331 |             return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
 | 
| 1332 | 
 | 
| 1333 |         raise SyntaxError, 'unknown node type: %s' % t
 | 
| 1334 | 
 | 
| 1335 |     def com_select_member(self, primaryNode, nodelist):
 | 
| 1336 |         if nodelist[0] != token.NAME:
 | 
| 1337 |             raise SyntaxError, "member must be a name"
 | 
| 1338 |         return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
 | 
| 1339 | 
 | 
| 1340 |     def com_call_function(self, primaryNode, nodelist):
 | 
| 1341 |         if nodelist[0] == token.RPAR:
 | 
| 1342 |             return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
 | 
| 1343 |         args = []
 | 
| 1344 |         kw = 0
 | 
| 1345 |         star_node = dstar_node = None
 | 
| 1346 |         len_nodelist = len(nodelist)
 | 
| 1347 |         i = 1
 | 
| 1348 |         while i < len_nodelist:
 | 
| 1349 |             node = nodelist[i]
 | 
| 1350 | 
 | 
| 1351 |             if node[0]==token.STAR:
 | 
| 1352 |                 if star_node is not None:
 | 
| 1353 |                     raise SyntaxError, 'already have the varargs identifier'
 | 
| 1354 |                 star_node = self.com_node(nodelist[i+1])
 | 
| 1355 |                 i = i + 3
 | 
| 1356 |                 continue
 | 
| 1357 |             elif node[0]==token.DOUBLESTAR:
 | 
| 1358 |                 if dstar_node is not None:
 | 
| 1359 |                     raise SyntaxError, 'already have the kwargs identifier'
 | 
| 1360 |                 dstar_node = self.com_node(nodelist[i+1])
 | 
| 1361 |                 i = i + 3
 | 
| 1362 |                 continue
 | 
| 1363 | 
 | 
| 1364 |             # positional or named parameters
 | 
| 1365 |             kw, result = self.com_argument(node, kw, star_node)
 | 
| 1366 | 
 | 
| 1367 |             if len_nodelist != 2 and isinstance(result, GenExpr) \
 | 
| 1368 |                and len(node) == 3 and node[2][0] == symbol.comp_for:
 | 
| 1369 |                 # allow f(x for x in y), but reject f(x for x in y, 1)
 | 
| 1370 |                 # should use f((x for x in y), 1) instead of f(x for x in y, 1)
 | 
| 1371 |                 raise SyntaxError, 'generator expression needs parenthesis'
 | 
| 1372 | 
 | 
| 1373 |             args.append(result)
 | 
| 1374 |             i = i + 2
 | 
| 1375 | 
 | 
| 1376 |         return CallFunc(primaryNode, args, star_node, dstar_node,
 | 
| 1377 |                         lineno=extractLineNo(nodelist))
 | 
| 1378 | 
 | 
| 1379 |     def com_argument(self, nodelist, kw, star_node):
 | 
| 1380 |         if len(nodelist) == 3 and nodelist[2][0] == symbol.comp_for:
 | 
| 1381 |             test = self.com_node(nodelist[1])
 | 
| 1382 |             return 0, self.com_generator_expression(test, nodelist[2])
 | 
| 1383 |         if len(nodelist) == 2:
 | 
| 1384 |             if kw:
 | 
| 1385 |                 raise SyntaxError, "non-keyword arg after keyword arg"
 | 
| 1386 |             if star_node:
 | 
| 1387 |                 raise SyntaxError, "only named arguments may follow *expression"
 | 
| 1388 |             return 0, self.com_node(nodelist[1])
 | 
| 1389 |         result = self.com_node(nodelist[3])
 | 
| 1390 |         n = nodelist[1]
 | 
| 1391 |         while len(n) == 2 and n[0] != token.NAME:
 | 
| 1392 |             n = n[1]
 | 
| 1393 |         if n[0] != token.NAME:
 | 
| 1394 |             raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
 | 
| 1395 |         node = Keyword(n[1], result, lineno=n[2])
 | 
| 1396 |         return 1, node
 | 
| 1397 | 
 | 
| 1398 |     def com_subscriptlist(self, primary, nodelist, assigning):
 | 
| 1399 |         # slicing:      simple_slicing | extended_slicing
 | 
| 1400 |         # simple_slicing:   primary "[" short_slice "]"
 | 
| 1401 |         # extended_slicing: primary "[" slice_list "]"
 | 
| 1402 |         # slice_list:   slice_item ("," slice_item)* [","]
 | 
| 1403 | 
 | 
| 1404 |         # backwards compat slice for '[i:j]'
 | 
| 1405 |         if len(nodelist) == 2:
 | 
| 1406 |             sub = nodelist[1]
 | 
| 1407 |             if (sub[1][0] == token.COLON or \
 | 
| 1408 |                             (len(sub) > 2 and sub[2][0] == token.COLON)) and \
 | 
| 1409 |                             sub[-1][0] != symbol.sliceop:
 | 
| 1410 |                 return self.com_slice(primary, sub, assigning)
 | 
| 1411 | 
 | 
| 1412 |         subscripts = []
 | 
| 1413 |         for i in range(1, len(nodelist), 2):
 | 
| 1414 |             subscripts.append(self.com_subscript(nodelist[i]))
 | 
| 1415 |         return Subscript(primary, assigning, subscripts,
 | 
| 1416 |                          lineno=extractLineNo(nodelist))
 | 
| 1417 | 
 | 
| 1418 |     def com_subscript(self, node):
 | 
| 1419 |         # slice_item: expression | proper_slice | ellipsis
 | 
| 1420 |         ch = node[1]
 | 
| 1421 |         t = ch[0]
 | 
| 1422 |         if t == token.DOT and node[2][0] == token.DOT:
 | 
| 1423 |             return Ellipsis()
 | 
| 1424 |         if t == token.COLON or len(node) > 2:
 | 
| 1425 |             return self.com_sliceobj(node)
 | 
| 1426 |         return self.com_node(ch)
 | 
| 1427 | 
 | 
| 1428 |     def com_sliceobj(self, node):
 | 
| 1429 |         # proper_slice: short_slice | long_slice
 | 
| 1430 |         # short_slice:  [lower_bound] ":" [upper_bound]
 | 
| 1431 |         # long_slice:   short_slice ":" [stride]
 | 
| 1432 |         # lower_bound:  expression
 | 
| 1433 |         # upper_bound:  expression
 | 
| 1434 |         # stride:       expression
 | 
| 1435 |         #
 | 
| 1436 |         # Note: a stride may be further slicing...
 | 
| 1437 | 
 | 
| 1438 |         items = []
 | 
| 1439 | 
 | 
| 1440 |         if node[1][0] == token.COLON:
 | 
| 1441 |             items.append(Const(None))
 | 
| 1442 |             i = 2
 | 
| 1443 |         else:
 | 
| 1444 |             items.append(self.com_node(node[1]))
 | 
| 1445 |             # i == 2 is a COLON
 | 
| 1446 |             i = 3
 | 
| 1447 | 
 | 
| 1448 |         if i < len(node) and node[i][0] == symbol.test:
 | 
| 1449 |             items.append(self.com_node(node[i]))
 | 
| 1450 |             i = i + 1
 | 
| 1451 |         else:
 | 
| 1452 |             items.append(Const(None))
 | 
| 1453 | 
 | 
| 1454 |         # a short_slice has been built. look for long_slice now by looking
 | 
| 1455 |         # for strides...
 | 
| 1456 |         for j in range(i, len(node)):
 | 
| 1457 |             ch = node[j]
 | 
| 1458 |             if len(ch) == 2:
 | 
| 1459 |                 items.append(Const(None))
 | 
| 1460 |             else:
 | 
| 1461 |                 items.append(self.com_node(ch[2]))
 | 
| 1462 |         return Sliceobj(items, lineno=extractLineNo(node))
 | 
| 1463 | 
 | 
| 1464 |     def com_slice(self, primary, node, assigning):
 | 
| 1465 |         # short_slice:  [lower_bound] ":" [upper_bound]
 | 
| 1466 |         lower = upper = None
 | 
| 1467 |         if len(node) == 3:
 | 
| 1468 |             if node[1][0] == token.COLON:
 | 
| 1469 |                 upper = self.com_node(node[2])
 | 
| 1470 |             else:
 | 
| 1471 |                 lower = self.com_node(node[1])
 | 
| 1472 |         elif len(node) == 4:
 | 
| 1473 |             lower = self.com_node(node[1])
 | 
| 1474 |             upper = self.com_node(node[3])
 | 
| 1475 |         return Slice(primary, assigning, lower, upper,
 | 
| 1476 |                      lineno=extractLineNo(node))
 | 
| 1477 | 
 | 
| 1478 |     def get_docstring(self, node, n=None):
 | 
| 1479 |         if n is None:
 | 
| 1480 |             n = node[0]
 | 
| 1481 |             node = node[1:]
 | 
| 1482 |         if n == symbol.suite:
 | 
| 1483 |             if len(node) == 1:
 | 
| 1484 |                 return self.get_docstring(node[0])
 | 
| 1485 |             for sub in node:
 | 
| 1486 |                 if sub[0] == symbol.stmt:
 | 
| 1487 |                     return self.get_docstring(sub)
 | 
| 1488 |             return None
 | 
| 1489 |         if n == symbol.file_input:
 | 
| 1490 |             for sub in node:
 | 
| 1491 |                 if sub[0] == symbol.stmt:
 | 
| 1492 |                     return self.get_docstring(sub)
 | 
| 1493 |             return None
 | 
| 1494 |         if n == symbol.atom:
 | 
| 1495 |             if node[0][0] == token.STRING:
 | 
| 1496 |                 s = ''
 | 
| 1497 |                 for t in node:
 | 
| 1498 |                     s = s + eval(t[1])
 | 
| 1499 |                 return s
 | 
| 1500 |             return None
 | 
| 1501 |         if n == symbol.stmt or n == symbol.simple_stmt \
 | 
| 1502 |            or n == symbol.small_stmt:
 | 
| 1503 |             return self.get_docstring(node[0])
 | 
| 1504 |         if n in _doc_nodes and len(node) == 1:
 | 
| 1505 |             return self.get_docstring(node[0])
 | 
| 1506 |         return None
 | 
| 1507 | 
 | 
| 1508 | 
 | 
| 1509 | def debug_tree(tree):
 | 
| 1510 |     l = []
 | 
| 1511 |     for elt in tree:
 | 
| 1512 |         if isinstance(elt, int):
 | 
| 1513 |             l.append(_names.get(elt, elt))
 | 
| 1514 |         elif isinstance(elt, str):
 | 
| 1515 |             l.append(elt)
 | 
| 1516 |         else:
 | 
| 1517 |             l.append(debug_tree(elt))
 | 
| 1518 |     return l
 |