package rs.etf.pp1.symboltable;
import rs.etf.pp1.symboltable.concepts.Obj;
import rs.etf.pp1.symboltable.concepts.Scope;
import rs.etf.pp1.symboltable.concepts.Struct;
import rs.etf.pp1.symboltable.visitors.DumpSymbolTableVisitor;
import rs.etf.pp1.symboltable.visitors.SymbolTableVisitor;
/**
* MikroJava tabela simbola
*
* @author ETF
*
*/
public class Tab {
// standardni tipovi
public static final Struct noType = new Struct(Struct.None),
intType = new Struct(Struct.Int), charType = new Struct(Struct.Char),
nullType = new Struct(Struct.Class);
/*
static SymbolDataStructure loc = new HashTableDataStructure();
static {
loc.insertKey(new Obj(Obj.Fld, "x", intType, 0, -1), false);
loc.insertKey(new Obj(Obj.Fld, "y", intType, 1, -1), false);
nullType = new Struct(Struct.Class, null, loc);
}
*/
public static final Obj noObj = new Obj(Obj.Var, "noObj", noType);
public static Obj chrObj, ordObj, lenObj;
public static Scope currentScope; // tekuci opseg
private static int currentLevel; // nivo ugnezdavanja tekuceg opsega
/**
* Inicijalizacija universe opsega, tj. njegovo popunjavanje Obj cvorovima,
* kao sto je izlozeno na vezbama i predavanjima. Razlika je sto se Obj
* cvorovu umecu u hes tabelu.
*/
public static void init() {
Scope universe = currentScope = new Scope(null);
universe.addToLocals(new Obj(Obj.Type, "int", intType));
universe.addToLocals(new Obj(Obj.Type, "char", charType));
universe.addToLocals(new Obj(Obj.Con, "eol", charType, 10, 0));
universe.addToLocals(new Obj(Obj.Con, "null", nullType, 0, 0));
universe.addToLocals(chrObj = new Obj(Obj.Meth, "chr", charType, 0, 1));
{
openScope();
currentScope.addToLocals(new Obj(Obj.Var, "i", intType, 0, 1));
chrObj.setLocals(currentScope.getLocals());
closeScope();
}
universe.addToLocals(ordObj = new Obj(Obj.Meth, "ord", intType, 0, 1));
{
openScope();
currentScope.addToLocals(new Obj(Obj.Var, "ch", charType, 0, 1));
ordObj.setLocals(currentScope.getLocals());
closeScope();
}
universe.addToLocals(lenObj = new Obj(Obj.Meth, "len", intType, 0, 1));
{
openScope();
currentScope.addToLocals(new Obj(Obj.Var, "arr", new Struct(Struct.Array, noType), 0, 1));
lenObj.setLocals(currentScope.getLocals());
closeScope();
}
currentLevel = -1;
}
public static void chainLocalSymbols(Obj outerScopeObj) {
outerScopeObj.setLocals(currentScope.getLocals());
}
public static void chainLocalSymbols(Struct innerClass) {
innerClass.setMembers(currentScope.getLocals());
}
/**
* Otvaranje novog opsega
*/
public static void openScope() {
currentScope = new Scope(currentScope);
currentLevel++;
}
/**
* Zatvaranje opsega
*/
public static void closeScope() {
currentScope = currentScope.getOuter();
currentLevel--;
}
/**
* Pravi se novi Obj cvor sa prosledjenim atributima kind, name i type, pa se
* zatim ubacuje u tabelu simbola. Povratna vrednost: - novostvoreni cvor, ako
* cvor sa tim imenom nije vec postojao u tabeli simbola. - postojeci cvor iz
* tabele simbola, ako je doslo do greske jer smo pokusali da u tabelu simbola
* za opseg ubacimo cvor sa imenom koje vec postoji.
*/
public static Obj insert(int kind, String name, Struct type) {
// create a new Object node with kind, name, type
Obj newObj = new Obj(kind, name, type, 0, ((currentLevel != 0)? 1 : 0));
// append the node to the end of the symbol list
if (!currentScope.addToLocals(newObj)) {
Obj res = currentScope.findSymbol(name);
return (res != null) ? res : noObj;
}
else
return newObj;
}
/**
* U hes tabeli opsega trazi Obj cvor sa imenom name, pocevsi od
* najugnezdenijeg opsega, pa redom kroz opsege na nizim nivoima. Povratna
* vrednost: - pronadjeni Obj cvor, ako je pretrazivanje bilo uspesno. -
* Tab.noObj objekat, ako je pretrazivanje bilo neuspesno.
*/
public static Obj find(String name) {
Obj resultObj = null;
for (Scope s = currentScope; s != null; s = s.getOuter()) {
if (s.getLocals() != null) {
resultObj = s.getLocals().searchKey(name);
if (resultObj != null) break;
}
}
return (resultObj != null) ? resultObj : noObj;
}
public static Scope currentScope() {
return currentScope;
}
public static void dump(SymbolTableVisitor stv) {
System.out.println("=====================SYMBOL TABLE DUMP=========================");
if (stv == null)
stv = new DumpSymbolTableVisitor();
for (Scope s = currentScope; s != null; s = s.getOuter()) {
s.accept(stv);
}
System.out.println(stv.getOutput());
}
/** Stampa sadrzaj tabele simbola. */
public static void dump() {
dump(null);
}
}