You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Reduce Python 2.5- grammar rules
This commit is contained in:
@@ -39,7 +39,7 @@ entry_points = {
|
|||||||
'pydisassemble=uncompyle6.bin.pydisassemble:main',
|
'pydisassemble=uncompyle6.bin.pydisassemble:main',
|
||||||
]}
|
]}
|
||||||
ftp_url = None
|
ftp_url = None
|
||||||
install_requires = ['spark-parser >= 1.8.0, < 1.9.0',
|
install_requires = ['spark-parser >= 1.8.2, < 1.9.0',
|
||||||
'xdis >= 3.6.1, < 3.7.0']
|
'xdis >= 3.6.1, < 3.7.0']
|
||||||
license = 'MIT'
|
license = 'MIT'
|
||||||
mailing_list = 'python-debugger@googlegroups.com'
|
mailing_list = 'python-debugger@googlegroups.com'
|
||||||
|
55
test-unit/test_grammar.py
Normal file
55
test-unit/test_grammar.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
from uncompyle6 import PYTHON_VERSION, IS_PYPY # , PYTHON_VERSION
|
||||||
|
from uncompyle6.parser import get_python_parser, python_parser
|
||||||
|
|
||||||
|
class TestGrammar(unittest.TestCase):
|
||||||
|
def test_grammar(self):
|
||||||
|
|
||||||
|
def check_tokens(tokens, opcode_set):
|
||||||
|
remain_tokens = set(tokens) - opcode_set
|
||||||
|
remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens])
|
||||||
|
remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens])
|
||||||
|
remain_tokens = set(remain_tokens) - opcode_set
|
||||||
|
self.assertEqual(remain_tokens, set([]),
|
||||||
|
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dump_grammar()))
|
||||||
|
|
||||||
|
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
|
||||||
|
(lhs, rhs, tokens,
|
||||||
|
right_recursive, dup_rhs) = p.check_sets()
|
||||||
|
expect_lhs = set(['expr1024', 'pos_arg'])
|
||||||
|
unused_rhs = set(['build_list', 'call_function', 'mkfunc',
|
||||||
|
'mklambda',
|
||||||
|
'unpack',])
|
||||||
|
|
||||||
|
expect_right_recursive = frozenset([('designList',
|
||||||
|
('designator', 'DUP_TOP', 'designList'))])
|
||||||
|
expect_lhs.add('kwarg')
|
||||||
|
|
||||||
|
self.assertEqual(expect_lhs, set(lhs))
|
||||||
|
self.assertEqual(unused_rhs, set(rhs))
|
||||||
|
self.assertEqual(expect_right_recursive, right_recursive)
|
||||||
|
|
||||||
|
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
|
||||||
|
('LOAD_CONST',),
|
||||||
|
('JUMP_BACK',), ('JUMP_FORWARD',)])
|
||||||
|
|
||||||
|
reduced_dup_rhs = {}
|
||||||
|
for k in dup_rhs:
|
||||||
|
if k not in expect_dup_rhs:
|
||||||
|
reduced_dup_rhs[k] = dup_rhs[k]
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
for k in reduced_dup_rhs:
|
||||||
|
print(k, reduced_dup_rhs[k])
|
||||||
|
# assert not reduced_dup_rhs, reduced_dup_rhs
|
||||||
|
|
||||||
|
def test_dup_rule(self):
|
||||||
|
import inspect
|
||||||
|
python_parser(PYTHON_VERSION, inspect.currentframe().f_code,
|
||||||
|
is_pypy=IS_PYPY,
|
||||||
|
parser_debug={
|
||||||
|
'dups': True, 'transition': False, 'reduce': False,
|
||||||
|
'rules': False, 'errorstack': None, 'context': True})
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@@ -108,8 +108,9 @@ class Python2Parser(PythonParser):
|
|||||||
buildclass ::= LOAD_CONST expr mkfunc
|
buildclass ::= LOAD_CONST expr mkfunc
|
||||||
CALL_FUNCTION_0 BUILD_CLASS
|
CALL_FUNCTION_0 BUILD_CLASS
|
||||||
|
|
||||||
stmt ::= classdefdeco
|
# Class decorators starting in 2.6
|
||||||
classdefdeco ::= classdefdeco1 designator
|
stmt ::= classdefdeco
|
||||||
|
classdefdeco ::= classdefdeco1 designator
|
||||||
classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
|
classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
|
||||||
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
|
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
|
||||||
classdefdeco2 ::= LOAD_CONST expr mkfunc CALL_FUNCTION_0 BUILD_CLASS
|
classdefdeco2 ::= LOAD_CONST expr mkfunc CALL_FUNCTION_0 BUILD_CLASS
|
||||||
|
@@ -50,14 +50,27 @@ class Python25Parser(Python26Parser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def add_custom_rules(self, tokens, customize):
|
def add_custom_rules(self, tokens, customize):
|
||||||
# grammar rules inherited from Python 2.6
|
# Remove grammar rules inherited from Python 2.6 or Python 2
|
||||||
self.remove_rules("""
|
self.remove_rules("""
|
||||||
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
||||||
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||||
withasstmt ::= expr setupwithas designator suite_stmts_opt
|
withasstmt ::= expr setupwithas designator suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||||
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
|
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
|
||||||
|
stmt ::= classdefdeco
|
||||||
|
classdefdeco ::= classdefdeco1 designator
|
||||||
|
classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
|
||||||
|
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
|
||||||
|
classdefdeco2 ::= LOAD_CONST expr mkfunc CALL_FUNCTION_0 BUILD_CLASS
|
||||||
|
mkfuncdeco ::= expr mkfuncdeco CALL_FUNCTION_1
|
||||||
|
ret_cond ::= expr jmp_false_then expr RETURN_END_IF POP_TOP ret_expr_or_cond
|
||||||
|
return_if_stmt ::= ret_expr RETURN_END_IF POP_TOP
|
||||||
|
return_if_stmts ::= return_if_stmt
|
||||||
|
return_stmt ::= ret_expr RETURN_END_IF POP_TOP
|
||||||
|
return_stmt ::= ret_expr RETURN_VALUE POP_TOP
|
||||||
|
stmt ::= conditional_lambda
|
||||||
|
setupwithas ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 setup_finally
|
||||||
""")
|
""")
|
||||||
super(Python25Parser, self).add_custom_rules(tokens, customize)
|
super(Python25Parser, self).add_custom_rules(tokens, customize)
|
||||||
if self.version == 2.5:
|
if self.version == 2.5:
|
||||||
|
@@ -72,8 +72,6 @@ class Python26Parser(Python2Parser):
|
|||||||
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
||||||
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
||||||
|
|
||||||
jf_pop ::= JUMP_FORWARD POP_TOP
|
|
||||||
jf_pop ::= JUMP_ABSOLUTE POP_TOP
|
|
||||||
jb_pop ::= JUMP_BACK POP_TOP
|
jb_pop ::= JUMP_BACK POP_TOP
|
||||||
|
|
||||||
jb_cont ::= JUMP_BACK
|
jb_cont ::= JUMP_BACK
|
||||||
|
Reference in New Issue
Block a user