These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1536 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1536 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Parse tree transformation module.
 | |
| 
 | |
| Transforms Python source code into an abstract syntax tree (AST)
 | |
| defined in the ast module.
 | |
| 
 | |
| The simplest ways to invoke this module are via parse and parseFile.
 | |
| parse(buf) -> AST
 | |
| parseFile(path) -> AST
 | |
| """
 | |
| 
 | |
| # Original version written by Greg Stein (gstein@lyra.org)
 | |
| #                         and Bill Tutt (rassilon@lima.mudlib.org)
 | |
| # February 1997.
 | |
| #
 | |
| # Modifications and improvements for Python 2.0 by Jeremy Hylton and
 | |
| # Mark Hammond
 | |
| #
 | |
| # Some fixes to try to have correct line number on almost all nodes
 | |
| # (except Module, Discard and Stmt) added by Sylvain Thenault
 | |
| #
 | |
| # Portions of this file are:
 | |
| # Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
 | |
| #
 | |
| # This module is provided under a BSD-ish license. See
 | |
| #   http://www.opensource.org/licenses/bsd-license.html
 | |
| # and replace OWNER, ORGANIZATION, and YEAR as appropriate.
 | |
| 
 | |
| from compiler.ast import *
 | |
| import parser
 | |
| import symbol
 | |
| import token
 | |
| 
 | |
| class WalkerError(StandardError):
 | |
|     pass
 | |
| 
 | |
| from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
 | |
| from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY
 | |
| 
 | |
| def parseFile(path):
 | |
|     f = open(path, "U")
 | |
|     # XXX The parser API tolerates files without a trailing newline,
 | |
|     # but not strings without a trailing newline.  Always add an extra
 | |
|     # newline to the file contents, since we're going through the string
 | |
|     # version of the API.
 | |
|     src = f.read() + "\n"
 | |
|     f.close()
 | |
|     return parse(src)
 | |
| 
 | |
| def parse(buf, mode="exec"):
 | |
|     if mode == "exec" or mode == "single":
 | |
|         return Transformer().parsesuite(buf)
 | |
|     elif mode == "eval":
 | |
|         return Transformer().parseexpr(buf)
 | |
|     else:
 | |
|         raise ValueError("compile() arg 3 must be"
 | |
|                          " 'exec' or 'eval' or 'single'")
 | |
| 
 | |
| def asList(nodes):
 | |
|     l = []
 | |
|     for item in nodes:
 | |
|         if hasattr(item, "asList"):
 | |
|             l.append(item.asList())
 | |
|         else:
 | |
|             if type(item) is type( (None, None) ):
 | |
|                 l.append(tuple(asList(item)))
 | |
|             elif type(item) is type( [] ):
 | |
|                 l.append(asList(item))
 | |
|             else:
 | |
|                 l.append(item)
 | |
|     return l
 | |
| 
 | |
| def extractLineNo(ast):
 | |
|     if not isinstance(ast[1], tuple):
 | |
|         # get a terminal node
 | |
|         return ast[2]
 | |
|     for child in ast[1:]:
 | |
|         if isinstance(child, tuple):
 | |
|             lineno = extractLineNo(child)
 | |
|             if lineno is not None:
 | |
|                 return lineno
 | |
| 
 | |
| def Node(*args):
 | |
|     kind = args[0]
 | |
|     if kind in nodes:
 | |
|         try:
 | |
|             return nodes[kind](*args[1:])
 | |
|         except TypeError:
 | |
|             print nodes[kind], len(args), args
 | |
|             raise
 | |
|     else:
 | |
|         raise WalkerError, "Can't find appropriate Node type: %s" % str(args)
 | |
|         #return apply(ast.Node, args)
 | |
| 
 | |
| class Transformer:
 | |
|     """Utility object for transforming Python parse trees.
 | |
| 
 | |
|     Exposes the following methods:
 | |
|         tree = transform(ast_tree)
 | |
|         tree = parsesuite(text)
 | |
|         tree = parseexpr(text)
 | |
|         tree = parsefile(fileob | filename)
 | |
|     """
 | |
| 
 | |
|     def __init__(self):
 | |
|         self._dispatch = {}
 | |
|         for value, name in symbol.sym_name.items():
 | |
|             if hasattr(self, name):
 | |
|                 self._dispatch[value] = getattr(self, name)
 | |
|         self._dispatch[token.NEWLINE] = self.com_NEWLINE
 | |
|         self._atom_dispatch = {token.LPAR: self.atom_lpar,
 | |
|                                token.LSQB: self.atom_lsqb,
 | |
|                                token.LBRACE: self.atom_lbrace,
 | |
|                                token.BACKQUOTE: self.atom_backquote,
 | |
|                                token.NUMBER: self.atom_number,
 | |
|                                token.STRING: self.atom_string,
 | |
|                                token.NAME: self.atom_name,
 | |
|                                }
 | |
|         self.encoding = None
 | |
| 
 | |
|     def transform(self, tree):
 | |
|         """Transform an AST into a modified parse tree."""
 | |
|         if not (isinstance(tree, tuple) or isinstance(tree, list)):
 | |
|             tree = parser.st2tuple(tree, line_info=1)
 | |
|         return self.compile_node(tree)
 | |
| 
 | |
|     def parsesuite(self, text):
 | |
|         """Return a modified parse tree for the given suite text."""
 | |
|         return self.transform(parser.suite(text))
 | |
| 
 | |
|     def parseexpr(self, text):
 | |
|         """Return a modified parse tree for the given expression text."""
 | |
|         return self.transform(parser.expr(text))
 | |
| 
 | |
|     def parsefile(self, file):
 | |
|         """Return a modified parse tree for the contents of the given file."""
 | |
|         if type(file) == type(''):
 | |
|             file = open(file)
 | |
|         return self.parsesuite(file.read())
 | |
| 
 | |
|     # --------------------------------------------------------------
 | |
|     #
 | |
|     # PRIVATE METHODS
 | |
|     #
 | |
| 
 | |
|     def compile_node(self, node):
 | |
|         ### emit a line-number node?
 | |
|         n = node[0]
 | |
| 
 | |
|         if n == symbol.encoding_decl:
 | |
|             self.encoding = node[2]
 | |
|             node = node[1]
 | |
|             n = node[0]
 | |
| 
 | |
|         if n == symbol.single_input:
 | |
|             return self.single_input(node[1:])
 | |
|         if n == symbol.file_input:
 | |
|             return self.file_input(node[1:])
 | |
|         if n == symbol.eval_input:
 | |
|             return self.eval_input(node[1:])
 | |
|         if n == symbol.lambdef:
 | |
|             return self.lambdef(node[1:])
 | |
|         if n == symbol.funcdef:
 | |
|             return self.funcdef(node[1:])
 | |
|         if n == symbol.classdef:
 | |
|             return self.classdef(node[1:])
 | |
| 
 | |
|         raise WalkerError, ('unexpected node type', n)
 | |
| 
 | |
|     def single_input(self, node):
 | |
|         ### do we want to do anything about being "interactive" ?
 | |
| 
 | |
|         # NEWLINE | simple_stmt | compound_stmt NEWLINE
 | |
|         n = node[0][0]
 | |
|         if n != token.NEWLINE:
 | |
|             return self.com_stmt(node[0])
 | |
| 
 | |
|         return Pass()
 | |
| 
 | |
|     def file_input(self, nodelist):
 | |
|         doc = self.get_docstring(nodelist, symbol.file_input)
 | |
|         if doc is not None:
 | |
|             i = 1
 | |
|         else:
 | |
|             i = 0
 | |
|         stmts = []
 | |
|         for node in nodelist[i:]:
 | |
|             if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
 | |
|                 self.com_append_stmt(stmts, node)
 | |
|         return Module(doc, Stmt(stmts))
 | |
| 
 | |
|     def eval_input(self, nodelist):
 | |
|         # from the built-in function input()
 | |
|         ### is this sufficient?
 | |
|         return Expression(self.com_node(nodelist[0]))
 | |
| 
 | |
|     def decorator_name(self, nodelist):
 | |
|         listlen = len(nodelist)
 | |
|         assert listlen >= 1 and listlen % 2 == 1
 | |
| 
 | |
|         item = self.atom_name(nodelist)
 | |
|         i = 1
 | |
|         while i < listlen:
 | |
|             assert nodelist[i][0] == token.DOT
 | |
|             assert nodelist[i + 1][0] == token.NAME
 | |
|             item = Getattr(item, nodelist[i + 1][1])
 | |
|             i += 2
 | |
| 
 | |
|         return item
 | |
| 
 | |
|     def decorator(self, nodelist):
 | |
|         # '@' dotted_name [ '(' [arglist] ')' ]
 | |
|         assert len(nodelist) in (3, 5, 6)
 | |
|         assert nodelist[0][0] == token.AT
 | |
|         assert nodelist[-1][0] == token.NEWLINE
 | |
| 
 | |
|         assert nodelist[1][0] == symbol.dotted_name
 | |
|         funcname = self.decorator_name(nodelist[1][1:])
 | |
| 
 | |
|         if len(nodelist) > 3:
 | |
|             assert nodelist[2][0] == token.LPAR
 | |
|             expr = self.com_call_function(funcname, nodelist[3])
 | |
|         else:
 | |
|             expr = funcname
 | |
| 
 | |
|         return expr
 | |
| 
 | |
|     def decorators(self, nodelist):
 | |
|         # decorators: decorator ([NEWLINE] decorator)* NEWLINE
 | |
|         items = []
 | |
|         for dec_nodelist in nodelist:
 | |
|             assert dec_nodelist[0] == symbol.decorator
 | |
|             items.append(self.decorator(dec_nodelist[1:]))
 | |
|         return Decorators(items)
 | |
| 
 | |
|     def decorated(self, nodelist):
 | |
|         assert nodelist[0][0] == symbol.decorators
 | |
|         if nodelist[1][0] == symbol.funcdef:
 | |
|             n = [nodelist[0]] + list(nodelist[1][1:])
 | |
|             return self.funcdef(n)
 | |
|         elif nodelist[1][0] == symbol.classdef:
 | |
|             decorators = self.decorators(nodelist[0][1:])
 | |
|             cls = self.classdef(nodelist[1][1:])
 | |
|             cls.decorators = decorators
 | |
|             return cls
 | |
|         raise WalkerError()
 | |
| 
 | |
|     def funcdef(self, nodelist):
 | |
|         #                    -6   -5    -4         -3  -2    -1
 | |
|         # funcdef: [decorators] 'def' NAME parameters ':' suite
 | |
|         # parameters: '(' [varargslist] ')'
 | |
| 
 | |
|         if len(nodelist) == 6:
 | |
|             assert nodelist[0][0] == symbol.decorators
 | |
|             decorators = self.decorators(nodelist[0][1:])
 | |
|         else:
 | |
|             assert len(nodelist) == 5
 | |
|             decorators = None
 | |
| 
 | |
|         lineno = nodelist[-4][2]
 | |
|         name = nodelist[-4][1]
 | |
|         args = nodelist[-3][2]
 | |
| 
 | |
|         if args[0] == symbol.varargslist:
 | |
|             names, defaults, flags = self.com_arglist(args[1:])
 | |
|         else:
 | |
|             names = defaults = ()
 | |
|             flags = 0
 | |
|         doc = self.get_docstring(nodelist[-1])
 | |
| 
 | |
|         # code for function
 | |
|         code = self.com_node(nodelist[-1])
 | |
| 
 | |
|         if doc is not None:
 | |
|             assert isinstance(code, Stmt)
 | |
|             assert isinstance(code.nodes[0], Discard)
 | |
|             del code.nodes[0]
 | |
|         return Function(decorators, name, names, defaults, flags, doc, code,
 | |
|                      lineno=lineno)
 | |
| 
 | |
|     def lambdef(self, nodelist):
 | |
|         # lambdef: 'lambda' [varargslist] ':' test
 | |
|         if nodelist[2][0] == symbol.varargslist:
 | |
|             names, defaults, flags = self.com_arglist(nodelist[2][1:])
 | |
|         else:
 | |
|             names = defaults = ()
 | |
|             flags = 0
 | |
| 
 | |
|         # code for lambda
 | |
|         code = self.com_node(nodelist[-1])
 | |
| 
 | |
|         return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
 | |
|     old_lambdef = lambdef
 | |
| 
 | |
|     def classdef(self, nodelist):
 | |
|         # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
 | |
| 
 | |
|         name = nodelist[1][1]
 | |
|         doc = self.get_docstring(nodelist[-1])
 | |
|         if nodelist[2][0] == token.COLON:
 | |
|             bases = []
 | |
|         elif nodelist[3][0] == token.RPAR:
 | |
|             bases = []
 | |
|         else:
 | |
|             bases = self.com_bases(nodelist[3])
 | |
| 
 | |
|         # code for class
 | |
|         code = self.com_node(nodelist[-1])
 | |
| 
 | |
|         if doc is not None:
 | |
|             assert isinstance(code, Stmt)
 | |
|             assert isinstance(code.nodes[0], Discard)
 | |
|             del code.nodes[0]
 | |
| 
 | |
|         return Class(name, bases, doc, code, lineno=nodelist[1][2])
 | |
| 
 | |
|     def stmt(self, nodelist):
 | |
|         return self.com_stmt(nodelist[0])
 | |
| 
 | |
|     small_stmt = stmt
 | |
|     flow_stmt = stmt
 | |
|     compound_stmt = stmt
 | |
| 
 | |
|     def simple_stmt(self, nodelist):
 | |
|         # small_stmt (';' small_stmt)* [';'] NEWLINE
 | |
|         stmts = []
 | |
|         for i in range(0, len(nodelist), 2):
 | |
|             self.com_append_stmt(stmts, nodelist[i])
 | |
|         return Stmt(stmts)
 | |
| 
 | |
|     def parameters(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def varargslist(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def fpdef(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def fplist(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def dotted_name(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def comp_op(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def trailer(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def sliceop(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     def argument(self, nodelist):
 | |
|         raise WalkerError
 | |
| 
 | |
|     # --------------------------------------------------------------
 | |
|     #
 | |
|     # STATEMENT NODES  (invoked by com_node())
 | |
|     #
 | |
| 
 | |
|     def expr_stmt(self, nodelist):
 | |
|         # augassign testlist | testlist ('=' testlist)*
 | |
|         en = nodelist[-1]
 | |
|         exprNode = self.lookup_node(en)(en[1:])
 | |
|         if len(nodelist) == 1:
 | |
|             return Discard(exprNode, lineno=exprNode.lineno)
 | |
|         if nodelist[1][0] == token.EQUAL:
 | |
|             nodesl = []
 | |
|             for i in range(0, len(nodelist) - 2, 2):
 | |
|                 nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
 | |
|             return Assign(nodesl, exprNode, lineno=nodelist[1][2])
 | |
|         else:
 | |
|             lval = self.com_augassign(nodelist[0])
 | |
|             op = self.com_augassign_op(nodelist[1])
 | |
|             return AugAssign(lval, op[1], exprNode, lineno=op[2])
 | |
|         raise WalkerError, "can't get here"
 | |
| 
 | |
|     def print_stmt(self, nodelist):
 | |
|         # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
 | |
|         items = []
 | |
|         if len(nodelist) == 1:
 | |
|             start = 1
 | |
|             dest = None
 | |
|         elif nodelist[1][0] == token.RIGHTSHIFT:
 | |
|             assert len(nodelist) == 3 \
 | |
|                    or nodelist[3][0] == token.COMMA
 | |
|             dest = self.com_node(nodelist[2])
 | |
|             start = 4
 | |
|         else:
 | |
|             dest = None
 | |
|             start = 1
 | |
|         for i in range(start, len(nodelist), 2):
 | |
|             items.append(self.com_node(nodelist[i]))
 | |
|         if nodelist[-1][0] == token.COMMA:
 | |
|             return Print(items, dest, lineno=nodelist[0][2])
 | |
|         return Printnl(items, dest, lineno=nodelist[0][2])
 | |
| 
 | |
|     def del_stmt(self, nodelist):
 | |
|         return self.com_assign(nodelist[1], OP_DELETE)
 | |
| 
 | |
|     def pass_stmt(self, nodelist):
 | |
|         return Pass(lineno=nodelist[0][2])
 | |
| 
 | |
|     def break_stmt(self, nodelist):
 | |
|         return Break(lineno=nodelist[0][2])
 | |
| 
 | |
|     def continue_stmt(self, nodelist):
 | |
|         return Continue(lineno=nodelist[0][2])
 | |
| 
 | |
|     def return_stmt(self, nodelist):
 | |
|         # return: [testlist]
 | |
|         if len(nodelist) < 2:
 | |
|             return Return(Const(None), lineno=nodelist[0][2])
 | |
|         return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
 | |
| 
 | |
|     def yield_stmt(self, nodelist):
 | |
|         expr = self.com_node(nodelist[0])
 | |
|         return Discard(expr, lineno=expr.lineno)
 | |
| 
 | |
|     def yield_expr(self, nodelist):
 | |
|         if len(nodelist) > 1:
 | |
|             value = self.com_node(nodelist[1])
 | |
|         else:
 | |
|             value = Const(None)
 | |
|         return Yield(value, lineno=nodelist[0][2])
 | |
| 
 | |
|     def raise_stmt(self, nodelist):
 | |
|         # raise: [test [',' test [',' test]]]
 | |
|         if len(nodelist) > 5:
 | |
|             expr3 = self.com_node(nodelist[5])
 | |
|         else:
 | |
|             expr3 = None
 | |
|         if len(nodelist) > 3:
 | |
|             expr2 = self.com_node(nodelist[3])
 | |
|         else:
 | |
|             expr2 = None
 | |
|         if len(nodelist) > 1:
 | |
|             expr1 = self.com_node(nodelist[1])
 | |
|         else:
 | |
|             expr1 = None
 | |
|         return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
 | |
| 
 | |
|     def import_stmt(self, nodelist):
 | |
|         # import_stmt: import_name | import_from
 | |
|         assert len(nodelist) == 1
 | |
|         return self.com_node(nodelist[0])
 | |
| 
 | |
|     def import_name(self, nodelist):
 | |
|         # import_name: 'import' dotted_as_names
 | |
|         return Import(self.com_dotted_as_names(nodelist[1]),
 | |
|                       lineno=nodelist[0][2])
 | |
| 
 | |
|     def import_from(self, nodelist):
 | |
|         # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
 | |
|         #    '(' import_as_names ')' | import_as_names)
 | |
|         assert nodelist[0][1] == 'from'
 | |
|         idx = 1
 | |
|         while nodelist[idx][1] == '.':
 | |
|             idx += 1
 | |
|         level = idx - 1
 | |
|         if nodelist[idx][0] == symbol.dotted_name:
 | |
|             fromname = self.com_dotted_name(nodelist[idx])
 | |
|             idx += 1
 | |
|         else:
 | |
|             fromname = ""
 | |
|         assert nodelist[idx][1] == 'import'
 | |
|         if nodelist[idx + 1][0] == token.STAR:
 | |
|             return From(fromname, [('*', None)], level,
 | |
|                         lineno=nodelist[0][2])
 | |
|         else:
 | |
|             node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
 | |
|             return From(fromname, self.com_import_as_names(node), level,
 | |
|                         lineno=nodelist[0][2])
 | |
| 
 | |
|     def global_stmt(self, nodelist):
 | |
|         # global: NAME (',' NAME)*
 | |
|         names = []
 | |
|         for i in range(1, len(nodelist), 2):
 | |
|             names.append(nodelist[i][1])
 | |
|         return Global(names, lineno=nodelist[0][2])
 | |
| 
 | |
|     def exec_stmt(self, nodelist):
 | |
|         # exec_stmt: 'exec' expr ['in' expr [',' expr]]
 | |
|         expr1 = self.com_node(nodelist[1])
 | |
|         if len(nodelist) >= 4:
 | |
|             expr2 = self.com_node(nodelist[3])
 | |
|             if len(nodelist) >= 6:
 | |
|                 expr3 = self.com_node(nodelist[5])
 | |
|             else:
 | |
|                 expr3 = None
 | |
|         else:
 | |
|             expr2 = expr3 = None
 | |
| 
 | |
|         return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
 | |
| 
 | |
|     def assert_stmt(self, nodelist):
 | |
|         # 'assert': test, [',' test]
 | |
|         expr1 = self.com_node(nodelist[1])
 | |
|         if (len(nodelist) == 4):
 | |
|             expr2 = self.com_node(nodelist[3])
 | |
|         else:
 | |
|             expr2 = None
 | |
|         return Assert(expr1, expr2, lineno=nodelist[0][2])
 | |
| 
 | |
|     def if_stmt(self, nodelist):
 | |
|         # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
 | |
|         tests = []
 | |
|         for i in range(0, len(nodelist) - 3, 4):
 | |
|             testNode = self.com_node(nodelist[i + 1])
 | |
|             suiteNode = self.com_node(nodelist[i + 3])
 | |
|             tests.append((testNode, suiteNode))
 | |
| 
 | |
|         if len(nodelist) % 4 == 3:
 | |
|             elseNode = self.com_node(nodelist[-1])
 | |
| ##      elseNode.lineno = nodelist[-1][1][2]
 | |
|         else:
 | |
|             elseNode = None
 | |
|         return If(tests, elseNode, lineno=nodelist[0][2])
 | |
| 
 | |
|     def while_stmt(self, nodelist):
 | |
|         # 'while' test ':' suite ['else' ':' suite]
 | |
| 
 | |
|         testNode = self.com_node(nodelist[1])
 | |
|         bodyNode = self.com_node(nodelist[3])
 | |
| 
 | |
|         if len(nodelist) > 4:
 | |
|             elseNode = self.com_node(nodelist[6])
 | |
|         else:
 | |
|             elseNode = None
 | |
| 
 | |
|         return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
 | |
| 
 | |
|     def for_stmt(self, nodelist):
 | |
|         # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
 | |
| 
 | |
|         assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
 | |
|         listNode = self.com_node(nodelist[3])
 | |
|         bodyNode = self.com_node(nodelist[5])
 | |
| 
 | |
|         if len(nodelist) > 8:
 | |
|             elseNode = self.com_node(nodelist[8])
 | |
|         else:
 | |
|             elseNode = None
 | |
| 
 | |
|         return For(assignNode, listNode, bodyNode, elseNode,
 | |
|                    lineno=nodelist[0][2])
 | |
| 
 | |
|     def try_stmt(self, nodelist):
 | |
|         return self.com_try_except_finally(nodelist)
 | |
| 
 | |
|     def with_stmt(self, nodelist):
 | |
|         return self.com_with(nodelist)
 | |
| 
 | |
|     def with_var(self, nodelist):
 | |
|         return self.com_with_var(nodelist)
 | |
| 
 | |
|     def suite(self, nodelist):
 | |
|         # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
 | |
|         if len(nodelist) == 1:
 | |
|             return self.com_stmt(nodelist[0])
 | |
| 
 | |
|         stmts = []
 | |
|         for node in nodelist:
 | |
|             if node[0] == symbol.stmt:
 | |
|                 self.com_append_stmt(stmts, node)
 | |
|         return Stmt(stmts)
 | |
| 
 | |
|     # --------------------------------------------------------------
 | |
|     #
 | |
|     # EXPRESSION NODES  (invoked by com_node())
 | |
|     #
 | |
| 
 | |
|     def testlist(self, nodelist):
 | |
|         # testlist: expr (',' expr)* [',']
 | |
|         # testlist_safe: test [(',' test)+ [',']]
 | |
|         # exprlist: expr (',' expr)* [',']
 | |
|         return self.com_binary(Tuple, nodelist)
 | |
| 
 | |
|     testlist_safe = testlist # XXX
 | |
|     testlist1 = testlist
 | |
|     exprlist = testlist
 | |
| 
 | |
|     def testlist_comp(self, nodelist):
 | |
|         # test ( comp_for | (',' test)* [','] )
 | |
|         assert nodelist[0][0] == symbol.test
 | |
|         if len(nodelist) == 2 and nodelist[1][0] == symbol.comp_for:
 | |
|             test = self.com_node(nodelist[0])
 | |
|             return self.com_generator_expression(test, nodelist[1])
 | |
|         return self.testlist(nodelist)
 | |
| 
 | |
|     def test(self, nodelist):
 | |
|         # or_test ['if' or_test 'else' test] | lambdef
 | |
|         if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
 | |
|             return self.lambdef(nodelist[0])
 | |
|         then = self.com_node(nodelist[0])
 | |
|         if len(nodelist) > 1:
 | |
|             assert len(nodelist) == 5
 | |
|             assert nodelist[1][1] == 'if'
 | |
|             assert nodelist[3][1] == 'else'
 | |
|             test = self.com_node(nodelist[2])
 | |
|             else_ = self.com_node(nodelist[4])
 | |
|             return IfExp(test, then, else_, lineno=nodelist[1][2])
 | |
|         return then
 | |
| 
 | |
|     def or_test(self, nodelist):
 | |
|         # and_test ('or' and_test)* | lambdef
 | |
|         if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
 | |
|             return self.lambdef(nodelist[0])
 | |
|         return self.com_binary(Or, nodelist)
 | |
|     old_test = or_test
 | |
| 
 | |
|     def and_test(self, nodelist):
 | |
|         # not_test ('and' not_test)*
 | |
|         return self.com_binary(And, nodelist)
 | |
| 
 | |
|     def not_test(self, nodelist):
 | |
|         # 'not' not_test | comparison
 | |
|         result = self.com_node(nodelist[-1])
 | |
|         if len(nodelist) == 2:
 | |
|             return Not(result, lineno=nodelist[0][2])
 | |
|         return result
 | |
| 
 | |
|     def comparison(self, nodelist):
 | |
|         # comparison: expr (comp_op expr)*
 | |
|         node = self.com_node(nodelist[0])
 | |
|         if len(nodelist) == 1:
 | |
|             return node
 | |
| 
 | |
|         results = []
 | |
|         for i in range(2, len(nodelist), 2):
 | |
|             nl = nodelist[i-1]
 | |
| 
 | |
|             # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
 | |
|             #          | 'in' | 'not' 'in' | 'is' | 'is' 'not'
 | |
|             n = nl[1]
 | |
|             if n[0] == token.NAME:
 | |
|                 type = n[1]
 | |
|                 if len(nl) == 3:
 | |
|                     if type == 'not':
 | |
|                         type = 'not in'
 | |
|                     else:
 | |
|                         type = 'is not'
 | |
|             else:
 | |
|                 type = _cmp_types[n[0]]
 | |
| 
 | |
|             lineno = nl[1][2]
 | |
|             results.append((type, self.com_node(nodelist[i])))
 | |
| 
 | |
|         # we need a special "compare" node so that we can distinguish
 | |
|         #   3 < x < 5   from    (3 < x) < 5
 | |
|         # the two have very different semantics and results (note that the
 | |
|         # latter form is always true)
 | |
| 
 | |
|         return Compare(node, results, lineno=lineno)
 | |
| 
 | |
|     def expr(self, nodelist):
 | |
|         # xor_expr ('|' xor_expr)*
 | |
|         return self.com_binary(Bitor, nodelist)
 | |
| 
 | |
|     def xor_expr(self, nodelist):
 | |
|         # xor_expr ('^' xor_expr)*
 | |
|         return self.com_binary(Bitxor, nodelist)
 | |
| 
 | |
|     def and_expr(self, nodelist):
 | |
|         # xor_expr ('&' xor_expr)*
 | |
|         return self.com_binary(Bitand, nodelist)
 | |
| 
 | |
|     def shift_expr(self, nodelist):
 | |
|         # shift_expr ('<<'|'>>' shift_expr)*
 | |
|         node = self.com_node(nodelist[0])
 | |
|         for i in range(2, len(nodelist), 2):
 | |
|             right = self.com_node(nodelist[i])
 | |
|             if nodelist[i-1][0] == token.LEFTSHIFT:
 | |
|                 node = LeftShift([node, right], lineno=nodelist[1][2])
 | |
|             elif nodelist[i-1][0] == token.RIGHTSHIFT:
 | |
|                 node = RightShift([node, right], lineno=nodelist[1][2])
 | |
|             else:
 | |
|                 raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
 | |
|         return node
 | |
| 
 | |
|     def arith_expr(self, nodelist):
 | |
|         node = self.com_node(nodelist[0])
 | |
|         for i in range(2, len(nodelist), 2):
 | |
|             right = self.com_node(nodelist[i])
 | |
|             if nodelist[i-1][0] == token.PLUS:
 | |
|                 node = Add([node, right], lineno=nodelist[1][2])
 | |
|             elif nodelist[i-1][0] == token.MINUS:
 | |
|                 node = Sub([node, right], lineno=nodelist[1][2])
 | |
|             else:
 | |
|                 raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
 | |
|         return node
 | |
| 
 | |
|     def term(self, nodelist):
 | |
|         node = self.com_node(nodelist[0])
 | |
|         for i in range(2, len(nodelist), 2):
 | |
|             right = self.com_node(nodelist[i])
 | |
|             t = nodelist[i-1][0]
 | |
|             if t == token.STAR:
 | |
|                 node = Mul([node, right])
 | |
|             elif t == token.SLASH:
 | |
|                 node = Div([node, right])
 | |
|             elif t == token.PERCENT:
 | |
|                 node = Mod([node, right])
 | |
|             elif t == token.DOUBLESLASH:
 | |
|                 node = FloorDiv([node, right])
 | |
|             else:
 | |
|                 raise ValueError, "unexpected token: %s" % t
 | |
|             node.lineno = nodelist[1][2]
 | |
|         return node
 | |
| 
 | |
|     def factor(self, nodelist):
 | |
|         elt = nodelist[0]
 | |
|         t = elt[0]
 | |
|         node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
 | |
|         # need to handle (unary op)constant here...
 | |
|         if t == token.PLUS:
 | |
|             return UnaryAdd(node, lineno=elt[2])
 | |
|         elif t == token.MINUS:
 | |
|             return UnarySub(node, lineno=elt[2])
 | |
|         elif t == token.TILDE:
 | |
|             node = Invert(node, lineno=elt[2])
 | |
|         return node
 | |
| 
 | |
|     def power(self, nodelist):
 | |
|         # power: atom trailer* ('**' factor)*
 | |
|         node = self.com_node(nodelist[0])
 | |
|         for i in range(1, len(nodelist)):
 | |
|             elt = nodelist[i]
 | |
|             if elt[0] == token.DOUBLESTAR:
 | |
|                 return Power([node, self.com_node(nodelist[i+1])],
 | |
|                              lineno=elt[2])
 | |
| 
 | |
|             node = self.com_apply_trailer(node, elt)
 | |
| 
 | |
|         return node
 | |
| 
 | |
|     def atom(self, nodelist):
 | |
|         return self._atom_dispatch[nodelist[0][0]](nodelist)
 | |
| 
 | |
|     def atom_lpar(self, nodelist):
 | |
|         if nodelist[1][0] == token.RPAR:
 | |
|             return Tuple((), lineno=nodelist[0][2])
 | |
|         return self.com_node(nodelist[1])
 | |
| 
 | |
|     def atom_lsqb(self, nodelist):
 | |
|         if nodelist[1][0] == token.RSQB:
 | |
|             return List((), lineno=nodelist[0][2])
 | |
|         return self.com_list_constructor(nodelist[1])
 | |
| 
 | |
|     def atom_lbrace(self, nodelist):
 | |
|         if nodelist[1][0] == token.RBRACE:
 | |
|             return Dict((), lineno=nodelist[0][2])
 | |
|         return self.com_dictorsetmaker(nodelist[1])
 | |
| 
 | |
|     def atom_backquote(self, nodelist):
 | |
|         return Backquote(self.com_node(nodelist[1]))
 | |
| 
 | |
|     def atom_number(self, nodelist):
 | |
|         ### need to verify this matches compile.c
 | |
|         k = eval(nodelist[0][1])
 | |
|         return Const(k, lineno=nodelist[0][2])
 | |
| 
 | |
|     def decode_literal(self, lit):
 | |
|         if self.encoding:
 | |
|             # this is particularly fragile & a bit of a
 | |
|             # hack... changes in compile.c:parsestr and
 | |
|             # tokenizer.c must be reflected here.
 | |
|             if self.encoding not in ['utf-8', 'iso-8859-1']:
 | |
|                 lit = unicode(lit, 'utf-8').encode(self.encoding)
 | |
|             return eval("# coding: %s\n%s" % (self.encoding, lit))
 | |
|         else:
 | |
|             return eval(lit)
 | |
| 
 | |
|     def atom_string(self, nodelist):
 | |
|         k = ''
 | |
|         for node in nodelist:
 | |
|             k += self.decode_literal(node[1])
 | |
|         return Const(k, lineno=nodelist[0][2])
 | |
| 
 | |
|     def atom_name(self, nodelist):
 | |
|         return Name(nodelist[0][1], lineno=nodelist[0][2])
 | |
| 
 | |
|     # --------------------------------------------------------------
 | |
|     #
 | |
|     # INTERNAL PARSING UTILITIES
 | |
|     #
 | |
| 
 | |
|     # The use of com_node() introduces a lot of extra stack frames,
 | |
|     # enough to cause a stack overflow compiling test.test_parser with
 | |
|     # the standard interpreter recursionlimit.  The com_node() is a
 | |
|     # convenience function that hides the dispatch details, but comes
 | |
|     # at a very high cost.  It is more efficient to dispatch directly
 | |
|     # in the callers.  In these cases, use lookup_node() and call the
 | |
|     # dispatched node directly.
 | |
| 
 | |
|     def lookup_node(self, node):
 | |
|         return self._dispatch[node[0]]
 | |
| 
 | |
|     def com_node(self, node):
 | |
|         # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
 | |
|         #       break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
 | |
|         #       and compound_stmt.
 | |
|         #       We'll just dispatch them.
 | |
|         return self._dispatch[node[0]](node[1:])
 | |
| 
 | |
|     def com_NEWLINE(self, *args):
 | |
|         # A ';' at the end of a line can make a NEWLINE token appear
 | |
|         # here, Render it harmless. (genc discards ('discard',
 | |
|         # ('const', xxxx)) Nodes)
 | |
|         return Discard(Const(None))
 | |
| 
 | |
|     def com_arglist(self, nodelist):
 | |
|         # varargslist:
 | |
|         #     (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
 | |
|         #   | fpdef ['=' test] (',' fpdef ['=' test])* [',']
 | |
|         # fpdef: NAME | '(' fplist ')'
 | |
|         # fplist: fpdef (',' fpdef)* [',']
 | |
|         names = []
 | |
|         defaults = []
 | |
|         flags = 0
 | |
| 
 | |
|         i = 0
 | |
|         while i < len(nodelist):
 | |
|             node = nodelist[i]
 | |
|             if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
 | |
|                 if node[0] == token.STAR:
 | |
|                     node = nodelist[i+1]
 | |
|                     if node[0] == token.NAME:
 | |
|                         names.append(node[1])
 | |
|                         flags = flags | CO_VARARGS
 | |
|                         i = i + 3
 | |
| 
 | |
|                 if i < len(nodelist):
 | |
|                     # should be DOUBLESTAR
 | |
|                     t = nodelist[i][0]
 | |
|                     if t == token.DOUBLESTAR:
 | |
|                         node = nodelist[i+1]
 | |
|                     else:
 | |
|                         raise ValueError, "unexpected token: %s" % t
 | |
|                     names.append(node[1])
 | |
|                     flags = flags | CO_VARKEYWORDS
 | |
| 
 | |
|                 break
 | |
| 
 | |
|             # fpdef: NAME | '(' fplist ')'
 | |
|             names.append(self.com_fpdef(node))
 | |
| 
 | |
|             i = i + 1
 | |
|             if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
 | |
|                 defaults.append(self.com_node(nodelist[i + 1]))
 | |
|                 i = i + 2
 | |
|             elif len(defaults):
 | |
|                 # we have already seen an argument with default, but here
 | |
|                 # came one without
 | |
|                 raise SyntaxError, "non-default argument follows default argument"
 | |
| 
 | |
|             # skip the comma
 | |
|             i = i + 1
 | |
| 
 | |
|         return names, defaults, flags
 | |
| 
 | |
|     def com_fpdef(self, node):
 | |
|         # fpdef: NAME | '(' fplist ')'
 | |
|         if node[1][0] == token.LPAR:
 | |
|             return self.com_fplist(node[2])
 | |
|         return node[1][1]
 | |
| 
 | |
|     def com_fplist(self, node):
 | |
|         # fplist: fpdef (',' fpdef)* [',']
 | |
|         if len(node) == 2:
 | |
|             return self.com_fpdef(node[1])
 | |
|         list = []
 | |
|         for i in range(1, len(node), 2):
 | |
|             list.append(self.com_fpdef(node[i]))
 | |
|         return tuple(list)
 | |
| 
 | |
|     def com_dotted_name(self, node):
 | |
|         # String together the dotted names and return the string
 | |
|         name = ""
 | |
|         for n in node:
 | |
|             if type(n) == type(()) and n[0] == 1:
 | |
|                 name = name + n[1] + '.'
 | |
|         return name[:-1]
 | |
| 
 | |
|     def com_dotted_as_name(self, node):
 | |
|         assert node[0] == symbol.dotted_as_name
 | |
|         node = node[1:]
 | |
|         dot = self.com_dotted_name(node[0][1:])
 | |
|         if len(node) == 1:
 | |
|             return dot, None
 | |
|         assert node[1][1] == 'as'
 | |
|         assert node[2][0] == token.NAME
 | |
|         return dot, node[2][1]
 | |
| 
 | |
|     def com_dotted_as_names(self, node):
 | |
|         assert node[0] == symbol.dotted_as_names
 | |
|         node = node[1:]
 | |
|         names = [self.com_dotted_as_name(node[0])]
 | |
|         for i in range(2, len(node), 2):
 | |
|             names.append(self.com_dotted_as_name(node[i]))
 | |
|         return names
 | |
| 
 | |
|     def com_import_as_name(self, node):
 | |
|         assert node[0] == symbol.import_as_name
 | |
|         node = node[1:]
 | |
|         assert node[0][0] == token.NAME
 | |
|         if len(node) == 1:
 | |
|             return node[0][1], None
 | |
|         assert node[1][1] == 'as', node
 | |
|         assert node[2][0] == token.NAME
 | |
|         return node[0][1], node[2][1]
 | |
| 
 | |
|     def com_import_as_names(self, node):
 | |
|         assert node[0] == symbol.import_as_names
 | |
|         node = node[1:]
 | |
|         names = [self.com_import_as_name(node[0])]
 | |
|         for i in range(2, len(node), 2):
 | |
|             names.append(self.com_import_as_name(node[i]))
 | |
|         return names
 | |
| 
 | |
|     def com_bases(self, node):
 | |
|         bases = []
 | |
|         for i in range(1, len(node), 2):
 | |
|             bases.append(self.com_node(node[i]))
 | |
|         return bases
 | |
| 
 | |
|     def com_try_except_finally(self, nodelist):
 | |
|         # ('try' ':' suite
 | |
|         #  ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite]
 | |
|         #   | 'finally' ':' suite))
 | |
| 
 | |
|         if nodelist[3][0] == token.NAME:
 | |
|             # first clause is a finally clause: only try-finally
 | |
|             return TryFinally(self.com_node(nodelist[2]),
 | |
|                               self.com_node(nodelist[5]),
 | |
|                               lineno=nodelist[0][2])
 | |
| 
 | |
|         #tryexcept:  [TryNode, [except_clauses], elseNode)]
 | |
|         clauses = []
 | |
|         elseNode = None
 | |
|         finallyNode = None
 | |
|         for i in range(3, len(nodelist), 3):
 | |
|             node = nodelist[i]
 | |
|             if node[0] == symbol.except_clause:
 | |
|                 # except_clause: 'except' [expr [(',' | 'as') expr]] */
 | |
|                 if len(node) > 2:
 | |
|                     expr1 = self.com_node(node[2])
 | |
|                     if len(node) > 4:
 | |
|                         expr2 = self.com_assign(node[4], OP_ASSIGN)
 | |
|                     else:
 | |
|                         expr2 = None
 | |
|                 else:
 | |
|                     expr1 = expr2 = None
 | |
|                 clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
 | |
| 
 | |
|             if node[0] == token.NAME:
 | |
|                 if node[1] == 'else':
 | |
|                     elseNode = self.com_node(nodelist[i+2])
 | |
|                 elif node[1] == 'finally':
 | |
|                     finallyNode = self.com_node(nodelist[i+2])
 | |
|         try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
 | |
|                                lineno=nodelist[0][2])
 | |
|         if finallyNode:
 | |
|             return TryFinally(try_except, finallyNode, lineno=nodelist[0][2])
 | |
|         else:
 | |
|             return try_except
 | |
| 
 | |
|     def com_with(self, nodelist):
 | |
|         # with_stmt: 'with' with_item (',' with_item)* ':' suite
 | |
|         body = self.com_node(nodelist[-1])
 | |
|         for i in range(len(nodelist) - 3, 0, -2):
 | |
|             ret = self.com_with_item(nodelist[i], body, nodelist[0][2])
 | |
|             if i == 1:
 | |
|                 return ret
 | |
|             body = ret
 | |
| 
 | |
|     def com_with_item(self, nodelist, body, lineno):
 | |
|         # with_item: test ['as' expr]
 | |
|         if len(nodelist) == 4:
 | |
|             var = self.com_assign(nodelist[3], OP_ASSIGN)
 | |
|         else:
 | |
|             var = None
 | |
|         expr = self.com_node(nodelist[1])
 | |
|         return With(expr, var, body, lineno=lineno)
 | |
| 
 | |
|     def com_augassign_op(self, node):
 | |
|         assert node[0] == symbol.augassign
 | |
|         return node[1]
 | |
| 
 | |
|     def com_augassign(self, node):
 | |
|         """Return node suitable for lvalue of augmented assignment
 | |
| 
 | |
|         Names, slices, and attributes are the only allowable nodes.
 | |
|         """
 | |
|         l = self.com_node(node)
 | |
|         if l.__class__ in (Name, Slice, Subscript, Getattr):
 | |
|             return l
 | |
|         raise SyntaxError, "can't assign to %s" % l.__class__.__name__
 | |
| 
 | |
|     def com_assign(self, node, assigning):
 | |
|         # return a node suitable for use as an "lvalue"
 | |
|         # loop to avoid trivial recursion
 | |
|         while 1:
 | |
|             t = node[0]
 | |
|             if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_comp):
 | |
|                 if len(node) > 2:
 | |
|                     return self.com_assign_tuple(node, assigning)
 | |
|                 node = node[1]
 | |
|             elif t in _assign_types:
 | |
|                 if len(node) > 2:
 | |
|                     raise SyntaxError, "can't assign to operator"
 | |
|                 node = node[1]
 | |
|             elif t == symbol.power:
 | |
|                 if node[1][0] != symbol.atom:
 | |
|                     raise SyntaxError, "can't assign to operator"
 | |
|                 if len(node) > 2:
 | |
|                     primary = self.com_node(node[1])
 | |
|                     for i in range(2, len(node)-1):
 | |
|                         ch = node[i]
 | |
|                         if ch[0] == token.DOUBLESTAR:
 | |
|                             raise SyntaxError, "can't assign to operator"
 | |
|                         primary = self.com_apply_trailer(primary, ch)
 | |
|                     return self.com_assign_trailer(primary, node[-1],
 | |
|                                                    assigning)
 | |
|                 node = node[1]
 | |
|             elif t == symbol.atom:
 | |
|                 t = node[1][0]
 | |
|                 if t == token.LPAR:
 | |
|                     node = node[2]
 | |
|                     if node[0] == token.RPAR:
 | |
|                         raise SyntaxError, "can't assign to ()"
 | |
|                 elif t == token.LSQB:
 | |
|                     node = node[2]
 | |
|                     if node[0] == token.RSQB:
 | |
|                         raise SyntaxError, "can't assign to []"
 | |
|                     return self.com_assign_list(node, assigning)
 | |
|                 elif t == token.NAME:
 | |
|                     return self.com_assign_name(node[1], assigning)
 | |
|                 else:
 | |
|                     raise SyntaxError, "can't assign to literal"
 | |
|             else:
 | |
|                 raise SyntaxError, "bad assignment (%s)" % t
 | |
| 
 | |
|     def com_assign_tuple(self, node, assigning):
 | |
|         assigns = []
 | |
|         for i in range(1, len(node), 2):
 | |
|             assigns.append(self.com_assign(node[i], assigning))
 | |
|         return AssTuple(assigns, lineno=extractLineNo(node))
 | |
| 
 | |
|     def com_assign_list(self, node, assigning):
 | |
|         assigns = []
 | |
|         for i in range(1, len(node), 2):
 | |
|             if i + 1 < len(node):
 | |
|                 if node[i + 1][0] == symbol.list_for:
 | |
|                     raise SyntaxError, "can't assign to list comprehension"
 | |
|                 assert node[i + 1][0] == token.COMMA, node[i + 1]
 | |
|             assigns.append(self.com_assign(node[i], assigning))
 | |
|         return AssList(assigns, lineno=extractLineNo(node))
 | |
| 
 | |
|     def com_assign_name(self, node, assigning):
 | |
|         return AssName(node[1], assigning, lineno=node[2])
 | |
| 
 | |
|     def com_assign_trailer(self, primary, node, assigning):
 | |
|         t = node[1][0]
 | |
|         if t == token.DOT:
 | |
|             return self.com_assign_attr(primary, node[2], assigning)
 | |
|         if t == token.LSQB:
 | |
|             return self.com_subscriptlist(primary, node[2], assigning)
 | |
|         if t == token.LPAR:
 | |
|             raise SyntaxError, "can't assign to function call"
 | |
|         raise SyntaxError, "unknown trailer type: %s" % t
 | |
| 
 | |
|     def com_assign_attr(self, primary, node, assigning):
 | |
|         return AssAttr(primary, node[1], assigning, lineno=node[-1])
 | |
| 
 | |
|     def com_binary(self, constructor, nodelist):
 | |
|         "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
 | |
|         l = len(nodelist)
 | |
|         if l == 1:
 | |
|             n = nodelist[0]
 | |
|             return self.lookup_node(n)(n[1:])
 | |
|         items = []
 | |
|         for i in range(0, l, 2):
 | |
|             n = nodelist[i]
 | |
|             items.append(self.lookup_node(n)(n[1:]))
 | |
|         return constructor(items, lineno=extractLineNo(nodelist))
 | |
| 
 | |
|     def com_stmt(self, node):
 | |
|         result = self.lookup_node(node)(node[1:])
 | |
|         assert result is not None
 | |
|         if isinstance(result, Stmt):
 | |
|             return result
 | |
|         return Stmt([result])
 | |
| 
 | |
|     def com_append_stmt(self, stmts, node):
 | |
|         result = self.lookup_node(node)(node[1:])
 | |
|         assert result is not None
 | |
|         if isinstance(result, Stmt):
 | |
|             stmts.extend(result.nodes)
 | |
|         else:
 | |
|             stmts.append(result)
 | |
| 
 | |
|     def com_list_constructor(self, nodelist):
 | |
|         # listmaker: test ( list_for | (',' test)* [','] )
 | |
|         values = []
 | |
|         for i in range(1, len(nodelist)):
 | |
|             if nodelist[i][0] == symbol.list_for:
 | |
|                 assert len(nodelist[i:]) == 1
 | |
|                 return self.com_list_comprehension(values[0],
 | |
|                                                    nodelist[i])
 | |
|             elif nodelist[i][0] == token.COMMA:
 | |
|                 continue
 | |
|             values.append(self.com_node(nodelist[i]))
 | |
|         return List(values, lineno=values[0].lineno)
 | |
| 
 | |
|     def com_list_comprehension(self, expr, node):
 | |
|         return self.com_comprehension(expr, None, node, 'list')
 | |
| 
 | |
|     def com_comprehension(self, expr1, expr2, node, type):
 | |
|         # list_iter: list_for | list_if
 | |
|         # list_for: 'for' exprlist 'in' testlist [list_iter]
 | |
|         # list_if: 'if' test [list_iter]
 | |
| 
 | |
|         # XXX should raise SyntaxError for assignment
 | |
|         # XXX(avassalotti) Set and dict comprehensions should have generator
 | |
|         #                  semantics. In other words, they shouldn't leak
 | |
|         #                  variables outside of the comprehension's scope.
 | |
| 
 | |
|         lineno = node[1][2]
 | |
|         fors = []
 | |
|         while node:
 | |
|             t = node[1][1]
 | |
|             if t == 'for':
 | |
|                 assignNode = self.com_assign(node[2], OP_ASSIGN)
 | |
|                 compNode = self.com_node(node[4])
 | |
|                 newfor = ListCompFor(assignNode, compNode, [])
 | |
|                 newfor.lineno = node[1][2]
 | |
|                 fors.append(newfor)
 | |
|                 if len(node) == 5:
 | |
|                     node = None
 | |
|                 elif type == 'list':
 | |
|                     node = self.com_list_iter(node[5])
 | |
|                 else:
 | |
|                     node = self.com_comp_iter(node[5])
 | |
|             elif t == 'if':
 | |
|                 test = self.com_node(node[2])
 | |
|                 newif = ListCompIf(test, lineno=node[1][2])
 | |
|                 newfor.ifs.append(newif)
 | |
|                 if len(node) == 3:
 | |
|                     node = None
 | |
|                 elif type == 'list':
 | |
|                     node = self.com_list_iter(node[3])
 | |
|                 else:
 | |
|                     node = self.com_comp_iter(node[3])
 | |
|             else:
 | |
|                 raise SyntaxError, \
 | |
|                       ("unexpected comprehension element: %s %d"
 | |
|                        % (node, lineno))
 | |
|         if type == 'list':
 | |
|             return ListComp(expr1, fors, lineno=lineno)
 | |
|         elif type == 'set':
 | |
|             return SetComp(expr1, fors, lineno=lineno)
 | |
|         elif type == 'dict':
 | |
|             return DictComp(expr1, expr2, fors, lineno=lineno)
 | |
|         else:
 | |
|             raise ValueError("unexpected comprehension type: " + repr(type))
 | |
| 
 | |
|     def com_list_iter(self, node):
 | |
|         assert node[0] == symbol.list_iter
 | |
|         return node[1]
 | |
| 
 | |
|     def com_comp_iter(self, node):
 | |
|         assert node[0] == symbol.comp_iter
 | |
|         return node[1]
 | |
| 
 | |
|     def com_generator_expression(self, expr, node):
 | |
|         # comp_iter: comp_for | comp_if
 | |
|         # comp_for: 'for' exprlist 'in' test [comp_iter]
 | |
|         # comp_if: 'if' test [comp_iter]
 | |
| 
 | |
|         lineno = node[1][2]
 | |
|         fors = []
 | |
|         while node:
 | |
|             t = node[1][1]
 | |
|             if t == 'for':
 | |
|                 assignNode = self.com_assign(node[2], OP_ASSIGN)
 | |
|                 genNode = self.com_node(node[4])
 | |
|                 newfor = GenExprFor(assignNode, genNode, [],
 | |
|                                     lineno=node[1][2])
 | |
|                 fors.append(newfor)
 | |
|                 if (len(node)) == 5:
 | |
|                     node = None
 | |
|                 else:
 | |
|                     node = self.com_comp_iter(node[5])
 | |
|             elif t == 'if':
 | |
|                 test = self.com_node(node[2])
 | |
|                 newif = GenExprIf(test, lineno=node[1][2])
 | |
|                 newfor.ifs.append(newif)
 | |
|                 if len(node) == 3:
 | |
|                     node = None
 | |
|                 else:
 | |
|                     node = self.com_comp_iter(node[3])
 | |
|             else:
 | |
|                 raise SyntaxError, \
 | |
|                         ("unexpected generator expression element: %s %d"
 | |
|                          % (node, lineno))
 | |
|         fors[0].is_outmost = True
 | |
|         return GenExpr(GenExprInner(expr, fors), lineno=lineno)
 | |
| 
 | |
|     def com_dictorsetmaker(self, nodelist):
 | |
|         # dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
 | |
|         #                   (test (comp_for | (',' test)* [','])) )
 | |
|         assert nodelist[0] == symbol.dictorsetmaker
 | |
|         nodelist = nodelist[1:]
 | |
|         if len(nodelist) == 1 or nodelist[1][0] == token.COMMA:
 | |
|             # set literal
 | |
|             items = []
 | |
|             for i in range(0, len(nodelist), 2):
 | |
|                 items.append(self.com_node(nodelist[i]))
 | |
|             return Set(items, lineno=items[0].lineno)
 | |
|         elif nodelist[1][0] == symbol.comp_for:
 | |
|             # set comprehension
 | |
|             expr = self.com_node(nodelist[0])
 | |
|             return self.com_comprehension(expr, None, nodelist[1], 'set')
 | |
|         elif len(nodelist) > 3 and nodelist[3][0] == symbol.comp_for:
 | |
|             # dict comprehension
 | |
|             assert nodelist[1][0] == token.COLON
 | |
|             key = self.com_node(nodelist[0])
 | |
|             value = self.com_node(nodelist[2])
 | |
|             return self.com_comprehension(key, value, nodelist[3], 'dict')
 | |
|         else:
 | |
|             # dict literal
 | |
|             items = []
 | |
|             for i in range(0, len(nodelist), 4):
 | |
|                 items.append((self.com_node(nodelist[i]),
 | |
|                               self.com_node(nodelist[i+2])))
 | |
|             return Dict(items, lineno=items[0][0].lineno)
 | |
| 
 | |
|     def com_apply_trailer(self, primaryNode, nodelist):
 | |
|         t = nodelist[1][0]
 | |
|         if t == token.LPAR:
 | |
|             return self.com_call_function(primaryNode, nodelist[2])
 | |
|         if t == token.DOT:
 | |
|             return self.com_select_member(primaryNode, nodelist[2])
 | |
|         if t == token.LSQB:
 | |
|             return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
 | |
| 
 | |
|         raise SyntaxError, 'unknown node type: %s' % t
 | |
| 
 | |
|     def com_select_member(self, primaryNode, nodelist):
 | |
|         if nodelist[0] != token.NAME:
 | |
|             raise SyntaxError, "member must be a name"
 | |
|         return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
 | |
| 
 | |
|     def com_call_function(self, primaryNode, nodelist):
 | |
|         if nodelist[0] == token.RPAR:
 | |
|             return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
 | |
|         args = []
 | |
|         kw = 0
 | |
|         star_node = dstar_node = None
 | |
|         len_nodelist = len(nodelist)
 | |
|         i = 1
 | |
|         while i < len_nodelist:
 | |
|             node = nodelist[i]
 | |
| 
 | |
|             if node[0]==token.STAR:
 | |
|                 if star_node is not None:
 | |
|                     raise SyntaxError, 'already have the varargs indentifier'
 | |
|                 star_node = self.com_node(nodelist[i+1])
 | |
|                 i = i + 3
 | |
|                 continue
 | |
|             elif node[0]==token.DOUBLESTAR:
 | |
|                 if dstar_node is not None:
 | |
|                     raise SyntaxError, 'already have the kwargs indentifier'
 | |
|                 dstar_node = self.com_node(nodelist[i+1])
 | |
|                 i = i + 3
 | |
|                 continue
 | |
| 
 | |
|             # positional or named parameters
 | |
|             kw, result = self.com_argument(node, kw, star_node)
 | |
| 
 | |
|             if len_nodelist != 2 and isinstance(result, GenExpr) \
 | |
|                and len(node) == 3 and node[2][0] == symbol.comp_for:
 | |
|                 # allow f(x for x in y), but reject f(x for x in y, 1)
 | |
|                 # should use f((x for x in y), 1) instead of f(x for x in y, 1)
 | |
|                 raise SyntaxError, 'generator expression needs parenthesis'
 | |
| 
 | |
|             args.append(result)
 | |
|             i = i + 2
 | |
| 
 | |
|         return CallFunc(primaryNode, args, star_node, dstar_node,
 | |
|                         lineno=extractLineNo(nodelist))
 | |
| 
 | |
|     def com_argument(self, nodelist, kw, star_node):
 | |
|         if len(nodelist) == 3 and nodelist[2][0] == symbol.comp_for:
 | |
|             test = self.com_node(nodelist[1])
 | |
|             return 0, self.com_generator_expression(test, nodelist[2])
 | |
|         if len(nodelist) == 2:
 | |
|             if kw:
 | |
|                 raise SyntaxError, "non-keyword arg after keyword arg"
 | |
|             if star_node:
 | |
|                 raise SyntaxError, "only named arguments may follow *expression"
 | |
|             return 0, self.com_node(nodelist[1])
 | |
|         result = self.com_node(nodelist[3])
 | |
|         n = nodelist[1]
 | |
|         while len(n) == 2 and n[0] != token.NAME:
 | |
|             n = n[1]
 | |
|         if n[0] != token.NAME:
 | |
|             raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
 | |
|         node = Keyword(n[1], result, lineno=n[2])
 | |
|         return 1, node
 | |
| 
 | |
|     def com_subscriptlist(self, primary, nodelist, assigning):
 | |
|         # slicing:      simple_slicing | extended_slicing
 | |
|         # simple_slicing:   primary "[" short_slice "]"
 | |
|         # extended_slicing: primary "[" slice_list "]"
 | |
|         # slice_list:   slice_item ("," slice_item)* [","]
 | |
| 
 | |
|         # backwards compat slice for '[i:j]'
 | |
|         if len(nodelist) == 2:
 | |
|             sub = nodelist[1]
 | |
|             if (sub[1][0] == token.COLON or \
 | |
|                             (len(sub) > 2 and sub[2][0] == token.COLON)) and \
 | |
|                             sub[-1][0] != symbol.sliceop:
 | |
|                 return self.com_slice(primary, sub, assigning)
 | |
| 
 | |
|         subscripts = []
 | |
|         for i in range(1, len(nodelist), 2):
 | |
|             subscripts.append(self.com_subscript(nodelist[i]))
 | |
|         return Subscript(primary, assigning, subscripts,
 | |
|                          lineno=extractLineNo(nodelist))
 | |
| 
 | |
|     def com_subscript(self, node):
 | |
|         # slice_item: expression | proper_slice | ellipsis
 | |
|         ch = node[1]
 | |
|         t = ch[0]
 | |
|         if t == token.DOT and node[2][0] == token.DOT:
 | |
|             return Ellipsis()
 | |
|         if t == token.COLON or len(node) > 2:
 | |
|             return self.com_sliceobj(node)
 | |
|         return self.com_node(ch)
 | |
| 
 | |
|     def com_sliceobj(self, node):
 | |
|         # proper_slice: short_slice | long_slice
 | |
|         # short_slice:  [lower_bound] ":" [upper_bound]
 | |
|         # long_slice:   short_slice ":" [stride]
 | |
|         # lower_bound:  expression
 | |
|         # upper_bound:  expression
 | |
|         # stride:       expression
 | |
|         #
 | |
|         # Note: a stride may be further slicing...
 | |
| 
 | |
|         items = []
 | |
| 
 | |
|         if node[1][0] == token.COLON:
 | |
|             items.append(Const(None))
 | |
|             i = 2
 | |
|         else:
 | |
|             items.append(self.com_node(node[1]))
 | |
|             # i == 2 is a COLON
 | |
|             i = 3
 | |
| 
 | |
|         if i < len(node) and node[i][0] == symbol.test:
 | |
|             items.append(self.com_node(node[i]))
 | |
|             i = i + 1
 | |
|         else:
 | |
|             items.append(Const(None))
 | |
| 
 | |
|         # a short_slice has been built. look for long_slice now by looking
 | |
|         # for strides...
 | |
|         for j in range(i, len(node)):
 | |
|             ch = node[j]
 | |
|             if len(ch) == 2:
 | |
|                 items.append(Const(None))
 | |
|             else:
 | |
|                 items.append(self.com_node(ch[2]))
 | |
|         return Sliceobj(items, lineno=extractLineNo(node))
 | |
| 
 | |
|     def com_slice(self, primary, node, assigning):
 | |
|         # short_slice:  [lower_bound] ":" [upper_bound]
 | |
|         lower = upper = None
 | |
|         if len(node) == 3:
 | |
|             if node[1][0] == token.COLON:
 | |
|                 upper = self.com_node(node[2])
 | |
|             else:
 | |
|                 lower = self.com_node(node[1])
 | |
|         elif len(node) == 4:
 | |
|             lower = self.com_node(node[1])
 | |
|             upper = self.com_node(node[3])
 | |
|         return Slice(primary, assigning, lower, upper,
 | |
|                      lineno=extractLineNo(node))
 | |
| 
 | |
|     def get_docstring(self, node, n=None):
 | |
|         if n is None:
 | |
|             n = node[0]
 | |
|             node = node[1:]
 | |
|         if n == symbol.suite:
 | |
|             if len(node) == 1:
 | |
|                 return self.get_docstring(node[0])
 | |
|             for sub in node:
 | |
|                 if sub[0] == symbol.stmt:
 | |
|                     return self.get_docstring(sub)
 | |
|             return None
 | |
|         if n == symbol.file_input:
 | |
|             for sub in node:
 | |
|                 if sub[0] == symbol.stmt:
 | |
|                     return self.get_docstring(sub)
 | |
|             return None
 | |
|         if n == symbol.atom:
 | |
|             if node[0][0] == token.STRING:
 | |
|                 s = ''
 | |
|                 for t in node:
 | |
|                     s = s + eval(t[1])
 | |
|                 return s
 | |
|             return None
 | |
|         if n == symbol.stmt or n == symbol.simple_stmt \
 | |
|            or n == symbol.small_stmt:
 | |
|             return self.get_docstring(node[0])
 | |
|         if n in _doc_nodes and len(node) == 1:
 | |
|             return self.get_docstring(node[0])
 | |
|         return None
 | |
| 
 | |
| 
 | |
| _doc_nodes = [
 | |
|     symbol.expr_stmt,
 | |
|     symbol.testlist,
 | |
|     symbol.testlist_safe,
 | |
|     symbol.test,
 | |
|     symbol.or_test,
 | |
|     symbol.and_test,
 | |
|     symbol.not_test,
 | |
|     symbol.comparison,
 | |
|     symbol.expr,
 | |
|     symbol.xor_expr,
 | |
|     symbol.and_expr,
 | |
|     symbol.shift_expr,
 | |
|     symbol.arith_expr,
 | |
|     symbol.term,
 | |
|     symbol.factor,
 | |
|     symbol.power,
 | |
|     ]
 | |
| 
 | |
| # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
 | |
| #             | 'in' | 'not' 'in' | 'is' | 'is' 'not'
 | |
| _cmp_types = {
 | |
|     token.LESS : '<',
 | |
|     token.GREATER : '>',
 | |
|     token.EQEQUAL : '==',
 | |
|     token.EQUAL : '==',
 | |
|     token.LESSEQUAL : '<=',
 | |
|     token.GREATEREQUAL : '>=',
 | |
|     token.NOTEQUAL : '!=',
 | |
|     }
 | |
| 
 | |
| _legal_node_types = [
 | |
|     symbol.funcdef,
 | |
|     symbol.classdef,
 | |
|     symbol.stmt,
 | |
|     symbol.small_stmt,
 | |
|     symbol.flow_stmt,
 | |
|     symbol.simple_stmt,
 | |
|     symbol.compound_stmt,
 | |
|     symbol.expr_stmt,
 | |
|     symbol.print_stmt,
 | |
|     symbol.del_stmt,
 | |
|     symbol.pass_stmt,
 | |
|     symbol.break_stmt,
 | |
|     symbol.continue_stmt,
 | |
|     symbol.return_stmt,
 | |
|     symbol.raise_stmt,
 | |
|     symbol.import_stmt,
 | |
|     symbol.global_stmt,
 | |
|     symbol.exec_stmt,
 | |
|     symbol.assert_stmt,
 | |
|     symbol.if_stmt,
 | |
|     symbol.while_stmt,
 | |
|     symbol.for_stmt,
 | |
|     symbol.try_stmt,
 | |
|     symbol.with_stmt,
 | |
|     symbol.suite,
 | |
|     symbol.testlist,
 | |
|     symbol.testlist_safe,
 | |
|     symbol.test,
 | |
|     symbol.and_test,
 | |
|     symbol.not_test,
 | |
|     symbol.comparison,
 | |
|     symbol.exprlist,
 | |
|     symbol.expr,
 | |
|     symbol.xor_expr,
 | |
|     symbol.and_expr,
 | |
|     symbol.shift_expr,
 | |
|     symbol.arith_expr,
 | |
|     symbol.term,
 | |
|     symbol.factor,
 | |
|     symbol.power,
 | |
|     symbol.atom,
 | |
|     ]
 | |
| 
 | |
| if hasattr(symbol, 'yield_stmt'):
 | |
|     _legal_node_types.append(symbol.yield_stmt)
 | |
| if hasattr(symbol, 'yield_expr'):
 | |
|     _legal_node_types.append(symbol.yield_expr)
 | |
| 
 | |
| _assign_types = [
 | |
|     symbol.test,
 | |
|     symbol.or_test,
 | |
|     symbol.and_test,
 | |
|     symbol.not_test,
 | |
|     symbol.comparison,
 | |
|     symbol.expr,
 | |
|     symbol.xor_expr,
 | |
|     symbol.and_expr,
 | |
|     symbol.shift_expr,
 | |
|     symbol.arith_expr,
 | |
|     symbol.term,
 | |
|     symbol.factor,
 | |
|     ]
 | |
| 
 | |
| _names = {}
 | |
| for k, v in symbol.sym_name.items():
 | |
|     _names[k] = v
 | |
| for k, v in token.tok_name.items():
 | |
|     _names[k] = v
 | |
| 
 | |
| def debug_tree(tree):
 | |
|     l = []
 | |
|     for elt in tree:
 | |
|         if isinstance(elt, int):
 | |
|             l.append(_names.get(elt, elt))
 | |
|         elif isinstance(elt, str):
 | |
|             l.append(elt)
 | |
|         else:
 | |
|             l.append(debug_tree(elt))
 | |
|     return l
 |