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