![]() | ![]() | ![]() | Declaration Descriptors |
Declaration descriptors are more complex than identifier descriptors. Depending on the type of declaration involved ( a type definition or a function definition or a variable 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 is shown in figure *.
/* This union describes the type of all declaration descriptors */
typedef union dcldesc {
struct unkdesc unk;
struct funcdesc func;
struct vardesc unkvar;
struct vardesc var;
struct formaldesc formal;
struct fielddesc field;
struct unktypedesc unktype;
struct arraydesc array;
struct structdesc structure;
} decldesc;
While many distinct structure
types are used as declaration descriptors they share several
common fields. The declarations of these common fields
is grouped in a #define
named COMMONFIELDS
.
This #define
is
used to include the fields in each of the distinct structure
type definitions. As in the syntax tree definitions, all declaration
descriptors contain a common type
field used to determine the
actual format of a member of the union type. The value of this type
field will be an element of the enumerated type decltype
.
Also, 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 declarations of COMMONFIELDS
,
decltype
and unkdesc
are shown in figure *.
/* Enumeration type used to label the various type of declaration */
/* descriptors that can occur in the symbol table. */
typedef enum {
funcdecl, /* function declarations */
vardecl, /* global and local variables */
formaldecl, /* Formal parameter names */
fielddecl, /* Component names of struct type */
arraydecl, /* Type names for array types */
structdecl, /* Type names for struct types */
integertype /* Label for pseudo-declaration of integer */
} decltype;
/* All declaration descriptors contain the following components */
/* (although structure 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 declaration occurred. */
union dcldesc *levellink; /* list of declarations 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
};
The first of the common fields is the type
field which holds an
element of the enumeration type decltype
.
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.
The next two common fields are not used in all declaration
descriptors. In particular, they are not used in descriptors for
structure 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.
There are many different kinds of declaration descriptors, but
they all fall within three main groups. While all descriptors
share the COMMONFIELDS
, descriptors within each group
share additional features.
![]() | ![]() | ![]() | Declaration Descriptors |