You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
BIN
test/bytecode_2.6_run/01_ifelse_listcomp.pyc
Normal file
BIN
test/bytecode_2.6_run/01_ifelse_listcomp.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7_run/01_ifelse_listcomp.pyc
Normal file
BIN
test/bytecode_2.7_run/01_ifelse_listcomp.pyc
Normal file
Binary file not shown.
4
test/simple_source/bug26/01_ifelse_listcomp.py
Normal file
4
test/simple_source/bug26/01_ifelse_listcomp.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Bug from issue #171: parsing "if x if a else y" inside a list comprehension on 2.7
|
||||||
|
# This is RUNNABLE!
|
||||||
|
assert [False, True, True, True, True] == [False if not a else True for a in range(5)]
|
||||||
|
assert [True, False, False, False, False] == [False if a else True for a in range(5)]
|
@@ -264,6 +264,9 @@ class Python26Parser(Python2Parser):
|
|||||||
dict ::= BUILD_MAP kvlist
|
dict ::= BUILD_MAP kvlist
|
||||||
kvlist ::= kvlist kv3
|
kvlist ::= kvlist kv3
|
||||||
|
|
||||||
|
expr ::= conditional_not
|
||||||
|
conditional_not ::= expr jmp_true expr _jump COME_FROM POP_TOP expr COME_FROM
|
||||||
|
|
||||||
conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt
|
conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt
|
||||||
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
|
||||||
|
|
||||||
|
@@ -165,6 +165,9 @@ class Python27Parser(Python2Parser):
|
|||||||
::= expr jmp_true expr return_if_lambda
|
::= expr jmp_true expr return_if_lambda
|
||||||
return_stmt_lambda LAMBDA_MARKER
|
return_stmt_lambda LAMBDA_MARKER
|
||||||
|
|
||||||
|
expr ::= conditional_not
|
||||||
|
conditional_not ::= expr jmp_true expr _jump expr COME_FROM
|
||||||
|
|
||||||
kv3 ::= expr expr STORE_MAP
|
kv3 ::= expr expr STORE_MAP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -172,12 +175,17 @@ class Python27Parser(Python2Parser):
|
|||||||
# 2.7 changes COME_FROM to COME_FROM_FINALLY
|
# 2.7 changes COME_FROM to COME_FROM_FINALLY
|
||||||
self.remove_rules("""
|
self.remove_rules("""
|
||||||
while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK else_suite COME_FROM
|
while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK else_suite COME_FROM
|
||||||
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM suite_stmts_opt END_FINALLY
|
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt
|
||||||
|
POP_BLOCK LOAD_CONST COME_FROM suite_stmts_opt
|
||||||
|
END_FINALLY
|
||||||
""")
|
""")
|
||||||
super(Python27Parser, self).customize_grammar_rules(tokens, customize)
|
super(Python27Parser, self).customize_grammar_rules(tokens, customize)
|
||||||
self.check_reduce['and'] = 'AST'
|
self.check_reduce['and'] = 'AST'
|
||||||
|
# self.check_reduce['or'] = 'AST'
|
||||||
self.check_reduce['raise_stmt1'] = 'AST'
|
self.check_reduce['raise_stmt1'] = 'AST'
|
||||||
# self.check_reduce['conditional_true'] = 'AST'
|
self.check_reduce['list_if_not'] = 'AST'
|
||||||
|
self.check_reduce['list_if'] = 'AST'
|
||||||
|
self.check_reduce['conditional_true'] = 'AST'
|
||||||
return
|
return
|
||||||
|
|
||||||
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
||||||
@@ -195,6 +203,21 @@ class Python27Parser(Python2Parser):
|
|||||||
tokens[last].pattr == jmp_false.pattr)
|
tokens[last].pattr == jmp_false.pattr)
|
||||||
elif rule[0] == ('raise_stmt1'):
|
elif rule[0] == ('raise_stmt1'):
|
||||||
return ast[0] == 'expr' and ast[0][0] == 'or'
|
return ast[0] == 'expr' and ast[0][0] == 'or'
|
||||||
|
elif rule == ('list_if_not', ('expr', 'jmp_true', 'list_iter')):
|
||||||
|
jump_inst = ast[1][0]
|
||||||
|
jump_offset = jump_inst.attr
|
||||||
|
return jump_offset > jump_inst.offset and jump_offset < tokens[last].offset
|
||||||
|
elif rule == ('list_if', ('expr', 'jmp_false', 'list_iter')):
|
||||||
|
jump_inst = ast[1][0]
|
||||||
|
jump_offset = jump_inst.attr
|
||||||
|
return jump_offset > jump_inst.offset and jump_offset < tokens[last].offset
|
||||||
|
elif rule == ('or', ('expr', 'jmp_true', 'expr', '\\e_come_from_opt')):
|
||||||
|
# Test that jmp_true doesn't jump inside the middle the "or"
|
||||||
|
# or that it jumps to the same place as the end of "and"
|
||||||
|
jmp_true = ast[1][0]
|
||||||
|
jmp_target = jmp_true.offset + jmp_true.attr + 3
|
||||||
|
return not (jmp_target == tokens[last].offset or
|
||||||
|
tokens[last].pattr == jmp_true.pattr)
|
||||||
# elif rule[0] == ('conditional_true'):
|
# elif rule[0] == ('conditional_true'):
|
||||||
# # FIXME: the below is a hack: we check expr for
|
# # FIXME: the below is a hack: we check expr for
|
||||||
# # nodes that could have possibly been a been a Boolean.
|
# # nodes that could have possibly been a been a Boolean.
|
||||||
|
@@ -207,7 +207,7 @@ TABLE_DIRECT = {
|
|||||||
'conditional': ( '%p if %p else %p', (2, 27), (0, 27), (4, 27) ),
|
'conditional': ( '%p if %p else %p', (2, 27), (0, 27), (4, 27) ),
|
||||||
'conditional_true': ( '%p if 1 else %p', (0, 27), (2, 27) ),
|
'conditional_true': ( '%p if 1 else %p', (0, 27), (2, 27) ),
|
||||||
'ret_cond': ( '%p if %p else %p', (2, 27), (0, 27), (-1, 27) ),
|
'ret_cond': ( '%p if %p else %p', (2, 27), (0, 27), (-1, 27) ),
|
||||||
'conditionalnot': ( '%p if not %p else %p', (2, 27), (0, 22), (4, 27) ),
|
'conditional_not': ( '%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), (-1, 27) ),
|
'ret_cond_not': ( '%p if not %p else %p', (2, 27), (0, 22), (-1, 27) ),
|
||||||
'conditional_lambda':
|
'conditional_lambda':
|
||||||
( '%c if %c else %c',
|
( '%c if %c else %c',
|
||||||
|
@@ -784,7 +784,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
def n_list_comp(self, node):
|
def n_list_comp(self, node):
|
||||||
"""List comprehensions"""
|
"""List comprehensions"""
|
||||||
p = self.prec
|
p = self.prec
|
||||||
self.prec = 27
|
self.prec = 100
|
||||||
if self.version >= 2.7:
|
if self.version >= 2.7:
|
||||||
if self.is_pypy:
|
if self.is_pypy:
|
||||||
self.n_list_comp_pypy27(node)
|
self.n_list_comp_pypy27(node)
|
||||||
|
Reference in New Issue
Block a user