Start allowing node names in template engine

These are now used to assert we have the right node type.

Simplify import_from
This commit is contained in:
rocky
2017-10-13 11:16:10 -04:00
parent 2fc3886693
commit 9dd881fae1
6 changed files with 74 additions and 53 deletions

View File

@@ -56,10 +56,18 @@ def test_tables():
elif typ in frozenset(['c', 'p', 'P', 'C', 'D']):
# One arg - should be int or tuple of int
if typ == 'c':
assert isinstance(entry[arg], int), (
item = entry[arg]
if isinstance(item, tuple):
assert isinstance(item[1], str), (
"%s[%s][%d] kind %s is '%s' should be str but is %s. "
"Full entry: %s" %
(name, k, arg, typ, item[1], type(item[1]), entry)
)
item = item[0]
assert isinstance(item, int), (
"%s[%s][%d] kind %s is '%s' should be an int but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
(name, k, arg, typ, item, type(item), entry)
)
elif typ in frozenset(['C', 'D']):
tup = entry[arg]

View File

@@ -394,15 +394,15 @@ class PythonParser(GenericASTBuilder):
stmt ::= importstar
stmt ::= importmultiple
importlist2 ::= importlist2 import_as
importlist2 ::= import_as
import_as ::= IMPORT_NAME designator
import_as ::= IMPORT_NAME load_attrs designator
import_as ::= IMPORT_FROM designator
importlist ::= importlist import_as
importlist ::= import_as
import_as ::= IMPORT_NAME designator
import_as ::= IMPORT_NAME load_attrs designator
import_as ::= IMPORT_FROM designator
importstmt ::= LOAD_CONST LOAD_CONST import_as
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist2 POP_TOP
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist POP_TOP
importmultiple ::= LOAD_CONST LOAD_CONST import_as imports_cont
imports_cont ::= imports_cont import_cont

View File

@@ -27,7 +27,7 @@ class Python24Parser(Python25Parser):
# keep positions similar to simplify semantic actions
importstmt ::= filler LOAD_CONST import_as
importfrom ::= filler LOAD_CONST IMPORT_NAME importlist2 POP_TOP
importfrom ::= filler LOAD_CONST IMPORT_NAME importlist POP_TOP
importstar ::= filler LOAD_CONST IMPORT_NAME IMPORT_STAR
importmultiple ::= filler LOAD_CONST import_as imports_cont

View File

@@ -258,7 +258,8 @@ TABLE_DIRECT = {
'kv2': ( '%c: %c', 1, 2 ),
'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ),
'importstmt': ( '%|import %c\n', 2),
'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ),
'importfrom': ( '%|from %[2]{pattr} import %c\n',
(3, 'importlist') ),
'importstar': ( '%|from %[2]{pattr} import *\n', ),
}

View File

@@ -1510,7 +1510,17 @@ class FragmentsWalker(pysource.SourceWalker, object):
arg += 1
elif typ == 'c':
start = len(self.f.getvalue())
self.preorder(node[entry[arg]])
index = entry[arg]
if isinstance(index, tuple):
assert node[index[0]] == index[1], (
"at %s[%d], %s vs %s" % (
node.kind, arg, node[index[0]].kind, index[1])
)
index = index[0]
if isinstance(index, int):
self.preorder(node[index])
finish = len(self.f.getvalue())
# FIXME rocky: figure out how to get this to be table driven

View File

@@ -68,7 +68,10 @@ Python.
# Escapes in the format string are:
#
# %c evaluate the node recursively. Its argument is a single
# integer representing a node index.
# integer or tuple representing a node index.
# If a tuple is given, the first item is the node index while
# the second item is a string giving the node/noterminal name.
# This name will be checked at runtime against the node type.
#
# %p like %c but sets the operator precedence.
# Its argument then is a tuple indicating the node
@@ -131,7 +134,7 @@ from uncompyle6.semantics.consts import (
LINE_LENGTH, RETURN_LOCALS, NONE, RETURN_NONE, PASS,
ASSIGN_DOC_STRING, NAME_MODULE, TAB,
INDENT_PER_LEVEL, TABLE_R, TABLE_DIRECT, MAP_DIRECT,
MAP, PRECEDENCE, ASSIGN_TUPLE_PARAM, escape, maxint, minint)
MAP, PRECEDENCE, ASSIGN_TUPLE_PARAM, escape, minint)
from uncompyle6.show import (
@@ -278,47 +281,39 @@ class SourceWalker(GenericASTTraversal, object):
'DELETE_DEREF': ( '%{pattr}', 0 ),
})
if version < 2.0:
TABLE_DIRECT.update({
'importlist': ( '%C', (0, maxint, ', ') ),
})
else:
TABLE_DIRECT.update({
'importlist2': ( '%C', (0, maxint, ', ') ),
})
if version <= 2.4:
if version == 2.3:
TABLE_DIRECT.update({
'if1_stmt': ( '%|if 1\n%+%c%-', 5 )
})
global NAME_MODULE
NAME_MODULE = AST('stmt',
[ AST('assign',
[ AST('expr',
[Token('LOAD_GLOBAL', pattr='__name__',
offset=0, has_arg=True)]),
AST('designator',
[ Token('STORE_NAME', pattr='__module__',
offset=3, has_arg=True)])
])])
pass
if version <= 2.3:
if version <= 2.4:
if version == 2.3:
TABLE_DIRECT.update({
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 4 )
'if1_stmt': ( '%|if 1\n%+%c%-', 5 )
})
elif version >= 2.5:
########################
# Import style for 2.5+
########################
TABLE_DIRECT.update({
'importmultiple': ( '%|import %c%c\n', 2, 3 ),
'import_cont' : ( ', %c', 2 ),
# With/as is allowed as "from future" thing in 2.5
'withstmt': ( '%|with %c:\n%+%c%-', 0, 3),
'withasstmt': ( '%|with %c as %c:\n%+%c%-', 0, 2, 3),
})
global NAME_MODULE
NAME_MODULE = AST('stmt',
[ AST('assign',
[ AST('expr',
[Token('LOAD_GLOBAL', pattr='__name__',
offset=0, has_arg=True)]),
AST('designator',
[ Token('STORE_NAME', pattr='__module__',
offset=3, has_arg=True)])
])])
pass
if version <= 2.3:
TABLE_DIRECT.update({
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 4 )
})
elif version >= 2.5:
########################
# Import style for 2.5+
########################
TABLE_DIRECT.update({
'importmultiple': ( '%|import %c%c\n', 2, 3 ),
'import_cont' : ( ', %c', 2 ),
# With/as is allowed as "from future" thing in 2.5
'withstmt': ( '%|with %c:\n%+%c%-', 0, 3),
'withasstmt': ( '%|with %c as %c:\n%+%c%-', 0, 2, 3),
})
########################################
# Python 2.6+
@@ -1864,8 +1859,15 @@ class SourceWalker(GenericASTTraversal, object):
node[0].attr == 1):
self.write(',')
elif typ == 'c':
entry_node = node[entry[arg]]
self.preorder(entry_node)
index = entry[arg]
if isinstance(index, tuple):
assert node[index[0]] == index[1], (
"at %s[%d], %s vs %s" % (
node.kind, arg, node[index[0]].kind, index[1])
)
index = index[0]
if isinstance(index, int):
self.preorder(node[index])
arg += 1
elif typ == 'p':
p = self.prec