def move_nodes(nodes, new_parent, in_place=True, remove_empty=True, remove_trivial_unary=True): if not in_place: nodes = pstree.clone_and_find(nodes + [new_parent]) new_parent = nodes[-1] nodes = nodes[:-1] # Find the insertion point in the new parent's subtrees old_parent = nodes[0].parent nodes.sort(key=lambda x: x.span) node_span = (nodes[0].span[0], nodes[-1].span[1]) insertion_point = 0 if new_parent.subtrees[0].span[0] == node_span[1]: # Inserting before all that are there currently pass elif new_parent.subtrees[0].span[0] == node_span[0]: # Inserting before all that are there currently pass else: for subtree in new_parent.subtrees: if subtree.span[0] == node_span[1]: break insertion_point += 1 if subtree.span[1] == node_span[0]: break if insertion_point > len(new_parent.subtrees): return (False, "new_parent did not have suitable insertion point") # Move the nodes across for node in nodes: node.parent.subtrees.remove(node) new_parent.subtrees.insert(insertion_point, node) node.parent = new_parent insertion_point += 1 # If the nodes left behind are empty, remove them to_check_for_unary = old_parent if remove_empty and len(old_parent.subtrees) == 0: to_remove = old_parent while len(to_remove.parent.subtrees) == 1: to_remove = to_remove.parent to_remove.parent.remove(to_remove) # If the removal applies, then we will need to check at that level for # unaries, rather than down at the old_parent to_check_for_unary = to_remove.parent # Remove trivial unaries if remove_trivial_unary: to_check = to_check_for_unary if len(to_check.subtrees) == 1 and to_check.label == to_check.subtrees[0].label: to_check.subtrees = to_check.subtrees[0].subtrees for subtree in to_check.subtrees: subtree.parent = to_check new_parent.root().calculate_spans() return (True, (new_parent.root(), nodes, new_parent))
def remove_node_by_node(node, in_place): if not in_place: node = pstree.clone_and_find(node) parent = node.parent position = parent.subtrees.index(node) init_position = position parent.subtrees.pop(position) for subtree in node.subtrees: subtree.parent = parent parent.subtrees.insert(position, subtree) position += 1 return (True, (parent, node, init_position, position))
def change_label_by_node(node, new_label, in_place): if not in_place: node = pstree.clone_and_find(node) node.label = new_label return (True, (node.root(), node))