package de.skuzzle.polly.core.parser.ast;
import de.skuzzle.polly.core.parser.Location;
import de.skuzzle.polly.core.parser.Position;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversal;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException;
import de.skuzzle.polly.core.parser.ast.visitor.ASTVisitor;
import de.skuzzle.polly.core.parser.ast.visitor.ParentSetter;
import de.skuzzle.polly.core.parser.ast.visitor.Transformation;
import de.skuzzle.polly.core.parser.ast.visitor.Visitable;
import de.skuzzle.polly.tools.EqualsHelper;
import de.skuzzle.polly.tools.Equatable;
/**
* Super class for all elements of the AST. It stores the parent Node and the Nodes
* position in the input String.
*
* @author Simon Taddiken
*/
public abstract class Node implements Visitable<ASTVisitor>, Equatable, Location {
private Node parent;
private Position position;
/**
* Creates a new Node with the given position.
*
* @param position The Node's position.
*/
public Node(Position position) {
this.position = position;
}
/**
* Updates all parent edges of the subtree represented by this node. This requires
* traversal of the whole subtree.
* @return Reference to this node (intended for chaining methods).
* @throws ASTTraversalException If traversal of the subtree fails for any reason.
*/
public Node updateParents() throws ASTTraversalException {
this.visit(new ParentSetter());
return this;
}
/**
* Gets the parent Node of this node. Returns <code>null</code> for the root of the
* AST.
*
* @return The parent Node.
*/
public Node getParent() {
return this.parent;
}
/**
* Sets the parent Node of this Node.
*
* @param parent The new parent Node.
*/
public void setParent(Node parent) {
this.parent = parent;
}
@Override
public Position getPosition() {
return this.position;
}
/**
* Sets the position of this Node. A Node's position should always span from the
* beginning of its left most child to the end of its right most child.
*
* @param position New position for this node.
*/
public void setPosition(Position position) {
this.position = position;
}
/**
* Visitor-style method used to transform the AST. The actual {@link Transformation}
* implementation will decide for each node with what new node it will be replaced.
*
* @param transformation The transformation to apply.
* @return The transformed AST.
* @throws ASTTraversalException Can be thrown during AST traversal.
*/
public abstract Node transform(Transformation transformation)
throws ASTTraversalException;
/**
* Uses an {@link ASTTraversal} to traverse the AST in depth first order. If you want
* to traverse the AST in different order, use the {@link #visit(ASTVisitor)} method.
*
* @param visitor Visitor to traverse the AST with.
* @return Whether traversal should continue;
* @throws ASTTraversalException If AST traversal fails.
*/
public abstract boolean traverse(ASTTraversal visitor) throws ASTTraversalException;
@Override
public final boolean equals(Object obj) {
return EqualsHelper.testEquality(this, obj);
}
@Override
public Class<?> getEquivalenceClass() {
return Node.class;
}
@Override
public boolean actualEquals(Equatable o) {
final Node other = (Node) o;
return this.position.equals(other.position);
}
}