You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Merge pull request #489 from rocky/withasstmt-to-with_as
withasstmt -> with_as
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2023 Rocky Bernstein
|
# Copyright (c) 2015-2024 Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# Copyright (c) 1999 John Aycock
|
# Copyright (c) 1999 John Aycock
|
||||||
@@ -21,10 +21,11 @@ Common uncompyle6 parser routines.
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG, GenericASTBuilder
|
||||||
from uncompyle6.show import maybe_show_asm
|
|
||||||
from xdis import iscode
|
from xdis import iscode
|
||||||
|
|
||||||
|
from uncompyle6.show import maybe_show_asm
|
||||||
|
|
||||||
|
|
||||||
class ParserError(Exception):
|
class ParserError(Exception):
|
||||||
def __init__(self, token, offset, debug=PARSER_DEFAULT_DEBUG):
|
def __init__(self, token, offset, debug=PARSER_DEFAULT_DEBUG):
|
||||||
@@ -91,7 +92,14 @@ class PythonParser(GenericASTBuilder):
|
|||||||
# singleton reduction that we can simplify. It also happens to be optional
|
# singleton reduction that we can simplify. It also happens to be optional
|
||||||
# in its other derivation
|
# in its other derivation
|
||||||
self.optional_nt |= frozenset(
|
self.optional_nt |= frozenset(
|
||||||
("come_froms", "suite_stmts", "l_stmts_opt", "c_stmts_opt", "stmts_opt", "stmt")
|
(
|
||||||
|
"come_froms",
|
||||||
|
"suite_stmts",
|
||||||
|
"l_stmts_opt",
|
||||||
|
"c_stmts_opt",
|
||||||
|
"stmts_opt",
|
||||||
|
"stmt",
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Reduce singleton reductions in these nonterminals:
|
# Reduce singleton reductions in these nonterminals:
|
||||||
@@ -113,10 +121,10 @@ class PythonParser(GenericASTBuilder):
|
|||||||
|
|
||||||
def add_unique_rule(self, rule, opname, arg_count, customize):
|
def add_unique_rule(self, rule, opname, arg_count, customize):
|
||||||
"""Add rule to grammar, but only if it hasn't been added previously
|
"""Add rule to grammar, but only if it hasn't been added previously
|
||||||
opname and stack_count are used in the customize() semantic
|
opname and stack_count are used in the customize() semantic
|
||||||
the actions to add the semantic action rule. Stack_count is
|
the actions to add the semantic action rule. Stack_count is
|
||||||
used in custom opcodes like MAKE_FUNCTION to indicate how
|
used in custom opcodes like MAKE_FUNCTION to indicate how
|
||||||
many arguments it has. Often it is not used.
|
many arguments it has. Often it is not used.
|
||||||
"""
|
"""
|
||||||
if rule not in self.new_rules:
|
if rule not in self.new_rules:
|
||||||
# print("XXX ", rule) # debug
|
# print("XXX ", rule) # debug
|
||||||
@@ -223,7 +231,9 @@ class PythonParser(GenericASTBuilder):
|
|||||||
"""
|
"""
|
||||||
# Low byte indicates number of positional parameters,
|
# Low byte indicates number of positional parameters,
|
||||||
# high byte number of keyword parameters
|
# high byte number of keyword parameters
|
||||||
assert token.kind.startswith("CALL_FUNCTION") or token.kind.startswith("CALL_METHOD")
|
assert token.kind.startswith("CALL_FUNCTION") or token.kind.startswith(
|
||||||
|
"CALL_METHOD"
|
||||||
|
)
|
||||||
args_pos = token.attr & 0xFF
|
args_pos = token.attr & 0xFF
|
||||||
args_kw = (token.attr >> 8) & 0xFF
|
args_kw = (token.attr >> 8) & 0xFF
|
||||||
return args_pos, args_kw
|
return args_pos, args_kw
|
||||||
@@ -364,7 +374,7 @@ class PythonParser(GenericASTBuilder):
|
|||||||
stmt ::= tryelsestmt
|
stmt ::= tryelsestmt
|
||||||
stmt ::= tryfinallystmt
|
stmt ::= tryfinallystmt
|
||||||
stmt ::= with
|
stmt ::= with
|
||||||
stmt ::= withasstmt
|
stmt ::= with_as
|
||||||
|
|
||||||
stmt ::= delete
|
stmt ::= delete
|
||||||
delete ::= DELETE_FAST
|
delete ::= DELETE_FAST
|
||||||
@@ -907,7 +917,7 @@ def python_parser(
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
def parse_test(co):
|
def parse_test(co):
|
||||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
from xdis import IS_PYPY, PYTHON_VERSION_TRIPLE
|
||||||
|
|
||||||
ast = python_parser(PYTHON_VERSION_TRIPLE, co, showasm=True, is_pypy=IS_PYPY)
|
ast = python_parser(PYTHON_VERSION_TRIPLE, co, showasm=True, is_pypy=IS_PYPY)
|
||||||
print(ast)
|
print(ast)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2018, 2020, 2022-2023 Rocky Bernstein
|
# Copyright (c) 2016-2018, 2020, 2022-2024 Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
spark grammar differences over Python2.5 for Python 2.4.
|
spark grammar differences over Python2.5 for Python 2.4.
|
||||||
"""
|
"""
|
||||||
@@ -89,12 +89,14 @@ class Python24Parser(Python25Parser):
|
|||||||
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM
|
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM
|
||||||
while1stmt ::= SETUP_LOOP returns COME_FROM
|
while1stmt ::= SETUP_LOOP returns COME_FROM
|
||||||
whilestmt ::= SETUP_LOOP testexpr returns POP_BLOCK COME_FROM
|
whilestmt ::= SETUP_LOOP testexpr returns POP_BLOCK COME_FROM
|
||||||
|
with ::= expr setupwith SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||||
|
LOAD_CONST COME_FROM with_cleanup
|
||||||
|
with_as ::= expr setupwithas store suite_stmts_opt POP_BLOCK
|
||||||
|
LOAD_CONST COME_FROM with_cleanup
|
||||||
with_cleanup ::= LOAD_FAST DELETE_FAST WITH_CLEANUP END_FINALLY
|
with_cleanup ::= LOAD_FAST DELETE_FAST WITH_CLEANUP END_FINALLY
|
||||||
with_cleanup ::= LOAD_NAME DELETE_NAME WITH_CLEANUP END_FINALLY
|
with_cleanup ::= LOAD_NAME DELETE_NAME WITH_CLEANUP END_FINALLY
|
||||||
withasstmt ::= expr setupwithas store suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
stmt ::= with
|
||||||
with ::= expr setupwith SETUP_FINALLY suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
stmt ::= with_as
|
||||||
stmt ::= with
|
|
||||||
stmt ::= withasstmt
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
|
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2018, 2020, 2022 Rocky Bernstein
|
# Copyright (c) 2016-2018, 2020, 2022, 2024 Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
spark grammar differences over Python2.6 for Python 2.5.
|
spark grammar differences over Python2.6 for Python 2.5.
|
||||||
"""
|
"""
|
||||||
@@ -33,7 +33,7 @@ class Python25Parser(Python26Parser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
||||||
|
|
||||||
# Semantic actions want store to be at index 2
|
# Semantic actions want store to be at index 2
|
||||||
withasstmt ::= expr setupwithas store suite_stmts_opt
|
with_as ::= expr setupwithas store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
POP_BLOCK LOAD_CONST COME_FROM with_cleanup
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ class Python25Parser(Python26Parser):
|
|||||||
|
|
||||||
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
|
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
|
||||||
# withas is allowed as a "from future" in 2.5
|
# withas is allowed as a "from future" in 2.5
|
||||||
withasstmt ::= expr setupwithas store suite_stmts_opt
|
with_as ::= expr setupwithas store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM
|
POP_BLOCK LOAD_CONST COME_FROM
|
||||||
with_cleanup
|
with_cleanup
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ class Python25Parser(Python26Parser):
|
|||||||
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
|
||||||
with ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
with ::= 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 store suite_stmts_opt
|
with_as ::= expr setupwithas store 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
|
||||||
classdefdeco ::= classdefdeco1 store
|
classdefdeco ::= classdefdeco1 store
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2017-2023 Rocky Bernstein
|
# Copyright (c) 2017-2024 Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
spark grammar differences over Python2 for Python 2.6.
|
spark grammar differences over Python2 for Python 2.6.
|
||||||
"""
|
"""
|
||||||
@@ -136,7 +136,7 @@ class Python26Parser(Python2Parser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
# Semantic actions want store to be at index 2
|
# Semantic actions want store to be at index 2
|
||||||
withasstmt ::= expr setupwithas store suite_stmts_opt
|
with_as ::= expr setupwithas store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
# This is truly weird. 2.7 does this (not including POP_TOP) with
|
# This is truly weird. 2.7 does this (not including POP_TOP) with
|
||||||
@@ -352,9 +352,9 @@ class Python26Parser(Python2Parser):
|
|||||||
def customize_grammar_rules(self, tokens, customize):
|
def customize_grammar_rules(self, tokens, customize):
|
||||||
self.remove_rules(
|
self.remove_rules(
|
||||||
"""
|
"""
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt
|
with_as ::= expr SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
super(Python26Parser, self).customize_grammar_rules(tokens, customize)
|
super(Python26Parser, self).customize_grammar_rules(tokens, customize)
|
||||||
@@ -391,7 +391,6 @@ class Python26Parser(Python2Parser):
|
|||||||
("and", ("expr", "jmp_false", "expr", "come_from_opt")),
|
("and", ("expr", "jmp_false", "expr", "come_from_opt")),
|
||||||
("assert_expr_and", ("assert_expr", "jmp_false", "expr")),
|
("assert_expr_and", ("assert_expr", "jmp_false", "expr")),
|
||||||
):
|
):
|
||||||
|
|
||||||
# FIXME: workaround profiling bug
|
# FIXME: workaround profiling bug
|
||||||
if ast[1] is None:
|
if ast[1] is None:
|
||||||
return False
|
return False
|
||||||
@@ -491,7 +490,6 @@ class Python26Parser(Python2Parser):
|
|||||||
("JUMP_FORWARD", "RETURN_VALUE")
|
("JUMP_FORWARD", "RETURN_VALUE")
|
||||||
) or (tokens[last - 3] == "JUMP_FORWARD" and tokens[last - 3].attr != 2)
|
) or (tokens[last - 3] == "JUMP_FORWARD" and tokens[last - 3].attr != 2)
|
||||||
elif lhs == "tryelsestmt":
|
elif lhs == "tryelsestmt":
|
||||||
|
|
||||||
# We need to distinguish "try_except" from "tryelsestmt"; we do that
|
# We need to distinguish "try_except" from "tryelsestmt"; we do that
|
||||||
# by making sure that the jump before the except handler jumps to
|
# by making sure that the jump before the except handler jumps to
|
||||||
# code somewhere before the end of the construct.
|
# code somewhere before the end of the construct.
|
||||||
|
@@ -161,9 +161,9 @@ class Python27Parser(Python2Parser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt
|
with_as ::= expr SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
whilestmt ::= SETUP_LOOP testexpr returns
|
whilestmt ::= SETUP_LOOP testexpr returns
|
||||||
_come_froms POP_BLOCK COME_FROM
|
_come_froms POP_BLOCK COME_FROM
|
||||||
|
@@ -287,9 +287,9 @@ class Python3Parser(PythonParser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt
|
with_as ::= expr SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
expr_jt ::= expr jmp_true
|
expr_jt ::= expr jmp_true
|
||||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||||
|
@@ -66,7 +66,7 @@ class Python30Parser(Python31Parser):
|
|||||||
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE COME_FROM POP_TOP
|
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE COME_FROM POP_TOP
|
||||||
|
|
||||||
|
|
||||||
withasstmt ::= expr setupwithas store suite_stmts_opt
|
with_as ::= expr setupwithas store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
||||||
LOAD_FAST DELETE_FAST WITH_CLEANUP END_FINALLY
|
LOAD_FAST DELETE_FAST WITH_CLEANUP END_FINALLY
|
||||||
setupwithas ::= DUP_TOP LOAD_ATTR STORE_FAST LOAD_ATTR CALL_FUNCTION_0 setup_finally
|
setupwithas ::= DUP_TOP LOAD_ATTR STORE_FAST LOAD_ATTR CALL_FUNCTION_0 setup_finally
|
||||||
@@ -222,12 +222,17 @@ class Python30Parser(Python31Parser):
|
|||||||
# The were found using grammar coverage
|
# The were found using grammar coverage
|
||||||
while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP
|
while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM_LOOP
|
||||||
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK else_suitel COME_FROM_LOOP
|
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM_LOOP
|
else_suitel COME_FROM_LOOP
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK JUMP_BACK COME_FROM_LOOP
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
|
COME_FROM_LOOP
|
||||||
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK JUMP_BACK
|
||||||
|
COME_FROM_LOOP
|
||||||
whilestmt ::= SETUP_LOOP testexpr returns POP_TOP POP_BLOCK COME_FROM_LOOP
|
whilestmt ::= SETUP_LOOP testexpr returns POP_TOP POP_BLOCK COME_FROM_LOOP
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
|
with_as ::= expr SETUP_WITH store suite_stmts_opt POP_BLOCK LOAD_CONST
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
|
COME_FROM_WITH WITH_CLEANUP END_FINALLY
|
||||||
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST
|
||||||
|
COME_FROM_WITH WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
# lc_body ::= LOAD_FAST expr LIST_APPEND
|
# lc_body ::= LOAD_FAST expr LIST_APPEND
|
||||||
# lc_body ::= LOAD_NAME expr LIST_APPEND
|
# lc_body ::= LOAD_NAME expr LIST_APPEND
|
||||||
|
@@ -23,7 +23,7 @@ class Python31Parser(Python32Parser):
|
|||||||
# Keeps Python 3.1 "with .. as" designator in the same position as it is in other version.
|
# Keeps Python 3.1 "with .. as" designator in the same position as it is in other version.
|
||||||
setupwithas31 ::= setupwithas SETUP_FINALLY load delete
|
setupwithas31 ::= setupwithas SETUP_FINALLY load delete
|
||||||
|
|
||||||
withasstmt ::= expr setupwithas31 store
|
with_as ::= expr setupwithas31 store
|
||||||
suite_stmts_opt
|
suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
||||||
load delete WITH_CLEANUP END_FINALLY
|
load delete WITH_CLEANUP END_FINALLY
|
||||||
|
@@ -1,15 +1,17 @@
|
|||||||
# Copyright (c) 2016-2017, 2019, 2021, 2023 Rocky Bernstein
|
# Copyright (c) 2016-2017, 2019, 2021, 2023-2024
|
||||||
|
# Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
spark grammar differences over Python 3.4 for Python 3.5.
|
spark grammar differences over Python 3.4 for Python 3.5.
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
from uncompyle6.parser import PythonParserSingle, nop_func
|
|
||||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
|
|
||||||
|
from uncompyle6.parser import PythonParserSingle, nop_func
|
||||||
from uncompyle6.parsers.parse34 import Python34Parser
|
from uncompyle6.parsers.parse34 import Python34Parser
|
||||||
|
|
||||||
class Python35Parser(Python34Parser):
|
|
||||||
|
|
||||||
|
class Python35Parser(Python34Parser):
|
||||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||||
super(Python35Parser, self).__init__(debug_parser)
|
super(Python35Parser, self).__init__(debug_parser)
|
||||||
self.customized = {}
|
self.customized = {}
|
||||||
@@ -55,7 +57,7 @@ class Python35Parser(Python34Parser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
|
|
||||||
withasstmt ::= expr
|
with_as ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
@@ -135,40 +137,42 @@ class Python35Parser(Python34Parser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def customize_grammar_rules(self, tokens, customize):
|
def customize_grammar_rules(self, tokens, customize):
|
||||||
self.remove_rules("""
|
self.remove_rules(
|
||||||
|
"""
|
||||||
yield_from ::= expr GET_ITER LOAD_CONST YIELD_FROM
|
yield_from ::= expr GET_ITER LOAD_CONST YIELD_FROM
|
||||||
yield_from ::= expr expr YIELD_FROM
|
yield_from ::= expr expr YIELD_FROM
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt
|
with_as ::= expr SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
super(Python35Parser, self).customize_grammar_rules(tokens, customize)
|
super(Python35Parser, self).customize_grammar_rules(tokens, customize)
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
opname = token.kind
|
opname = token.kind
|
||||||
if opname == 'LOAD_ASSERT':
|
if opname == "LOAD_ASSERT":
|
||||||
if 'PyPy' in customize:
|
if "PyPy" in customize:
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= JUMP_IF_NOT_DEBUG stmts COME_FROM
|
stmt ::= JUMP_IF_NOT_DEBUG stmts COME_FROM
|
||||||
"""
|
"""
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
# FIXME: I suspect this is wrong for 3.6 and 3.5, but
|
# FIXME: I suspect this is wrong for 3.6 and 3.5, but
|
||||||
# I haven't verified what the 3.7ish fix is
|
# I haven't verified what the 3.7ish fix is
|
||||||
elif opname == 'BUILD_MAP_UNPACK_WITH_CALL':
|
elif opname == "BUILD_MAP_UNPACK_WITH_CALL":
|
||||||
if self.version < (3, 7):
|
if self.version < (3, 7):
|
||||||
self.addRule("expr ::= unmapexpr", nop_func)
|
self.addRule("expr ::= unmapexpr", nop_func)
|
||||||
nargs = token.attr % 256
|
nargs = token.attr % 256
|
||||||
map_unpack_n = "map_unpack_%s" % nargs
|
map_unpack_n = "map_unpack_%s" % nargs
|
||||||
rule = map_unpack_n + ' ::= ' + 'expr ' * (nargs)
|
rule = map_unpack_n + " ::= " + "expr " * (nargs)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
rule = "unmapexpr ::= %s %s" % (map_unpack_n, opname)
|
rule = "unmapexpr ::= %s %s" % (map_unpack_n, opname)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
call_token = tokens[i+1]
|
call_token = tokens[i + 1]
|
||||||
rule = 'call ::= expr unmapexpr ' + call_token.kind
|
rule = "call ::= expr unmapexpr " + call_token.kind
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif opname == 'BEFORE_ASYNC_WITH' and self.version < (3, 8):
|
elif opname == "BEFORE_ASYNC_WITH" and self.version < (3, 8):
|
||||||
# Some Python 3.5+ async additions
|
# Some Python 3.5+ async additions
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= async_with_stmt
|
stmt ::= async_with_stmt
|
||||||
@@ -199,24 +203,27 @@ class Python35Parser(Python34Parser):
|
|||||||
async_with_post
|
async_with_post
|
||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
elif opname == 'BUILD_MAP_UNPACK':
|
elif opname == "BUILD_MAP_UNPACK":
|
||||||
self.addRule("""
|
self.addRule(
|
||||||
|
"""
|
||||||
expr ::= dict_unpack
|
expr ::= dict_unpack
|
||||||
dict_unpack ::= dict_comp BUILD_MAP_UNPACK
|
dict_unpack ::= dict_comp BUILD_MAP_UNPACK
|
||||||
""", nop_func)
|
""",
|
||||||
|
nop_func,
|
||||||
|
)
|
||||||
|
|
||||||
elif opname == 'SETUP_WITH':
|
elif opname == "SETUP_WITH":
|
||||||
# Python 3.5+ has WITH_CLEANUP_START/FINISH
|
# Python 3.5+ has WITH_CLEANUP_START/FINISH
|
||||||
rules_str = """
|
rules_str = """
|
||||||
with ::= expr
|
with ::= expr
|
||||||
SETUP_WITH POP_TOP suite_stmts_opt
|
SETUP_WITH POP_TOP suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
|
|
||||||
withasstmt ::= expr
|
with_as ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
pass
|
pass
|
||||||
@@ -230,19 +237,24 @@ class Python35Parser(Python34Parser):
|
|||||||
# 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
|
# 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
|
||||||
# 2 for * and ** args (CALL_FUNCTION_VAR_KW).
|
# 2 for * and ** args (CALL_FUNCTION_VAR_KW).
|
||||||
# Yes, this computation based on instruction name is a little bit hoaky.
|
# Yes, this computation based on instruction name is a little bit hoaky.
|
||||||
nak = ( len(opname)-len('CALL_FUNCTION') ) // 3
|
nak = (len(opname) - len("CALL_FUNCTION")) // 3
|
||||||
uniq_param = args_kw + args_pos
|
uniq_param = args_kw + args_pos
|
||||||
|
|
||||||
if frozenset(('GET_AWAITABLE', 'YIELD_FROM')).issubset(self.seen_ops):
|
if frozenset(("GET_AWAITABLE", "YIELD_FROM")).issubset(self.seen_ops):
|
||||||
rule = ('async_call ::= expr ' +
|
rule = (
|
||||||
('pos_arg ' * args_pos) +
|
"async_call ::= expr "
|
||||||
('kwarg ' * args_kw) +
|
+ ("pos_arg " * args_pos)
|
||||||
'expr ' * nak + token.kind +
|
+ ("kwarg " * args_kw)
|
||||||
' GET_AWAITABLE LOAD_CONST YIELD_FROM')
|
+ "expr " * nak
|
||||||
|
+ token.kind
|
||||||
|
+ " GET_AWAITABLE LOAD_CONST YIELD_FROM"
|
||||||
|
)
|
||||||
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
||||||
self.add_unique_rule('expr ::= async_call', token.kind, uniq_param, customize)
|
self.add_unique_rule(
|
||||||
|
"expr ::= async_call", token.kind, uniq_param, customize
|
||||||
|
)
|
||||||
|
|
||||||
if opname.startswith('CALL_FUNCTION_VAR'):
|
if opname.startswith("CALL_FUNCTION_VAR"):
|
||||||
# Python 3.5 changes the stack position of *args. KW args come
|
# Python 3.5 changes the stack position of *args. KW args come
|
||||||
# after *args.
|
# after *args.
|
||||||
|
|
||||||
@@ -250,43 +262,55 @@ class Python35Parser(Python34Parser):
|
|||||||
# CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX
|
# CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX
|
||||||
|
|
||||||
token.kind = self.call_fn_name(token)
|
token.kind = self.call_fn_name(token)
|
||||||
if opname.endswith('KW'):
|
if opname.endswith("KW"):
|
||||||
kw = 'expr '
|
kw = "expr "
|
||||||
else:
|
else:
|
||||||
kw = ''
|
kw = ""
|
||||||
rule = ('call ::= expr expr ' +
|
rule = (
|
||||||
('pos_arg ' * args_pos) +
|
"call ::= expr expr "
|
||||||
('kwarg ' * args_kw) + kw + token.kind)
|
+ ("pos_arg " * args_pos)
|
||||||
|
+ ("kwarg " * args_kw)
|
||||||
|
+ kw
|
||||||
|
+ token.kind
|
||||||
|
)
|
||||||
|
|
||||||
# Note: semantic actions make use of the fact of whether "args_pos"
|
# Note: semantic actions make use of the fact of whether "args_pos"
|
||||||
# zero or not in creating a template rule.
|
# zero or not in creating a template rule.
|
||||||
self.add_unique_rule(rule, token.kind, args_pos, customize)
|
self.add_unique_rule(rule, token.kind, args_pos, customize)
|
||||||
else:
|
else:
|
||||||
super(Python35Parser, self).custom_classfunc_rule(opname, token, customize, *args
|
super(Python35Parser, self).custom_classfunc_rule(
|
||||||
|
opname, token, customize, *args
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Python35ParserSingle(Python35Parser, PythonParserSingle):
|
class Python35ParserSingle(Python35Parser, PythonParserSingle):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
# Check grammar
|
# Check grammar
|
||||||
p = Python35Parser()
|
p = Python35Parser()
|
||||||
p.check_grammar()
|
p.check_grammar()
|
||||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE
|
||||||
|
|
||||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 5):
|
if PYTHON_VERSION_TRIPLE[:2] == (3, 5):
|
||||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||||
from uncompyle6.scanner import get_scanner
|
from uncompyle6.scanner import get_scanner
|
||||||
|
|
||||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||||
opcode_set = set(s.opc.opname).union(set(
|
opcode_set = set(s.opc.opname).union(
|
||||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
set(
|
||||||
|
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||||
LAMBDA_MARKER RETURN_LAST
|
LAMBDA_MARKER RETURN_LAST
|
||||||
""".split()))
|
""".split()
|
||||||
|
)
|
||||||
|
)
|
||||||
remain_tokens = set(tokens) - opcode_set
|
remain_tokens = set(tokens) - opcode_set
|
||||||
import re
|
import re
|
||||||
remain_tokens = set([re.sub(r'_\d+$', '', t) for t in remain_tokens])
|
|
||||||
remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens])
|
remain_tokens = set([re.sub(r"_\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
|
remain_tokens = set(remain_tokens) - opcode_set
|
||||||
print(remain_tokens)
|
print(remain_tokens)
|
||||||
# print(sorted(p.rule2name.items()))
|
# print(sorted(p.rule2name.items()))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2020, 2022-2023 Rocky Bernstein
|
# Copyright (c) 2016-2020, 2022-2024 Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,24 +17,25 @@ spark grammar differences over Python 3.5 for Python 3.6.
|
|||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
from uncompyle6.parser import PythonParserSingle, nop_func
|
|
||||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
|
|
||||||
|
from uncompyle6.parser import PythonParserSingle, nop_func
|
||||||
from uncompyle6.parsers.parse35 import Python35Parser
|
from uncompyle6.parsers.parse35 import Python35Parser
|
||||||
from uncompyle6.scanners.tok import Token
|
from uncompyle6.scanners.tok import Token
|
||||||
|
|
||||||
class Python36Parser(Python35Parser):
|
|
||||||
|
|
||||||
|
class Python36Parser(Python35Parser):
|
||||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||||
super(Python36Parser, self).__init__(debug_parser)
|
super(Python36Parser, self).__init__(debug_parser)
|
||||||
self.customized = {}
|
self.customized = {}
|
||||||
|
|
||||||
|
|
||||||
def p_36_jump(self, args):
|
def p_36_jump(self, args):
|
||||||
"""
|
"""
|
||||||
# Zero or one COME_FROM
|
# Zero or one COME_FROM
|
||||||
# And/or expressions have this
|
# And/or expressions have this
|
||||||
come_from_opt ::= COME_FROM?
|
come_from_opt ::= COME_FROM?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_36_misc(self, args):
|
def p_36_misc(self, args):
|
||||||
"""sstmt ::= sstmt RETURN_LAST
|
"""sstmt ::= sstmt RETURN_LAST
|
||||||
|
|
||||||
@@ -207,7 +208,8 @@ class Python36Parser(Python35Parser):
|
|||||||
# self.remove_rules("""
|
# self.remove_rules("""
|
||||||
# """)
|
# """)
|
||||||
super(Python36Parser, self).customize_grammar_rules(tokens, customize)
|
super(Python36Parser, self).customize_grammar_rules(tokens, customize)
|
||||||
self.remove_rules("""
|
self.remove_rules(
|
||||||
|
"""
|
||||||
_ifstmts_jumpl ::= c_stmts_opt
|
_ifstmts_jumpl ::= c_stmts_opt
|
||||||
_ifstmts_jumpl ::= _ifstmts_jump
|
_ifstmts_jumpl ::= _ifstmts_jump
|
||||||
except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts END_FINALLY COME_FROM
|
except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts END_FINALLY COME_FROM
|
||||||
@@ -234,7 +236,8 @@ class Python36Parser(Python35Parser):
|
|||||||
for_block pb_ja
|
for_block pb_ja
|
||||||
else_suite COME_FROM_LOOP
|
else_suite COME_FROM_LOOP
|
||||||
|
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
self.check_reduce["call_kw"] = "AST"
|
self.check_reduce["call_kw"] = "AST"
|
||||||
|
|
||||||
# Opcode names in the custom_ops_processed set have rules that get added
|
# Opcode names in the custom_ops_processed set have rules that get added
|
||||||
@@ -247,24 +250,23 @@ class Python36Parser(Python35Parser):
|
|||||||
# the start.
|
# the start.
|
||||||
custom_ops_processed = set()
|
custom_ops_processed = set()
|
||||||
|
|
||||||
|
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
opname = token.kind
|
opname = token.kind
|
||||||
|
|
||||||
if opname == 'FORMAT_VALUE':
|
if opname == "FORMAT_VALUE":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
expr ::= formatted_value1
|
expr ::= formatted_value1
|
||||||
formatted_value1 ::= expr FORMAT_VALUE
|
formatted_value1 ::= expr FORMAT_VALUE
|
||||||
"""
|
"""
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
elif opname == 'FORMAT_VALUE_ATTR':
|
elif opname == "FORMAT_VALUE_ATTR":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
expr ::= formatted_value2
|
expr ::= formatted_value2
|
||||||
formatted_value2 ::= expr expr FORMAT_VALUE_ATTR
|
formatted_value2 ::= expr expr FORMAT_VALUE_ATTR
|
||||||
"""
|
"""
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
elif opname == 'MAKE_FUNCTION_CLOSURE':
|
elif opname == "MAKE_FUNCTION_CLOSURE":
|
||||||
if 'LOAD_DICTCOMP' in self.seen_ops:
|
if "LOAD_DICTCOMP" in self.seen_ops:
|
||||||
# Is there something general going on here?
|
# Is there something general going on here?
|
||||||
rule = """
|
rule = """
|
||||||
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
|
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
|
||||||
@@ -272,7 +274,7 @@ class Python36Parser(Python35Parser):
|
|||||||
GET_ITER CALL_FUNCTION_1
|
GET_ITER CALL_FUNCTION_1
|
||||||
"""
|
"""
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif 'LOAD_SETCOMP' in self.seen_ops:
|
elif "LOAD_SETCOMP" in self.seen_ops:
|
||||||
rule = """
|
rule = """
|
||||||
set_comp ::= load_closure LOAD_SETCOMP LOAD_STR
|
set_comp ::= load_closure LOAD_SETCOMP LOAD_STR
|
||||||
MAKE_FUNCTION_CLOSURE expr
|
MAKE_FUNCTION_CLOSURE expr
|
||||||
@@ -280,7 +282,7 @@ class Python36Parser(Python35Parser):
|
|||||||
"""
|
"""
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
|
|
||||||
elif opname == 'BEFORE_ASYNC_WITH':
|
elif opname == "BEFORE_ASYNC_WITH":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= async_with_stmt
|
stmt ::= async_with_stmt
|
||||||
async_with_pre ::= BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM SETUP_ASYNC_WITH
|
async_with_pre ::= BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM SETUP_ASYNC_WITH
|
||||||
@@ -306,30 +308,37 @@ class Python36Parser(Python35Parser):
|
|||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
|
|
||||||
elif opname.startswith('BUILD_STRING'):
|
elif opname.startswith("BUILD_STRING"):
|
||||||
v = token.attr
|
v = token.attr
|
||||||
rules_str = """
|
rules_str = """
|
||||||
expr ::= joined_str
|
expr ::= joined_str
|
||||||
joined_str ::= %sBUILD_STRING_%d
|
joined_str ::= %sBUILD_STRING_%d
|
||||||
""" % ("expr " * v, v)
|
""" % (
|
||||||
|
"expr " * v,
|
||||||
|
v,
|
||||||
|
)
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
if 'FORMAT_VALUE_ATTR' in self.seen_ops:
|
if "FORMAT_VALUE_ATTR" in self.seen_ops:
|
||||||
rules_str = """
|
rules_str = """
|
||||||
formatted_value_attr ::= expr expr FORMAT_VALUE_ATTR expr BUILD_STRING
|
formatted_value_attr ::= expr expr FORMAT_VALUE_ATTR expr BUILD_STRING
|
||||||
expr ::= formatted_value_attr
|
expr ::= formatted_value_attr
|
||||||
"""
|
"""
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
elif opname.startswith('BUILD_MAP_UNPACK_WITH_CALL'):
|
elif opname.startswith("BUILD_MAP_UNPACK_WITH_CALL"):
|
||||||
v = token.attr
|
v = token.attr
|
||||||
rule = 'build_map_unpack_with_call ::= %s%s' % ('expr ' * v, opname)
|
rule = "build_map_unpack_with_call ::= %s%s" % ("expr " * v, opname)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif opname.startswith('BUILD_TUPLE_UNPACK_WITH_CALL'):
|
elif opname.startswith("BUILD_TUPLE_UNPACK_WITH_CALL"):
|
||||||
v = token.attr
|
v = token.attr
|
||||||
rule = ('build_tuple_unpack_with_call ::= ' + 'expr1024 ' * int(v//1024) +
|
rule = (
|
||||||
'expr32 ' * int((v//32) % 32) +
|
"build_tuple_unpack_with_call ::= "
|
||||||
'expr ' * (v % 32) + opname)
|
+ "expr1024 " * int(v // 1024)
|
||||||
|
+ "expr32 " * int((v // 32) % 32)
|
||||||
|
+ "expr " * (v % 32)
|
||||||
|
+ opname
|
||||||
|
)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
rule = ('starred ::= %s %s' % ('expr ' * v, opname))
|
rule = "starred ::= %s %s" % ("expr " * v, opname)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif opname == "GET_AITER":
|
elif opname == "GET_AITER":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
@@ -475,7 +484,6 @@ class Python36Parser(Python35Parser):
|
|||||||
)
|
)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
|
|
||||||
|
|
||||||
elif opname == "GET_ANEXT":
|
elif opname == "GET_ANEXT":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
"""
|
"""
|
||||||
@@ -500,7 +508,7 @@ class Python36Parser(Python35Parser):
|
|||||||
)
|
)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
|
|
||||||
elif opname == 'SETUP_ANNOTATIONS':
|
elif opname == "SETUP_ANNOTATIONS":
|
||||||
# 3.6 Variable Annotations PEP 526
|
# 3.6 Variable Annotations PEP 526
|
||||||
# This seems to come before STORE_ANNOTATION, and doesn't
|
# This seems to come before STORE_ANNOTATION, and doesn't
|
||||||
# correspond to direct Python source code.
|
# correspond to direct Python source code.
|
||||||
@@ -516,7 +524,7 @@ class Python36Parser(Python35Parser):
|
|||||||
"""
|
"""
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
# Check to combine assignment + annotation into one statement
|
# Check to combine assignment + annotation into one statement
|
||||||
self.check_reduce['assign'] = 'token'
|
self.check_reduce["assign"] = "token"
|
||||||
elif opname == "WITH_CLEANUP_START":
|
elif opname == "WITH_CLEANUP_START":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= with_null
|
stmt ::= with_null
|
||||||
@@ -524,13 +532,13 @@ class Python36Parser(Python35Parser):
|
|||||||
with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
elif opname == 'SETUP_WITH':
|
elif opname == "SETUP_WITH":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
|
|
||||||
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
with_as ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
||||||
BEGIN_FINALLY COME_FROM_WITH
|
BEGIN_FINALLY COME_FROM_WITH
|
||||||
@@ -542,7 +550,6 @@ class Python36Parser(Python35Parser):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def custom_classfunc_rule(self, opname, token, customize, next_token, is_pypy):
|
def custom_classfunc_rule(self, opname, token, customize, next_token, is_pypy):
|
||||||
|
|
||||||
args_pos, args_kw = self.get_pos_kw(token)
|
args_pos, args_kw = self.get_pos_kw(token)
|
||||||
|
|
||||||
# Additional exprs for * and ** args:
|
# Additional exprs for * and ** args:
|
||||||
@@ -550,140 +557,186 @@ class Python36Parser(Python35Parser):
|
|||||||
# 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
|
# 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
|
||||||
# 2 for * and ** args (CALL_FUNCTION_VAR_KW).
|
# 2 for * and ** args (CALL_FUNCTION_VAR_KW).
|
||||||
# Yes, this computation based on instruction name is a little bit hoaky.
|
# Yes, this computation based on instruction name is a little bit hoaky.
|
||||||
nak = ( len(opname)-len('CALL_FUNCTION') ) // 3
|
nak = (len(opname) - len("CALL_FUNCTION")) // 3
|
||||||
uniq_param = args_kw + args_pos
|
uniq_param = args_kw + args_pos
|
||||||
|
|
||||||
if frozenset(('GET_AWAITABLE', 'YIELD_FROM')).issubset(self.seen_ops):
|
if frozenset(("GET_AWAITABLE", "YIELD_FROM")).issubset(self.seen_ops):
|
||||||
rule = ('async_call ::= expr ' +
|
rule = (
|
||||||
('pos_arg ' * args_pos) +
|
"async_call ::= expr "
|
||||||
('kwarg ' * args_kw) +
|
+ ("pos_arg " * args_pos)
|
||||||
'expr ' * nak + token.kind +
|
+ ("kwarg " * args_kw)
|
||||||
' GET_AWAITABLE LOAD_CONST YIELD_FROM')
|
+ "expr " * nak
|
||||||
|
+ token.kind
|
||||||
|
+ " GET_AWAITABLE LOAD_CONST YIELD_FROM"
|
||||||
|
)
|
||||||
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
||||||
self.add_unique_rule('expr ::= async_call', token.kind, uniq_param, customize)
|
self.add_unique_rule(
|
||||||
|
"expr ::= async_call", token.kind, uniq_param, customize
|
||||||
|
)
|
||||||
|
|
||||||
if opname.startswith('CALL_FUNCTION_KW'):
|
if opname.startswith("CALL_FUNCTION_KW"):
|
||||||
if is_pypy:
|
if is_pypy:
|
||||||
# PYPY doesn't follow CPython 3.6 CALL_FUNCTION_KW conventions
|
# PYPY doesn't follow CPython 3.6 CALL_FUNCTION_KW conventions
|
||||||
super(Python36Parser, self).custom_classfunc_rule(opname, token, customize, next_token, is_pypy)
|
super(Python36Parser, self).custom_classfunc_rule(
|
||||||
|
opname, token, customize, next_token, is_pypy
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.addRule("expr ::= call_kw36", nop_func)
|
self.addRule("expr ::= call_kw36", nop_func)
|
||||||
values = 'expr ' * token.attr
|
values = "expr " * token.attr
|
||||||
rule = "call_kw36 ::= expr {values} LOAD_CONST {opname}".format(**locals())
|
rule = "call_kw36 ::= expr {values} LOAD_CONST {opname}".format(
|
||||||
|
**locals()
|
||||||
|
)
|
||||||
self.add_unique_rule(rule, token.kind, token.attr, customize)
|
self.add_unique_rule(rule, token.kind, token.attr, customize)
|
||||||
elif opname == 'CALL_FUNCTION_EX_KW':
|
elif opname == "CALL_FUNCTION_EX_KW":
|
||||||
# Note: this doesn't exist in 3.7 and later
|
# Note: this doesn't exist in 3.7 and later
|
||||||
self.addRule("""expr ::= call_ex_kw4
|
self.addRule(
|
||||||
|
"""expr ::= call_ex_kw4
|
||||||
call_ex_kw4 ::= expr
|
call_ex_kw4 ::= expr
|
||||||
expr
|
expr
|
||||||
expr
|
expr
|
||||||
CALL_FUNCTION_EX_KW
|
CALL_FUNCTION_EX_KW
|
||||||
""",
|
""",
|
||||||
nop_func)
|
nop_func,
|
||||||
if 'BUILD_MAP_UNPACK_WITH_CALL' in self.seen_op_basenames:
|
)
|
||||||
self.addRule("""expr ::= call_ex_kw
|
if "BUILD_MAP_UNPACK_WITH_CALL" in self.seen_op_basenames:
|
||||||
|
self.addRule(
|
||||||
|
"""expr ::= call_ex_kw
|
||||||
call_ex_kw ::= expr expr build_map_unpack_with_call
|
call_ex_kw ::= expr expr build_map_unpack_with_call
|
||||||
CALL_FUNCTION_EX_KW
|
CALL_FUNCTION_EX_KW
|
||||||
""", nop_func)
|
""",
|
||||||
if 'BUILD_TUPLE_UNPACK_WITH_CALL' in self.seen_op_basenames:
|
nop_func,
|
||||||
|
)
|
||||||
|
if "BUILD_TUPLE_UNPACK_WITH_CALL" in self.seen_op_basenames:
|
||||||
# FIXME: should this be parameterized by EX value?
|
# FIXME: should this be parameterized by EX value?
|
||||||
self.addRule("""expr ::= call_ex_kw3
|
self.addRule(
|
||||||
|
"""expr ::= call_ex_kw3
|
||||||
call_ex_kw3 ::= expr
|
call_ex_kw3 ::= expr
|
||||||
build_tuple_unpack_with_call
|
build_tuple_unpack_with_call
|
||||||
expr
|
expr
|
||||||
CALL_FUNCTION_EX_KW
|
CALL_FUNCTION_EX_KW
|
||||||
""", nop_func)
|
""",
|
||||||
if 'BUILD_MAP_UNPACK_WITH_CALL' in self.seen_op_basenames:
|
nop_func,
|
||||||
|
)
|
||||||
|
if "BUILD_MAP_UNPACK_WITH_CALL" in self.seen_op_basenames:
|
||||||
# FIXME: should this be parameterized by EX value?
|
# FIXME: should this be parameterized by EX value?
|
||||||
self.addRule("""expr ::= call_ex_kw2
|
self.addRule(
|
||||||
|
"""expr ::= call_ex_kw2
|
||||||
call_ex_kw2 ::= expr
|
call_ex_kw2 ::= expr
|
||||||
build_tuple_unpack_with_call
|
build_tuple_unpack_with_call
|
||||||
build_map_unpack_with_call
|
build_map_unpack_with_call
|
||||||
CALL_FUNCTION_EX_KW
|
CALL_FUNCTION_EX_KW
|
||||||
""", nop_func)
|
""",
|
||||||
|
nop_func,
|
||||||
|
)
|
||||||
|
|
||||||
elif opname == 'CALL_FUNCTION_EX':
|
elif opname == "CALL_FUNCTION_EX":
|
||||||
self.addRule("""
|
self.addRule(
|
||||||
|
"""
|
||||||
expr ::= call_ex
|
expr ::= call_ex
|
||||||
starred ::= expr
|
starred ::= expr
|
||||||
call_ex ::= expr starred CALL_FUNCTION_EX
|
call_ex ::= expr starred CALL_FUNCTION_EX
|
||||||
""", nop_func)
|
""",
|
||||||
|
nop_func,
|
||||||
|
)
|
||||||
if self.version >= (3, 6):
|
if self.version >= (3, 6):
|
||||||
if 'BUILD_MAP_UNPACK_WITH_CALL' in self.seen_ops:
|
if "BUILD_MAP_UNPACK_WITH_CALL" in self.seen_ops:
|
||||||
self.addRule("""
|
self.addRule(
|
||||||
|
"""
|
||||||
expr ::= call_ex_kw
|
expr ::= call_ex_kw
|
||||||
call_ex_kw ::= expr expr
|
call_ex_kw ::= expr expr
|
||||||
build_map_unpack_with_call CALL_FUNCTION_EX
|
build_map_unpack_with_call CALL_FUNCTION_EX
|
||||||
""", nop_func)
|
""",
|
||||||
if 'BUILD_TUPLE_UNPACK_WITH_CALL' in self.seen_ops:
|
nop_func,
|
||||||
self.addRule("""
|
)
|
||||||
|
if "BUILD_TUPLE_UNPACK_WITH_CALL" in self.seen_ops:
|
||||||
|
self.addRule(
|
||||||
|
"""
|
||||||
expr ::= call_ex_kw3
|
expr ::= call_ex_kw3
|
||||||
call_ex_kw3 ::= expr
|
call_ex_kw3 ::= expr
|
||||||
build_tuple_unpack_with_call
|
build_tuple_unpack_with_call
|
||||||
%s
|
%s
|
||||||
CALL_FUNCTION_EX
|
CALL_FUNCTION_EX
|
||||||
""" % 'expr ' * token.attr, nop_func)
|
"""
|
||||||
|
% "expr "
|
||||||
|
* token.attr,
|
||||||
|
nop_func,
|
||||||
|
)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# FIXME: Is this right?
|
# FIXME: Is this right?
|
||||||
self.addRule("""
|
self.addRule(
|
||||||
|
"""
|
||||||
expr ::= call_ex_kw4
|
expr ::= call_ex_kw4
|
||||||
call_ex_kw4 ::= expr
|
call_ex_kw4 ::= expr
|
||||||
expr
|
expr
|
||||||
expr
|
expr
|
||||||
CALL_FUNCTION_EX
|
CALL_FUNCTION_EX
|
||||||
""", nop_func)
|
""",
|
||||||
|
nop_func,
|
||||||
|
)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
super(Python36Parser, self).custom_classfunc_rule(opname, token, customize, next_token, is_pypy)
|
super(Python36Parser, self).custom_classfunc_rule(
|
||||||
|
opname, token, customize, next_token, is_pypy
|
||||||
|
)
|
||||||
|
|
||||||
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
||||||
invalid = super(Python36Parser,
|
invalid = super(Python36Parser, self).reduce_is_invalid(
|
||||||
self).reduce_is_invalid(rule, ast,
|
rule, ast, tokens, first, last
|
||||||
tokens, first, last)
|
)
|
||||||
if invalid:
|
if invalid:
|
||||||
return invalid
|
return invalid
|
||||||
if rule[0] == 'assign':
|
if rule[0] == "assign":
|
||||||
# Try to combine assignment + annotation into one statement
|
# Try to combine assignment + annotation into one statement
|
||||||
if (len(tokens) >= last + 1 and
|
if (
|
||||||
tokens[last] == 'LOAD_NAME' and
|
len(tokens) >= last + 1
|
||||||
tokens[last+1] == 'STORE_ANNOTATION' and
|
and tokens[last] == "LOAD_NAME"
|
||||||
tokens[last-1].pattr == tokens[last+1].pattr):
|
and tokens[last + 1] == "STORE_ANNOTATION"
|
||||||
|
and tokens[last - 1].pattr == tokens[last + 1].pattr
|
||||||
|
):
|
||||||
# Will handle as ann_assign_init_value
|
# Will handle as ann_assign_init_value
|
||||||
return True
|
return True
|
||||||
pass
|
pass
|
||||||
if rule[0] == 'call_kw':
|
if rule[0] == "call_kw":
|
||||||
# Make sure we don't derive call_kw
|
# Make sure we don't derive call_kw
|
||||||
nt = ast[0]
|
nt = ast[0]
|
||||||
while not isinstance(nt, Token):
|
while not isinstance(nt, Token):
|
||||||
if nt[0] == 'call_kw':
|
if nt[0] == "call_kw":
|
||||||
return True
|
return True
|
||||||
nt = nt[0]
|
nt = nt[0]
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Python36ParserSingle(Python36Parser, PythonParserSingle):
|
class Python36ParserSingle(Python36Parser, PythonParserSingle):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
# Check grammar
|
# Check grammar
|
||||||
p = Python36Parser()
|
p = Python36Parser()
|
||||||
p.check_grammar()
|
p.check_grammar()
|
||||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE
|
||||||
|
|
||||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 6):
|
if PYTHON_VERSION_TRIPLE[:2] == (3, 6):
|
||||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||||
from uncompyle6.scanner import get_scanner
|
from uncompyle6.scanner import get_scanner
|
||||||
|
|
||||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||||
opcode_set = set(s.opc.opname).union(set(
|
opcode_set = set(s.opc.opname).union(
|
||||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
set(
|
||||||
|
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||||
LAMBDA_MARKER RETURN_LAST
|
LAMBDA_MARKER RETURN_LAST
|
||||||
""".split()))
|
""".split()
|
||||||
|
)
|
||||||
|
)
|
||||||
remain_tokens = set(tokens) - opcode_set
|
remain_tokens = set(tokens) - opcode_set
|
||||||
import re
|
import re
|
||||||
remain_tokens = set([re.sub(r'_\d+$', '', t) for t in remain_tokens])
|
|
||||||
remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens])
|
remain_tokens = set([re.sub(r"_\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
|
remain_tokens = set(remain_tokens) - opcode_set
|
||||||
print(remain_tokens)
|
print(remain_tokens)
|
||||||
# print(sorted(p.rule2name.items()))
|
# print(sorted(p.rule2name.items()))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2017-2020, 2022-2023 Rocky Bernstein
|
# Copyright (c) 2017-2020, 2022-2024 Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,10 +17,12 @@ Python 3.7 grammar for the spark Earley-algorithm parser.
|
|||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
from uncompyle6.scanners.tok import Token
|
|
||||||
from uncompyle6.parser import PythonParserSingle, nop_func
|
|
||||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||||
|
|
||||||
|
from uncompyle6.parser import PythonParserSingle, nop_func
|
||||||
from uncompyle6.parsers.parse37base import Python37BaseParser
|
from uncompyle6.parsers.parse37base import Python37BaseParser
|
||||||
|
from uncompyle6.scanners.tok import Token
|
||||||
|
|
||||||
|
|
||||||
class Python37Parser(Python37BaseParser):
|
class Python37Parser(Python37BaseParser):
|
||||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||||
@@ -249,8 +251,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def p_generator_exp(self, args):
|
def p_generator_exp(self, args):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
def p_jump(self, args):
|
def p_jump(self, args):
|
||||||
"""
|
"""
|
||||||
@@ -757,7 +758,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def p_dict_comp3(self, args):
|
def p_dict_comp3(self, args):
|
||||||
""""
|
""" "
|
||||||
expr ::= dict_comp
|
expr ::= dict_comp
|
||||||
stmt ::= dict_comp_func
|
stmt ::= dict_comp_func
|
||||||
|
|
||||||
@@ -1554,7 +1555,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
|
|
||||||
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
with_as ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
"""
|
"""
|
||||||
if self.version < (3, 8):
|
if self.version < (3, 8):
|
||||||
@@ -1575,7 +1576,6 @@ class Python37Parser(Python37BaseParser):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def custom_classfunc_rule(self, opname, token, customize, next_token):
|
def custom_classfunc_rule(self, opname, token, customize, next_token):
|
||||||
|
|
||||||
args_pos, args_kw = self.get_pos_kw(token)
|
args_pos, args_kw = self.get_pos_kw(token)
|
||||||
|
|
||||||
# Additional exprs for * and ** args:
|
# Additional exprs for * and ** args:
|
||||||
@@ -1718,6 +1718,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def info(args):
|
def info(args):
|
||||||
# Check grammar
|
# Check grammar
|
||||||
p = Python37Parser()
|
p = Python37Parser()
|
||||||
@@ -1748,7 +1749,7 @@ if __name__ == "__main__":
|
|||||||
# FIXME: DRY this with other parseXX.py routines
|
# FIXME: DRY this with other parseXX.py routines
|
||||||
p = Python37Parser()
|
p = Python37Parser()
|
||||||
p.check_grammar()
|
p.check_grammar()
|
||||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE
|
||||||
|
|
||||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 7):
|
if PYTHON_VERSION_TRIPLE[:2] == (3, 7):
|
||||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2017, 2019-2020, 2022-2023 Rocky Bernstein
|
# Copyright (c) 2016-2017, 2019-2020, 2022-2024 Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
Python 3.7 base code. We keep non-custom-generated grammar rules out of this file.
|
Python 3.7 base code. We keep non-custom-generated grammar rules out of this file.
|
||||||
"""
|
"""
|
||||||
@@ -1055,14 +1055,14 @@ class Python37BaseParser(PythonParser):
|
|||||||
elif opname == "SETUP_WITH":
|
elif opname == "SETUP_WITH":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= with
|
stmt ::= with
|
||||||
stmt ::= withasstmt
|
stmt ::= with_as
|
||||||
|
|
||||||
with ::= expr
|
with ::= expr
|
||||||
SETUP_WITH POP_TOP
|
SETUP_WITH POP_TOP
|
||||||
suite_stmts_opt
|
suite_stmts_opt
|
||||||
COME_FROM_WITH
|
COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
with_as ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
|
|
||||||
with ::= expr
|
with ::= expr
|
||||||
@@ -1071,7 +1071,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
|
|
||||||
withasstmt ::= expr
|
with_as ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
@@ -1080,7 +1080,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
SETUP_WITH POP_TOP suite_stmts_opt
|
SETUP_WITH POP_TOP suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
withasstmt ::= expr
|
with_as ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
@@ -1098,17 +1098,18 @@ class Python37BaseParser(PythonParser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
|
|
||||||
withasstmt ::= expr
|
|
||||||
SETUP_WITH store suite_stmts_opt
|
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
|
||||||
|
|
||||||
withasstmt ::= expr
|
|
||||||
SETUP_WITH store suite_stmts
|
|
||||||
POP_BLOCK BEGIN_FINALLY COME_FROM_WITH with_suffix
|
|
||||||
|
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
||||||
BEGIN_FINALLY COME_FROM_WITH
|
BEGIN_FINALLY COME_FROM_WITH
|
||||||
with_suffix
|
with_suffix
|
||||||
|
|
||||||
|
with_as ::= expr
|
||||||
|
SETUP_WITH store suite_stmts_opt
|
||||||
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
|
|
||||||
|
with_as ::= expr
|
||||||
|
SETUP_WITH store suite_stmts
|
||||||
|
POP_BLOCK BEGIN_FINALLY COME_FROM_WITH with_suffix
|
||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
|
|
||||||
|
@@ -378,6 +378,46 @@ TABLE_DIRECT = {
|
|||||||
(0, PRECEDENCE["named_expr"]-1)),
|
(0, PRECEDENCE["named_expr"]-1)),
|
||||||
"break": ("%|break\n",),
|
"break": ("%|break\n",),
|
||||||
"continue": ("%|continue\n",),
|
"continue": ("%|continue\n",),
|
||||||
|
|
||||||
|
"except": ("%|except:\n%+%c%-", 3),
|
||||||
|
"except_cond1": ("%|except %c:\n", 1),
|
||||||
|
"except_cond2": ("%|except %c as %c:\n", (1, "expr"), (5, "store")),
|
||||||
|
"except_suite": ("%+%c%-%C", 0, (1, maxint, "")),
|
||||||
|
# In Python 3.6+, this is more complicated in the presence of "returns"
|
||||||
|
"except_suite_finalize": ("%+%c%-%C", 1, (3, maxint, "")),
|
||||||
|
|
||||||
|
"expr_stmt": (
|
||||||
|
"%|%p\n",
|
||||||
|
# When a statement contains only a named_expr (:=)
|
||||||
|
# the named_expr should have parenthesis around it.
|
||||||
|
(0, "expr", PRECEDENCE["named_expr"] - 1)
|
||||||
|
),
|
||||||
|
|
||||||
|
# Note: Python 3.8+ changes this
|
||||||
|
"for": ("%|for %c in %c:\n%+%c%-\n\n", (3, "store"), (1, "expr"), (4, "for_block")),
|
||||||
|
|
||||||
|
"forelsestmt": (
|
||||||
|
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
|
||||||
|
(3, "store"),
|
||||||
|
(1, "expr"),
|
||||||
|
(4, "for_block"),
|
||||||
|
-2,
|
||||||
|
),
|
||||||
|
"forelselaststmt": (
|
||||||
|
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-",
|
||||||
|
(3, "store"),
|
||||||
|
(1, "expr"),
|
||||||
|
(4, "for_block"),
|
||||||
|
-2,
|
||||||
|
),
|
||||||
|
"forelselaststmtl": (
|
||||||
|
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
|
||||||
|
(3, "store"),
|
||||||
|
(1, "expr"),
|
||||||
|
(4, "for_block"),
|
||||||
|
-2,
|
||||||
|
),
|
||||||
|
|
||||||
"raise_stmt0": ("%|raise\n",),
|
"raise_stmt0": ("%|raise\n",),
|
||||||
"raise_stmt1": ("%|raise %c\n", 0),
|
"raise_stmt1": ("%|raise %c\n", 0),
|
||||||
"raise_stmt3": ("%|raise %c, %c, %c\n", 0, 1, 2),
|
"raise_stmt3": ("%|raise %c, %c, %c\n", 0, 1, 2),
|
||||||
@@ -419,72 +459,7 @@ TABLE_DIRECT = {
|
|||||||
1,
|
1,
|
||||||
3,
|
3,
|
||||||
), # has COME_FROM
|
), # has COME_FROM
|
||||||
"whileTruestmt": ("%|while True:\n%+%c%-\n\n", 1),
|
|
||||||
"whilestmt": ("%|while %c:\n%+%c%-\n\n", 1, 2),
|
|
||||||
"while1stmt": ("%|while 1:\n%+%c%-\n\n", 1),
|
|
||||||
"while1elsestmt": ("%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n", 1, -2),
|
|
||||||
"whileelsestmt": ("%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n", 1, 2, -2),
|
|
||||||
"whileelsestmt2": ("%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n", 1, 2, -3),
|
|
||||||
"whileelselaststmt": ("%|while %c:\n%+%c%-%|else:\n%+%c%-", 1, 2, -2),
|
|
||||||
|
|
||||||
# If there are situations where we need "with ... as ()"
|
|
||||||
# We may need to customize this in n_withasstmt
|
|
||||||
"withasstmt": (
|
|
||||||
"%|with %c as %c:\n%+%c%-",
|
|
||||||
(0, "expr"),
|
|
||||||
(2, "store"),
|
|
||||||
(3, ("suite_stmts_opt", "suite_stmts")),
|
|
||||||
),
|
|
||||||
|
|
||||||
"expr_stmt": (
|
|
||||||
"%|%p\n",
|
|
||||||
# When a statement contains only a named_expr (:=)
|
|
||||||
# the named_expr should have parenthesis around it.
|
|
||||||
(0, "expr", PRECEDENCE["named_expr"] - 1)
|
|
||||||
),
|
|
||||||
|
|
||||||
# Note: Python 3.8+ changes this
|
|
||||||
"for": ("%|for %c in %c:\n%+%c%-\n\n", (3, "store"), (1, "expr"), (4, "for_block")),
|
|
||||||
|
|
||||||
"forelsestmt": (
|
|
||||||
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
|
|
||||||
(3, "store"),
|
|
||||||
(1, "expr"),
|
|
||||||
(4, "for_block"),
|
|
||||||
-2,
|
|
||||||
),
|
|
||||||
"forelselaststmt": (
|
|
||||||
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-",
|
|
||||||
(3, "store"),
|
|
||||||
(1, "expr"),
|
|
||||||
(4, "for_block"),
|
|
||||||
-2,
|
|
||||||
),
|
|
||||||
"forelselaststmtl": (
|
|
||||||
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
|
|
||||||
(3, "store"),
|
|
||||||
(1, "expr"),
|
|
||||||
(4, "for_block"),
|
|
||||||
-2,
|
|
||||||
),
|
|
||||||
"try_except": ("%|try:\n%+%c%-%c\n\n", 1, 3),
|
|
||||||
"tryelsestmt": ("%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n", 1, 3, 4),
|
|
||||||
"tryelsestmtc": ("%|try:\n%+%c%-%c%|else:\n%+%c%-", 1, 3, 4),
|
|
||||||
"tryelsestmtl": ("%|try:\n%+%c%-%c%|else:\n%+%c%-", 1, 3, 4),
|
|
||||||
# Note: this is generated generated by grammar rules but in this phase.
|
|
||||||
"tf_try_except": ("%c%-%c%+", 1, 3),
|
|
||||||
"tf_tryelsestmt": ("%c%-%c%|else:\n%+%c", 1, 3, 4),
|
|
||||||
"tryfinallystmt": ("%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", 1, 5),
|
|
||||||
"except": ("%|except:\n%+%c%-", 3),
|
|
||||||
"except_cond1": ("%|except %c:\n", 1),
|
|
||||||
"except_cond2": ("%|except %c as %c:\n", (1, "expr"), (5, "store")),
|
|
||||||
"except_suite": ("%+%c%-%C", 0, (1, maxint, "")),
|
|
||||||
# In Python 3.6+, this is more complicated in the presence of "returns"
|
|
||||||
"except_suite_finalize": ("%+%c%-%C", 1, (3, maxint, "")),
|
|
||||||
"pass": ("%|pass\n",),
|
|
||||||
"STORE_FAST": ("%{pattr}",),
|
|
||||||
"kv": ("%c: %c", 3, 1),
|
|
||||||
"kv2": ("%c: %c", 1, 2),
|
|
||||||
"import": ("%|import %c\n", 2),
|
"import": ("%|import %c\n", 2),
|
||||||
"importlist": ("%C", (0, maxint, ", ")),
|
"importlist": ("%C", (0, maxint, ", ")),
|
||||||
|
|
||||||
@@ -498,6 +473,36 @@ TABLE_DIRECT = {
|
|||||||
"import_from_star": (
|
"import_from_star": (
|
||||||
"%|from %[2]{pattr} import *\n",
|
"%|from %[2]{pattr} import *\n",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
"kv": ("%c: %c", 3, 1),
|
||||||
|
"kv2": ("%c: %c", 1, 2),
|
||||||
|
"pass": ("%|pass\n",),
|
||||||
|
|
||||||
|
"whileTruestmt": ("%|while True:\n%+%c%-\n\n", 1),
|
||||||
|
"whilestmt": ("%|while %c:\n%+%c%-\n\n", 1, 2),
|
||||||
|
"while1stmt": ("%|while 1:\n%+%c%-\n\n", 1),
|
||||||
|
"while1elsestmt": ("%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n", 1, -2),
|
||||||
|
"whileelsestmt": ("%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n", 1, 2, -2),
|
||||||
|
"whileelsestmt2": ("%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n", 1, 2, -3),
|
||||||
|
"whileelselaststmt": ("%|while %c:\n%+%c%-%|else:\n%+%c%-", 1, 2, -2),
|
||||||
|
|
||||||
|
# If there are situations where we need "with ... as ()"
|
||||||
|
# We may need to customize this in n_with_as
|
||||||
|
"with_as": (
|
||||||
|
"%|with %c as %c:\n%+%c%-",
|
||||||
|
(0, "expr"),
|
||||||
|
(2, "store"),
|
||||||
|
(3, ("suite_stmts_opt", "suite_stmts")),
|
||||||
|
),
|
||||||
|
|
||||||
|
"try_except": ("%|try:\n%+%c%-%c\n\n", 1, 3),
|
||||||
|
"tryelsestmt": ("%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n", 1, 3, 4),
|
||||||
|
"tryelsestmtc": ("%|try:\n%+%c%-%c%|else:\n%+%c%-", 1, 3, 4),
|
||||||
|
"tryelsestmtl": ("%|try:\n%+%c%-%c%|else:\n%+%c%-", 1, 3, 4),
|
||||||
|
# Note: this is generated generated by grammar rules but in this phase.
|
||||||
|
"tf_try_except": ("%c%-%c%+", 1, 3),
|
||||||
|
"tf_tryelsestmt": ("%c%-%c%|else:\n%+%c", 1, 3, 4),
|
||||||
|
"tryfinallystmt": ("%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", 1, 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user