if self._table.name == "top": return "<{0}SymbolTable for module {1}>".format(kind, self._filename) else: return "<{0}SymbolTable for {1} in {2}>".format(kind, self._table.name, self._filename)
def get_type(self): if self._table.type == _symtable.TYPE_MODULE: return "module" if self._table.type == _symtable.TYPE_FUNCTION: return "function" if self._table.type == _symtable.TYPE_CLASS: return "class" assert self._table.type in (1, 2, 3), \ "unexpected type: {0}".format(self._table.type)
def get_methods(self): if self.__methods is None: d = {} for st in self._table.children: d[st.name] = 1 self.__methods = tuple(d) return self.__methods
def is_global(self): """Return *True* if the sysmbol is global. """ return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) or (self.__module_scope and self.__flags & DEF_BOUND))
def is_local(self): """Return *True* if the symbol is local. """ return bool(self.__scope in (LOCAL, CELL) or (self.__module_scope and self.__flags & DEF_BOUND))
def is_namespace(self): """Returns true if name binding introduces new namespace.
If the name is used as the target of a function or class statement, this will be true.
Note that a single name can be bound to multiple objects. If is_namespace() is true, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace. """ return bool(self.__namespaces)
def get_namespaces(self): """Return a list of namespaces bound to this name""" return self.__namespaces
def get_namespace(self): """Returns the single namespace bound to this name.
Raises ValueError if the name is bound to multiple namespaces. """ if len(self.__namespaces) != 1: raise ValueError("name is bound to multiple namespaces") return self.__namespaces[0]
if __name__ == "__main__": import os, sys with open(sys.argv[0]) as f: src = f.read() mod = symtable(src, os.path.split(sys.argv[0])[1], "exec") for ident in mod.get_identifiers(): info = mod.lookup(ident) print(info, info.is_local(), info.is_namespace())