verbIntervening |= prevModHadVerb;
  private void collectModifierStats(HeadTreeNode tree,				    Subcat subcat,				    int gapIdx,				    boolean side) {    Symbol parent = tree.label();    Symbol head = tree.headChild().label();    // it's crucial to use a copy of the head word, so that    // alterLowFrequencyWords doesn't change equals status of ModifierEvent    // objects when it alters words from HeadEvent objects (i.e., we don't    // want ModifierEvent and HeadEvent objects to share the same head word    // Word objects)    Word headWord = tree.headWord().copy();    Iterator mods = (side == Constants.LEFT ?		     tree.preMods().iterator() : tree.postMods().iterator());    SexpList prevModList = new SexpList(numPrevMods);    for (int i = 0; i < numPrevMods; i++)      prevModList.add(startSym);    Subcat dynamicSubcat = (Subcat)subcat.copy();    // if there's a gap to generate, add as requirement to end of subcat list    if (gapIdx != -1)      dynamicSubcat.add(gapAugmentation);    boolean verbIntervening = false;    // collect modifier generation events    boolean prevModHadVerb = false;    // the next two booleans only necessary for (currently) unused method of    // determining modifier adjacency, which is that no *words* appear between    // head and currently-generated left- or right-edge frontier word of    // currently-generated modifier subtree    boolean wordsIntervening = false;    boolean headAlreadyHasMods =      (side == Constants.LEFT ?       tree.headChild().leftIdx() < headWord.index() :       tree.headChild().rightIdx() > headWord.index() + 1);    for (int modIdx = 0; mods.hasNext(); modIdx++) {      HeadTreeNode currMod = (HeadTreeNode)mods.next();      Symbol modifier = currMod.label();      verbIntervening |= prevModHadVerb;      wordsIntervening = (modIdx > 0 ? true : headAlreadyHasMods);      // crucial to copy modifier's head word object (see comment above)      Subcat dynamicSubcatCopy =	((Subcat)dynamicSubcat.copy()).getCanonical(canonicalSubcatMap, false);      ModifierEvent modEvent = new ModifierEvent(currMod.headWord().copy(),						 headWord,						 modifier,						 new SexpList(prevModList),						 parent,						 head,						 dynamicSubcatCopy,						 verbIntervening,						 side);      modifierEvents.add(modEvent);      if (modIdx == gapIdx) {	Symbol direction = (side == Constants.LEFT ?			    GapEvent.toLeft : GapEvent.toRight);	GapEvent gapEvent = new GapEvent(direction, headWord, parent, head);	gapEvents.add(gapEvent);	if (dynamicSubcat.size() == 0)	  System.err.println(className + ": error: gap detected in " +			     tree + " but subcat list is empty!");	if (!dynamicSubcat.remove(gapAugmentation)) {	  System.err.println(className + ": warning: gap detected in " +			     "modifier " + tree.label() + " but not present " +			     "in subcat list");	}      }      dynamicSubcat.remove(modifier);      prevModHadVerb = currMod.containsVerb();      prevModList.remove(prevModList.length() - 1);      prevModList.add(0, currMod.label()); // an O(n) op (list is usu. len. 1)    }    if (!dynamicSubcat.empty())      System.err.println(className + ": warning: dynamic subcat not empty: " +			 dynamicSubcat);    Subcat emptySubcat = dynamicSubcat.getCanonical(canonicalSubcatMap, false);    // transition to stop symbol    ModifierEvent modEvent = new ModifierEvent(stopWord,					       headWord,					       stopSym,					       prevModList,					       parent,					       head,					       emptySubcat,					       verbIntervening,					       side);    modifierEvents.add(modEvent);  }