}
  protected void joinItems(CKYItem modificand, CKYItem modifier,                           boolean side)  throws RemoteException {    /*    if (useCommaConstraint &&        commaConstraintViolation(modificand, modifier, side))      return;    */    // if this side's subcat contains the the current modifier's label as one    // of its requirements, make a copy of it and remove the requirement    Subcat thisSideSubcat = (Subcat)modificand.subcat(side);    Symbol modLabel = (Symbol)modifier.label();    if (thisSideSubcat.contains(modLabel)) {      thisSideSubcat = (Subcat)thisSideSubcat.copy();      thisSideSubcat.remove(modLabel);    }    Subcat oppositeSideSubcat = modificand.subcat(!side);    SLNode thisSideChildren = new SLNode(modifier, modificand.children(side));    SLNode oppositeSideChildren = modificand.children(!side);    SexpList thisSidePrevMods = getPrevMods(modificand.prevMods(side),                                            modificand.children(side));    SexpList oppositeSidePrevMods = modificand.prevMods(!side);    int thisSideEdgeIndex = modifier.edgeIndex(side);    int oppositeSideEdgeIndex = modificand.edgeIndex(!side);    boolean thisSideVerbIntervening =      modificand.verb(side) || modifier.containsVerb();    boolean oppositeSideVerbIntervening = modificand.verb(!side);    ModifierEvent modEvent = lookupModEvent;    modEvent.set(modifier.headWord(),                 modificand.headWord(),                 (Symbol)modifier.label(),                 thisSidePrevMods,                 (Symbol)modificand.label(),                 modificand.headLabel(),                 modificand.subcat(side),                 modificand.verb(side),                 side);    if (!futurePossible(modEvent, side))      return;    if (debugJoin) {      if (modificand.headWord().tag() == mdSym &&          modificand.headWord().word() == willSym) {        Debug.level = 20;      }    }    double logModProb = server.logProbMod(id, modEvent, side);    if (logModProb <= Constants.logOfZero) {      return;    }    double logTreeProb =      modificand.logTreeProb() + modifier.logTreeProb() + logModProb;    HeadEvent priorEvent = lookupPriorEvent;    priorEvent.set(modificand.headWord(), stopSym, modificand.headLabel(),                   emptySubcat, emptySubcat);    double logPrior = server.logPrior(id, priorEvent);    double logProb = logTreeProb + logPrior;    if (debugJoin) {      if (modificand.headWord().tag() == mdSym &&          modificand.headWord().word() == willSym) {        System.err.println(className +                           ": trying to join modificand " + modificand +                           " to modifier " + modifier  + "; logModProb: " +                           logModProb + "; logPrior: " + logPrior +                           "; logProb: " + logProb);      }      Debug.level = 0;    }    if (logProb <= Constants.logOfZero)      return;    CKYItem newItem = chart.getNewItem();    newItem.set((Symbol)modificand.label(), modificand.headWord(),                null, null, modificand.headChild(), null, null, null, null,                0, 0, false, false, false, logTreeProb, logProb);    newItem.setSideInfo(side,                        thisSideSubcat, thisSideChildren,                        thisSidePrevMods, thisSideEdgeIndex,                        thisSideVerbIntervening);    newItem.setSideInfo(!side,                        oppositeSideSubcat, oppositeSideChildren,                        oppositeSidePrevMods, oppositeSideEdgeIndex,                        oppositeSideVerbIntervening);    int lowerIndex = Math.min(thisSideEdgeIndex, oppositeSideEdgeIndex);    int higherIndex = Math.max(thisSideEdgeIndex, oppositeSideEdgeIndex);    boolean added = chart.add(lowerIndex, higherIndex, newItem);    if (!added)      chart.reclaimItem(newItem);  }