You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
store_subscript precedence fix and...
Allow format specifier "%p" to indicate a nonterminal name, like "%c" allows. store_subscr -> store_subscript to match Python AST a little closer.
This commit is contained in:
@@ -127,11 +127,17 @@ def test_tables():
|
|||||||
"Full entry: %s" %
|
"Full entry: %s" %
|
||||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||||
)
|
)
|
||||||
assert len(tup) == 2
|
assert 2 <= len(tup) <= 3
|
||||||
for j, x in enumerate(tup):
|
for j, x in enumerate(tup):
|
||||||
assert isinstance(x, int), (
|
if len(tup) == 3 and j == 1:
|
||||||
"%s[%s][%d][%d] type '%s' is '%s should be an int but is %s. Full entry: %s" %
|
assert isinstance(x, str), (
|
||||||
(name, k, arg, j, typ, x, type(x), entry)
|
"%s[%s][%d][%d] type '%s' is '%s should be an string but is %s. Full entry: %s" %
|
||||||
|
(name, k, arg, j, typ, x, type(x), entry)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert isinstance(x, int), (
|
||||||
|
"%s[%s][%d][%d] type '%s' is '%s should be an int but is %s. Full entry: %s" %
|
||||||
|
(name, k, arg, j, typ, x, type(x), entry)
|
||||||
)
|
)
|
||||||
pass
|
pass
|
||||||
arg += 1
|
arg += 1
|
||||||
|
BIN
test/bytecode_2.7_run/04_subscript.pyc
Normal file
BIN
test/bytecode_2.7_run/04_subscript.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.6_run/04_subscript.pyc
Normal file
BIN
test/bytecode_3.6_run/04_subscript.pyc
Normal file
Binary file not shown.
11
test/simple_source/expression/04_subscript.py
Normal file
11
test/simple_source/expression/04_subscript.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# From 3.6.8 idlelib/query.py
|
||||||
|
# Bug was handling parens around subscript
|
||||||
|
|
||||||
|
# RUNNABLE!
|
||||||
|
a = {'text': 1}
|
||||||
|
b = {'text': 3}
|
||||||
|
for widget, entry, expect in (
|
||||||
|
(a, b, 1),
|
||||||
|
(None, b, 3)
|
||||||
|
):
|
||||||
|
assert (widget or entry)['text'] == expect
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2018 Rocky Bernstein
|
# Copyright (c) 2015-2019 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
|
||||||
@@ -589,14 +589,14 @@ class PythonParser(GenericASTBuilder):
|
|||||||
## designLists ::=
|
## designLists ::=
|
||||||
## Will need to redo semantic actiion
|
## Will need to redo semantic actiion
|
||||||
|
|
||||||
store ::= STORE_FAST
|
store ::= STORE_FAST
|
||||||
store ::= STORE_NAME
|
store ::= STORE_NAME
|
||||||
store ::= STORE_GLOBAL
|
store ::= STORE_GLOBAL
|
||||||
store ::= STORE_DEREF
|
store ::= STORE_DEREF
|
||||||
store ::= expr STORE_ATTR
|
store ::= expr STORE_ATTR
|
||||||
store ::= store_subscr
|
store ::= store_subscript
|
||||||
store_subscr ::= expr expr STORE_SUBSCR
|
store_subscript ::= expr expr STORE_SUBSCR
|
||||||
store ::= unpack
|
store ::= unpack
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
@@ -27,6 +27,78 @@ else:
|
|||||||
maxint = sys.maxint
|
maxint = sys.maxint
|
||||||
|
|
||||||
|
|
||||||
|
# Operator precidence
|
||||||
|
# See https://docs.python.org/2/reference/expressions.html
|
||||||
|
# or https://docs.python.org/3/reference/expressions.html
|
||||||
|
# for a list.
|
||||||
|
|
||||||
|
# Things at the top of this list below with low-value precidence will
|
||||||
|
# tend to have parenthesis around them. Things at the bottom
|
||||||
|
# of the list will tend not to have parenthesis around them.
|
||||||
|
PRECEDENCE = {
|
||||||
|
'list': 0,
|
||||||
|
'dict': 0,
|
||||||
|
'unary_convert': 0,
|
||||||
|
'dict_comp': 0,
|
||||||
|
'set_comp': 0,
|
||||||
|
'set_comp_expr': 0,
|
||||||
|
'list_comp': 0,
|
||||||
|
'generator_exp': 0,
|
||||||
|
|
||||||
|
'attribute': 2,
|
||||||
|
'subscript': 2,
|
||||||
|
'subscript2': 2,
|
||||||
|
'store_subscript': 2,
|
||||||
|
'delete_subscr': 2,
|
||||||
|
'slice0': 2,
|
||||||
|
'slice1': 2,
|
||||||
|
'slice2': 2,
|
||||||
|
'slice3': 2,
|
||||||
|
'buildslice2': 2,
|
||||||
|
'buildslice3': 2,
|
||||||
|
'call': 2,
|
||||||
|
|
||||||
|
'BINARY_POWER': 4,
|
||||||
|
|
||||||
|
'unary_expr': 6,
|
||||||
|
|
||||||
|
'BINARY_MULTIPLY': 8,
|
||||||
|
'BINARY_DIVIDE': 8,
|
||||||
|
'BINARY_TRUE_DIVIDE': 8,
|
||||||
|
'BINARY_FLOOR_DIVIDE': 8,
|
||||||
|
'BINARY_MODULO': 8,
|
||||||
|
|
||||||
|
'BINARY_ADD': 10,
|
||||||
|
'BINARY_SUBTRACT': 10,
|
||||||
|
|
||||||
|
'BINARY_LSHIFT': 12,
|
||||||
|
'BINARY_RSHIFT': 12,
|
||||||
|
|
||||||
|
'BINARY_AND': 14,
|
||||||
|
'BINARY_XOR': 16,
|
||||||
|
'BINARY_OR': 18,
|
||||||
|
|
||||||
|
'compare': 20,
|
||||||
|
'unary_not': 22,
|
||||||
|
'and': 24,
|
||||||
|
'ret_and': 24,
|
||||||
|
|
||||||
|
'or': 26,
|
||||||
|
'ret_or': 26,
|
||||||
|
|
||||||
|
'conditional': 28,
|
||||||
|
'conditional_lamdba': 28,
|
||||||
|
'conditional_not_lamdba': 28,
|
||||||
|
'conditionalnot': 28,
|
||||||
|
'ret_cond': 28,
|
||||||
|
'ret_cond_not': 28,
|
||||||
|
|
||||||
|
'_mklambda': 30,
|
||||||
|
|
||||||
|
'yield': 101,
|
||||||
|
'yield_from': 101
|
||||||
|
}
|
||||||
|
|
||||||
LINE_LENGTH = 80
|
LINE_LENGTH = 80
|
||||||
|
|
||||||
# Some parse trees created below are used for comparing code
|
# Some parse trees created below are used for comparing code
|
||||||
@@ -150,15 +222,17 @@ TABLE_DIRECT = {
|
|||||||
'DELETE_FAST': ( '%|del %{pattr}\n', ),
|
'DELETE_FAST': ( '%|del %{pattr}\n', ),
|
||||||
'DELETE_NAME': ( '%|del %{pattr}\n', ),
|
'DELETE_NAME': ( '%|del %{pattr}\n', ),
|
||||||
'DELETE_GLOBAL': ( '%|del %{pattr}\n', ),
|
'DELETE_GLOBAL': ( '%|del %{pattr}\n', ),
|
||||||
'delete_subscr': ( '%|del %c[%c]\n',
|
'delete_subscr': ( '%|del %p[%c]\n',
|
||||||
(0, 'expr'), (1, 'expr') ),
|
(0, 'expr', PRECEDENCE['subscript']), (1, 'expr') ),
|
||||||
'subscript': ( '%c[%p]',
|
'subscript': ( '%p[%c]',
|
||||||
(0, 'expr'),
|
(0, 'expr', PRECEDENCE['subscript']),
|
||||||
(1, 100) ),
|
|
||||||
'subscript2': ( '%c[%c]',
|
|
||||||
(0, 'expr'),
|
|
||||||
(1, 'expr') ),
|
(1, 'expr') ),
|
||||||
'store_subscr': ( '%c[%c]', 0, 1),
|
'subscript2': ( '%p[%c]',
|
||||||
|
(0, 'expr', PRECEDENCE['subscript']),
|
||||||
|
(1, 'expr') ),
|
||||||
|
'store_subscript': ( '%p[%c]',
|
||||||
|
(0, 'expr', PRECEDENCE['subscript']),
|
||||||
|
(1, 'expr') ),
|
||||||
'STORE_FAST': ( '%{pattr}', ),
|
'STORE_FAST': ( '%{pattr}', ),
|
||||||
'STORE_NAME': ( '%{pattr}', ),
|
'STORE_NAME': ( '%{pattr}', ),
|
||||||
'STORE_GLOBAL': ( '%{pattr}', ),
|
'STORE_GLOBAL': ( '%{pattr}', ),
|
||||||
@@ -337,76 +411,6 @@ MAP = {
|
|||||||
'exprlist': MAP_R0,
|
'exprlist': MAP_R0,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Operator precidence
|
|
||||||
# See https://docs.python.org/2/reference/expressions.html
|
|
||||||
# or https://docs.python.org/3/reference/expressions.html
|
|
||||||
# for a list.
|
|
||||||
|
|
||||||
# Things at the top of this list below with low-value precidence will
|
|
||||||
# tend to have parenthesis around them. Things at the bottom
|
|
||||||
# of the list will tend not to have parenthesis around them.
|
|
||||||
PRECEDENCE = {
|
|
||||||
'list': 0,
|
|
||||||
'dict': 0,
|
|
||||||
'unary_convert': 0,
|
|
||||||
'dict_comp': 0,
|
|
||||||
'set_comp': 0,
|
|
||||||
'set_comp_expr': 0,
|
|
||||||
'list_comp': 0,
|
|
||||||
'generator_exp': 0,
|
|
||||||
|
|
||||||
'attribute': 2,
|
|
||||||
'subscript': 2,
|
|
||||||
'subscript2': 2,
|
|
||||||
'slice0': 2,
|
|
||||||
'slice1': 2,
|
|
||||||
'slice2': 2,
|
|
||||||
'slice3': 2,
|
|
||||||
'buildslice2': 2,
|
|
||||||
'buildslice3': 2,
|
|
||||||
'call': 2,
|
|
||||||
|
|
||||||
'BINARY_POWER': 4,
|
|
||||||
|
|
||||||
'unary_expr': 6,
|
|
||||||
|
|
||||||
'BINARY_MULTIPLY': 8,
|
|
||||||
'BINARY_DIVIDE': 8,
|
|
||||||
'BINARY_TRUE_DIVIDE': 8,
|
|
||||||
'BINARY_FLOOR_DIVIDE': 8,
|
|
||||||
'BINARY_MODULO': 8,
|
|
||||||
|
|
||||||
'BINARY_ADD': 10,
|
|
||||||
'BINARY_SUBTRACT': 10,
|
|
||||||
|
|
||||||
'BINARY_LSHIFT': 12,
|
|
||||||
'BINARY_RSHIFT': 12,
|
|
||||||
|
|
||||||
'BINARY_AND': 14,
|
|
||||||
'BINARY_XOR': 16,
|
|
||||||
'BINARY_OR': 18,
|
|
||||||
|
|
||||||
'compare': 20,
|
|
||||||
'unary_not': 22,
|
|
||||||
'and': 24,
|
|
||||||
'ret_and': 24,
|
|
||||||
|
|
||||||
'or': 26,
|
|
||||||
'ret_or': 26,
|
|
||||||
|
|
||||||
'conditional': 28,
|
|
||||||
'conditional_lamdba': 28,
|
|
||||||
'conditional_not_lamdba': 28,
|
|
||||||
'conditionalnot': 28,
|
|
||||||
'ret_cond': 28,
|
|
||||||
'ret_cond_not': 28,
|
|
||||||
|
|
||||||
'_mklambda': 30,
|
|
||||||
|
|
||||||
'yield': 101,
|
|
||||||
'yield_from': 101
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSIGN_TUPLE_PARAM = lambda param_name: \
|
ASSIGN_TUPLE_PARAM = lambda param_name: \
|
||||||
SyntaxTree('expr', [ Token('LOAD_FAST', pattr=param_name) ])
|
SyntaxTree('expr', [ Token('LOAD_FAST', pattr=param_name) ])
|
||||||
|
|
||||||
|
@@ -88,7 +88,8 @@ Python.
|
|||||||
#
|
#
|
||||||
# %p like %c but sets the operator precedence.
|
# %p like %c but sets the operator precedence.
|
||||||
# Its argument then is a tuple indicating the node
|
# Its argument then is a tuple indicating the node
|
||||||
# index and the precidence value, an integer.
|
# index and the precedence value, an integer. If 3 items are given,
|
||||||
|
# the second item is the nonterminal name and the precedence is given last.
|
||||||
#
|
#
|
||||||
# %C evaluate children recursively, with sibling children separated by the
|
# %C evaluate children recursively, with sibling children separated by the
|
||||||
# given string. It needs a 3-tuple: a starting node, the maximimum
|
# given string. It needs a 3-tuple: a starting node, the maximimum
|
||||||
@@ -616,7 +617,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
node[-2][0].kind = 'build_tuple2'
|
node[-2][0].kind = 'build_tuple2'
|
||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
n_store_subscr = n_subscript = n_delete_subscr
|
n_store_subscript = n_subscript = n_delete_subscr
|
||||||
|
|
||||||
# Note: this node is only in Python 2.x
|
# Note: this node is only in Python 2.x
|
||||||
# FIXME: figure out how to get this into customization
|
# FIXME: figure out how to get this into customization
|
||||||
@@ -1873,7 +1874,18 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
arg += 1
|
arg += 1
|
||||||
elif typ == 'p':
|
elif typ == 'p':
|
||||||
p = self.prec
|
p = self.prec
|
||||||
(index, self.prec) = entry[arg]
|
tup = entry[arg]
|
||||||
|
assert isinstance(tup, tuple)
|
||||||
|
if len(tup) == 3:
|
||||||
|
(index, nonterm_name, self.prec) = tup
|
||||||
|
assert node[index] == nonterm_name, (
|
||||||
|
"at %s[%d], expected '%s' node; got '%s'" % (
|
||||||
|
node.kind, arg, nonterm_name, node[index].kind)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert len(tup) == 2
|
||||||
|
(index, self.prec) = entry[arg]
|
||||||
|
|
||||||
self.preorder(node[index])
|
self.preorder(node[index])
|
||||||
self.prec = p
|
self.prec = p
|
||||||
arg += 1
|
arg += 1
|
||||||
|
Reference in New Issue
Block a user