Start to DRY Python2 and Python3 grammars

Separate out 3.2, and 3.5+ specific grammar code
This commit is contained in:
rocky
2016-05-01 07:13:36 -04:00
parent fa48c9fc61
commit dc80b140c6
3 changed files with 113 additions and 123 deletions

View File

@@ -192,6 +192,51 @@ class PythonParser(GenericASTBuilder):
load_attrs ::= load_attrs LOAD_ATTR
'''
def p_list_comprehension(self, args):
"""
expr ::= list_compr
list_compr ::= BUILD_LIST_0 list_iter
list_iter ::= list_for
list_iter ::= list_if
list_iter ::= list_if_not
list_iter ::= lc_body
_come_from ::= COME_FROM
_come_from ::=
list_if ::= expr jmp_false list_iter
list_if_not ::= expr jmp_true list_iter
lc_body ::= expr LIST_APPEND
"""
def p_setcomp(self, args):
"""
expr ::= setcomp
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= setcomp_func
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
JUMP_BACK RETURN_VALUE RETURN_LAST
comp_iter ::= comp_if
comp_iter ::= comp_ifnot
comp_iter ::= comp_for
comp_iter ::= comp_body
comp_body ::= set_comp_body
comp_body ::= gen_comp_body
comp_body ::= dict_comp_body
set_comp_body ::= expr SET_ADD
gen_comp_body ::= expr YIELD_VALUE POP_TOP
dict_comp_body ::= expr expr MAP_ADD
comp_if ::= expr jmp_false comp_iter
comp_ifnot ::= expr jmp_true comp_iter
"""
def parse(p, tokens, customize):
p.add_custom_rules(tokens, customize)
@@ -201,12 +246,11 @@ def parse(p, tokens, customize):
def get_python_parser(version, debug_parser, compile_mode='exec'):
"""
Returns parser object for Python version 2 or 3
depending on the parameter passed. *compile_mode*
is either 'exec', 'eval', or 'single'. See
https://docs.python.org/3.6/library/functions.html#compile for an explanation
of the different modes.
"""Returns parser object for Python version 2 or 3, 3.2, 3.5on,
etc., depending on the parameters passed. *compile_mode* is either
'exec', 'eval', or 'single'. See
https://docs.python.org/3.6/library/functions.html#compile for an
explanation of the different modes.
"""
if version < 3.0:
@@ -217,13 +261,34 @@ def get_python_parser(version, debug_parser, compile_mode='exec'):
p = parse2.Python2ParserSingle(debug_parser)
else:
import uncompyle6.parsers.parse3 as parse3
if compile_mode == 'exec':
p = parse3.Python3Parser(debug_parser)
if version == 3.2:
if compile_mode == 'exec':
p = parse3.Python32Parser(debug_parser)
else:
p = parse3.Python32ParserSingle(debug_parser)
elif version >= 3.5:
if compile_mode == 'exec':
p = parse3.Python35onParser(debug_parser)
else:
p = parse3.Python35onParserSingle(debug_parser)
else:
p = parse3.Python3ParserSingle(debug_parser)
if compile_mode == 'exec':
p = parse3.Python3Parser(debug_parser)
else:
p = parse3.Python3ParserSingle(debug_parser)
p.version = version
return p
class PythonParserSingle(PythonParser):
def p_call_stmt(self, args):
'''
# single-mode compilation. Eval-mode interactive compilation
# drops the last rule.
call_stmt ::= expr POP_TOP
call_stmt ::= expr PRINT_EXPR
'''
def python_parser(version, co, out=sys.stdout, showasm=False,
parser_debug=PARSER_DEFAULT_DEBUG):
assert iscode(co)

View File

@@ -17,9 +17,9 @@ that a later phase can tern into a sequence of ASCII text.
from __future__ import print_function
from uncompyle6.parser import PythonParser, nop_func
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
from uncompyle6.parsers.astnode import AST
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6 import PYTHON3
class Python2Parser(PythonParser):
@@ -31,52 +31,14 @@ class Python2Parser(PythonParser):
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
self.customized = {}
def p_list_comprehension(self, args):
'''
expr ::= list_compr
list_compr ::= BUILD_LIST_0 list_iter
list_iter ::= list_for
list_iter ::= list_if
list_iter ::= list_if_not
list_iter ::= lc_body
_come_from ::= COME_FROM
_come_from ::=
def p_list_comprehension2(self, args):
"""
list_for ::= expr _for designator list_iter JUMP_BACK
list_if ::= expr jmp_false list_iter
list_if_not ::= expr jmp_true list_iter
"""
lc_body ::= expr LIST_APPEND
def p_setcomp2(self, args):
'''
def p_setcomp(self, args):
'''
expr ::= setcomp
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= setcomp_func
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
JUMP_BACK RETURN_VALUE RETURN_LAST
comp_iter ::= comp_if
comp_iter ::= comp_ifnot
comp_iter ::= comp_for
comp_iter ::= comp_body
comp_body ::= set_comp_body
comp_body ::= gen_comp_body
comp_body ::= dict_comp_body
set_comp_body ::= expr SET_ADD
gen_comp_body ::= expr YIELD_VALUE POP_TOP
dict_comp_body ::= expr expr MAP_ADD
comp_if ::= expr jmp_false comp_iter
comp_ifnot ::= expr jmp_true comp_iter
# This is different in python3 - shout it be?
# This is different in python3 - should it be?
comp_for ::= expr _for designator comp_iter JUMP_BACK
'''
@@ -609,12 +571,5 @@ class Python2Parser(PythonParser):
raise Exception('unknown customize token %s' % k)
self.addRule(rule, nop_func)
class Python2ParserSingle(Python2Parser):
def p_call_stmt(self, args):
'''
# single-mode compilation. eval-mode interactive compilation
# drops the last rule.
call_stmt ::= expr POP_TOP
call_stmt ::= expr PRINT_EXPR
'''
class Python2ParserSingle(Python2Parser, PythonParserSingle):
pass

View File

@@ -17,7 +17,7 @@ that a later phase can tern into a sequence of ASCII text.
from __future__ import print_function
from uncompyle6.parser import PythonParser, nop_func
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
from uncompyle6.parsers.astnode import AST
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6 import PYTHON3
@@ -42,60 +42,26 @@ class Python3Parser(PythonParser):
pass
return
def p_list_comprehension(self, args):
'''
def p_list_comprehension3(self, args):
"""
# Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
# other comprehensions (set, dictionary).
# listcomp is a custom rule
# listcomp is a custom Python3 rule
expr ::= listcomp
expr ::= list_compr
list_compr ::= BUILD_LIST_0 list_iter
list_iter ::= list_for
list_iter ::= list_if
list_iter ::= list_if_not
list_iter ::= lc_body
_come_from ::= COME_FROM
_come_from ::=
list_for ::= expr FOR_ITER designator list_iter JUMP_BACK
list_if ::= expr jmp_false list_iter
list_if_not ::= expr jmp_true list_iter
lc_body ::= expr LIST_APPEND
'''
# See also common Python p_list_comprehension
"""
def p_setcomp(self, args):
'''
expr ::= setcomp
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= setcomp_func
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
JUMP_BACK RETURN_VALUE RETURN_LAST
comp_iter ::= comp_if
comp_iter ::= comp_ifnot
comp_iter ::= comp_for
comp_iter ::= comp_body
comp_body ::= set_comp_body
comp_body ::= gen_comp_body
comp_body ::= dict_comp_body
set_comp_body ::= expr SET_ADD
gen_comp_body ::= expr YIELD_VALUE POP_TOP
dict_comp_body ::= expr expr MAP_ADD
comp_if ::= expr jmp_false comp_iter
comp_ifnot ::= expr jmp_true comp_iter
# This is different in python2 - should it be?
def p_setcomp3(self, args):
"""
# This is different in Python 2 - should it be?
comp_for ::= expr _for designator comp_iter JUMP_ABSOLUTE
'''
# See also common Python p_setcomp
"""
def p_grammar(self, args):
'''
@@ -154,9 +120,6 @@ class Python3Parser(PythonParser):
designList ::= designator designator
designList ::= designator DUP_TOP designList
# FIXME: Store local is only used in Python 3.2
designator ::= STORE_LOCALS
designator ::= STORE_FAST
designator ::= STORE_NAME
designator ::= STORE_GLOBAL
@@ -278,9 +241,6 @@ class Python3Parser(PythonParser):
_ifstmts_jump ::= return_if_stmts
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from _come_from
# FIXME: this optimization is only used in Python 3.5 and beyond
_ifstmts_jump ::= c_stmts_opt
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
@@ -693,12 +653,22 @@ class Python3Parser(PythonParser):
self.add_unique_rule(rule, opname, token.attr, customize)
return
class Python3ParserSingle(Python3Parser):
def p_call_stmt(self, args):
'''
# single-mode compilation. Eval-mode interactive compilation
# drops the last rule.
class Python32Parser(Python3Parser):
def p_32(self, args):
"""
# Store locals is only used in Python 3.2
designator ::= STORE_LOCALS
"""
call_stmt ::= expr POP_TOP
call_stmt ::= expr PRINT_EXPR
'''
class Python32ParserSingle(Python32Parser, PythonParserSingle):
pass
class Python35onParser(Python3Parser):
def p_35on(self, args):
"""
# this optimization is only used in Python 3.5 and beyond
_ifstmts_jump ::= c_stmts_opt
"""
class Python35onParserSingle(Python35onParser, PythonParserSingle):
pass