// Copyright (C) 2006 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.caja.parser; /** * A parse tree node with mutating operations. * * @author mikesamuel@gmail.com (Mike Samuel) */ public interface MutableParseTreeNode extends ParseTreeNode { /** * {@inheritDoc} * <p> * As per {@link ParseTreeNode#acceptPreOrder}, but with the following caveats * relating to parse tree manipulation during visiting: * <p>Will work even if visitor {@link #replaceChild replaces} this node or a * descendant, {@link #removeChild removes} this node or a descendant, or * {@link #insertBefore inserts} a sibling before this node.</p> * <p>This implementation will have undefined behavior if the visitor modifies * ancestor nodes, or subsequent siblings of this node. */ boolean acceptPreOrder(Visitor v, AncestorChain<?> ancestors); /** * {@inheritDoc} * <p> * As per {@link ParseTreeNode#acceptPostOrder}, but with the following * caveats relating to parse tree manipulation during visiting: * <p>Will work even if visitor {@link #replaceChild replaces} this node or a * descendant, {@link #removeChild removes} this node or a descendant, or * {@link #insertBefore inserts} a sibling before this node.</p> * <p>This implementation will have undefined behavior if the visitor modifies * ancestor nodes, or subsequent siblings of this node. */ boolean acceptPostOrder(Visitor v, AncestorChain<?> ancestors); /** * Replace the given child of the current node with the given replacement. * * @param replacement a node that is not in a children list and is not an * ancestor of this node. * @param child a node in {@link ParseTreeNode#children}. */ void replaceChild(ParseTreeNode replacement, ParseTreeNode child); /** * Add the given child to the current node's child list before the given node. * * @param toAdd a node that is not in a children list and is not the * root containing this node. * @param before a node in {@link ParseTreeNode#children}, or null to indicate * add should happen at the end. */ void insertBefore(ParseTreeNode toAdd, ParseTreeNode before); /** * Removes the given child from the current node's child list. * * @param toRemove a child of this node. */ void removeChild(ParseTreeNode toRemove); /** * Add the given child to the current node's child list at the end. * * @param toAppend a node to add. */ void appendChild(ParseTreeNode toAppend); /** * Allows multiple adds and removals when adding one at a time might leave the * tree in an inconsistent state. */ Mutation createMutation(); public static interface Mutation { /** * Replace the given child of the current node with the given replacement. * Does not take effect until {@link #execute} is called. * * @param replacement a node that is not in a children list and is not the * root containing this node. * @param child a node in {@link ParseTreeNode#children}. * @return this */ Mutation replaceChild(ParseTreeNode replacement, ParseTreeNode child); /** * Add the given child to the current node's child list. * Does not take effect until {@link #execute} is called. * * @param toAdd a node that is not in a children list and is not the * root containing this node. * @param before a node in {@link ParseTreeNode#children}, or null to * indicate add should happen at the end. * @return this */ Mutation insertBefore(ParseTreeNode toAdd, ParseTreeNode before); /** * Remove the given child from the current node's child list. * Does not take effect until {@link #execute} is called. * * @param toRemove a child of this node. * @return this */ Mutation removeChild(ParseTreeNode toRemove); /** * Add the given child to the current node's child list at the end. * Does not take effect until {@link #execute} is called. * * @param toAppend a child to add. */ Mutation appendChild(ParseTreeNode toAppend); /** * Add the given child to the current node's child list at the end. * Does not take effect until {@link #execute} is called. * * @param toAppend children to add. */ Mutation appendChildren(Iterable<? extends ParseTreeNode> toAppend); /** * Perform the mutation. */ void execute(); } }