001: /*************************************************************************
002: * *
003: * 1) This source code file, in unmodified form, and compiled classes *
004: * derived from it can be used and distributed without restriction, *
005: * including for commercial use. (Attribution is not required *
006: * but is appreciated.) *
007: * *
008: * 2) Modified versions of this file can be made and distributed *
009: * provided: the modified versions are put into a Java package *
010: * different from the original package, edu.hws; modified *
011: * versions are distributed under the same terms as the original; *
012: * and the modifications are documented in comments. (Modification *
013: * here does not include simply making subclasses that belong to *
014: * a package other than edu.hws, which can be done without any *
015: * restriction.) *
016: * *
017: * David J. Eck *
018: * Department of Mathematics and Computer Science *
019: * Hobart and William Smith Colleges *
020: * Geneva, New York 14456, USA *
021: * Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
022: * *
023: *************************************************************************/package edu.hws.jcm.data;
024:
025: import java.util.Hashtable;
026:
027: /**
028: * A symbol table contains MathObjects, associating them
029: * with their names. To support scoping (for example), a symbol
030: * table can have a parent symbol table. If a symbol is not found
031: * in the table itself, the search procedes to its parent.
032: * MathObjects in the parent are hidden by MathObjects of
033: * the same name in a SymbolTable.
034: * Note that a NullPointerException error will occur if an
035: * attempt is made to add a MathObject with a null name to a
036: * SymbolTable.
037: * A MathObject should not be renamed while it is registered
038: * in a SymbolTable.
039: * Note that a Parser has an associated SymbolTable. I expect
040: * SymbolTables to be used only through Parsers.
041: */
042: public class SymbolTable implements java.io.Serializable {
043:
044: private Hashtable symbols; // Objects are stored here and in the parent.
045: private SymbolTable parent; // Parent symbol table, possibly null.
046:
047: /**
048: * Construct a symbol table with null parent.
049: */
050: SymbolTable() {
051: this (null);
052: }
053:
054: /**
055: * Construct a symbol table with specified parent.
056: */
057: SymbolTable(SymbolTable parent) {
058: this .parent = parent;
059: symbols = new Hashtable();
060: }
061:
062: /**
063: * Returns the parent symbol table of this symbol table.
064: */
065: SymbolTable getParent() {
066: return parent;
067: }
068:
069: /**
070: * Look up the object with the given name, if any.
071: * If not found, return null. (If the name is not found
072: * in the HashTable, symbols, the search is delegated to
073: * the parent.) If the name is null, then
074: * null is returned.
075: */
076: synchronized public MathObject get(String name) {
077: if (name == null)
078: return null;
079: Object sym = symbols.get(name);
080: if (sym != null)
081: return (MathObject) sym;
082: else if (parent != null)
083: return parent.get(name);
084: else
085: return null;
086: }
087:
088: /**
089: * Adds sym to the SymbolTable, associating it with its name.
090: */
091: synchronized public void add(MathObject sym) {
092: if (sym == null)
093: throw new NullPointerException(
094: "Can't put a null symbol in SymbolTable.");
095: add(sym.getName(), sym);
096: }
097:
098: /**
099: * Adds the given MathObject, sym, to the symbol table,
100: * associating it with the given name (which is probably
101: * the name of the symbol or that name transformed to lower
102: * case, but it doesn't have to be).
103: * If the same name is already in use in the HashTable
104: * then the new object replaces the current object.
105: * Note that if the name is defined in the parent
106: * symbol table, then the old object is hidden, not
107: * removed from the parent. If sym is null or if
108: * sym's name is null, than a NullPointerException is
109: * thrown.
110: */
111: synchronized public void add(String name, MathObject sym) {
112: if (sym == null)
113: throw new NullPointerException(
114: "Can't put a null symbol in SymbolTable.");
115: else if (name == null)
116: throw new NullPointerException(
117: "Can't put unnamed MathObject in SymbolTable.");
118: symbols.put(name, sym);
119: }
120:
121: /**
122: * Remove the object with the given name from the symbol table,
123: * but NOT from the parent symbol table. No error occurs
124: * if the name is not in the table or if name is null.
125: * If an object of the same name occurs in the parent,
126: * this routine will un-hide it.
127: */
128: synchronized public void remove(String name) {
129: if (name != null)
130: symbols.remove(name);
131: }
132:
133: } // end class SymbolTable
|