From 4f2ae2f60382cdfb1bcf245393d4f880f88147ab Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 5 Mar 2017 00:05:52 -0500 Subject: [PATCH] More accurate ranges of try blocks in 3.x --- pytest/test_grammar.py | 4 +++- uncompyle6/parsers/parse3.py | 19 ++++++++++++++----- uncompyle6/parsers/parse33.py | 13 +++++++++++++ uncompyle6/scanners/scanner3.py | 6 ++++++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/pytest/test_grammar.py b/pytest/test_grammar.py index a2e3f728..adccec02 100644 --- a/pytest/test_grammar.py +++ b/pytest/test_grammar.py @@ -40,7 +40,9 @@ def test_grammar(): ignore_set = set( """ JUMP_BACK CONTINUE RETURN_END_IF - COME_FROM COME_FROM_EXCEPT COME_FROM_LOOP COME_FROM_WITH + COME_FROM COME_FROM_EXCEPT + COME_FROM_EXCEPT_CLAUSE + COME_FROM_LOOP COME_FROM_WITH COME_FROM_FINALLY ELSE LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LAMBDA_MARKER RETURN_LAST diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 9ac1c55c..a13b2517 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -180,14 +180,17 @@ class Python3Parser(PythonParser): POP_BLOCK LOAD_CONST come_from_or_finally suite_stmts_opt END_FINALLY + tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK + try_middle else_suite come_from_except_clauses + tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK try_middle else_suite come_froms tryelsestmtc ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK - try_middle else_suitec COME_FROM + try_middle else_suitec come_from_except_clauses tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK - try_middle else_suitel COME_FROM + try_middle else_suitel come_from_except_clauses try_middle ::= jmp_abs COME_FROM except_stmts END_FINALLY @@ -254,7 +257,10 @@ class Python3Parser(PythonParser): def p_misc3(self, args): """ - try_middle ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts END_FINALLY COME_FROM + try_middle ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts + END_FINALLY COME_FROM + try_middle ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts + END_FINALLY COME_FROM_EXCEPT_CLAUSE for_block ::= l_stmts_opt opt_come_from_loop JUMP_BACK for_block ::= l_stmts @@ -285,10 +291,13 @@ class Python3Parser(PythonParser): """ opt_come_from_except ::= COME_FROM_EXCEPT opt_come_from_except ::= come_froms + opt_come_from_except ::= come_from_except_clauses - come_froms ::= come_froms COME_FROM - come_froms ::= + come_froms ::= COME_FROM* + come_from_except_clauses ::= COME_FROM_EXCEPT_CLAUSE+ + + opt_come_from_loop ::= opt_come_from_loop COME_FROM_LOOP opt_come_from_loop ::= opt_come_from_loop COME_FROM_LOOP opt_come_from_loop ::= diff --git a/uncompyle6/parsers/parse33.py b/uncompyle6/parsers/parse33.py index 990a914e..9d87f7f7 100644 --- a/uncompyle6/parsers/parse33.py +++ b/uncompyle6/parsers/parse33.py @@ -21,6 +21,19 @@ class Python33Parser(Python32Parser): iflaststmt ::= testexpr c_stmts_opt33 c_stmts_opt33 ::= JUMP_BACK JUMP_ABSOLUTE c_stmts_opt _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from + + # Python 3.5+ has jump optimization to remove the redundant + # jump_excepts. But in 3.3 we need them added + + tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK + try_middle else_suite + jump_excepts come_from_except_clauses + + trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK + try_middle + jump_excepts come_from_except_clauses + + jump_excepts ::= jump_except+ """ class Python33ParserSingle(Python33Parser, PythonParserSingle): diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index 60b6ee19..ec4c9deb 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -221,6 +221,9 @@ class Scanner3(Scanner): come_from_type = opname[len('SETUP_'):] come_from_name = 'COME_FROM_%s' % come_from_type pass + elif inst.offset in self.except_targets: + come_from_name = 'COME_FROM_EXCEPT_CLAUSE' + pass tokens.append(Token(come_from_name, None, repr(jump_offset), offset='%s_%s' % (inst.offset, jump_idx), @@ -443,6 +446,7 @@ class Scanner3(Scanner): # Map fixed jumps to their real destination self.fixed_jumps = {} + self.except_targets = {} self.ignore_if = set() self.build_statement_indices() self.else_start = {} @@ -907,6 +911,8 @@ class Scanner3(Scanner): target = self.get_target(next_offset) if target > next_offset: self.fixed_jumps[next_offset] = target + self.except_targets[target] = next_offset + elif op == self.opc.SETUP_FINALLY: target = self.get_target(offset) end = self.restrict_to_parent(target, parent)