public AstNode ReplaceWith(Func <AstNode, AstNode> replaceFunction) { if (replaceFunction == null) { throw new ArgumentNullException("replaceFunction"); } if (parent == null) { throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); } AstNode oldParent = parent; AstNode oldSuccessor = nextSibling; Role oldRole = role; Remove(); AstNode replacement = replaceFunction(this); if (oldSuccessor != null && oldSuccessor.parent != oldParent) { throw new InvalidOperationException("replace function changed nextSibling of node being replaced?"); } if (!(replacement == null || replacement.IsNull)) { if (replacement.parent != null) { throw new InvalidOperationException("replace function must return the root of a tree"); } if (!oldRole.IsValid(replacement)) { throw new InvalidOperationException(string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString())); } if (oldSuccessor != null) { oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldRole); } else { oldParent.AddChildUnsafe(replacement, oldRole); } } return(replacement); }
/// <summary> /// Clones the whole subtree starting at this AST node. /// </summary> /// <remarks>Annotations are copied over to the new nodes; and any annotations implementating ICloneable will be cloned.</remarks> public AstNode Clone() { AstNode copy = (AstNode)MemberwiseClone(); // First, reset the shallow pointer copies copy.parent = null; copy.firstChild = null; copy.lastChild = null; copy.prevSibling = null; copy.nextSibling = null; copy.flags &= ~frozenBit; // unfreeze the copy // Then perform a deep copy: for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) { copy.AddChildUnsafe(cur.Clone(), cur.Role); } // Finally, clone the annotation, if necessary copy.CloneAnnotations(); return(copy); }