[an error occurred while processing this directive]
The topLevel variable is returned by calls to currentLevel(), and also serves as the index for the top of the stack. When enterScope() is called, a new Table is pushed onto the stack. When exitScope() is called, the top Table is popped from the stack.
When a Descriptor is added to the SymbolTable by a call to addDescriptor(), the Descriptor is added to the top Table in the stack.
The level() function checks all tables in Tables in the stack for the target identifier, working from top to bottom. When it locates the identifier, it returns its level.
The descriptorFor() function selects a Table as described in the next subsection. The Descriptor for the identifier is then retrieved from the selected Table.
The cache variables cacheId and cacheLevel can be invalid. This occurs before level() has been called the first time and may occur after a call to exitScope(). This condition is signified by a null value for cacheId. It can be rectified by calling level().
The private function initializeStack() is provided for the initial stack allocation. This function also creates the level 0 Table and pushes it onto the stack.
Since there is no public function for initialization, topLevel is initialized to -1 to indicate that the stack is not yet initialized. Public functions addDescriptor(), currentLevel(), and enterScope() must check topLevel and initialize the stack if it is -1.
System errors can arise from dynamic memory allocation in initializeStack() and reallocation in doubleStackCapacity(). The returned values from C library functions calloc() and realloc() should be checked for null values that indicate memory allocation failure. A null returned value should lead to program termination with an error message that indicates the nature of the problem.
#include "Descriptor.h" #include "Table.h" #include "SymbolTable.h"
Preconditions:
The stack has been initialized.
topLevel = 0
capacity = 4
allocate array for stack with capacity entries (use calloc())
if calloc returns null
terminate the program with a system error message
put a new Table at stack[topLevel]
double capacity
reallocate array for stack with capacity entries (use realloc())
if realloc returns null
terminate the program with a system error message
parameter: char * id
local variable: int currentLevel
cacheId = id
currentLevel = topLevel
while currentLevel >= 0
if id is a key in stack[currentLevel]
break
decrement currentLevel
cacheLevel = currentLevel
return currentLevel
parameter: char * id
if cacheId is null or cacheId is not the same as id
call level(id)
if cacheLevel < 0
terminate the program with a precondition violation error message
return the data from stack[cacheLevel] for key id
parameter: char * id
parameter: Descriptor dscr
if topLevel is -1
initialize the stack
if the stack[topLevel] has an entry whose key is id
terminate the program with a precondition violation error message
add dscr to stack[topLevel] with key id
if topLevel is -1
initialize the stack
return topLevel
if topLevel is -1
initialize the stack
increment topLevel
if topLevel >= capacity
double capacity of stack
put a new Table at stack[topLevel]
if topLevel <= 0
terminate the program with a precondition violation error message
free stack[topLevel]
decrement topLevel
if topLevel < cacheLevel
cacheId = null