You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Grammar improvement
This commit is contained in:
@@ -18,7 +18,7 @@ hashes get pretty-printed.
|
||||
a tool called 'decompyle'. This tool has been vastly improved by
|
||||
Hartmut Goebel `http://www.crazy-compilers.com/`_
|
||||
|
||||
### Additional note (3 July 2004, Ben Burton):
|
||||
# Additional note (3 July 2004, Ben Burton):
|
||||
|
||||
This software is no longer available from the original website. It has
|
||||
now become a commercial decompilation service, with no software
|
||||
@@ -28,7 +28,7 @@ Any developers seeking to make alterations or enhancements to this code
|
||||
should therefore consider these debian packages an appropriate starting
|
||||
point.
|
||||
|
||||
### Additional note (5 June 2012):
|
||||
# Additional note (5 June 2012):
|
||||
|
||||
The decompilation of python bytecode 2.5 & 2.6 is based on the work of
|
||||
Eloi Vanderbeken. bytecode is translated to a pseudo 2.7 python bytecode
|
||||
@@ -86,9 +86,9 @@ http://www.python.org/doc/current/inst/inst.html
|
||||
Usage
|
||||
-----
|
||||
|
||||
uncompyle2 -h prints short usage
|
||||
uncompyle2 --help prints long usage
|
||||
./uncompyle2.py -h prints usage
|
||||
|
||||
./test_pythonlib.py test files and python library
|
||||
|
||||
Known Bugs/Restrictions
|
||||
-----------------------
|
||||
|
@@ -231,9 +231,7 @@ class Parser(GenericASTBuilder):
|
||||
importlist2 ::= importlist2 import_as
|
||||
importlist2 ::= import_as
|
||||
import_as ::= IMPORT_NAME designator
|
||||
import_as ::= IMPORT_NAME LOAD_ATTR designator
|
||||
import_as ::= IMPORT_NAME LOAD_ATTR LOAD_ATTR designator
|
||||
import_as ::= IMPORT_NAME LOAD_ATTR LOAD_ATTR LOAD_ATTR designator
|
||||
import_as ::= IMPORT_NAME load_attrs designator
|
||||
import_as ::= IMPORT_FROM designator
|
||||
|
||||
importstmt ::= LOAD_CONST LOAD_CONST import_as
|
||||
@@ -247,10 +245,11 @@ class Parser(GenericASTBuilder):
|
||||
imports_cont ::= import_cont
|
||||
import_cont ::= LOAD_CONST LOAD_CONST import_as_cont
|
||||
import_as_cont ::= IMPORT_NAME_CONT designator
|
||||
import_as_cont ::= IMPORT_NAME_CONT LOAD_ATTR designator
|
||||
import_as_cont ::= IMPORT_NAME_CONT LOAD_ATTR LOAD_ATTR designator
|
||||
import_as_cont ::= IMPORT_NAME_CONT LOAD_ATTR LOAD_ATTR LOAD_ATTR designator
|
||||
import_as_cont ::= IMPORT_NAME_CONT load_attrs designator
|
||||
import_as_cont ::= IMPORT_FROM designator
|
||||
|
||||
load_attrs ::= LOAD_ATTR
|
||||
load_attrs ::= load_attrs LOAD_ATTR
|
||||
'''
|
||||
|
||||
def p_grammar(self, args):
|
||||
@@ -331,13 +330,13 @@ class Parser(GenericASTBuilder):
|
||||
call_stmt ::= expr POP_TOP
|
||||
|
||||
stmt ::= return_stmt
|
||||
return_stmt ::= expr RETURN_VALUE
|
||||
return_stmt ::= ret_expr RETURN_VALUE
|
||||
return_stmts ::= return_stmt
|
||||
return_stmts ::= _stmts return_stmt
|
||||
|
||||
return_if_stmts ::= return_if_stmt
|
||||
return_if_stmts ::= _stmts return_if_stmt
|
||||
return_if_stmt ::= expr RETURN_END_IF
|
||||
return_if_stmt ::= ret_expr RETURN_END_IF
|
||||
|
||||
stmt ::= break_stmt
|
||||
break_stmt ::= BREAK_LOOP
|
||||
@@ -349,9 +348,15 @@ class Parser(GenericASTBuilder):
|
||||
continue_stmts ::= lastl_stmt continue_stmt
|
||||
continue_stmts ::= continue_stmt
|
||||
|
||||
stmt ::= raise_stmt
|
||||
raise_stmt ::= exprlist RAISE_VARARGS
|
||||
raise_stmt ::= nullexprlist RAISE_VARARGS
|
||||
stmt ::= raise_stmt0
|
||||
stmt ::= raise_stmt1
|
||||
stmt ::= raise_stmt2
|
||||
stmt ::= raise_stmt3
|
||||
|
||||
raise_stmt0 ::= RAISE_VARARGS_0
|
||||
raise_stmt1 ::= expr RAISE_VARARGS_1
|
||||
raise_stmt2 ::= expr expr RAISE_VARARGS_2
|
||||
raise_stmt3 ::= expr expr expr RAISE_VARARGS_3
|
||||
|
||||
stmt ::= exec_stmt
|
||||
exec_stmt ::= expr exprlist DUP_TOP EXEC_STMT
|
||||
@@ -407,23 +412,13 @@ class Parser(GenericASTBuilder):
|
||||
jmp_true ::= POP_JUMP_IF_TRUE
|
||||
jmp_true ::= JUMP_IF_TRUE
|
||||
|
||||
multi_come_from ::= multi_come_from COME_FROM
|
||||
multi_come_from ::=
|
||||
assert_end ::= multi_come_from POP_TOP
|
||||
assert_end ::=
|
||||
|
||||
assert ::= assert_expr jmp_true
|
||||
LOAD_ASSERT RAISE_VARARGS assert_end
|
||||
assert2 ::= assert_expr jmp_true
|
||||
LOAD_ASSERT expr RAISE_VARARGS assert_end
|
||||
assert ::= assert_expr jmp_true
|
||||
LOAD_GLOBAL RAISE_VARARGS assert_end
|
||||
assert2 ::= assert_expr jmp_true
|
||||
LOAD_GLOBAL expr RAISE_VARARGS assert_end
|
||||
assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1
|
||||
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
|
||||
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr RAISE_VARARGS_2
|
||||
|
||||
assert_expr ::= expr
|
||||
assert_expr ::= assert_expr_or
|
||||
assert_expr ::= assert_expr_and
|
||||
assert_expr ::= expr
|
||||
assert_expr_or ::= assert_expr jmp_true expr
|
||||
assert_expr_and ::= assert_expr jmp_false expr
|
||||
|
||||
@@ -639,11 +634,23 @@ class Parser(GenericASTBuilder):
|
||||
expr ::= conditionalnot
|
||||
conditionalnot ::= expr jmp_true expr _jump expr COME_FROM
|
||||
|
||||
ret_expr ::= expr
|
||||
ret_expr ::= ret_and
|
||||
ret_expr ::= ret_or
|
||||
|
||||
ret_expr_or_cond ::= ret_expr
|
||||
ret_expr_or_cond ::= ret_cond
|
||||
ret_expr_or_cond ::= ret_cond_not
|
||||
|
||||
ret_and ::= expr jmp_false ret_expr_or_cond COME_FROM
|
||||
ret_or ::= expr jmp_true ret_expr_or_cond COME_FROM
|
||||
ret_cond ::= expr jmp_false expr RETURN_END_IF ret_expr_or_cond
|
||||
ret_cond_not ::= expr jmp_true expr RETURN_END_IF ret_expr_or_cond
|
||||
|
||||
stmt ::= return_lambda
|
||||
stmt ::= conditional_lambda
|
||||
stmt ::= conditional_lambda2
|
||||
|
||||
return_lambda ::= expr RETURN_VALUE LAMBDA_MARKER
|
||||
return_lambda ::= ret_expr RETURN_VALUE LAMBDA_MARKER
|
||||
conditional_lambda ::= expr jmp_false return_if_stmt return_stmt LAMBDA_MARKER
|
||||
|
||||
cmp ::= cmp_list
|
||||
@@ -744,7 +751,7 @@ def parse(tokens, customize):
|
||||
rule = 'unpack ::= ' + k + ' designator'*v
|
||||
elif op == 'UNPACK_LIST':
|
||||
rule = 'unpack_list ::= ' + k + ' designator'*v
|
||||
elif op == 'DUP_TOPX':
|
||||
elif op in ('DUP_TOPX', 'RAISE_VARARGS'):
|
||||
# no need to add a rule
|
||||
continue
|
||||
#rule = 'dup_topx ::= ' + 'expr '*v + k
|
||||
|
@@ -93,8 +93,8 @@ class Scanner(object):
|
||||
return target
|
||||
|
||||
def get_argument(self, pos):
|
||||
target = self.code[pos+1] + self.code[pos+2] * 256
|
||||
return target
|
||||
arg = self.code[pos+1] + self.code[pos+2] * 256
|
||||
return arg
|
||||
|
||||
def print_bytecode(self):
|
||||
for i in self.op_range(0, len(self.code)):
|
||||
|
@@ -78,6 +78,13 @@ class Scanner25(scan.Scanner):
|
||||
while j < codelen:
|
||||
self.lines.append(linetuple(prev_line_no, codelen))
|
||||
j+=1
|
||||
|
||||
self.load_asserts = set()
|
||||
for i in self.op_range(0, codelen):
|
||||
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
|
||||
if names[self.get_argument(i+3)] == 'AssertionError':
|
||||
self.load_asserts.add(i+3)
|
||||
|
||||
# self.lines contains (block,addrLastInstr)
|
||||
cf = self.find_jump_targets(self.code)
|
||||
# contains (code, [addrRefToCode])
|
||||
@@ -163,7 +170,7 @@ class Scanner25(scan.Scanner):
|
||||
UNPACK_SEQUENCE,
|
||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||
CALL_FUNCTION_VAR, CALL_FUNCTION_KW,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX, RAISE_VARARGS
|
||||
):
|
||||
# CE - Hack for >= 2.5
|
||||
# Now all values loaded via LOAD_CLOSURE are packed into
|
||||
@@ -185,11 +192,8 @@ class Scanner25(scan.Scanner):
|
||||
op_name = 'JUMP_BACK'
|
||||
|
||||
elif op == LOAD_GLOBAL:
|
||||
try:
|
||||
if pattr == 'AssertionError' and rv and rv[-1] == 'JUMP_IF_TRUE':
|
||||
if offset in self.load_asserts:
|
||||
op_name = 'LOAD_ASSERT'
|
||||
except AttributeError:
|
||||
pass
|
||||
elif op == RETURN_VALUE:
|
||||
if offset in self.return_end_ifs:
|
||||
op_name = 'RETURN_END_IF'
|
||||
@@ -573,6 +577,7 @@ class Scanner25(scan.Scanner):
|
||||
if except_match:
|
||||
jmp = self.prev[self.get_target(except_match)]
|
||||
self.ignore_if.add(except_match)
|
||||
self.not_continue.add(jmp)
|
||||
return jmp
|
||||
|
||||
count_END_FINALLY = 0
|
||||
@@ -584,6 +589,7 @@ class Scanner25(scan.Scanner):
|
||||
if self.code[self.prev[i]] == NOP:
|
||||
i = self.prev[i]
|
||||
assert self.code[self.prev[i]] in (JA, JF, RETURN_VALUE)
|
||||
self.not_continue.add(self.prev[i])
|
||||
return self.prev[i]
|
||||
count_END_FINALLY += 1
|
||||
elif op in (SETUP_EXCEPT, SETUP_FINALLY):
|
||||
@@ -784,6 +790,11 @@ class Scanner25(scan.Scanner):
|
||||
self.fixed_jumps[pos] = match[-1]
|
||||
return
|
||||
else: # op == PJIT
|
||||
if (pos+3) in self.load_asserts:
|
||||
if code[pre[rtarget]] == RAISE_VARARGS:
|
||||
return
|
||||
self.load_asserts.remove(pos+3)
|
||||
|
||||
next = self.next_stmt[pos]
|
||||
if pre[next] == pos:
|
||||
pass
|
||||
|
@@ -79,6 +79,13 @@ class Scanner26(scan.Scanner):
|
||||
self.lines.append(linetuple(prev_line_no, codelen))
|
||||
j+=1
|
||||
# self.lines contains (block,addrLastInstr)
|
||||
|
||||
self.load_asserts = set()
|
||||
for i in self.op_range(0, codelen):
|
||||
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
|
||||
if names[self.get_argument(i+3)] == 'AssertionError':
|
||||
self.load_asserts.add(i+3)
|
||||
|
||||
cf = self.find_jump_targets(self.code)
|
||||
# contains (code, [addrRefToCode])
|
||||
|
||||
@@ -164,7 +171,7 @@ class Scanner26(scan.Scanner):
|
||||
UNPACK_SEQUENCE,
|
||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||
CALL_FUNCTION_VAR, CALL_FUNCTION_KW,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX, RAISE_VARARGS
|
||||
):
|
||||
# CE - Hack for >= 2.5
|
||||
# Now all values loaded via LOAD_CLOSURE are packed into
|
||||
@@ -186,11 +193,8 @@ class Scanner26(scan.Scanner):
|
||||
op_name = 'JUMP_BACK'
|
||||
|
||||
elif op == LOAD_GLOBAL:
|
||||
try:
|
||||
if pattr == 'AssertionError' and rv and rv[-1] == 'JUMP_IF_TRUE':
|
||||
if offset in self.load_asserts:
|
||||
op_name = 'LOAD_ASSERT'
|
||||
except AttributeError:
|
||||
pass
|
||||
elif op == RETURN_VALUE:
|
||||
if offset in self.return_end_ifs:
|
||||
op_name = 'RETURN_END_IF'
|
||||
@@ -569,6 +573,7 @@ class Scanner26(scan.Scanner):
|
||||
if except_match:
|
||||
jmp = self.prev[self.get_target(except_match)]
|
||||
self.ignore_if.add(except_match)
|
||||
self.not_continue.add(jmp)
|
||||
return jmp
|
||||
|
||||
count_END_FINALLY = 0
|
||||
@@ -580,6 +585,7 @@ class Scanner26(scan.Scanner):
|
||||
if self.code[self.prev[i]] == NOP:
|
||||
i = self.prev[i]
|
||||
assert self.code[self.prev[i]] in (JA, JF, RETURN_VALUE)
|
||||
self.not_continue.add(self.prev[i])
|
||||
return self.prev[i]
|
||||
count_END_FINALLY += 1
|
||||
elif op in (SETUP_EXCEPT, SETUP_FINALLY):
|
||||
@@ -783,6 +789,11 @@ class Scanner26(scan.Scanner):
|
||||
self.fixed_jumps[pos] = match[-1]
|
||||
return
|
||||
else: # op == PJIT
|
||||
if (pos+3) in self.load_asserts:
|
||||
if code[pre[rtarget]] == RAISE_VARARGS:
|
||||
return
|
||||
self.load_asserts.remove(pos+3)
|
||||
|
||||
next = self.next_stmt[pos]
|
||||
if pre[next] == pos:
|
||||
pass
|
||||
|
@@ -56,8 +56,6 @@ class Scanner27(scan.Scanner):
|
||||
self.lines.append(linetuple(prev_line_no, n))
|
||||
j+=1
|
||||
# self.lines contains (block,addrLastInstr)
|
||||
cf = self.find_jump_targets(code)
|
||||
# contains (code, [addrRefToCode])
|
||||
if classname:
|
||||
classname = '_' + classname.lstrip('_') + '__'
|
||||
def unmangle(name):
|
||||
@@ -73,6 +71,14 @@ class Scanner27(scan.Scanner):
|
||||
names = co.co_names
|
||||
varnames = co.co_varnames
|
||||
|
||||
self.load_asserts = set()
|
||||
for i in self.op_range(0, n):
|
||||
if code[i] == PJIT and code[i+3] == LOAD_GLOBAL:
|
||||
if names[self.get_argument(i+3)] == 'AssertionError':
|
||||
self.load_asserts.add(i+3)
|
||||
|
||||
cf = self.find_jump_targets(code)
|
||||
# contains (code, [addrRefToCode])
|
||||
last_stmt = self.next_stmt[0]
|
||||
i = self.next_stmt[last_stmt]
|
||||
replace = {}
|
||||
@@ -108,7 +114,7 @@ class Scanner27(scan.Scanner):
|
||||
op_name = opname[op]
|
||||
oparg = None; pattr = None
|
||||
if op >= HAVE_ARGUMENT:
|
||||
oparg = code[offset+1] + code[offset+2] * 256 + extended_arg
|
||||
oparg = self.get_argument(offset) + extended_arg
|
||||
extended_arg = 0
|
||||
if op == EXTENDED_ARG:
|
||||
extended_arg = oparg * 65536L
|
||||
@@ -151,7 +157,7 @@ class Scanner27(scan.Scanner):
|
||||
UNPACK_SEQUENCE,
|
||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||
CALL_FUNCTION_VAR, CALL_FUNCTION_KW,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX,
|
||||
CALL_FUNCTION_VAR_KW, DUP_TOPX, RAISE_VARARGS
|
||||
):
|
||||
# CE - Hack for >= 2.5
|
||||
# Now all values loaded via LOAD_CLOSURE are packed into
|
||||
@@ -173,11 +179,8 @@ class Scanner27(scan.Scanner):
|
||||
op_name = 'JUMP_BACK'
|
||||
|
||||
elif op == LOAD_GLOBAL:
|
||||
try:
|
||||
if pattr == 'AssertionError' and rv and rv[-1] == 'POP_JUMP_IF_TRUE':
|
||||
if offset in self.load_asserts:
|
||||
op_name = 'LOAD_ASSERT'
|
||||
except AttributeError:
|
||||
pass
|
||||
elif op == RETURN_VALUE:
|
||||
if offset in self.return_end_ifs:
|
||||
op_name = 'RETURN_END_IF'
|
||||
@@ -299,6 +302,7 @@ class Scanner27(scan.Scanner):
|
||||
if except_match:
|
||||
jmp = self.prev[self.get_target(except_match)]
|
||||
self.ignore_if.add(except_match)
|
||||
self.not_continue.add(jmp)
|
||||
return jmp
|
||||
|
||||
count_END_FINALLY = 0
|
||||
@@ -308,6 +312,7 @@ class Scanner27(scan.Scanner):
|
||||
if op == END_FINALLY:
|
||||
if count_END_FINALLY == count_SETUP_:
|
||||
assert self.code[self.prev[i]] in (JA, JF, RETURN_VALUE)
|
||||
self.not_continue.add(self.prev[i])
|
||||
return self.prev[i]
|
||||
count_END_FINALLY += 1
|
||||
elif op in (SETUP_EXCEPT, SETUP_WITH, SETUP_FINALLY):
|
||||
@@ -503,6 +508,11 @@ class Scanner27(scan.Scanner):
|
||||
self.fixed_jumps[pos] = match[-1]
|
||||
return
|
||||
else: # op == PJIT
|
||||
if (pos+3) in self.load_asserts:
|
||||
if code[pre[rtarget]] == RAISE_VARARGS:
|
||||
return
|
||||
self.load_asserts.remove(pos+3)
|
||||
|
||||
next = self.next_stmt[pos]
|
||||
if pre[next] == pos:
|
||||
pass
|
||||
@@ -511,8 +521,12 @@ class Scanner27(scan.Scanner):
|
||||
if code[next] == JF or target != rtarget or code[pre[pre[rtarget]]] not in (JA, RETURN_VALUE):
|
||||
self.fixed_jumps[pos] = pre[next]
|
||||
return
|
||||
elif code[next] == JA and code[target] in (JA, JF) \
|
||||
and self.get_target(target) == self.get_target(next):
|
||||
elif code[next] == JA and code[target] in (JA, JF):
|
||||
next_target = self.get_target(next)
|
||||
if self.get_target(target) == next_target:
|
||||
self.fixed_jumps[pos] = pre[next]
|
||||
return
|
||||
elif code[next_target] in (JA, JF) and self.get_target(next_target) == self.get_target(target):
|
||||
self.fixed_jumps[pos] = pre[next]
|
||||
return
|
||||
|
||||
@@ -521,8 +535,15 @@ class Scanner27(scan.Scanner):
|
||||
return
|
||||
|
||||
if code[pre[rtarget]] == JA and pre[rtarget] in self.stmts \
|
||||
and pre[rtarget] != pos and pre[pre[rtarget]] != pos \
|
||||
and not (code[rtarget] == JA and code[rtarget+3] == POP_BLOCK and code[pre[pre[rtarget]]] != JA):
|
||||
and pre[rtarget] != pos and pre[pre[rtarget]] != pos:
|
||||
if code[rtarget] == JA and code[rtarget+3] == POP_BLOCK:
|
||||
if code[pre[pre[rtarget]]] != JA:
|
||||
pass
|
||||
elif self.get_target(pre[pre[rtarget]]) != target:
|
||||
pass
|
||||
else:
|
||||
rtarget = pre[rtarget]
|
||||
else:
|
||||
rtarget = pre[rtarget]
|
||||
#does the if jump just beyond a jump op, then this is probably an if statement
|
||||
if code[pre[rtarget]] in (JA, JF):
|
||||
@@ -552,16 +573,8 @@ class Scanner27(scan.Scanner):
|
||||
|
||||
elif op in (JUMP_IF_FALSE_OR_POP, JUMP_IF_TRUE_OR_POP):
|
||||
target = self.get_target(pos, op)
|
||||
if target > pos:
|
||||
unop_target = self.last_instr(pos, target, JF, target)
|
||||
if unop_target and code[unop_target+3] != ROT_TWO:
|
||||
self.fixed_jumps[pos] = unop_target
|
||||
else:
|
||||
self.fixed_jumps[pos] = self.restrict_to_parent(target, parent)
|
||||
|
||||
|
||||
|
||||
|
||||
def find_jump_targets(self, code):
|
||||
'''
|
||||
Detect all offsets in a byte code which are jump targets.
|
||||
|
@@ -54,7 +54,7 @@ minint = -sys.maxint-1
|
||||
# the end of functions).
|
||||
|
||||
RETURN_LOCALS = AST('return_stmt',
|
||||
[ AST('expr', [ Token('LOAD_LOCALS') ]),
|
||||
[ AST('ret_expr', [AST('expr', [ Token('LOAD_LOCALS') ])]),
|
||||
Token('RETURN_VALUE')])
|
||||
|
||||
|
||||
@@ -199,13 +199,15 @@ TABLE_DIRECT = {
|
||||
# 'dup_topx': ( '%c', 0),
|
||||
'designList': ( '%c = %c', 0, -1 ),
|
||||
'and': ( '%c and %c', 0, 2 ),
|
||||
'ret_and': ( '%c and %c', 0, 2 ),
|
||||
'and2': ( '%c', 3 ),
|
||||
'or': ( '%c or %c', 0, 2 ),
|
||||
'ret_or': ( '%c or %c', 0, 2 ),
|
||||
'conditional': ( '%p if %p else %p', (2,27), (0,27), (4,27)),
|
||||
'conditionaland': ( '%p if %p and %p else %p', (4,27), (0,24), (2,24), (6,27)),
|
||||
'ret_cond': ( '%p if %p else %p', (2,27), (0,27), (4,27)),
|
||||
'conditionalnot': ( '%p if not %p else %p', (2,27), (0,22), (4,27)),
|
||||
'ret_cond_not': ( '%p if not %p else %p', (2,27), (0,22), (4,27)),
|
||||
'conditional_lambda': ( '(%c if %c else %c)', 2, 0, 3),
|
||||
'conditional_lambda2': ( '(%c if %p and %p else %c)', 4, (0,24), (2,24), 5),
|
||||
'return_lambda': ('%c', 0),
|
||||
'compare': ( '%p %[-1]{pattr} %p', (0,19), (1,19) ),
|
||||
'cmp_list': ( '%p %p', (0,20), (1,19)),
|
||||
@@ -237,8 +239,11 @@ TABLE_DIRECT = {
|
||||
'call_stmt': ( '%|%p\n', (0,200)),
|
||||
'break_stmt': ( '%|break\n', ),
|
||||
'continue_stmt': ( '%|continue\n', ),
|
||||
'jcontinue_stmt': ( '%|continue\n', ),
|
||||
'raise_stmt': ( '%|raise %[0]C\n', (0,sys.maxint,', ') ),
|
||||
|
||||
'raise_stmt0': ( '%|raise\n', ),
|
||||
'raise_stmt1': ( '%|raise %c\n', 0),
|
||||
'raise_stmt2': ( '%|raise %c, %c\n', 0, 1),
|
||||
'raise_stmt3': ( '%|raise %c, %c, %c\n', 0, 1, 2),
|
||||
# 'yield': ( 'yield %c', 0),
|
||||
# 'return_stmt': ( '%|return %c\n', 0),
|
||||
|
||||
@@ -365,12 +370,15 @@ PRECEDENCE = {
|
||||
'unary_not': 22,
|
||||
|
||||
'and': 24,
|
||||
'ret_and': 24,
|
||||
|
||||
'or': 26,
|
||||
'ret_or': 26,
|
||||
|
||||
'conditional': 28,
|
||||
'conditionaland': 28,
|
||||
'conditionalnot': 28,
|
||||
'ret_cond': 28,
|
||||
'ret_cond_not': 28,
|
||||
|
||||
'_mklambda': 30,
|
||||
'yield': 101
|
||||
@@ -593,7 +601,7 @@ class Walker(GenericASTTraversal, object):
|
||||
self.prune()
|
||||
else:
|
||||
self.write(self.indent, 'return')
|
||||
if self.return_none or node != AST('return_stmt', [NONE, Token('RETURN_VALUE')]):
|
||||
if self.return_none or node != AST('return_stmt', [AST('ret_expr', [NONE]), Token('RETURN_VALUE')]):
|
||||
self.write(' ')
|
||||
self.preorder(node[0])
|
||||
self.print_()
|
||||
@@ -605,7 +613,7 @@ class Walker(GenericASTTraversal, object):
|
||||
self.prune()
|
||||
else:
|
||||
self.write(self.indent, 'return')
|
||||
if self.return_none or node != AST('return_if_stmt', [NONE, Token('RETURN_END_IF')]):
|
||||
if self.return_none or node != AST('return_stmt', [AST('ret_expr', [NONE]), Token('RETURN_END_IF')]):
|
||||
self.write(' ')
|
||||
self.preorder(node[0])
|
||||
self.print_()
|
||||
@@ -668,6 +676,14 @@ class Walker(GenericASTTraversal, object):
|
||||
self.prec = p
|
||||
self.prune()
|
||||
|
||||
def n_ret_expr(self, node):
|
||||
if len(node) == 1 and node[0] == 'expr':
|
||||
self.n_expr(node[0])
|
||||
else:
|
||||
self.n_expr(node)
|
||||
|
||||
n_ret_expr_or_cond = n_expr
|
||||
|
||||
def n_binary_expr(self, node):
|
||||
self.preorder(node[0])
|
||||
self.write(' ')
|
||||
@@ -1073,6 +1089,11 @@ class Walker(GenericASTTraversal, object):
|
||||
n[0].type = 'unpack_w_parens'
|
||||
self.default(node)
|
||||
|
||||
def n_except_cond2(self, node):
|
||||
if node[5][0] == 'unpack':
|
||||
node[5][0].type = 'unpack_w_parens'
|
||||
self.default(node)
|
||||
|
||||
def engine(self, entry, startnode):
|
||||
#self.print_("-----")
|
||||
#self.print_(str(startnode.__dict__))
|
||||
|
Reference in New Issue
Block a user