from ast_nodes import * def _tup(nodes): # transform a list of nodes in format "expr (',' expr)* [',']" # into a single expression 'expr' or a tuple-forming expression if # there is a ','. if len(nodes) > 1: return Tuple(list(nodes[::2])) else: return nodes[0] def single_input(stmtlist, *nodes): "NEWLINE | simple_stmt | compound_stmt NEWLINE" if stmtlist == '\n': return [] else: return stmtlist def file_input(*nodes): "(NEWLINE | stmt)* ENDMARKER" result = [] for stmtlist in nodes[:-1]: if stmtlist != '\n': result += stmtlist return result def eval_input(testlist, *nodes): "testlist NEWLINE* ENDMARKER" return _tup(testlist) def funcdef(def_, name, parameters, colon, suite): "'def' NAME parameters ':' suite" return Function(name, parameters, suite) def parameters(*nodes): "'(' [varargslist] ')'" if len(nodes) == 2: return Parameters() else: return nodes[1] def varargslist(*nodes): "(fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']" p = Parameters() nodes = list(nodes) while nodes: arg = nodes.pop(0) if arg == ',': pass elif arg == '*': p.vararg = nodes.pop(0) elif arg == '**': p.kwarg = nodes.pop(0) elif len(nodes) > 1 and nodes[0] == '=': nodes.pop(0) p.add(arg, nodes.pop(0)) else: p.add(arg, None) return p def fpdef(*nodes): "NAME | '(' fplist ')'" if len(nodes) == 1: return nodes[0] else: return Tuple(nodes[1]) def fplist(*nodes): "fpdef (',' fpdef)* [',']" return list(nodes[::2]) def stmt(stmtlist): "simple_stmt | compound_stmt" return stmtlist def simple_stmt(*nodes): "small_stmt (';' small_stmt)* [';'] NEWLINE" return list(nodes[:-1:2]) def small_stmt(s): "expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt" return s def expr_stmt(testlist, *nodes): "testlist [augassign testlist | ('=' testlist)*)" if len(nodes) == 2 and nodes[0] != '=': return InPlaceAssign(_tup(testlist), nodes[0], _tup(nodes[1])) elif nodes: return Assign( [_tup(testlist)] + [_tup(t) for t in nodes[1:-1:2]], _tup(nodes[-1])) else: return Discard(_tup(testlist)) def augassign(op): "'+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='" return op def print_stmt(print_, *nodes): "'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] )" p = Print() if nodes and nodes[0] == '>>': p.target = nodes[1] nodes = nodes[3:] p.nodes = list(nodes[::2]) p.newline = not (nodes and nodes[-1] == ',') return p def del_stmt(del_, exprlist): "'del' exprlist" return Del(exprlist) def pass_stmt(pass_): "'pass'" return Pass() def flow_stmt(s): "break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt" return s def break_stmt(break_): "'break'" return Break() def continue_stmt(continue_): "'continue'" return Continue() def return_stmt(return_, testlist=None): "'return' [testlist]" if testlist: return Return(_tup(testlist)) else: return Return() def yield_stmt(yield_, testlist): "'yield' testlist" return Yield(_tup(testlist)) def raise_stmt(raise_, *nodes): "'raise' [test [',' test [',' test]]]" return Raise(*nodes[::2]) def import_stmt(*nodes): "'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)" if nodes[0] == 'import': return Import(list(nodes[1::2])) elif nodes[3] == '*': return ImportFrom(nodes[1], '*') else: return ImportFrom(nodes[1], list(nodes[3::2])) def import_as_name(name, as_=None, as_name=None): "NAME [NAME NAME]" return name, as_name or name def dotted_as_name(dotted_name, as_=None, as_name=None): "dotted_name [NAME NAME]" return '.'.join(dotted_name), as_name or dotted_name[0] def dotted_name(*nodes): "NAME ('.' NAME)*" return nodes[::2] def global_stmt(global_, *nodes): "'global' NAME (',' NAME)*" return Global(list(nodes[1::2])) def exec_stmt(exec_, expr, *nodes): "'exec' expr ['in' test [',' test]]" glob = loc = None if nodes: glob = nodes[1] if len(nodes) > 2: loc = nodes[3] return Exec(expr, glob, loc) def assert_stmt(assert_, test, comma=None, value=None): "'assert' test [',' test]" return Assert(test, value) def compound_stmt(s): "if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef" return [s] def if_stmt(if_, test, colon, suite, *nodes): "'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]" result = If(test, suite) if nodes: if nodes[0] == 'elif': result.else_ = [if_stmt(*nodes)] else: result.else_ = nodes[-1] return result def while_stmt(while_, test, colon, suite, else_=None, colon_=None, suite_=None): "'while' test ':' suite ['else' ':' suite]" return While(test, suite, suite_) def for_stmt(for_, exprlist, in_, testlist, colon, suite, else_=None, colon_=None, suite_=None): "'for' exprlist 'in' testlist ':' suite ['else' ':' suite]" return For(exprlist, _tup(testlist), suite, suite_) def try_stmt(try_, colon, suite, *nodes): "('try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)" if nodes[0] == 'finally': return TryFinally(suite, nodes[-1]) else: if nodes[-3] == 'else': else_ = nodes[-1] nodes = nodes[:-3] else: else_ = None return TryExcept(suite, zip(nodes[0::3], nodes[2::3]), else_) def except_clause(except_, type=None, comma=None, value=None): "'except' [test [',' test]]" return type, value def suite(*nodes): "simple_stmt | NEWLINE INDENT stmt+ DEDENT" if len(nodes) == 1: return nodes[0] else: result = [] for stmtlist in nodes[2:-1]: result += stmtlist return result def test(*nodes): "and_test ('or' and_test)* | lambdef" if len(nodes) == 1: return nodes[0] else: return Or(nodes[::2]) def and_test(*nodes): "not_test ('and' not_test)*" if len(nodes) == 1: return nodes[0] else: return And(nodes[::2]) def not_test(*nodes): "'not' not_test | comparison" if len(nodes) == 1: return nodes[0] else: return UnaryOp(*nodes) def comparison(*nodes): "expr (comp_op expr)*" if len(nodes) > 1: return Compare(list(nodes)) else: return nodes[0] def comp_op(*nodes): "'<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'" return ' '.join(nodes) def binary_(nodes): # generic builder for binary operators n = nodes[0] for op, n2 in zip(nodes[1::2], nodes[2::2]): n = BinaryOp(n, op, n2) return n def expr(*nodes): "xor_expr ('|' xor_expr)*" return binary_(nodes) def xor_expr(*nodes): "and_expr ('^' and_expr)*" return binary_(nodes) def and_expr(*nodes): "shift_expr ('&' shift_expr)*" return binary_(nodes) def shift_expr(*nodes): "arith_expr (('<<'|'>>') arith_expr)*" return binary_(nodes) def arith_expr(*nodes): "term (('+'|'-') term)*" return binary_(nodes) def term(*nodes): "factor (('*'|'/'|'%'|'//') factor)*" return binary_(nodes) def factor(*nodes): "('+'|'-'|'~') factor | power" if len(nodes) == 1: return nodes[0] else: return UnaryOp(*nodes) def power(n, *nodes): "atom trailer* ['**' factor]" for trailer in nodes: if trailer == '**': return BinaryOp(n, '**', nodes[-1]) trailer.obj = n n = trailer return n def atom(*nodes): "'(' [testlist] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+" if len(nodes) == 1: return nodes[0] left = nodes[0] right = nodes[-1] middle = nodes[1:-1] if left == '(': if middle: return _tup(middle[0]) else: return Const(()) elif left == '[': if middle: return middle[0] else: return List([]) elif left == '{': if middle: return middle[0] else: return Dict([]) elif left == '`': return UnaryOp('`', _tup(middle[0])) else: return Const(''.join([c.value for c in nodes])) def listmaker(*nodes): "test ( list_for | (',' test)* [','] )" if len(nodes) == 1 or nodes[1] == ',': return List(list(nodes[::2])) else: expr, stmt = nodes stmt.innerlist[:] = [ListCompAppend(expr)] return ListComp(stmt) def lambdef(*nodes): "'lambda' [varargslist] ':' test" if len(nodes) == 4: parameters = nodes[1] else: parameters = Parameters() return Lambda(parameters, nodes[-1]) def trailer(op, next, *nodes): "'(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME" if op == '(': if nodes: return Call(None, next) else: return Call(None, []) elif op == '[': return Subscript(None, next) else: return Attr(None, next) def subscriptlist(*nodes): "subscript (',' subscript)* [',']" return _tup(nodes) def subscript(*nodes): "'.' '.' '.' | test | [test] ':' [test] [sliceop]" if nodes == ('.', '.', '.'): return Ellipsis() elif len(nodes) == 1: if nodes[0] == ':': return Slice() else: return nodes[0] else: if isinstance(nodes[-1], tuple): nodes = nodes[:-1] + nodes[-1] args = [None, None, None] i = 0 for n in nodes: if n == ':': i += 1 else: args[i] = n return Slice(*args) def sliceop(*nodes): "':' [test]" return nodes def exprlist(*nodes): "expr (',' expr)* [',']" return _tup(nodes) def testlist(*nodes): "test (',' test)* [',']" # depending on context, a testlist must be parsed either as # a tuple-forming expression or as a comma-separated list # so this function returns the nodes unprocessed as a tuple. return nodes def testlist_safe(*nodes): "test [(',' test)+ [',']]" return testlist(*nodes) def dictmaker(*nodes): "test ':' test (',' test ':' test)* [',']" return Dict(zip(nodes[0::4], nodes[2::4])) def classdef(class_, name, *nodes): "'class' NAME ['(' testlist ')'] ':' suite" if nodes[0] == '(': bases_testlist = list(nodes[1]) bases = bases_testlist[::2] else: bases = [] return Class(name, bases, nodes[-1]) def arglist(*nodes): "(argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)" p = Parameters() nodes = list(nodes) while nodes: arg = nodes.pop(0) if arg == ',': pass elif arg == '*': p.vararg = nodes.pop(0) elif arg == '**': p.kwarg = nodes.pop(0) else: name, value = arg p.add(name, value) return p def argument(*nodes): "[test '='] test" if len(nodes) == 1: return None, nodes[0] else: return nodes[0], nodes[2] def list_iter(stmt): "list_for | list_if" return stmt def list_for(for_, exprlist, in_, testlist, list_iter=None): "'for' exprlist 'in' testlist_safe [list_iter]" result = For(exprlist, _tup(testlist), [list_iter]) if list_iter: result.innerlist = list_iter.innerlist else: result.innerlist = result.body return result def list_if(if_, test, list_iter=None): "'if' test [list_iter]" result = If(test, [list_iter]) if list_iter: result.innerlist = list_iter.innerlist else: result.innerlist = result.then return result def testlist1(*nodes): "test (',' test)*" return testlist(*nodes) def encoding_decl(stmtlist, encoding): return stmtlist # ____________________________________________________________ import symbol symbolmap = {} for i, name in symbol.sym_name.items(): symbolmap[i] = globals()[name]