diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 892b2d1c..b56384ac 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -35,6 +35,7 @@ from uncompyle6.parsers.reducecheck import ( ifelsestmt, ifstmt, iflaststmt, + or_check, testtrue, tryelsestmtl3, tryexcept, @@ -1532,7 +1533,10 @@ class Python3Parser(PythonParser): self.reduce_check_table = { "except_handler_else": except_handler_else, # "ifstmt": ifstmt, + "ifstmtl": ifstmt, "ifelsestmtc": ifstmt, + "ifelsestmt": ifelsestmt, + "or": or_check, "testtrue": testtrue, "tryelsestmtl3": tryelsestmtl3, "try_except": tryexcept, @@ -1542,19 +1546,19 @@ class Python3Parser(PythonParser): self.reduce_check_table["and"] = and_check self.check_reduce["and"] = "AST" + self.check_reduce["annotate_tuple"] = "noAST" self.check_reduce["aug_assign1"] = "AST" self.check_reduce["aug_assign2"] = "AST" - self.check_reduce["while1stmt"] = "noAST" - self.check_reduce["while1elsestmt"] = "noAST" + self.check_reduce["except_handler_else"] = "tokens" self.check_reduce["ifelsestmt"] = "AST" self.check_reduce["ifelsestmtc"] = "AST" self.check_reduce["ifstmt"] = "AST" + self.check_reduce["ifstmtl"] = "AST" if self.version == 3.6: self.reduce_check_table["iflaststmtl"] = iflaststmt self.check_reduce["iflaststmt"] = "AST" self.check_reduce["iflaststmtl"] = "AST" - self.check_reduce["annotate_tuple"] = "noAST" - self.check_reduce["except_handler_else"] = "tokens" + self.check_reduce["or"] = "AST" self.check_reduce["testtrue"] = "tokens" if not PYTHON3: self.check_reduce["kwarg"] = "noAST" @@ -1564,8 +1568,8 @@ class Python3Parser(PythonParser): self.check_reduce["try_except"] = "AST" self.check_reduce["tryelsestmtl3"] = "AST" - # FIXME: remove parser errors caused by the below - # self.check_reduce['while1elsestmt'] = 'noAST' + self.check_reduce["while1stmt"] = "noAST" + self.check_reduce["while1elsestmt"] = "noAST" return def reduce_is_invalid(self, rule, ast, tokens, first, last): diff --git a/uncompyle6/parsers/parse36.py b/uncompyle6/parsers/parse36.py index 728cae6a..67d15f60 100644 --- a/uncompyle6/parsers/parse36.py +++ b/uncompyle6/parsers/parse36.py @@ -114,7 +114,7 @@ class Python36Parser(Python35Parser): jb_cfs ::= JUMP_BACK come_froms - # If statement inside a loop? FIXME: NO not always - fix this up. + # If statement inside a loop. stmt ::= ifstmtl ifstmtl ::= testexpr _ifstmts_jumpl _ifstmts_jumpl ::= c_stmts JUMP_BACK diff --git a/uncompyle6/parsers/reducecheck/ifelsestmt.py b/uncompyle6/parsers/reducecheck/ifelsestmt.py index 1eeabe21..8c1612a7 100644 --- a/uncompyle6/parsers/reducecheck/ifelsestmt.py +++ b/uncompyle6/parsers/reducecheck/ifelsestmt.py @@ -87,6 +87,12 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last): if rule not in IFELSE_STMT_RULES: return False + # Avoid if/else where the "then" is a "raise_stmt1". Parse this + # as an "assert" instead. + stmts = ast[1] + if stmts in ("c_stmts",) and len(stmts) == 1 and stmts[0] == "raise_stmt1": + return True + # Make sure all of the "come froms" offset at the # end of the "if" come from somewhere inside the "if". # Since the come_froms are ordered so that lowest diff --git a/uncompyle6/parsers/reducecheck/ifstmt.py b/uncompyle6/parsers/reducecheck/ifstmt.py index 2aefac45..d2abe490 100644 --- a/uncompyle6/parsers/reducecheck/ifstmt.py +++ b/uncompyle6/parsers/reducecheck/ifstmt.py @@ -7,7 +7,9 @@ def ifstmt(self, lhs, n, rule, ast, tokens, first, last): last -= 1 pass if tokens[last].attr and isinstance(tokens[last].attr, int): - return tokens[first].offset < tokens[last].attr + if tokens[first].offset >= tokens[last].attr: + return True + pass pass # Make sure jumps don't extend beyond the end of the if statement. diff --git a/uncompyle6/parsers/reducecheck/or_check.py b/uncompyle6/parsers/reducecheck/or_check.py index e72c33be..c9af5be8 100644 --- a/uncompyle6/parsers/reducecheck/or_check.py +++ b/uncompyle6/parsers/reducecheck/or_check.py @@ -1,9 +1,9 @@ # Copyright (c) 2020 Rocky Bernstein - +ASSERT_OPS = frozenset(["LOAD_ASSERT", "RAISE_VARARGS_1"]) def or_check(self, lhs, n, rule, ast, tokens, first, last): if rule == ("or", ("expr", "jmp_true", "expr")): - if tokens[last] in ("LOAD_ASSERT", "RAISE_VARARGS_1",): + if tokens[last] in ASSERT_OPS or tokens[last-1] in ASSERT_OPS: return True # The following test is be the most accurate. It prevents "or" from being diff --git a/uncompyle6/semantics/transform.py b/uncompyle6/semantics/transform.py index 5ae3ef5e..f8bbd041 100644 --- a/uncompyle6/semantics/transform.py +++ b/uncompyle6/semantics/transform.py @@ -121,14 +121,14 @@ class TreeTransform(GenericASTTraversal, object): if ifstmts_jump == "_ifstmts_jumpl" and ifstmts_jump[0] == "_ifstmts_jump": ifstmts_jump = ifstmts_jump[0] - elif ifstmts_jump not in ("_ifstmts_jump", "ifstmts_jumpl"): + elif ifstmts_jump not in ("_ifstmts_jump", "_ifstmts_jumpl", "ifstmts_jumpl"): return node stmts = ifstmts_jump[0] else: # iflaststmtl works this way stmts = node[1] - if stmts in ("c_stmts", "stmts") and len(stmts) == 1: + if stmts in ("c_stmts", "stmts", "stmts_opt") and len(stmts) == 1: raise_stmt = stmts[0] if raise_stmt != "raise_stmt1": raise_stmt = raise_stmt[0]