/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.template.soy.exprtree; import com.google.template.soy.basetree.AbstractNodeVisitor; import com.google.template.soy.basetree.ParentNode; import com.google.template.soy.exprtree.ExprNode.OperatorNode; import com.google.template.soy.exprtree.ExprNode.ParentExprNode; import com.google.template.soy.exprtree.ExprNode.PrimitiveNode; import com.google.template.soy.exprtree.OperatorNodes.AndOpNode; import com.google.template.soy.exprtree.OperatorNodes.ConditionalOpNode; import com.google.template.soy.exprtree.OperatorNodes.DivideByOpNode; import com.google.template.soy.exprtree.OperatorNodes.EqualOpNode; import com.google.template.soy.exprtree.OperatorNodes.GreaterThanOpNode; import com.google.template.soy.exprtree.OperatorNodes.GreaterThanOrEqualOpNode; import com.google.template.soy.exprtree.OperatorNodes.LessThanOpNode; import com.google.template.soy.exprtree.OperatorNodes.LessThanOrEqualOpNode; import com.google.template.soy.exprtree.OperatorNodes.MinusOpNode; import com.google.template.soy.exprtree.OperatorNodes.ModOpNode; import com.google.template.soy.exprtree.OperatorNodes.NegativeOpNode; import com.google.template.soy.exprtree.OperatorNodes.NotEqualOpNode; import com.google.template.soy.exprtree.OperatorNodes.NotOpNode; import com.google.template.soy.exprtree.OperatorNodes.NullCoalescingOpNode; import com.google.template.soy.exprtree.OperatorNodes.OrOpNode; import com.google.template.soy.exprtree.OperatorNodes.PlusOpNode; import com.google.template.soy.exprtree.OperatorNodes.TimesOpNode; /** * Abstract base class for all ExprNode visitors. A visitor is basically a function implemented for * some or all ExprNodes, where the implementation can be different for each specific node class. * * <p>Same as {@link AbstractReturningExprNodeVisitor} except that in this class, internal {@code * visit()} calls do not return a value. * * <p>Important: Do not use outside of Soy code (treat as superpackage-private). * * <p>To create a visitor: * * <ol> * <li> Subclass this class. * <li> Implement {@code visit*Node()} methods for some specific node types. * <li> Implement fallback methods for node types not specifically handled. The most general * fallback method is {@link #visitExprNode visitExprNode()}, which is usually needed. Other * fallback methods include {@code visitPrimitiveNode()} and {@code visitOperatorNode()}. * <li> Maybe implement a constructor, taking appropriate parameters for your visitor call. * <li> Maybe implement {@link #exec exec()} if this visitor needs to return a non-null final * result and/or if this visitor has state that needs to be setup/reset before each unrelated * use of {@code visit()}. * </ol> * * @param <R> The return type of this visitor. * @see AbstractReturningExprNodeVisitor */ public abstract class AbstractExprNodeVisitor<R> extends AbstractNodeVisitor<ExprNode, R> { @Override protected final void visit(ExprNode node) { switch (node.getKind()) { case EXPR_ROOT_NODE: visitExprRootNode((ExprRootNode) node); break; case NULL_NODE: visitNullNode((NullNode) node); break; case BOOLEAN_NODE: visitBooleanNode((BooleanNode) node); break; case INTEGER_NODE: visitIntegerNode((IntegerNode) node); break; case FLOAT_NODE: visitFloatNode((FloatNode) node); break; case STRING_NODE: visitStringNode((StringNode) node); break; case LIST_LITERAL_NODE: visitListLiteralNode((ListLiteralNode) node); break; case MAP_LITERAL_NODE: visitMapLiteralNode((MapLiteralNode) node); break; case VAR_REF_NODE: visitVarRefNode((VarRefNode) node); break; case FIELD_ACCESS_NODE: visitFieldAccessNode((FieldAccessNode) node); break; case ITEM_ACCESS_NODE: visitItemAccessNode((ItemAccessNode) node); break; case GLOBAL_NODE: visitGlobalNode((GlobalNode) node); break; case NEGATIVE_OP_NODE: visitNegativeOpNode((NegativeOpNode) node); break; case NOT_OP_NODE: visitNotOpNode((NotOpNode) node); break; case TIMES_OP_NODE: visitTimesOpNode((TimesOpNode) node); break; case DIVIDE_BY_OP_NODE: visitDivideByOpNode((DivideByOpNode) node); break; case MOD_OP_NODE: visitModOpNode((ModOpNode) node); break; case PLUS_OP_NODE: visitPlusOpNode((PlusOpNode) node); break; case MINUS_OP_NODE: visitMinusOpNode((MinusOpNode) node); break; case LESS_THAN_OP_NODE: visitLessThanOpNode((LessThanOpNode) node); break; case GREATER_THAN_OP_NODE: visitGreaterThanOpNode((GreaterThanOpNode) node); break; case LESS_THAN_OR_EQUAL_OP_NODE: visitLessThanOrEqualOpNode((LessThanOrEqualOpNode) node); break; case GREATER_THAN_OR_EQUAL_OP_NODE: visitGreaterThanOrEqualOpNode((GreaterThanOrEqualOpNode) node); break; case EQUAL_OP_NODE: visitEqualOpNode((EqualOpNode) node); break; case NOT_EQUAL_OP_NODE: visitNotEqualOpNode((NotEqualOpNode) node); break; case AND_OP_NODE: visitAndOpNode((AndOpNode) node); break; case OR_OP_NODE: visitOrOpNode((OrOpNode) node); break; case NULL_COALESCING_OP_NODE: visitNullCoalescingOpNode((NullCoalescingOpNode) node); break; case CONDITIONAL_OP_NODE: visitConditionalOpNode((ConditionalOpNode) node); break; case FUNCTION_NODE: visitFunctionNode((FunctionNode) node); break; case PROTO_INIT_NODE: visitProtoInitNode((ProtoInitNode) node); break; default: throw new UnsupportedOperationException(); } } /** * Helper to visit all the children of a node, in order. * * @param node The parent node whose children to visit. * @see #visitChildrenAllowingConcurrentModification */ protected void visitChildren(ParentExprNode node) { visitChildren((ParentNode<ExprNode>) node); } /** * Helper to visit all the children of a node, in order. * * <p>This method differs from {@code visitChildren} in that we are iterating through a copy of * the children. Thus, concurrent modification of the list of children is allowed. * * @param node The parent node whose children to visit. * @see #visitChildren */ protected void visitChildrenAllowingConcurrentModification(ParentExprNode node) { visitChildrenAllowingConcurrentModification((ParentNode<ExprNode>) node); } // ----------------------------------------------------------------------------------------------- // Implementations for misc nodes. protected void visitExprRootNode(ExprRootNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Implementations for primitive nodes. protected void visitNullNode(NullNode node) { visitPrimitiveNode(node); } protected void visitBooleanNode(BooleanNode node) { visitPrimitiveNode(node); } protected void visitIntegerNode(IntegerNode node) { visitPrimitiveNode(node); } protected void visitFloatNode(FloatNode node) { visitPrimitiveNode(node); } protected void visitStringNode(StringNode node) { visitPrimitiveNode(node); } protected void visitPrimitiveNode(PrimitiveNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Implementations for collection nodes. protected void visitListLiteralNode(ListLiteralNode node) { visitExprNode(node); } protected void visitMapLiteralNode(MapLiteralNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Implementations for reference nodes. protected void visitVarRefNode(VarRefNode node) { visitExprNode(node); } protected void visitDataAccessNode(DataAccessNode node) { visitExprNode(node); } protected void visitFieldAccessNode(FieldAccessNode node) { visitDataAccessNode(node); } protected void visitItemAccessNode(ItemAccessNode node) { visitDataAccessNode(node); } protected void visitGlobalNode(GlobalNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Implementations for operator nodes. protected void visitNegativeOpNode(NegativeOpNode node) { visitOperatorNode(node); } protected void visitNotOpNode(NotOpNode node) { visitOperatorNode(node); } protected void visitTimesOpNode(TimesOpNode node) { visitOperatorNode(node); } protected void visitDivideByOpNode(DivideByOpNode node) { visitOperatorNode(node); } protected void visitModOpNode(ModOpNode node) { visitOperatorNode(node); } protected void visitPlusOpNode(PlusOpNode node) { visitOperatorNode(node); } protected void visitMinusOpNode(MinusOpNode node) { visitOperatorNode(node); } protected void visitLessThanOpNode(LessThanOpNode node) { visitOperatorNode(node); } protected void visitGreaterThanOpNode(GreaterThanOpNode node) { visitOperatorNode(node); } protected void visitLessThanOrEqualOpNode(LessThanOrEqualOpNode node) { visitOperatorNode(node); } protected void visitGreaterThanOrEqualOpNode(GreaterThanOrEqualOpNode node) { visitOperatorNode(node); } protected void visitEqualOpNode(EqualOpNode node) { visitOperatorNode(node); } protected void visitNotEqualOpNode(NotEqualOpNode node) { visitOperatorNode(node); } protected void visitAndOpNode(AndOpNode node) { visitOperatorNode(node); } protected void visitOrOpNode(OrOpNode node) { visitOperatorNode(node); } protected void visitNullCoalescingOpNode(NullCoalescingOpNode node) { visitOperatorNode(node); } protected void visitConditionalOpNode(ConditionalOpNode node) { visitOperatorNode(node); } protected void visitOperatorNode(OperatorNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Implementations for function nodes. protected void visitFunctionNode(FunctionNode node) { visitExprNode(node); } protected void visitProtoInitNode(ProtoInitNode node) { visitExprNode(node); } // ----------------------------------------------------------------------------------------------- // Fallback implementation. /** @param node The node being visited. */ protected void visitExprNode(ExprNode node) { throw new UnsupportedOperationException(); } }