/* Copyright (c) 2000 The Regents of the University of California. All rights reserved. Permission to use, copy, modify, and distribute this software for any purpose, without fee, and without written agreement is hereby granted, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ import java.util.Stack; import java.util.Hashtable; /** Implements the symbol table data abstraction. * *

* * In addition to strings, compilers must also determine and manage the * scope of program names. A symbol table is a data structure for * managing scope. Conceptually, a symbol table is just another lookup * table. The key is the symbol (the name) and the result is whatever * information has been associated with that symbol (e.g., the symbol's * type). * *

* * In addition to adding and removing symbols, symbol tables also * support operations for entering and exiting scopes and for checking * whether an identifier is already defined in the current scope. The * lookup operation must also observe the scoping rules of the language; * if there are multiple definitions of identifier x, the * scoping rules determine which definition a lookup of x * returns. In most languages, including Cool, inner definitions hide * outer definitions. Thus, a lookup on x returns the * definition of x from the innermost scope with a * definition of x. * *

* * Cool symbol tables are implemented using Java hashtables. Each * hashtable represents a scope and associates a symbol with some * data. The ``data'' is whatever data the programmer wishes to * associate with each identifier. An example illustrating the use of * symbol tables is in the file SymtabExample.java. * * @see AbstractSymbol * @see SymtabExample * */ class SymbolTable { private Stack tbl; /** Creates an empty symbol table. */ public SymbolTable() { tbl = new Stack(); } /** Enters a new scope. A scope must be entered before anything * can be added to the table. * */ public void enterScope() { tbl.push(new Hashtable()); } /** Exits the most recently entered scope. */ public void exitScope() { if (tbl.empty()) { Utilities.fatalError("existScope: can't remove scope from an empty symbol table."); } tbl.pop(); } /** Adds a new entry to the symbol table. * * @param id the symbol * @param info the data asosciated with id * */ public void addId(AbstractSymbol id, Object info) { if (tbl.empty()) { Utilities.fatalError("addId: can't add a symbol without a scope."); } ((Hashtable)tbl.peek()).put(id, info); } /** * Looks up an item through all scopes of the symbol table. If * found it returns the associated information field, if not it * returns null. * * @param sym the symbol * @return the info associated with sym, or null if not found * */ public Object lookup(AbstractSymbol sym) { if (tbl.empty()) { Utilities.fatalError("lookup: no scope in symbol table."); } // I break the abstraction here a bit by knowing that stack is // really a vector... for (int i = tbl.size() - 1; i >= 0; i--) { Object info = ((Hashtable)tbl.elementAt(i)).get(sym); if (info != null) return info; } return null; } /** * Probes the symbol table. Check the top scope (only) for the * symbol sym. If found, return the information field. * If not return null. * * @param sym the symbol * @return the info associated with sym, or null if not found * */ public Object probe(AbstractSymbol sym) { if (tbl.empty()) { Utilities.fatalError("lookup: no scope in symbol table."); } return ((Hashtable)tbl.peek()).get(sym); } /** Gets the string representation of the symbol table. * * @return the string rep * */ public String toString() { String res = ""; // I break the abstraction here a bit by knowing that stack is // really a vector... for (int i = tbl.size() - 1, j = 0; i >= 0; i--, j++) { res += "Scope " + j + ": " + tbl.elementAt(i) + "\n"; } return res; } }