Skip to content

Commit 02ed25e

Browse files
committed
Bugs found in 3.0 decomplation...
parsers/parse30.py; fix set comprehension grammar bug uncompyle6/semantics/n_actions.py: evidence of the evils of modifying node data (via node.pop)
1 parent ca04ae9 commit 02ed25e

File tree

2 files changed

+44
-39
lines changed

2 files changed

+44
-39
lines changed

uncompyle6/parsers/parse30.py

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2016-2017, 2022-2023 Rocky Bernstein
1+
# Copyright (c) 2016-2017, 2022-2024 Rocky Bernstein
22
"""
33
spark grammar differences over Python 3.1 for Python 3.0.
44
"""
@@ -7,8 +7,8 @@
77
from uncompyle6.parser import PythonParserSingle
88
from uncompyle6.parsers.parse31 import Python31Parser
99

10-
class Python30Parser(Python31Parser):
1110

11+
class Python30Parser(Python31Parser):
1212
def p_30(self, args):
1313
"""
1414
@@ -78,7 +78,6 @@ def p_30(self, args):
7878
set_comp_func ::= set_comp_header
7979
LOAD_ARG FOR_ITER store comp_iter
8080
JUMP_BACK ending_return
81-
RETURN_VALUE RETURN_LAST
8281
8382
list_comp_header ::= BUILD_LIST_0 DUP_TOP STORE_FAST
8483
list_comp ::= list_comp_header
@@ -118,7 +117,7 @@ def p_30(self, args):
118117
# From Python 2.6
119118
120119
121-
lc_body ::= LOAD_FAST expr LIST_APPEND
120+
lc_body ::= LOAD_FAST expr LIST_APPEND
122121
lc_body ::= LOAD_NAME expr LIST_APPEND
123122
list_if ::= expr jmp_false_then list_iter
124123
list_if_not ::= expr jmp_true list_iter JUMP_BACK come_froms POP_TOP
@@ -216,9 +215,9 @@ def p_30(self, args):
216215
compare_chained_right ::= expr COMPARE_OP RETURN_END_IF
217216
"""
218217

219-
220218
def remove_rules_30(self):
221-
self.remove_rules("""
219+
self.remove_rules(
220+
"""
222221
223222
# The were found using grammar coverage
224223
while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP
@@ -286,37 +285,41 @@ def remove_rules_30(self):
286285
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
287286
and ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
288287
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
289-
""")
288+
"""
289+
)
290290

291291
def customize_grammar_rules(self, tokens, customize):
292292
super(Python30Parser, self).customize_grammar_rules(tokens, customize)
293293
self.remove_rules_30()
294294

295295
self.check_reduce["iflaststmtl"] = "AST"
296-
self.check_reduce['ifstmt'] = "AST"
296+
self.check_reduce["ifstmt"] = "AST"
297297
self.check_reduce["ifelsestmtc"] = "AST"
298298
self.check_reduce["ifelsestmt"] = "AST"
299299
# self.check_reduce["and"] = "stmt"
300300
return
301301

302302
def reduce_is_invalid(self, rule, ast, tokens, first, last):
303-
invalid = super(Python30Parser,
304-
self).reduce_is_invalid(rule, ast,
305-
tokens, first, last)
303+
invalid = super(Python30Parser, self).reduce_is_invalid(
304+
rule, ast, tokens, first, last
305+
)
306306
if invalid:
307307
return invalid
308308
lhs = rule[0]
309309
if (
310-
lhs in ("iflaststmtl", "ifstmt",
311-
"ifelsestmt", "ifelsestmtc") and ast[0] == "testexpr"
310+
lhs in ("iflaststmtl", "ifstmt", "ifelsestmt", "ifelsestmtc")
311+
and ast[0] == "testexpr"
312312
):
313313
testexpr = ast[0]
314314
if testexpr[0] == "testfalse":
315315
testfalse = testexpr[0]
316316
if lhs == "ifelsestmtc" and ast[2] == "jump_absolute_else":
317317
jump_absolute_else = ast[2]
318318
come_from = jump_absolute_else[2]
319-
return come_from == "COME_FROM" and come_from.attr < tokens[first].offset
319+
return (
320+
come_from == "COME_FROM"
321+
and come_from.attr < tokens[first].offset
322+
)
320323
pass
321324
elif lhs in ("ifelsestmt", "ifelsestmtc") and ast[2] == "jump_cf_pop":
322325
jump_cf_pop = ast[2]
@@ -339,20 +342,21 @@ def reduce_is_invalid(self, rule, ast, tokens, first, last):
339342
jmp_false = testfalse[1]
340343
if last == len(tokens):
341344
last -= 1
342-
while (isinstance(tokens[first].offset, str) and first < last):
345+
while isinstance(tokens[first].offset, str) and first < last:
343346
first += 1
344347
if first == last:
345348
return True
346-
while (first < last and isinstance(tokens[last].offset, str)):
349+
while first < last and isinstance(tokens[last].offset, str):
347350
last -= 1
348351
if rule[0] == "iflaststmtl":
349352
return not (jmp_false[0].attr <= tokens[last].offset)
350353
else:
351354
jmp_false_target = jmp_false[0].attr
352355
if tokens[first].offset > jmp_false_target:
353356
return True
354-
return (
355-
(jmp_false_target > tokens[last].offset) and tokens[last] != "JUMP_FORWARD")
357+
return (jmp_false_target > tokens[last].offset) and tokens[
358+
last
359+
] != "JUMP_FORWARD"
356360
pass
357361
pass
358362
pass
@@ -361,33 +365,43 @@ def reduce_is_invalid(self, rule, ast, tokens, first, last):
361365

362366
pass
363367

368+
364369
class Python30ParserSingle(Python30Parser, PythonParserSingle):
365370
pass
366371

367-
if __name__ == '__main__':
372+
373+
if __name__ == "__main__":
368374
# Check grammar
369375
p = Python30Parser()
370376
p.remove_rules_30()
371377
p.check_grammar()
372-
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
378+
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE
379+
373380
if PYTHON_VERSION_TRIPLE[:2] == (3, 0):
374381
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
375382
from uncompyle6.scanner import get_scanner
383+
376384
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
377-
opcode_set = set(s.opc.opname).union(set(
378-
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
385+
opcode_set = set(s.opc.opname).union(
386+
set(
387+
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
379388
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
380389
LAMBDA_MARKER RETURN_LAST
381-
""".split()))
390+
""".split()
391+
)
392+
)
382393
## FIXME: try this
383394
remain_tokens = set(tokens) - opcode_set
384395
import re
385-
remain_tokens = set([re.sub(r'_\d+$', '', t) for t in remain_tokens])
386-
remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens])
396+
397+
remain_tokens = set([re.sub(r"_\d+$", "", t) for t in remain_tokens])
398+
remain_tokens = set([re.sub("_CONT$", "", t) for t in remain_tokens])
387399
remain_tokens = set(remain_tokens) - opcode_set
388400
print(remain_tokens)
389401
import sys
402+
390403
if len(sys.argv) > 1:
391404
from spark_parser.spark import rule2str
405+
392406
for rule in sorted(p.rule2name.items()):
393407
print(rule2str(rule[0]))

uncompyle6/semantics/n_actions.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2022-2023 by Rocky Bernstein
1+
# Copyright (c) 2022-2024 by Rocky Bernstein
22
#
33
# This program is free software: you can redistribute it and/or modify
44
# it under the terms of the GNU General Public License as published by
@@ -16,22 +16,12 @@
1616
Custom Nonterminal action functions. See NonterminalActions docstring.
1717
"""
1818

19-
from uncompyle6.semantics.consts import (
20-
INDENT_PER_LEVEL,
21-
NONE,
22-
PRECEDENCE,
23-
minint,
24-
)
25-
2619
from uncompyle6.parsers.treenode import SyntaxTree
2720
from uncompyle6.scanners.tok import Token
21+
from uncompyle6.semantics.consts import INDENT_PER_LEVEL, NONE, PRECEDENCE, minint
22+
from uncompyle6.semantics.helper import find_code_node, flatten_list
2823
from uncompyle6.util import better_repr, get_code_name
2924

30-
from uncompyle6.semantics.helper import (
31-
find_code_node,
32-
flatten_list,
33-
)
34-
3525

3626
class NonterminalActions:
3727
"""
@@ -826,7 +816,8 @@ def n_list(self, node):
826816

827817
p = self.prec
828818
self.prec = PRECEDENCE["yield"] - 1
829-
lastnode = node.pop()
819+
lastnode = node[-1]
820+
node = node[:-1]
830821
lastnodetype = lastnode.kind
831822

832823
# If this build list is inside a CALL_FUNCTION_VAR,

0 commit comments

Comments
 (0)