Fix bug in 2.6 tryelse get test_grammar working...

localize grammar rules
This commit is contained in:
rocky
2017-12-02 01:35:43 -05:00
parent fc33a4a72d
commit 6d0f72f13b
10 changed files with 59 additions and 31 deletions

View File

@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='3.5.3 3.6.2 2.6.9 3.3.6 2.7.14 3.4.2'
export PYVERSIONS='3.5.3 3.6.3 2.6.9 3.3.6 2.7.14 3.4.2'

View File

@@ -17,10 +17,9 @@ def test_grammar():
(lhs, rhs, tokens,
right_recursive, dup_rhs) = p.check_sets()
expect_lhs = set(['expr1024', 'pos_arg'])
unused_rhs = set(['list', 'call', 'mkfunc',
unused_rhs = set(['list', 'mkfunc',
'mklambda',
'unpack',])
expect_right_recursive = frozenset([('designList',
('store', 'DUP_TOP', 'designList'))])
if PYTHON3:
@@ -32,13 +31,24 @@ def test_grammar():
except_pop_except generator_exp classdefdeco2
dict
""".split()))
if 3.0 <= PYTHON_VERSION:
if PYTHON_VERSION >= 3.0:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
if PYTHON_VERSION != 3.6:
# 3.6 has at least one non-custom call rule
# the others don't
unused_rhs.add('call')
else:
# These are custom rules set in 3.5
unused_rhs.add('build_map_unpack_with_call')
unused_rhs.add('unmapexpr')
pass
pass
pass
else:
expect_lhs.add('kwarg')
unused_rhs.add('call')
assert expect_lhs == set(lhs)
assert unused_rhs == set(rhs)

View File

@@ -268,7 +268,6 @@ class PythonParser(GenericASTBuilder):
stmt ::= return_stmt
return_stmt ::= ret_expr RETURN_VALUE
return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
# return_stmts are a sequence of statements that ends in a RETURN statement.
# In later Python versions with jump optimization, this can cause JUMPs
@@ -487,14 +486,10 @@ class PythonParser(GenericASTBuilder):
ret_expr_or_cond ::= ret_cond
stmt ::= return_lambda
stmt ::= conditional_lambda
return_lambda ::= ret_expr RETURN_VALUE_LAMBDA LAMBDA_MARKER
return_lambda ::= ret_expr RETURN_VALUE_LAMBDA
# Doesn't seem to be used anymore, but other conditional_lambda's are
# conditional_lambda ::= expr jmp_false return_if_stmt return_stmt LAMBDA_MARKER
compare ::= compare_chained
compare ::= compare_single
compare_single ::= expr expr COMPARE_OP

View File

@@ -67,6 +67,8 @@ class Python2Parser(PythonParser):
return_if_stmts ::= _stmts return_if_stmt
return_if_stmt ::= ret_expr RETURN_END_IF
return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
stmt ::= break_stmt
break_stmt ::= BREAK_LOOP

View File

@@ -71,9 +71,12 @@ class Python25Parser(Python26Parser):
return_if_stmts ::= return_if_stmt
return_stmt ::= ret_expr RETURN_END_IF POP_TOP
return_stmt ::= ret_expr RETURN_VALUE POP_TOP
return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
setupwithas ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 setup_finally
stmt ::= classdefdeco
stmt ::= conditional_lambda
conditional_lambda ::= expr jmp_false_then expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER
""")
super(Python25Parser, self).add_custom_rules(tokens, customize)
if self.version == 2.5:

View File

@@ -248,6 +248,7 @@ class Python26Parser(Python2Parser):
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
jmp_false compare_chained2 _come_from
return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP
stmt ::= conditional_lambda
conditional_lambda ::= expr jmp_false_then expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER
"""

View File

@@ -126,6 +126,7 @@ class Python27Parser(Python2Parser):
# Common with 2.6
return_if_lambda ::= RETURN_END_IF_LAMBDA COME_FROM
stmt ::= conditional_lambda
conditional_lambda ::= expr jmp_false expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER

View File

@@ -615,6 +615,8 @@ class Python3Parser(PythonParser):
assign3_pypy ::= expr expr expr store store store
assign2_pypy ::= expr expr store store
return_if_lambda ::= RETURN_END_IF_LAMBDA
return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
stmt ::= conditional_lambda
conditional_lambda ::= expr jmp_false expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER
""", nop_func)

View File

@@ -20,12 +20,12 @@ class Python36Parser(Python35Parser):
# 3.6 redoes how return_closure works
return_closure ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST
stmt ::= conditional_lambda
conditional_lambda ::= expr jmp_false expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER
return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
return_if_lambda ::= RETURN_END_IF_LAMBDA
fstring_multi ::= fstring_expr_or_strs BUILD_STRING
fstring_expr_or_strs ::= fstring_expr_or_str+
func_args36 ::= expr BUILD_TUPLE_0
call ::= func_args36 unmapexpr CALL_FUNCTION_EX
@@ -97,6 +97,8 @@ class Python36Parser(Python35Parser):
fstring_expr_or_str ::= str
expr ::= fstring_multi
fstring_multi ::= fstring_expr_or_strs BUILD_STRING
fstring_expr_or_strs ::= fstring_expr_or_str+
fstring_multi ::= %s BUILD_STRING
%s ::= %sBUILD_STRING
""" % (fstring_expr_or_str_n, fstring_expr_or_str_n, "fstring_expr_or_str " * v)

View File

@@ -1023,33 +1023,45 @@ class Scanner2(Scanner):
pass
pass
# FIXME: All the < 2.7 conditions are is horrible. We need a better way.
# FIXME FIXME FIXME
# All the conditions are horrible, and I am not sure I
# undestand fully what's going l
# WeR REALLY REALLY need a better way to handle control flow
# Expecially for < 2.7
if label is not None and label != -1:
# In Python < 2.7, the POP_TOP in:
# RETURN_VALUE, POP_TOP
# does now start a new statement
# Otherwise, we have want to add a "COME_FROM"
if not (self.version < 2.7 and
code[label] == self.opc.POP_TOP and
if self.version == 2.7:
# FIXME: rocky: I think we need something like this...
if label in self.setup_loops:
source = self.setup_loops[label]
else:
source = offset
targets[label] = targets.get(label, []) + [source]
elif not (code[label] == self.opc.POP_TOP and
code[self.prev[label]] == self.opc.RETURN_VALUE):
# In Python < 2.7, don't add a COME_FROM, for:
# JUMP_FORWARD, END_FINALLY
# RETURN_VALUE POP_TOP .. END_FINALLY
# or:
# JUMP_FORWARD, POP_TOP, END_FINALLY
if not (self.version < 2.7 and op == self.opc.JUMP_FORWARD
and ((code[offset+3] == self.opc.END_FINALLY)
or (code[offset+3] == self.opc.POP_TOP
and code[offset+4] == self.opc.END_FINALLY))):
# RETURN_VALUE POP_TOP .. POP_TOP END_FINALLY
skip_come_from = False
if self.version <= 2.1:
skip_come_from = (code[offset+3] == self.opc.END_FINALLY or
(code[offset+3] == self.opc.POP_TOP
and code[offset+4] == self.opc.END_FINALLY))
else:
skip_come_from = (code[offset+3] == self.opc.END_FINALLY or
(op != self.opc.JUMP_FORWARD
and code[offset+3] == self.opc.POP_TOP
and code[offset+4] == self.opc.END_FINALLY))
if not skip_come_from:
# FIXME: rocky: I think we need something like this...
if offset not in set(self.ignore_if) or self.version == 2.7:
if offset not in set(self.ignore_if):
if label in self.setup_loops:
source = self.setup_loops[label]
else:
source = offset
targets[label] = targets.get(label, []) + [source]
pass
pass
pass
pass
elif op == self.opc.END_FINALLY and offset in self.fixed_jumps and self.version == 2.7: