Traductor e intérprete del lenguaje CL 1.23
|
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 }