From 92d562e600e16025d9b450ad9417edd79a4e6554 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 7 Mar 2018 07:38:13 -0500 Subject: [PATCH] Need additional try vs try/else checks --- uncompyle6/parsers/parse26.py | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 09ac34b6..cf0c45f4 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -369,8 +369,9 @@ class Python26Parser(Python2Parser): # We need to distingush try_except from tryelsestmt and we do that # by making sure that the jump before the except handler jumps to # code somewhere before the end of the construct. - # This AST method is slower, but more correct than what we had - # which is given after this. + # This AST method is slower, but the token-only based approach + # didn't work as it failed with a "try" embedded inside a "try/else" + # since we can't detect COME_FROM boundaries. if ast[3] == 'except_handler': except_handler = ast[3] @@ -382,32 +383,31 @@ class Python26Parser(Python2Parser): last_offset = int(tokens[last].offset.split('_')[0]) return else_start >= last_offset - # Before we resorted to using the AST here is the more hacky way we - # did things. This fails with a "try" embedded inside a "try/else" - # since we can't detect COME_FROM boundaries. - # # We need to distinguish try_except from tryelsestmt and we do that - # # by checking the jump before the END_FINALLY - # # If we have: - # # insn - # # POP_TOP - # # END_FINALLY - # # COME_FROM - # # then insn is neither a JUMP_FORWARD nor RETURN_VALUE, - # # or if it is JUMP_FORWARD, then it can't be a JUMP_FORWARD to right after - # # COME_FROM - # if last == len(tokens): - # last -= 1 - # while tokens[last-1] == 'COME_FROM' and tokens[last-2] == 'COME_FROM': - # last -= 1 - # if tokens[last] == 'COME_FROM' and tokens[last-1] == 'COME_FROM': - # last -= 1 - # if (tokens[last] == 'COME_FROM' - # and tokens[last-1] == 'END_FINALLY' - # and tokens[last-2] == 'POP_TOP'): - # # A jump of 2 is a jump around POP_TOP, END_FINALLY which - # # would indicate try/else rather than try - # return (tokens[last-3].kind in frozenset(('JUMP_FORWARD', 'RETURN_VALUE')) - # and (tokens[last-3] != 'JUMP_FORWARD' or tokens[last-3].attr == 2)) + + # The above test apparently isn't good enough, so we have additional + # checks distinguish try_except from tryelsestmt and we do that + # by checking the jump before the END_FINALLY + # If we have: + # insn + # POP_TOP + # END_FINALLY + # COME_FROM + # then insn is neither a JUMP_FORWARD nor RETURN_VALUE, + # or if it is JUMP_FORWARD, then it can't be a JUMP_FORWARD to right after + # COME_FROM + if last == len(tokens): + last -= 1 + while tokens[last-1] == 'COME_FROM' and tokens[last-2] == 'COME_FROM': + last -= 1 + if tokens[last] == 'COME_FROM' and tokens[last-1] == 'COME_FROM': + last -= 1 + if (tokens[last] == 'COME_FROM' + and tokens[last-1] == 'END_FINALLY' + and tokens[last-2] == 'POP_TOP'): + # A jump of 2 is a jump around POP_TOP, END_FINALLY which + # would indicate try/else rather than try + return (tokens[last-3].kind in frozenset(('JUMP_FORWARD', 'RETURN_VALUE')) + and (tokens[last-3] != 'JUMP_FORWARD' or tokens[last-3].attr == 2)) return False