FootnotesTopSyntax Tree OrganizationSymbol Table Details

Symbol Table Details

Now, to complete the discussion of our scheme for representing STApL programs, we must discuss more details of the types used in the symbol table.

As explained in the overview presented above, the symbol table is composed of identifier descriptors and declaration descriptors. Identifier descriptors are actually quite simple. There is one such descriptor for each distinct identifier used in the program.3 A C language structure specification for the type identdesc used to store identifier descriptors is shown in figure *.

 
typedef struct iddesc {
  char *name;               /* The character string for the identifier */
  struct iddesc *hashlink;  /* Link for hash chains used by scanner    */
  union dcldesc *declstack; /* Head pointer for stack of declarations  */
                            /*    in open scopes.                      */
} identdesc;
Declation for Type `identdesc'
 

The name field is just a pointer to the characters that form the identifier. The hashlink field is used to maintain lists of identifier with the same hash value when building the hash table used by the scanner. It will not be of concern to you when doing semantic processing. The declstack component is to be used as a pointer to the head of the linked list representing the stack of declarations of the identifier found in scopes that are still open. The scanner initializes this field to NULL.

    /* Enumeration type used to label the various type of declaration  */
    /* descriptors that can occur in the symbol table.                 */
typedef enum {
  funcdecl,        /* function declarations                   */
  valdecl,         /* names bound by value bindings           */
  formaldecl,      /* Formal parameter names                  */
  listdecl,        /* Type names for list types               */
  recddecl,        /* Type names for record types             */
  fielddecl,       /* Component names of record type          */
  integertype      /* Label for pseudo-declaration of integer */
  } decltype;

    /* All declartion descriptors contain the following components */
    /*(although  record component descriptors don't use them all.) */
#define COMMONFIELDS  \
decltype type;            /* Type of this declaration descriptor        */ \
identdesc *ident;         /* pointer to associated ident. descriptor    */ \
int line;                 /* Line number at which decl. occurred.       */ \
union dcldesc *levellink; /* list of decl.s made at nesting level       */ \
int level;                /* nesting level of this declaration          */ \
union dcldesc * decllink; /* stack of active declarations of this ident */

    /* Generic structure used to access common fields of decl. descriptors. */
struct unkdesc {
   COMMONFIELDS
};
Some Definitions Related to the Type `decldesc'
 

Declaration descriptors are more complex than identifier descriptors. Depending on the type of declaration involved ( a type definition or a function definition or a value declaration, etc.) different structures must be used. Accordingly, as with tree nodes, the type used to describe declaration descriptors is a union type. The C declaration for this union type and the declarations of the record types from which it is formed are shown in figure *. First, however, we must discuss some related definitions shown in figure *.

The most important portion of figure * is the #define for COMMONFIELDS. While many distinct structure types are used as declaration descriptors they all share several common fields. This #define specifies all these fields and is in fact used to include the fields in each of the distinct structure type definitions. As in the syntax tree definitions, a structure type unkdesc is provided to allow one to reference the common fields of a declaration descriptor before the actual type of the descriptor involved can be determined.

The first of the common fields is the type field which holds an element of the enumeration type decltype (whose definition also appears in the figure). The field ident is used by all declaration descriptors to hold a pointer back to the identifier descriptor for the identifier associated with the declaration. The line component is used to hold the line number on which the declaration occurred.

    /* Structure used for value name declatation descriptors.     */
struct valdesc { COMMONFIELDS
   union dcldesc * valtype;     /* decl. descriptor for the value's type */
 };

    /* Stucture used for function declaration descriptors.    */
struct funcdesc { COMMONFIELDS
   union dcldesc * formallist;  /* head of list of this proc's formals. */
   union dcldesc * retntype  ;  /* descriptor for type returned by func */
 };

    /* Structure used for formal parameter declaration descriptors.    */
struct formaldesc { COMMONFIELDS
   union dcldesc * valtype;     /* decl. descriptor for the formal's type */
   union dcldesc * formallink;  /* link for list of func's formals. */
 };

    /* Structure used for list type declaration descriptors.     */
struct listdesc { COMMONFIELDS
   union dcldesc * elmnttype; /* decl. descriptor for list's element type */
 };

    /* Structure used for record type declaration descriptors.      */
struct recorddesc { COMMONFIELDS
 };

    /* Structure used for record field name declartion descriptors.   */
struct fielddesc { COMMONFIELDS
   union dcldesc * hashlink;    /* link pointer for hash chain */
   union dcldesc * comptype;    /* decl. descriptor for component's type */
   union dcldesc * recdtype;    /* decl. descriptor for type to which the */
                                /*       component belong  */
 };

    /* This union describes the type of all declaration descriptors */
typedef union dcldesc {
  struct unkdesc unk;
  struct funcdesc func;
  struct valdesc val;
  struct formaldesc formal;
  struct listdesc list;
  struct recorddesc record;
  struct fielddesc field
} decldesc;
Declarations for type `decldesc'
 

The next two common fields are not used in all declaration descriptors. In particular, they are not used in descriptors for record component names. The first of these two fields is levellink. This is used to link all of the declarations found in an open scope together in a linked list. The second is level which holds the nesting level of the scope in which the declaration occurred.

The last component in COMMONFIELDS is decllink. During declaration processing, this field is used as the "next" pointer for the linked list that is used to implement the stack of declaration descriptors associated with a given identifier descriptor. The head pointers for these stacks are stored in the declstack components of identifier descriptors.

With this understanding of the common fields of all declaration descriptors, we can consider the various kinds of declaration descriptors used. Definitions of structure types for all these different sorts of declaration descriptors are shown in figure *.

These definitions are not complete. Later in the semester we will add additional fields. The fields included at this point are sufficient to enable you to complete this phase and to justify the distinct types of declaration descriptors used.

The six structure types used are:


Computer Science 434
Department of Computer Science
Williams College

FootnotesTopSyntax Tree OrganizationSymbol Table Details