package de.fuberlin.projecta.analysis;
import java.util.List;
import de.fuberlin.commons.parser.ISyntaxTree;
import de.fuberlin.projecta.analysis.ast.AbstractSyntaxTree;
import de.fuberlin.projecta.analysis.ast.Id;
import de.fuberlin.projecta.analysis.ast.RecordVarCall;
import de.fuberlin.projecta.analysis.ast.Type;
/**
* Wrapper class for symbolTables.
*
* Searches recursively upwards in the AST to find the correct symbol table.
*/
public class SymbolTableHelper {
public static EntryType lookup(String name, AbstractSyntaxTree node) {
SymbolTable t = node.getTable();
EntryType entry = null;
if (t != null) {
if (t.lookup(name) != null) {
entry = t.lookup(name);
}
} else {
AbstractSyntaxTree parent = (AbstractSyntaxTree) (node).getParent();
while (parent != null) {
t = parent.getTable();
if (t != null) {
entry = t.lookup(name);
if (entry != null) {
return entry;
}
}
parent = (AbstractSyntaxTree) parent.getParent();
}
}
return null;
}
private static Id checkRecordVarCall(Type r, String names) {
if (names.isEmpty()) {
return (Id) (r.getParent().getChild(1));
}
int index = names.indexOf(".");
String name = (index >= 0) ? names.substring(0, index) : names;
for (ISyntaxTree c : r.getChildren()) {
if (((Id) c.getChild(1)).getValue().equals(name)) {
if (index >= 0) {
return checkRecordVarCall((Type) c.getChild(0),
names.substring(index + 1));
} else {
return (Id) c.getChild(1);
}
}
}
return null;
}
/**
* This should be used for searching record entries.
*
* @param recName
* The record where varName is searched in.
* @param node
* The node to start searching from.
* @return The Type of the corresponding EntryType for varName
*/
public static Type lookupRecordVarCall(RecordVarCall node) {
// recName is name of outer record (e.g: a.b.c => recName = 'a')
String recName = node.getRecordId().getValue();
EntryType entry = lookup(recName, node);
if (entry == null) {
throw new SemanticException("Record " + recName
+ " not defined before!", null);
}
String route = "";
ISyntaxTree child = node;
do {
route = "." + ((Id) child.getChild(1)).getValue() + route;
child = child.getChild(0);
} while (child instanceof RecordVarCall);
route = route.substring(1);
Type returnType = checkRecordVarCall(entry.getType(), route);
return returnType;
}
public static EntryType lookup(String name, List<EntryType> params,
AbstractSyntaxTree node) {
SymbolTable t = node.getTable();
EntryType entry = null;
if (t != null) {
if (t.lookup(name, params) != null) {
entry = t.lookup(name, params);
}
} else {
AbstractSyntaxTree parent = (AbstractSyntaxTree) (node).getParent();
while (parent != null) {
t = parent.getTable();
if (t != null) {
entry = t.lookup(name, params);
if (entry != null) {
return entry;
}
}
parent = (AbstractSyntaxTree) parent.getParent();
}
}
return null;
}
}