Files
python-uncompyle6/uncompyle6/parsers/parse14.py
2022-05-02 22:03:52 -04:00

92 lines
3.1 KiB
Python

# Copyright (c) 2018, 2022 Rocky Bernstein
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parser import PythonParserSingle, nop_func
from uncompyle6.parsers.parse15 import Python15Parser
class Python14Parser(Python15Parser):
def p_misc14(self, args):
"""
# Not much here yet, but will probably need to add UNARY_CALL,
# LOAD_LOCAL, SET_FUNC_ARGS
args ::= RESERVE_FAST UNPACK_ARG args_store
args_store ::= STORE_FAST*
call ::= expr tuple BINARY_CALL
expr ::= call
kv ::= DUP_TOP expr ROT_TWO LOAD_CONST STORE_SUBSCR
mkfunc ::= LOAD_CODE BUILD_FUNCTION
print_expr_stmt ::= expr PRINT_EXPR
raise_stmt2 ::= expr expr RAISE_EXCEPTION
star_args ::= RESERVE_FAST UNPACK_VARARG_1 args_store
stmt ::= args
stmt ::= print_expr_stmt
stmt ::= star_args
stmt ::= varargs
varargs ::= RESERVE_FAST UNPACK_VARARG_0 args_store
# Not strictly needed, but tidies up output
stmt ::= doc_junk
doc_junk ::= LOAD_CONST POP_TOP
# Not sure why later Python's omit the COME_FROM
jb_pop14 ::= JUMP_BACK COME_FROM POP_TOP
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt
jb_pop14
POP_BLOCK else_suitel COME_FROM
print_items_nl_stmt ::= expr PRINT_ITEM_CONT print_items_opt PRINT_NEWLINE_CONT
# 1.4 doesn't have linenotab, and although this shouldn't
# be a show stopper, our CONTINUE detection is off here.
continue ::= JUMP_BACK
"""
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
super(Python14Parser, self).__init__(debug_parser)
self.customized = {}
def customize_grammar_rules(self, tokens, customize):
super(Python14Parser, self).customize_grammar_rules(tokens, customize)
self.remove_rules("""
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt
jb_pop
POP_BLOCK else_suitel COME_FROM
""")
self.check_reduce["doc_junk"] = "tokens"
for i, token in enumerate(tokens):
opname = token.kind
opname_base = opname[:opname.rfind("_")]
if opname_base == "UNPACK_VARARG":
if token.attr > 1:
self.addRule(f"star_args ::= RESERVE_FAST {opname} args_store", nop_func)
def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python14Parser,
self).reduce_is_invalid(rule, ast,
tokens, first, last)
if invalid or tokens is None:
return invalid
if rule[0] == 'doc_junk':
return not isinstance(tokens[first].pattr, str)
class Python14ParserSingle(Python14Parser, PythonParserSingle):
pass
if __name__ == '__main__':
# Check grammar
p = Python14Parser()
p.check_grammar()
p.dump_grammar()
# local variables:
# tab-width: 4