Fix "for ... if" bug introduced since 3.6.2...

However we've isolated and documented the 3.x grammar a little bit better
This commit is contained in:
rocky
2020-01-17 04:29:47 -05:00
parent 549c33113b
commit 027c9a7dc0
7 changed files with 31 additions and 8 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,7 @@
# 101_0 COME_FROM '50' statement: if name == ...to fictional "end if" # 101_0 COME_FROM '50' statement: if name == ...to fictional "end if"
# 101 JUMP_BACK '16' jump as before to loop head # 101 JUMP_BACK '16' jump as before to loop head
# RUNNABLE!
def _slotnames(cls): def _slotnames(cls):
names = [] names = []
for c in cls.__mro__: for c in cls.__mro__:
@@ -21,3 +22,18 @@ def _slotnames(cls):
continue continue
else: else:
names.append(name) # 3.2 bug here jumping to outer for names.append(name) # 3.2 bug here jumping to outer for
# From 3.2.6 pdb.py
# There is no "come_from" after the "if" since the
# if jumps back to the loop. For this we use
# grammar rule "ifstmtl"
def lasti2lineno(linestarts, a):
for i in linestarts:
if a:
return a
return -1
assert lasti2lineno([], True) == -1
assert lasti2lineno([], False) == -1
assert lasti2lineno([1], False) == -1
assert lasti2lineno([1], True) == 1

View File

@@ -141,18 +141,20 @@ class Python3Parser(PythonParser):
assert_expr_or ::= assert_expr jmp_true expr assert_expr_or ::= assert_expr jmp_true expr
assert_expr_and ::= assert_expr jmp_false expr assert_expr_and ::= assert_expr jmp_false expr
ifstmt ::= testexpr _ifstmts_jump ifstmt ::= testexpr _ifstmts_jump
testexpr ::= testfalse testexpr ::= testfalse
testexpr ::= testtrue testexpr ::= testtrue
testfalse ::= expr jmp_false testfalse ::= expr jmp_false
testtrue ::= expr jmp_true testtrue ::= expr jmp_true
_ifstmts_jump ::= return_if_stmts _ifstmts_jump ::= return_if_stmts
_ifstmts_jump ::= c_stmts_opt come_froms _ifstmts_jump ::= c_stmts_opt come_froms
_ifstmts_jumpl ::= return_if_stmts
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
iflaststmtl ::= testexpr _ifstmts_jumpl
# These are used to keep parse tree indices the same # These are used to keep parse tree indices the same
jump_forward_else ::= JUMP_FORWARD ELSE jump_forward_else ::= JUMP_FORWARD ELSE
@@ -330,6 +332,10 @@ class Python3Parser(PythonParser):
def p_stmt3(self, args): def p_stmt3(self, args):
""" """
stmt ::= if_expr_lambda stmt ::= if_expr_lambda
# If statement inside a loop:
lastl_stmt ::= ifstmtl
stmt ::= conditional_not_lambda stmt ::= conditional_not_lambda
if_expr_lambda ::= expr jmp_false expr return_if_lambda if_expr_lambda ::= expr jmp_false expr return_if_lambda
return_stmt_lambda LAMBDA_MARKER return_stmt_lambda LAMBDA_MARKER

View File

@@ -952,6 +952,8 @@ class Python37Parser(Python37BaseParser):
""" """
stmt ::= if_expr_lambda stmt ::= if_expr_lambda
stmt ::= conditional_not_lambda stmt ::= conditional_not_lambda
# If statement inside a loop:
stmt ::= ifstmtl stmt ::= ifstmtl
if_expr_lambda ::= expr jmp_false expr return_if_lambda if_expr_lambda ::= expr jmp_false expr return_if_lambda

View File

@@ -371,14 +371,13 @@ TABLE_DIRECT = {
# 'return': ( '%|return %c\n', 0), # 'return': ( '%|return %c\n', 0),
'return_if_stmt': ( 'return %c\n', 0), 'return_if_stmt': ( 'return %c\n', 0),
'ifstmt': ( '%|if %c:\n%+%c%-', "ifstmt": ( "%|if %c:\n%+%c%-",
0, # "testexpr" or "testexpr_then" 0, # "testexpr" or "testexpr_then"
1, # "_ifstmts_jump" or "return_stmts" 1, # "_ifstmts_jump" or "return_stmts"
), ),
'iflaststmt': ( "%|if %c:\n%+%c%-", 0, 1 ),
'iflaststmt': ( '%|if %c:\n%+%c%-', 0, 1 ), 'iflaststmtl': ( "%|if %c:\n%+%c%-", 0, 1 ),
'iflaststmtl': ( '%|if %c:\n%+%c%-', 0, 1 ), 'testtrue': ( "not %p",
'testtrue': ( 'not %p',
(0, PRECEDENCE['unary_not']) ), (0, PRECEDENCE['unary_not']) ),
# Generally the args here are 0: (some sort of) "testexpr", # Generally the args here are 0: (some sort of) "testexpr",