From bc16cc93d65f328999c3d6fd81d9e46bce1c825b Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 23 Jun 2018 13:31:16 -0400 Subject: [PATCH 1/3] More Python 3.0 parse errors --- uncompyle6/parsers/parse26.py | 8 ++++---- uncompyle6/parsers/parse30.py | 7 ++++++- uncompyle6/semantics/pysource.py | 5 +++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 49cc1436..20f3c242 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -265,11 +265,11 @@ class Python26Parser(Python2Parser): kvlist ::= kvlist kv3 # Note: preserve positions 0 2 and 4 for semantic actions - conditional_not ::= expr jmp_true expr jf_cf_pop expr COME_FROM - conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt - expr ::= conditional_not + conditional_not : := expr jmp_true expr jf_cf_pop expr COME_FROM + conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt + expr ::= conditional_not - and ::= expr JUMP_IF_FALSE POP_TOP expr JUMP_IF_FALSE POP_TOP + and ::= expr JUMP_IF_FALSE POP_TOP expr JUMP_IF_FALSE POP_TOP # compare_chained is like x <= y <= z compare_chained ::= expr compare_chained1 ROT_TWO COME_FROM POP_TOP _come_froms diff --git a/uncompyle6/parsers/parse30.py b/uncompyle6/parsers/parse30.py index 5370f44a..82b6160b 100644 --- a/uncompyle6/parsers/parse30.py +++ b/uncompyle6/parsers/parse30.py @@ -59,6 +59,7 @@ class Python30Parser(Python31Parser): JUMP_BACK + # JUMP_IF_TRUE POP_TOP as a replacement comp_if ::= expr jmp_false comp_iter comp_iter ::= expr expr SET_ADD comp_iter ::= expr expr LIST_APPEND @@ -69,12 +70,16 @@ class Python30Parser(Python31Parser): except_suite_finalize ::= SETUP_FINALLY c_stmts_opt except_var_finalize END_FINALLY _jump POP_TOP jump_except ::= JUMP_FORWARD POP_TOP + or ::= expr jmp_false expr jmp_true expr ################################################################################ - # In many ways 3.0 is like 2.6. The below rules in fact are the same or similar. + # In many ways 3.0 is like 2.6. One similarity is there is no JUMP_IF_TRUE and + # JUMP_IF_FALSE + # The below rules in fact are the same or similar. jmp_true ::= JUMP_IF_TRUE POP_TOP jmp_false ::= JUMP_IF_FALSE POP_TOP + for_block ::= l_stmts_opt _come_froms POP_TOP JUMP_BACK except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 526f9218..b89d9099 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1170,6 +1170,11 @@ class SourceWalker(GenericASTTraversal, object): # collection = node[-3] collections = [node[-3]] list_ifs = [] + + if self.version == 3.0 and n != 'list_iter': + # FIXME 3.0 is a snowflake here. We'll need + # special code for this + return assert n == 'list_iter' stores = [] From 988efa3693363f7528f8fd95362448c5bc44d8e4 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 23 Jun 2018 13:48:01 -0400 Subject: [PATCH 2/3] Had botched 2.6 grammar --- uncompyle6/parsers/parse26.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 20f3c242..ba099505 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -265,7 +265,7 @@ class Python26Parser(Python2Parser): kvlist ::= kvlist kv3 # Note: preserve positions 0 2 and 4 for semantic actions - conditional_not : := expr jmp_true expr jf_cf_pop expr COME_FROM + conditional_not ::= expr jmp_true expr jf_cf_pop expr COME_FROM conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt expr ::= conditional_not From 3daf3732c30c9a3fcdd9d69335f1a1d10d7638f3 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 23 Jun 2018 23:04:17 -0400 Subject: [PATCH 3/3] Fix Python 3.0 "and" parse rule --- uncompyle6/parsers/parse30.py | 2 +- uncompyle6/semantics/pysource.py | 71 +++++++++++++++++--------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/uncompyle6/parsers/parse30.py b/uncompyle6/parsers/parse30.py index 82b6160b..fc74de97 100644 --- a/uncompyle6/parsers/parse30.py +++ b/uncompyle6/parsers/parse30.py @@ -88,7 +88,7 @@ class Python30Parser(Python31Parser): POP_TOP END_FINALLY return_if_stmt ::= ret_expr RETURN_END_IF POP_TOP - and ::= expr JUMP_IF_FALSE POP_TOP expr COME_FROM + and ::= expr jmp_false expr come_from_opt whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_TOP POP_BLOCK COME_FROM_LOOP whilestmt ::= SETUP_LOOP testexpr returns diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index b89d9099..95d1afb6 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1172,45 +1172,50 @@ class SourceWalker(GenericASTTraversal, object): list_ifs = [] if self.version == 3.0 and n != 'list_iter': - # FIXME 3.0 is a snowflake here. We'll need - # special code for this - return - assert n == 'list_iter' + # FIXME 3.0 is a snowflake here. We need + # special code for this. Not sure if this is totally + # correct. + stores = [ast[3]] + assert ast[4] == 'comp_iter' + n = ast[4] + # Skip over n[0] which is something like: _[1] + self.preorder(n[1]) - stores = [] - - # Find the list comprehension body. It is the inner-most - # node that is not list_.. . - while n == 'list_iter': - n = n[0] # recurse one step - if n == 'list_for': - stores.append(n[2]) - n = n[3] - if self.version >= 3.6 and n[0] == 'list_for': - # Dog-paddle down largely singleton reductions - # to find the collection (expr) - c = n[0][0] - if c == 'expr': - c = c[0] - # FIXME: grammar is wonky here? Is this really an attribute? - if c == 'attribute': - c = c[0] - collections.append(c) + else: + assert n == 'list_iter' + stores = [] + # Find the list comprehension body. It is the inner-most + # node that is not list_.. . + while n == 'list_iter': + n = n[0] # recurse one step + if n == 'list_for': + stores.append(n[2]) + n = n[3] + if self.version >= 3.6 and n[0] == 'list_for': + # Dog-paddle down largely singleton reductions + # to find the collection (expr) + c = n[0][0] + if c == 'expr': + c = c[0] + # FIXME: grammar is wonky here? Is this really an attribute? + if c == 'attribute': + c = c[0] + collections.append(c) + pass + elif n in ('list_if', 'list_if_not'): + # FIXME: just a guess + if n[0].kind == 'expr': + list_ifs.append(n) + else: + list_ifs.append([1]) + n = n[2] pass - elif n in ('list_if', 'list_if_not'): - # FIXME: just a guess - if n[0].kind == 'expr': - list_ifs.append(n) - else: - list_ifs.append([1]) - n = n[2] pass - pass - assert n == 'lc_body', ast + assert n == 'lc_body', ast + self.preorder(n[0]) # FIXME: add indentation around "for"'s and "in"'s - self.preorder(n[0]) if self.version < 3.6: self.write(' for ') self.preorder(stores[0])