package edu.stanford.nlp.trees.tregex.tsurgeon; import java.util.List; import edu.stanford.nlp.ling.CoreLabel; import edu.stanford.nlp.ling.Label; import edu.stanford.nlp.ling.LabelFactory; import edu.stanford.nlp.trees.Tree; import edu.stanford.nlp.trees.tregex.TregexMatcher; import edu.stanford.nlp.util.Generics; /** * Given the start and end children of a particular node, takes all * children between start and end (including the endpoints) and * combines them in a new node with the given label. * * @author John Bauer */ public class CreateSubtreeNode extends TsurgeonPattern { private final String newLabel; public CreateSubtreeNode(TsurgeonPattern start, String newLabel) { super("combineSubtrees", new TsurgeonPattern[] { start }); this.newLabel = newLabel; } public CreateSubtreeNode(TsurgeonPattern start, TsurgeonPattern end, String newLabel) { super("combineSubtrees", new TsurgeonPattern[] { start, end }); this.newLabel = newLabel; } /** * Combines all nodes between start and end into one subtree, then * replaces those nodes with the new subtree in the corresponding * location under parent */ @Override public Tree evaluate(Tree t, TregexMatcher tm) { Tree startChild = children[0].evaluate(t, tm); Tree endChild = (children.length == 2) ? children[1].evaluate(t, tm) : startChild; Tree parent = startChild.parent(t); // sanity check if (parent != endChild.parent(t)) { throw new TsurgeonRuntimeException("Parents did not match for trees when applied to " + this); } // prepare a new label Label label; LabelFactory lf = parent.labelFactory(); if (lf == null) { lf = t.labelFactory(); } if (lf == null) { label = new CoreLabel(); label.setValue(newLabel); } else { label = lf.newLabel(newLabel); } // Collect all the children of the parent of the node we care // about. If the child is one of the nodes we care about, or // between those two nodes, we add it to a list of inner children. // When we reach the second endpoint, we turn that list of inner // children into a new node using the newly created label. All // other children are kept in an outer list, with the new node // added at the appropriate location. List<Tree> children = Generics.newArrayList(); List<Tree> innerChildren = Generics.newArrayList(); boolean insideSpan = false; for (Tree child : parent.children()) { if (child == startChild || child == endChild) { if (!insideSpan && startChild != endChild) { insideSpan = true; innerChildren.add(child); } else { insideSpan = false; innerChildren.add(child); Tree newNode = t.treeFactory().newTreeNode(label, innerChildren); children.add(newNode); } } else if (insideSpan) { innerChildren.add(child); } else { children.add(child); } } parent.setChildren(children); return t; } }