package com.prezi.spaghetti.ast; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class ModuleVisitorBase<T> implements ModuleVisitor<T> { @Override public T visitAnnotationNode(AnnotationNode node) { return visitChildren(node); } @Override public T visitDocumentationNode(DocumentationNode node) { return visitChildren(node); } @Override public T visitConstEntryNode(ConstEntryNode node) { return visitChildren(node); } @Override public T visitConstNode(ConstNode node) { return visitChildren(node); } @Override public T visitEnumNode(EnumNode node) { return visitChildren(node); } @Override public T visitEnumReference(EnumReference reference) { return visitChildren(reference); } @Override public T visitEnumValueNode(EnumValueNode node) { return visitChildren(node); } @Override public T visitExternInterfaceNode(ExternInterfaceNode node) { return visitChildren(node); } @Override public T visitExternInterfaceReference(ExternInterfaceReference reference) { return visitChildren(reference); } @Override public T visitImportNode(ImportNode node) { return visitChildren(node); } @Override public T visitInterfaceNode(InterfaceNode node) { return visitChildren(node); } @Override public T visitInterfaceReference(InterfaceReference reference) { return visitChildren(reference); } @Override public T visitMethodNode(MethodNode node) { return visitChildren(node); } @Override public T visitMethodParameterNode(MethodParameterNode node) { return visitChildren(node); } @Override public T visitModuleNode(ModuleNode node) { return visitChildren(node); } @Override public T visitPrimitiveTypeReference(PrimitiveTypeReference reference) { return visitChildren(reference); } @Override public T visitPropertyNode(PropertyNode node) { return visitChildren(node); } @Override public T visitStructNode(StructNode node) { return visitChildren(node); } @Override public T visitStructReference(StructReference reference) { return visitChildren(reference); } @Override public T visitFunctionType(FunctionType node) { return visitChildren(node); } @Override public T visitTypeParameterNode(TypeParameterNode node) { return visitChildren(node); } @Override public T visitTypeParameterReference(TypeParameterReference reference) { return visitChildren(reference); } @Override public T visitVoidTypeReference(VoidTypeReference reference) { return visitChildren(reference); } public T visitChildren(AstNode node) { T result = defaultResult(); for (AstNode child : node.getChildren()) { T childResult = visit(child); result = aggregateResult(result, childResult); } return result; } private final LinkedList<AstNode> stackInternal = new LinkedList<AstNode>(); protected final List<AstNode> stack = Collections.unmodifiableList(stackInternal); protected AstNode getParentNode() { return stackInternal.isEmpty() ? null : stackInternal.getFirst(); } protected boolean hasAncestor(Class<? extends AstNode> type) { return findAncestor(type) != null; } protected boolean hasAncestor(Class<? extends AstNode> type, int startDepth) { return findAncestor(type, startDepth) != null; } protected <N extends AstNode> N findAncestor(Class<N> type) { return findAncestorInternal(stackInternal, type); } protected <N extends AstNode> N findAncestor(Class<N> type, int startDepth) { return findAncestorInternal(stackInternal.subList(startDepth, stackInternal.size()), type); } @SuppressWarnings("unchecked") private static <N extends AstNode> N findAncestorInternal(List<AstNode> stack, final Class<N> type) { N result = null; for (AstNode node : stack) { if (type.isAssignableFrom(node.getClass())) { result = (N) node; break; } } return result; } @Override public T beforeVisit(AstNode node) { stackInternal.add(0, node); return defaultResult(); } @Override public T afterVisit(AstNode node, T result) { stackInternal.remove(0); return result; } @Override public T visit(AstNode node) { return (T) node.accept(this); } protected T defaultResult() { return null; } @Override public T aggregateResult(T aggregate, T nextResult) { return nextResult; } }