You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Start to DRY Python2 and Python3 grammars
Separate out 3.2, and 3.5+ specific grammar code
This commit is contained in:
@@ -192,6 +192,51 @@ class PythonParser(GenericASTBuilder):
|
|||||||
load_attrs ::= load_attrs LOAD_ATTR
|
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):
|
def parse(p, tokens, customize):
|
||||||
p.add_custom_rules(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'):
|
def get_python_parser(version, debug_parser, compile_mode='exec'):
|
||||||
"""
|
"""Returns parser object for Python version 2 or 3, 3.2, 3.5on,
|
||||||
Returns parser object for Python version 2 or 3
|
etc., depending on the parameters passed. *compile_mode* is either
|
||||||
depending on the parameter passed. *compile_mode*
|
'exec', 'eval', or 'single'. See
|
||||||
is either 'exec', 'eval', or 'single'. See
|
https://docs.python.org/3.6/library/functions.html#compile for an
|
||||||
https://docs.python.org/3.6/library/functions.html#compile for an explanation
|
explanation of the different modes.
|
||||||
of the different modes.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if version < 3.0:
|
if version < 3.0:
|
||||||
@@ -217,13 +261,34 @@ def get_python_parser(version, debug_parser, compile_mode='exec'):
|
|||||||
p = parse2.Python2ParserSingle(debug_parser)
|
p = parse2.Python2ParserSingle(debug_parser)
|
||||||
else:
|
else:
|
||||||
import uncompyle6.parsers.parse3 as parse3
|
import uncompyle6.parsers.parse3 as parse3
|
||||||
if compile_mode == 'exec':
|
if version == 3.2:
|
||||||
p = parse3.Python3Parser(debug_parser)
|
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:
|
else:
|
||||||
p = parse3.Python3ParserSingle(debug_parser)
|
if compile_mode == 'exec':
|
||||||
|
p = parse3.Python3Parser(debug_parser)
|
||||||
|
else:
|
||||||
|
p = parse3.Python3ParserSingle(debug_parser)
|
||||||
p.version = version
|
p.version = version
|
||||||
return p
|
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,
|
def python_parser(version, co, out=sys.stdout, showasm=False,
|
||||||
parser_debug=PARSER_DEFAULT_DEBUG):
|
parser_debug=PARSER_DEFAULT_DEBUG):
|
||||||
assert iscode(co)
|
assert iscode(co)
|
||||||
|
@@ -17,9 +17,9 @@ that a later phase can tern into a sequence of ASCII text.
|
|||||||
|
|
||||||
from __future__ import print_function
|
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 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
|
from uncompyle6 import PYTHON3
|
||||||
|
|
||||||
class Python2Parser(PythonParser):
|
class Python2Parser(PythonParser):
|
||||||
@@ -31,52 +31,14 @@ class Python2Parser(PythonParser):
|
|||||||
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
||||||
self.customized = {}
|
self.customized = {}
|
||||||
|
|
||||||
def p_list_comprehension(self, args):
|
def p_list_comprehension2(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_for ::= expr _for designator list_iter JUMP_BACK
|
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):
|
||||||
'''
|
'''
|
||||||
|
# This is different in python3 - should it be?
|
||||||
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?
|
|
||||||
comp_for ::= expr _for designator comp_iter JUMP_BACK
|
comp_for ::= expr _for designator comp_iter JUMP_BACK
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -609,12 +571,5 @@ class Python2Parser(PythonParser):
|
|||||||
raise Exception('unknown customize token %s' % k)
|
raise Exception('unknown customize token %s' % k)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
|
|
||||||
class Python2ParserSingle(Python2Parser):
|
class Python2ParserSingle(Python2Parser, PythonParserSingle):
|
||||||
def p_call_stmt(self, args):
|
pass
|
||||||
'''
|
|
||||||
# single-mode compilation. eval-mode interactive compilation
|
|
||||||
# drops the last rule.
|
|
||||||
|
|
||||||
call_stmt ::= expr POP_TOP
|
|
||||||
call_stmt ::= expr PRINT_EXPR
|
|
||||||
'''
|
|
||||||
|
@@ -17,7 +17,7 @@ that a later phase can tern into a sequence of ASCII text.
|
|||||||
|
|
||||||
from __future__ import print_function
|
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 uncompyle6.parsers.astnode import AST
|
||||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
from uncompyle6 import PYTHON3
|
from uncompyle6 import PYTHON3
|
||||||
@@ -42,60 +42,26 @@ class Python3Parser(PythonParser):
|
|||||||
pass
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
def p_list_comprehension(self, args):
|
def p_list_comprehension3(self, args):
|
||||||
'''
|
"""
|
||||||
# Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
|
# Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
|
||||||
# other comprehensions (set, dictionary).
|
# other comprehensions (set, dictionary).
|
||||||
|
|
||||||
# listcomp is a custom rule
|
# listcomp is a custom Python3 rule
|
||||||
expr ::= listcomp
|
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_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):
|
def p_setcomp3(self, args):
|
||||||
'''
|
"""
|
||||||
expr ::= setcomp
|
# This is different in Python 2 - should it be?
|
||||||
|
|
||||||
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?
|
|
||||||
comp_for ::= expr _for designator comp_iter JUMP_ABSOLUTE
|
comp_for ::= expr _for designator comp_iter JUMP_ABSOLUTE
|
||||||
'''
|
|
||||||
|
# See also common Python p_setcomp
|
||||||
|
"""
|
||||||
|
|
||||||
def p_grammar(self, args):
|
def p_grammar(self, args):
|
||||||
'''
|
'''
|
||||||
@@ -154,9 +120,6 @@ class Python3Parser(PythonParser):
|
|||||||
designList ::= designator designator
|
designList ::= designator designator
|
||||||
designList ::= designator DUP_TOP designList
|
designList ::= designator DUP_TOP designList
|
||||||
|
|
||||||
# FIXME: Store local is only used in Python 3.2
|
|
||||||
designator ::= STORE_LOCALS
|
|
||||||
|
|
||||||
designator ::= STORE_FAST
|
designator ::= STORE_FAST
|
||||||
designator ::= STORE_NAME
|
designator ::= STORE_NAME
|
||||||
designator ::= STORE_GLOBAL
|
designator ::= STORE_GLOBAL
|
||||||
@@ -278,9 +241,6 @@ class Python3Parser(PythonParser):
|
|||||||
_ifstmts_jump ::= return_if_stmts
|
_ifstmts_jump ::= return_if_stmts
|
||||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from _come_from
|
_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
|
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
|
||||||
|
|
||||||
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
|
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
|
||||||
@@ -693,12 +653,22 @@ class Python3Parser(PythonParser):
|
|||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
return
|
return
|
||||||
|
|
||||||
class Python3ParserSingle(Python3Parser):
|
class Python32Parser(Python3Parser):
|
||||||
def p_call_stmt(self, args):
|
def p_32(self, args):
|
||||||
'''
|
"""
|
||||||
# single-mode compilation. Eval-mode interactive compilation
|
# Store locals is only used in Python 3.2
|
||||||
# drops the last rule.
|
designator ::= STORE_LOCALS
|
||||||
|
"""
|
||||||
|
|
||||||
call_stmt ::= expr POP_TOP
|
class Python32ParserSingle(Python32Parser, PythonParserSingle):
|
||||||
call_stmt ::= expr PRINT_EXPR
|
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
|
||||||
|
Reference in New Issue
Block a user