Traductor e intérprete del lenguaje CL 1.23
SymTab.java
Go to the documentation of this file.
00001 
00029 import java.util.Vector;
00030 import java.util.Map;
00031 import java.util.HashMap;
00032 
00033 
00038 enum SymbolClass {
00040     UNKNOWN_CLASS,
00042     VAR_LOCAL,
00044     PARAM_VALOR,
00046     PARAM_REFER,
00048     PROCEDURE,
00050     FUNCTION
00051 }
00052 
00053 
00058 enum SymTabMode {
00061     MODE_UNDEFINED,
00065     MODE_BUILDING,
00069     MODE_REVISITING
00070 }
00071 
00072 
00079 class InfoSym {
00080 
00081     // Numero de linea y columna donde fue declarado
00085     private int line;
00086 
00090     private int coln;
00091 
00092     // Atributos usados en TypeCheck y en CodeGen
00096     private SymbolClass clas;
00097 
00103     private TypeTree type;
00104 
00105     // Atributos establecidos, y usados, solo en CodeGen
00111     private int offset;
00112 
00117     private String label;
00118 
00126     InfoSym(int l, int c, SymbolClass cl, TypeTree t) {
00127         line = l;
00128         coln = c;
00129         clas = cl;
00130         type = t;
00131     }
00132 
00137     InfoSym(InfoSym s) {
00138         line = s.line;
00139         coln = s.coln;
00140         clas = s.clas;
00141         type = s.type;
00142     }
00143 
00149     int getLine() {
00150         return line;
00151     }
00152 
00158     int getColumn() {
00159         return coln;
00160     }
00161 
00166     SymbolClass getClas() {
00167         return clas;
00168     }
00169 
00174     TypeTree getTypeTree() {
00175         return type;
00176     }
00177 
00183     void setTypeTree(TypeTree t) {
00184         type = t;
00185     }
00186 
00193     int getIdentOffset() {
00194         return offset;
00195     }
00196 
00203     void setIdentOffset(int n) {
00204         offset = n;
00205     }
00206 
00215     String getIdentLabel() {
00216         return label;
00217     }
00218 
00227     void setIdentLabel(String s) {
00228         label = s;
00229     }
00230 
00235     static private String toStringSymbolClass(SymbolClass sc) {
00236         switch (sc) {
00237         case VAR_LOCAL:
00238             return "VAR_LOCAL";
00239         case PARAM_VALOR:
00240             return "PARAM_VALOR";
00241         case PARAM_REFER:
00242             return "PARAM_REFER";
00243         case PROCEDURE:
00244             return "PROCEDURE";
00245         case FUNCTION:
00246             return "FUNCTION";
00247         default:
00248             return "UNKNOWN_SYMBOL_CLASS";
00249         }
00250     }
00251 
00261     String toString(SymTabMode mode) {
00262         StringBuffer sb = new StringBuffer();
00263         sb.append("line: " + line + " coln: " + coln);
00264         sb.append("  class: " + toStringSymbolClass(clas));
00265         sb.append("  type: " + type.toStringTree());
00266         if (mode == SymTabMode.MODE_REVISITING) {  // En CodeGen
00267             switch (clas) {
00268             case VAR_LOCAL:
00269             case PARAM_VALOR:
00270             case PARAM_REFER:
00271                 sb.append("  offset: " + offset);
00272                 break;
00273             case PROCEDURE:
00274             case FUNCTION:
00275                 sb.append("  label: " +  label);
00276                 break;
00277             }
00278         }
00279         return sb.toString();
00280     }
00281 
00282 }
00283 
00284 
00293 final class OneScope {
00294 
00296     private String name;
00297 
00306     Map<String, InfoSym> table;
00307 
00317     Vector<String> orderedSymbols;
00318 
00322     OneScope(String s) {
00323         name = s;
00324         table = new HashMap<String, InfoSym>();
00325         orderedSymbols = new Vector<String>();
00326     }
00327 
00331     String getScopeName() {
00332         return name;
00333     }
00334 
00344     String toString(SymTabMode mode) {
00345         StringBuffer sb = new StringBuffer();
00346         sb.append("scopeName: " + name + " \n");
00347         // Escribe los simbolos ordenados por orden de insercion
00348         for (int i = 0; i < orderedSymbols.size(); i++) {
00349             sb.append("    '" + orderedSymbols.elementAt(i) + "'\t[");
00350             sb.append(table.get(orderedSymbols.elementAt(i)).toString(mode));
00351             sb.append("]\n");    
00352         }
00353         return sb.toString();
00354     }
00355 }
00356 
00357 
00374 final class SymTab {
00375 
00380     private Vector<OneScope> tablesHistory;
00381 
00386     private Vector<Integer> tableIndexStack;
00387 
00393     private SymTabMode mode;
00394 
00398     private int nextSavedInHistory;
00399 
00402     SymTab() {
00403         tablesHistory = new Vector<OneScope>();
00404         tableIndexStack = new Vector<Integer>();
00405         mode = SymTabMode.MODE_UNDEFINED;
00406     }
00407 
00413     void initNewSymTab() {
00414         tablesHistory.removeAllElements();
00415         tableIndexStack.removeAllElements();
00416         mode = SymTabMode.MODE_BUILDING;
00417     }
00418 
00426     void initSavedSymTab() {
00427         if (mode != SymTabMode.MODE_BUILDING) {
00428             System.err.println("Symbol Stack Error: initSavedSymTab. No previous 'building' mode detected.");
00429             return;
00430         }
00431         tableIndexStack.removeAllElements();
00432         mode = SymTabMode.MODE_REVISITING;
00433         nextSavedInHistory = 0;
00434     }
00435 
00448     void pushScope(String s) {
00449         if (mode == SymTabMode.MODE_BUILDING) {
00450             // Empila una nueva tabla de simbolos en modo BUILDING:
00451             // la nueva tabla esta completamente vacia y la informacion
00452             // que pongamos sera conservada para cuando usemos la pila
00453             // de tablas en modo REVISITING
00454             tablesHistory.add(new OneScope(getFullName(s)));
00455             tableIndexStack.add(tablesHistory.size() - 1);
00456         } else if (mode == SymTabMode.MODE_REVISITING) {
00457             // Empila una nueva tabla de simbolos en modo REVISITING:
00458             // la tabla que llevamos a la cima de la pila es la siguiente
00459             // del historico de tablas salvadas en modo BUILDING
00460             if (tablesHistory.isEmpty() || nextSavedInHistory >= tablesHistory.size()) {
00461                 System.err.println("Symbol Stack Error: pushScope. No more saved symbol table.");
00462                 return;
00463             }
00464             if (!(s.equals("")) && !(tablesHistory.elementAt(nextSavedInHistory).getScopeName().equals(getFullName(s)))) {
00465                 System.err.println("Symbol Stack Error: pushScope. Error in symbol table scope name (" + s + ").");
00466                 return;
00467             }
00468             tableIndexStack.add(nextSavedInHistory);
00469             nextSavedInHistory++;
00470         } else {
00471             System.err.println("Symbol Stack Error: pushScope. Current mode is 'undefined'.");
00472         }
00473     }
00474 
00485     void popScope() {
00486         if (tableIndexStack.isEmpty()) {
00487             System.err.println("Symbol Stack Error: popScope. Symbol table stack is empty.");
00488             return;
00489         }
00490         if (mode == SymTabMode.MODE_BUILDING) {
00491             // "Desempila pero salva" una tabla de simbolos en modo BUILDING:
00492             // la tabla que quitamos de la cima de la pila no es destruida,
00493             // sino que la guardamos en el 'historial' para cuando usemos
00494             // la pila de tablas en modo REVISITING
00495             tableIndexStack.removeElementAt(tableIndexStack.size() - 1);
00496         } else if (mode == SymTabMode.MODE_REVISITING) {
00497             // "Desempila y elimina" una tabla de simbolos en modo REVISITING:
00498             // la tabla que quitamos de la cima de la pila es completamente
00499             // eliminada
00500             tablesHistory.setElementAt(null, tableIndexStack.lastElement());
00501             tableIndexStack.removeElementAt(tableIndexStack.size() - 1);
00502         } else {
00503             System.err.println("Symbol Stack Error: pushScope. Current mode is 'undefined'.");
00504         }
00505     }
00506 
00518     private void insertSymbol(String s, int l, int c, SymbolClass sc, TypeTree t) {
00519         if (tableIndexStack.isEmpty()) {
00520             System.err.println("Symbol Table Error: insertSymbol '" + s + "'. Symbol table stack is empty");
00521         } else {
00522             if (tablesHistory.elementAt(tableIndexStack.lastElement()).table.containsKey(s)) {
00523                 System.err.println("Symbol Table Error: insertSymbol '" + s + "'. Already declared in the current scope.");
00524             } else {
00525                 tablesHistory.elementAt(tableIndexStack.lastElement()).table.put(s, new InfoSym(l, c, sc, t));
00526                 tablesHistory.elementAt(tableIndexStack.lastElement()).orderedSymbols.add(s);
00527             }
00528         }
00529     }
00530 
00541     void insertSymbol(CL_AST id, SymbolClass sc, TypeTree t) {
00542         insertSymbol(id.getText(), id.getLine(), id.getCharPositionInLine(), sc, t);
00543     }
00544 
00561     final class search_return extends InfoSym {
00564         private int levels;
00565 
00570         search_return(InfoSym info, int lev) {
00571             super(info);
00572             levels = lev;
00573         }
00574 
00579         int getLevelsDiff( ) {
00580             return levels;
00581         }
00582     }
00583 
00602     search_return searchSymbol(String s) {
00603         if (tableIndexStack.isEmpty()) {
00604             System.err.println("Symbol Table Error: searchSymbol '" + s + "'. Symbol table stack is empty.");
00605             return null;
00606         } else {
00607             int dl = 0;
00608             for (int i = tableIndexStack.size() - 1; i >= 0; i--) {
00609                 int n = tableIndexStack.elementAt(i);
00610                 if (tablesHistory.elementAt(n).table.containsKey(s)) {
00611                     return new search_return(tablesHistory.elementAt(n).table.get(s), dl);
00612                 }
00613                 dl++;
00614             }
00615             return null;
00616         }
00617     }
00618 
00628     search_return searchSymbolCurrScope(String s) {
00629         if (tableIndexStack.isEmpty()) {
00630             System.err.println("Symbol Table Error: searchSymbolCurrScope '" + s + "'. Symbol table stack is empty.");
00631             return null;
00632         } else {
00633             int n = tableIndexStack.lastElement();
00634             if (tablesHistory.elementAt(n).table.containsKey(s)) {
00635                 return new search_return(tablesHistory.elementAt(n).table.get(s), 0);
00636             }
00637             return null;
00638         }
00639     }
00640 
00657     search_return searchSymbolInScopeLevel(String s, int l) {
00658         if (l > tableIndexStack.size()) {
00659             System.err.println("Symbol Table Error: searchSymbolInScopeLevel '" + s + "'. Symbol table stack has only " + tableIndexStack.size() + " levels ('" + l + "' is greater.");
00660             return null;
00661         } else {
00662             int n = tableIndexStack.elementAt(l - 1);
00663             if (tablesHistory.elementAt(n).table.containsKey(s)) {
00664                 return new search_return(tablesHistory.elementAt(n).table.get(s), tableIndexStack.size() - l);
00665             }
00666             return null;
00667         }
00668     }
00669 
00682     String getFullPath(String s) {
00683         if (getStackDepth() > 0) {
00684             search_return ret = searchSymbol(s);
00685             if (ret == null) {
00686                 return "";
00687             }
00688             int difn = ret.getLevelsDiff();
00689             int index = tableIndexStack.elementAt(tableIndexStack.size() - 1 - difn);
00690             return tablesHistory.elementAt(index).getScopeName();
00691         } else {
00692             return "";
00693         }
00694     }
00695 
00721     String getFullName(String s) {
00722         String fn;
00723         if (getStackDepth() > 0) {
00724             search_return ret = searchSymbol(s);
00725             if (ret == null) {
00726                 return "";
00727             }
00728             int difn = ret.getLevelsDiff();
00729             int index = tableIndexStack.elementAt(tableIndexStack.size() - 1 - difn);
00730             if (ret.getClas() == SymbolClass.PROCEDURE ||
00731                 ret.getClas() == SymbolClass.FUNCTION) {
00732                 fn = tablesHistory.elementAt(index).getScopeName() + "_" + s;
00733             } else {
00734                 fn = tablesHistory.elementAt(index).getScopeName() + ":" + s;
00735             }
00736             return fn;
00737         } else {
00738             return s;
00739         }
00740     }
00741 
00742     // Metodos utilizados en el recorrido ordenado de los simbolos
00743     // de la tabla que se encuentre en la cima de la pila
00751     int topSymbolsNumber() {
00752         if (tableIndexStack.isEmpty()) {
00753             System.err.println("Symbol Table Error: topSymbolsNumber. Symbol table stack is empty.");
00754             return -1;
00755         }
00756         return tablesHistory.elementAt(tableIndexStack.lastElement()).table.size();
00757     }
00758 
00769     String getTopSymbolName(int i) {
00770         if (tableIndexStack.isEmpty()) {
00771             System.err.println("Symbol Table Error: getTopSymbolName. Symbol table stack is empty.");
00772             return "";
00773         }
00774         if (i < 0 || i >= tablesHistory.elementAt(tableIndexStack.lastElement()).orderedSymbols.size()) {
00775             System.err.println("Symbol Table Error: getTopSymbolName. Inexistent symbol number '" + i + "'.");
00776             return "";
00777         }
00778         return tablesHistory.elementAt(tableIndexStack.lastElement()).orderedSymbols.elementAt(i);
00779     }
00780 
00792     InfoSym getTopSymbolInfoPtr(int i) {
00793         if (tableIndexStack.isEmpty()) {
00794             System.err.println("Symbol Table Error: getTopSymbolInfoSym. Symbol table stack is empty.");
00795             return null;
00796         }
00797         if (i < 0 || i >= tablesHistory.elementAt(tableIndexStack.lastElement()).orderedSymbols.size()) {
00798             System.err.println("Symbol Table Error: getTopSymbolInfoSym. inexistent symbol number '" + i + "'.");
00799             return null;
00800         }
00801         String s = tablesHistory.elementAt(tableIndexStack.lastElement()).orderedSymbols.elementAt(i);
00802         return tablesHistory.elementAt(tableIndexStack.lastElement()).table.get(s);
00803     }
00804 
00809     int getStackDepth() {
00810         return tableIndexStack.size();
00811     }
00812 
00826     public String toString() {
00827         StringBuffer sb = new StringBuffer();
00828         sb.append("\n");
00829         sb.append("---------------- Symbol Table Stack: top -------------------\n");
00830         for (int i = tableIndexStack.size() - 1; i >= 0; i--) {
00831             int n = tableIndexStack.elementAt(i);
00832             sb.append(tablesHistory.elementAt(n).toString(mode));
00833             if (i > 0) {
00834                 sb.append("--------------------------------------------------------\n");
00835             }
00836         }
00837         sb.append("---------------- Symbol Table Stack: bottom ----------------\n");
00838         return sb.toString();
00839     }
00840 
00841 }
 All Classes Files Functions Variables Enumerations