/**
* The {@link VariableTable} class acts in conjunction with the {@link Variable}
* class. For an introduction as to the nature of this relationship see the
* introduction to {@link Variable}.
*
*/
public class VariableTable implements VariableDereferencer
{
/**
* The current maximum number of elements possible
*/
protected int capacity = 0;
/**
* The current number of elements
*/
protected int size = 0;
/**
* The elements contained in the table
*/
protected VariableReference [] variables;
/**
* The current maximum number of marks possible
*
* @see #mark
*/
protected int marksCapacity = 0;
/**
* The current number of marks
*
* @see #mark
*/
protected int marksSize = 0;
/**
* The set of marks in the table
*
* @see #mark
*/
int[] marks;
/**
* Creates a new empty table with a capacity of 20 elements
*/
public VariableTable()
{
this(20);
}
/**
* Creates a new empty table with a capacity of i elements.
* If i is 0 then the capacity is set to 1.
*/
public VariableTable(int i)
{
capacity = i;
if(capacity == 0)
capacity++;
variables = new VariableReference[capacity];
marksCapacity = 5;
marks = new int [marksCapacity];
}
/**
* Adds a {@link VariableReference} to the table. If there is not room in the table for
* the symbol then (in the fashion of {@link java.util.Vector}) the capacity is
* doubled thereby making space.
*
* @param o reference to be added
*/
public void add(VariableReference v)
{
if(size == capacity)
{
VariableReference[] tempTable = new VariableReference[capacity * 2];
for(int i = 0; i < size; i++)
tempTable[i] = variables[i];
variables = tempTable;
capacity *= 2;
}
variables[size] = v;
size++;
}
/**
* If s
isn't already in the table, a new {@link VariableReference}
* with a name s
and value 0 is added.
*
* @param s name of a variable to add
*/
public void add(String s)
{
if(!isInTable(s))
add(new VariableReference(s, 0));
}
/**
* Assigns value
to the reference of name
. If there is no
* reference of name
in the table then a new one is added with a value of
* value
.
*
* @param name the name of the variable
* @param value the value to set name
equal to
*/
public void assign(String name, int value)
{
boolean assigned = false;
for(int i = 0; i < size && !assigned; i++)
if(variables[i].name.equalsIgnoreCase(name))
{
variables[i].value = value;
assigned = true;
}
if(!assigned)
add(new VariableReference(name, value));
}
/**
* Checks to see if there is a variable with name s
in the table
*
* @return true
if s
is in the table
*/
public boolean isInTable(String s)
{
boolean found = false;
for(int i = 0; i < size && !found; i++)
if(variables[i].name.equalsIgnoreCase(s))
found = true;
return found;
}
/**
* Same as {@link #isInTable}
*
* @return the same as {@link #isInTable}
*/
public boolean exists(String s)
{
return isInTable(s);
}
/**
* Returns the value for the variable with name of name
.
* If name
is not in the table then a
* {@link NotATableElementExcepetion} will be thrown.
*
* @param name variable name to derefernce
*/
public int dereference(String name)
{
for(int i = 0; i < size; i++)
if(variables[i].name.equalsIgnoreCase(name))
return variables[i].value;
return 0;
}
/**
* Places a mark in the table. Marking is a process which allows for the localization
* of variables. When a point in the processing is reached where you wish to localize
* variables place a mark in the table and then when the table is {@link #demark demarked}
* all variables put in since the mark are removed from the table.
*/
public void mark()
{
if(marksSize == marksCapacity)
{
int[] tempMarks = new int[marksCapacity * 2];
for(int i = 0; i < marksSize; i++)
tempMarks[i] = marks[i];
marks = tempMarks;
marksCapacity *= 2;
}
marks[marksSize] = size;
System.out.println("Mark set at " + size);
marksSize++;
}
/**
* Removes all variables from the table added since the last {@link #mark}.
* If there are no marks then the talbe is cleared.
*/
public void demark()
{
if(marksSize <= 0)
size = 0;
else
{
size = marks[marksSize - 1];
marksSize--;
}
}
}