package de.fuberlin.projecta.analysis.ast; import de.fuberlin.commons.parser.ISyntaxTree; import de.fuberlin.projecta.analysis.SemanticException; import de.fuberlin.projecta.analysis.SymbolTable; import de.fuberlin.projecta.analysis.SymbolTableStack; import de.fuberlin.projecta.parser.Symbol; import de.fuberlin.projecta.parser.Tree; /** * This is the superclass of *all* AST nodes * * It provides the necessary interfaces for all subclasses */ public abstract class AbstractSyntaxTree extends Tree { /** * This is the symbolTable of this node. Caution: it may be null! */ SymbolTable table; public SymbolTable getTable() { return table; } public SymbolTable getHigherTable() { if (getParent() != null) { AbstractSyntaxTree parent = (AbstractSyntaxTree) getParent(); while (parent != null) { if (((AbstractSyntaxTree) getParent()).getTable() != null) { return ((AbstractSyntaxTree) getParent()).getTable(); } parent = (AbstractSyntaxTree) parent.getParent(); } } return null; } /** * Every block in LLVM has it's own memory counter, so does ours. * * @return * The highest node above this, which is instance of Block. */ public Block getHighestBlock() { Block block = null; if (getParent() != null) { ISyntaxTree parent = getParent(); while (parent != null) { if (parent instanceof Block) { block = (Block) parent; } parent = parent.getParent(); } } return block; } public AbstractSyntaxTree() { super(null); } public AbstractSyntaxTree(Symbol symbol) { super(symbol); } /** * Method for building the SymbolTables that the nodes should implement * * Default implementation does nothing * @note Reimplement in subclass if needed! **/ public void buildSymbolTable(SymbolTableStack tables) {} /** * Code generation * * Default implementation recursively calls this on its children **/ public String genCode() throws SemanticException { String out = ""; for (int i = 0; i < getChildrenCount(); i++) { out += ((AbstractSyntaxTree) getChild(i)).genCode() + "\n"; } return out; } /** * We must explicitly go through the whole tree twice, since identified * records has to be placed in the head! * * Default implementation recursively calls this on its children * @return Generated structs (LLVM code) */ protected String genStruct() throws SemanticException { String out = ""; for (int i = 0; i < getChildrenCount(); i++) { out += ((AbstractSyntaxTree) getChild(i)).genStruct(); } return out; } /** * Check types * * Default implementation recursively checks types * @note Reimplement in subclass if needed! */ public void checkTypes() throws SemanticException { for (ISyntaxTree child : this.getChildren()) { ((AbstractSyntaxTree) child).checkTypes(); } } /** * Check semantics (other than type errors) * * Default implementation recursively checks semantics * @note Reimplement in subclass if needed! */ public void checkSemantics() throws SemanticException { for (int i = 0; i < this.getChildrenCount(); i++) { ((AbstractSyntaxTree) this.getChild(i)).checkSemantics(); } } @Override public String toString() { // remove prefix from class name final String className = this.getClass().getName() .replaceAll("^.*\\.", ""); String value = ""; if (this instanceof BinaryOp) { value += ((BinaryOp) this).getOp(); } else if (this instanceof IntLiteral) { value += ((IntLiteral) this).getValue(); } else if (this instanceof Id) { value += ((Id) this).getValue(); } else if (this instanceof UnaryOp) { value += ((UnaryOp) this).getOp(); } else if (this instanceof BasicType) { value += ((BasicType) this).getTokenType(); } if (getTable() != null) { value += "table contents: " + getTable(); } if (value.isEmpty()) return className; return className + " [" + value + "]"; } }