code: def check_words(tree, tsurgeon_processor):
      """
      Check that the words of a sentence are in order
  
      If they are not, this applies a tsurgeon to rearrange simple cases
      The tsurgeon looks at the gap between words, eg _3 to _7, and looks
      for the words between, such as _4 _5 _6.  if those words are under
      a node at the same level as the 3-7 node and does not include any
      other nodes (such as _8), that subtree is moved to between _3 and _7
  
      Example:
  
      (vp (v-fin s4_6) (conj-c s4_8) (v-fin s4_9)) (pron-pers s4_7)
      -->
      (vp (v-fin s4_6) (pron-pers s4_7) (conj-c s4_8) (v-fin s4_9))
      """
      while True:
          words = tree.leaf_labels()
          indices = [int(w.split("_", 1)[1]) for w in words]
          for word_idx, word_label in enumerate(indices):
              if word_idx != word_label - 1:
                  break
          else:
              # if there are no weird indices, keep the tree
              return tree
  
          sorted_indices = sorted(indices)
          if indices == sorted_indices:
              raise ValueError(
                  "Skipped index!  This should already be accounted for  {}".format(
                      tree
                  )
              )
  
          if word_idx == 0:
              return None
  
          prefix = words[0].split("_", 1)[0]
          prev_idx = word_idx - 1
          prev_label = indices[prev_idx]
          missing_words = [
              "%s_%d" % (prefix, x)
              for x in range(prev_label + 1, word_label)
          ]
          missing_words = "|".join(missing_words)
          # move_tregex = "%s > (__=home > (__=parent > __=grandparent)) . (%s > (__=move > =grandparent))" % (words[word_idx], "|".join(missing_words))
          move_tregex = (
              "%s > (__=home > (__=parent << %s $+ (__=move <<, %s <<- %s)))"
              % (
                  words[word_idx],
                  words[prev_idx],
                  missing_words,
                  missing_words,
              )
          )
          move_tsurgeon = "move move $+ home"
          modified = tsurgeon_processor.process(
              tree, move_tregex, move_tsurgeon
          )[0]
          if modified == tree:
              # this only happens if the desired fix didn't happen
              # print("Failed to process:\n  {}\n  {} {}".format(tree, prev_label, word_label))
              return None
  
          tree = modified
  
file_path: stanza/stanza/utils/datasets/constituency/convert_arboretum.py
imports: from collections import namedtuple
  import io
  import xml.etree.ElementTree
  from tqdm import tqdm
  from stanza.models.constituency.parse_tree import Tree
  from stanza.server import tsurgeon
label_desc: Use image node_id 3 for calling a global function with example usage: check_words(tree, tsurgeon_processor) and returns: tree, None, None