fparser Reference Guide  0.0.14
fparser.two.symbol_table.SymbolTable Class Reference

Public Member Functions

def __init__ (self, name, parent=None, checking_enabled=False)
 
def __str__ (self)
 
def add_data_symbol (self, name, primitive_type)
 
def add_use_symbols (self, name, only_list=None, rename_list=None)
 
def lookup (self, name)
 
def name (self)
 
def parent (self)
 
def parent (self, value)
 
def add_child (self, child)
 
def del_child (self, name)
 
def children (self)
 
def root (self)
 

Public Attributes

 parent
 

Static Public Attributes

 Symbol
 

Detailed Description

Class implementing a single symbol table.

Since this functionality is not yet fully mature, checks that new symbols
don't clash with existing symbols are disabled by default.
Once #201 is complete it is planned to switch this so that the checks
are instead enabled by default.

:param str name: the name of this scope. Will be the name of the \
                 associated module or routine.
:param parent: the symbol table within which this one is nested (if any).
:type parent: :py:class:`fparser.two.symbol_table.SymbolTable.Symbol`
:param bool checking_enabled: whether or not validity checks are \
    performed for symbols added to the table.

Definition at line 493 of file symbol_table.py.

Member Function Documentation

◆ add_child()

def fparser.two.symbol_table.SymbolTable.add_child (   self,
  child 
)
Adds a child symbol table (scoping region nested within this one).

:param child: the nested symbol table.
:type child: :py:class:`fparser.two.symbol_table.SymbolTable`

:raises TypeError: if the supplied child is not a SymbolTable.

Definition at line 680 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._children.

680  def add_child(self, child):
681  """
682  Adds a child symbol table (scoping region nested within this one).
683 
684  :param child: the nested symbol table.
685  :type child: :py:class:`fparser.two.symbol_table.SymbolTable`
686 
687  :raises TypeError: if the supplied child is not a SymbolTable.
688 
689  """
690  if not isinstance(child, SymbolTable):
691  raise TypeError(
692  f"Expected a SymbolTable instance but got '{type(child).__name__}'"
693  )
694  self._children.append(child)
695 

◆ add_data_symbol()

def fparser.two.symbol_table.SymbolTable.add_data_symbol (   self,
  name,
  primitive_type 
)
Creates a new Symbol with the specified properties and adds it to
the symbol table. The supplied name is converted to lower case.

TODO #201 add support for other symbol properties (kind, shape
and visibility).

:param str name: the name of the symbol.
:param str primitive_type: the primitive type of the symbol.

:raises TypeError: if any of the supplied parameters are of the \
           wrong type.
:raises SymbolTableError: if the symbol table already contains an
                  entry with the supplied name.

Definition at line 542 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._checking_enabled, fparser.two.symbol_table.SymbolTable._data_symbols, and fparser.two.symbol_table.SymbolTable._modules.

542  def add_data_symbol(self, name, primitive_type):
543  """
544  Creates a new Symbol with the specified properties and adds it to
545  the symbol table. The supplied name is converted to lower case.
546 
547  TODO #201 add support for other symbol properties (kind, shape
548  and visibility).
549 
550  :param str name: the name of the symbol.
551  :param str primitive_type: the primitive type of the symbol.
552 
553  :raises TypeError: if any of the supplied parameters are of the \
554  wrong type.
555  :raises SymbolTableError: if the symbol table already contains an
556  entry with the supplied name.
557  """
558  if not isinstance(name, str):
559  raise TypeError(
560  f"The name of the symbol must be a str but got "
561  f"'{type(name).__name__}'"
562  )
563  # TODO #201 use an enumeration for the primitive type
564  if not isinstance(primitive_type, str):
565  raise TypeError(
566  f"The primitive type of the symbol must be specified as a str "
567  f"but got '{type(primitive_type).__name__}'"
568  )
569  lname = name.lower()
570 
571  if self._checking_enabled:
572  if lname in self._data_symbols:
573  raise SymbolTableError(
574  f"Symbol table already contains a symbol for"
575  f" a variable with name '{name}'"
576  )
577  if lname in self._modules:
578  raise SymbolTableError(
579  f"Symbol table already contains a use of a "
580  f"module with name '{name}'"
581  )
582  for mod_name, mod in self._modules.items():
583  if mod.symbol_names and lname in mod.symbol_names:
584  raise SymbolTableError(
585  f"Symbol table already contains a use of a symbol "
586  f"named '{name}' from module '{mod_name}'"
587  )
588 
589  self._data_symbols[lname] = SymbolTable.Symbol(lname, primitive_type.lower())
590 
def add_data_symbol(self, name, primitive_type)

◆ add_use_symbols()

def fparser.two.symbol_table.SymbolTable.add_use_symbols (   self,
  name,
  only_list = None,
  rename_list = None 
)
Creates an entry in the table for the USE of a module with the supplied
name. If no `only_list` is supplied then this USE represents a wildcard
import of all public symbols in the named module. If the USE statement
has an ONLY clause but without any named symbols then `only_list`
should be an empty list.

A USE can also have one or more rename entries *without* an only list.

:param str name: the name of the module being imported via a USE. Not \
    case sensitive.
:param only_list: if there is an 'only:' clause on the USE statement \
    then this contains a list of tuples, each holding the local name \
    of the symbol and its name in the module from which it is \
    imported. These names are case insensitive.
:type only_list: Optional[List[Tuple[str, str | NoneType]]]
:param rename_list: a list of symbols that are renamed from the scope \
    being imported. Each entry is a tuple containing the name in the \
    local scope and the corresponding name in the module from which it\
    is imported. These names are case insensitive.
:type rename_list: Optional[List[Tuple[str, str]]]

Definition at line 591 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._modules.

591  def add_use_symbols(self, name, only_list=None, rename_list=None):
592  """
593  Creates an entry in the table for the USE of a module with the supplied
594  name. If no `only_list` is supplied then this USE represents a wildcard
595  import of all public symbols in the named module. If the USE statement
596  has an ONLY clause but without any named symbols then `only_list`
597  should be an empty list.
598 
599  A USE can also have one or more rename entries *without* an only list.
600 
601  :param str name: the name of the module being imported via a USE. Not \
602  case sensitive.
603  :param only_list: if there is an 'only:' clause on the USE statement \
604  then this contains a list of tuples, each holding the local name \
605  of the symbol and its name in the module from which it is \
606  imported. These names are case insensitive.
607  :type only_list: Optional[List[Tuple[str, str | NoneType]]]
608  :param rename_list: a list of symbols that are renamed from the scope \
609  being imported. Each entry is a tuple containing the name in the \
610  local scope and the corresponding name in the module from which it\
611  is imported. These names are case insensitive.
612  :type rename_list: Optional[List[Tuple[str, str]]]
613 
614  """
615  use = ModuleUse(name, only_list, rename_list)
616 
617  if use.name in self._modules:
618  # The same module can appear in more than one use statement
619  # in Fortran.
620  self._modules[use.name].update(use)
621  else:
622  self._modules[use.name] = use
623 
def add_use_symbols(self, name, only_list=None, rename_list=None)

◆ children()

def fparser.two.symbol_table.SymbolTable.children (   self)
:returns: the child (nested) symbol tables, if any.
:rtype: list of :py:class:`fparser.two.symbol_table.SymbolTable`

Definition at line 717 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._children.

717  def children(self):
718  """
719  :returns: the child (nested) symbol tables, if any.
720  :rtype: list of :py:class:`fparser.two.symbol_table.SymbolTable`
721  """
722  return self._children
723 

◆ del_child()

def fparser.two.symbol_table.SymbolTable.del_child (   self,
  name 
)
Removes the named symbol table.

:param str name: the name of the child symbol table to delete (not \
         case sensitive).

:raises KeyError: if the named table is not a child of this one.

Definition at line 696 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._children.

696  def del_child(self, name):
697  """
698  Removes the named symbol table.
699 
700  :param str name: the name of the child symbol table to delete (not \
701  case sensitive).
702 
703  :raises KeyError: if the named table is not a child of this one.
704 
705  """
706  lname = name.lower()
707  for child in self._children:
708  if child.name == lname:
709  self._children.remove(child)
710  break
711  else:
712  raise KeyError(
713  f"Symbol table '{self.name}' does not contain a table named '{name}'"
714  )
715 

◆ lookup()

def fparser.two.symbol_table.SymbolTable.lookup (   self,
  name 
)
Lookup the symbol with the supplied name.

:param str name: the name of the symbol to lookup (not case sensitive).

:returns: the named symbol.
:rtype: :py:class:`fparser.two.symbol_table.SymbolTable.Symbol`

:raises KeyError: if the named symbol cannot be found in this or any \
          parent scope.

Definition at line 624 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._data_symbols, fparser.common.base_classes.Variable.parent, fparser.two.symbol_table.SymbolTable.parent, and fparser.common.base_classes.Statement.parent.

624  def lookup(self, name):
625  """
626  Lookup the symbol with the supplied name.
627 
628  :param str name: the name of the symbol to lookup (not case sensitive).
629 
630  :returns: the named symbol.
631  :rtype: :py:class:`fparser.two.symbol_table.SymbolTable.Symbol`
632 
633  :raises KeyError: if the named symbol cannot be found in this or any \
634  parent scope.
635  """
636  # Fortran is not case sensitive so convert input to lowercase.
637  lname = name.lower()
638  if lname in self._data_symbols:
639  return self._data_symbols[lname]
640  # No match in this scope - search in parent scope (if any)
641  if self.parent:
642  return self.parent.lookup(lname)
643  raise KeyError(f"Failed to find symbol named '{lname}'")
644 

◆ name()

def fparser.two.symbol_table.SymbolTable.name (   self)
:returns: the name of this symbol table (scoping region).
:rtype: str

Definition at line 646 of file symbol_table.py.

References fparser.two.symbol_table.ModuleUse._name, and fparser.two.symbol_table.SymbolTable._name.

646  def name(self):
647  """
648  :returns: the name of this symbol table (scoping region).
649  :rtype: str
650  """
651  return self._name
652 

◆ parent() [1/2]

def fparser.two.symbol_table.SymbolTable.parent (   self)
:returns: the parent symbol table (scoping region) that contains \
  this one (if any).
:rtype: :py:class:`fparser.two.symbol_table.SymbolTable` or NoneType

Definition at line 654 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._parent.

654  def parent(self):
655  """
656  :returns: the parent symbol table (scoping region) that contains \
657  this one (if any).
658  :rtype: :py:class:`fparser.two.symbol_table.SymbolTable` or NoneType
659  """
660  return self._parent
661 
Here is the caller graph for this function:

◆ parent() [2/2]

def fparser.two.symbol_table.SymbolTable.parent (   self,
  value 
)
Set the parent scope for this symbol table.

:param value: the parent symbol table.
:type value: :py:class:`fparser.two.symbol_table.SymbolTable`

:raises TypeError: if the supplied value is not None or a SymbolTable.

Definition at line 663 of file symbol_table.py.

References fparser.two.symbol_table.SymbolTable._parent.

663  def parent(self, value):
664  """
665  Set the parent scope for this symbol table.
666 
667  :param value: the parent symbol table.
668  :type value: :py:class:`fparser.two.symbol_table.SymbolTable`
669 
670  :raises TypeError: if the supplied value is not None or a SymbolTable.
671 
672  """
673  if value is not None and not isinstance(value, SymbolTable):
674  raise TypeError(
675  f"Unless it is None, the parent of a SymbolTable must also be "
676  f"a SymbolTable but got '{type(value).__name__}'"
677  )
678  self._parent = value
679 
Here is the caller graph for this function:

◆ root()

def fparser.two.symbol_table.SymbolTable.root (   self)
:returns: the top-level symbol table that contains the current \
  scoping region (symbol table).
:rtype: :py:class:`fparser.two.symbol_table.SymbolTable`

Definition at line 725 of file symbol_table.py.

725  def root(self):
726  """
727  :returns: the top-level symbol table that contains the current \
728  scoping region (symbol table).
729  :rtype: :py:class:`fparser.two.symbol_table.SymbolTable`
730 
731  """
732  current = self
733  while current.parent:
734  current = current.parent
735  return current
736 
737 
738 #: The single, global container for all symbol tables constructed while
739 #: parsing.

The documentation for this class was generated from the following file: