More 2.4-2.6 try vs try/else determination

This commit is contained in:
rocky
2018-02-22 20:14:52 -05:00
parent 26e65e0d90
commit 30fbdff29c
2 changed files with 45 additions and 25 deletions

View File

@@ -83,26 +83,14 @@ class Python25Parser(Python26Parser):
if self.version == 2.5: if self.version == 2.5:
self.check_reduce['try_except'] = 'tokens' self.check_reduce['try_except'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last): ## Don't need this for 2.5 yet..
invalid = super(Python25Parser, # def reduce_is_invalid(self, rule, ast, tokens, first, last):
self).reduce_is_invalid(rule, ast, # invalid = super(Python25Parser,
tokens, first, last) # self).reduce_is_invalid(rule, ast,
if invalid or tokens is None: # tokens, first, last)
return invalid # if invalid or tokens is None:
elif rule[0] == 'try_except': # return invalid
# Distinguish try/except from try/except/else # return False
if last == len(tokens):
last -= 1
if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM':
last -= 1
if (tokens[last] == 'COME_FROM'
and tokens[last-1] == 'END_FINALLY'
and tokens[last-2] == 'POP_TOP'):
# A jump of 2 is a jump around POP_TOP, END_FINALLY which
# would indicate try/else rather than try
return (tokens[last-3].kind != 'JUMP_FORWARD'
or tokens[last-3].attr != 2)
return False
class Python25ParserSingle(Python26Parser, PythonParserSingle): class Python25ParserSingle(Python26Parser, PythonParserSingle):

View File

@@ -314,6 +314,7 @@ class Python26Parser(Python2Parser):
self.check_reduce['and'] = 'AST' self.check_reduce['and'] = 'AST'
self.check_reduce['list_for'] = 'AST' self.check_reduce['list_for'] = 'AST'
self.check_reduce['try_except'] = 'tokens' self.check_reduce['try_except'] = 'tokens'
self.check_reduce['tryelsestmt'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last): def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python26Parser, invalid = super(Python26Parser,
@@ -341,7 +342,7 @@ class Python26Parser(Python2Parser):
ja_attr = ast[4].attr ja_attr = ast[4].attr
return tokens[last].offset != ja_attr return tokens[last].offset != ja_attr
elif rule[0] == 'try_except': elif rule[0] == 'try_except':
# We need to distingush try_except from try_except_else and we do that # We need to distingush try_except from tryelsestmt and we do that
# by checking the jump before the END_FINALLY # by checking the jump before the END_FINALLY
# If we have: # If we have:
# insn # insn
@@ -349,14 +350,45 @@ class Python26Parser(Python2Parser):
# END_FINALLY # END_FINALLY
# COME_FROM # COME_FROM
# then insn has to be either a JUMP_FORWARD or a RETURN_VALUE # then insn has to be either a JUMP_FORWARD or a RETURN_VALUE
# and if it is JUMP_FORWARD, then it has to be a JUMP_FORWARD to right after
# COME_FROM
if last == len(tokens): if last == len(tokens):
last -= 1 last -= 1
if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM': if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM':
last -= 1 last -= 1
return (tokens[last] == 'COME_FROM' if (tokens[last] == 'COME_FROM'
and tokens[last-1] == 'END_FINALLY' and tokens[last-1] == 'END_FINALLY'
and tokens[last-2] == 'POP_TOP' and tokens[last-2] == 'POP_TOP'):
and tokens[last-3].kind not in frozenset(('JUMP_FORWARD', 'RETURN_VALUE'))) # A jump of 2 is a jump around POP_TOP, END_FINALLY which
# would indicate try/else rather than try
return (tokens[last-3].kind not in frozenset(('JUMP_FORWARD', 'RETURN_VALUE'))
or (tokens[last-3] == 'JUMP_FORWARD' and tokens[last-3].attr != 2))
elif rule[0] == 'tryelsestmt':
# We need to distingush try_except from tryelsestmt and we do that
# by checking the jump before the END_FINALLY
# If we have:
# insn
# POP_TOP
# END_FINALLY
# COME_FROM
# then insn is neither a JUMP_FORWARD nor RETURN_VALUE,
# or if it is JUMP_FORWARD, then it can't be a JUMP_FORWARD to right after
# COME_FROM
if last == len(tokens):
last -= 1
while tokens[last-1] == 'COME_FROM' and tokens[last-2] == 'COME_FROM':
last -= 1
if tokens[last] == 'COME_FROM' and tokens[last-1] == 'COME_FROM':
last -= 1
if (tokens[last] == 'COME_FROM'
and tokens[last-1] == 'END_FINALLY'
and tokens[last-2] == 'POP_TOP'):
# A jump of 2 is a jump around POP_TOP, END_FINALLY which
# would indicate try/else rather than try
return (tokens[last-3].kind in frozenset(('JUMP_FORWARD', 'RETURN_VALUE'))
and (tokens[last-3] != 'JUMP_FORWARD' or tokens[last-3].attr == 2))
return False return False
class Python26ParserSingle(Python2Parser, PythonParserSingle): class Python26ParserSingle(Python2Parser, PythonParserSingle):
pass pass