public boolean parse(Lattice lr) {
    sentence = null; // better nullPointer exception than silent error
    if (lr != this.lr) {
      this.lr = lr;
      floodTags = false;
    }

    if (Test.verbose)
      Timing.tick("Doing lattice PCFG parse...");


    // The number of whitespace nodes in the lattice
    length = lr.getNumNodes() - 1; //Subtract 1 since considerCreatingArrays will add the final interstice
    if (length > arraySize)
      considerCreatingArrays(length);


    int goal = stateNumberer.number(goalStr);
//    if (Test.verbose) {
//      System.err.println("Unaries: " + ug.rules());
//      System.err.println("Binaries: " + bg.rules());
//      System.err.println("Initializing PCFG...");
//      System.err.println("   " + numStates + " states, " + goal + " is the goal state.");
//    }

//    System.err.println("Tagging states");
//    for(int i = 0; i < numStates; i++) {
//      if(isTag[i]) {
//        int tagId = Numberer.translate(stateSpace, "tags", i);
//        String tag = (String) tagNumberer.object(tagId);
//        System.err.printf(" %d: %s\n",i,tag);
//      }
//    }

    // Create a map of all words in the lattice
    //
//    int numEdges = lr.getNumEdges();
//    words = new int[numEdges];
//    offsets = new IntPair[numEdges];
//
//    int unk = 0;
//    int i = 0;
//    StringBuilder unkWords = new StringBuilder("[");
//    for (LatticeEdge edge : lr) {
//      String s = edge.word;
//      if (Test.verbose && !lex.isKnown(wordNumberer.number(s))) {
//        unk++;
//        unkWords.append(" " + s);
//      }
//      words[i++] = wordNumberer.number(s);
//    }

    for (int start = 0; start < length; start++) {
    	for (int end = start + 1; end <= length; end++) {
    		Arrays.fill(iScore[start][end], Float.NEGATIVE_INFINITY);
    		if (op.doDep) Arrays.fill(oScore[start][end], Float.NEGATIVE_INFINITY);
    	}
    }

    for (int loc = 0; loc <= length; loc++) {
      Arrays.fill(narrowLExtent[loc], -1); // the rightmost left with state s ending at i that we can get is the beginning
      Arrays.fill(wideLExtent[loc], length + 1); // the leftmost left with state s ending at i that we can get is the end
      Arrays.fill(narrowRExtent[loc], length + 1); // the leftmost right with state s starting at i that we can get is the end
      Arrays.fill(wideRExtent[loc], -1); // the rightmost right with state s starting at i that we can get is the beginning
    }

    initializeChart(lr);

    doInsideScores();
    bestScore = iScore[0][length][goal];

    if (Test.verbose) {
      Timing.tick("done.");
      System.err.println("PCFG " + length + " words (incl. stop) iScore " + bestScore);
    }

    boolean succeeded = hasParse();

    // Try a recovery parse
    if (!succeeded && Test.doRecovery && !floodTags) {
      floodTags = true;
      System.err.printf(this.getClass().getName() + ": Parse failed. Trying recovery parse...");
      succeeded = parse(lr);
      if(!succeeded) return false;
    }

    oScore[0][length][goal] = 0.0f;
    doOutsideScores();

    //WSGDEBUG
    //I don't understand the "half-filters" bit below...the arrays are used by the bilex
    //parser during edge combination
    if (Test.verbose) {
      Timing.tick("done.");
      System.err.print("Starting half-filters...");
    }
    for (int loc = 0; loc <= length; loc++) {
      Arrays.fill(iPossibleByL[loc], false);
      Arrays.fill(iPossibleByR[loc], false);
      Arrays.fill(oPossibleByL[loc], false);
      Arrays.fill(oPossibleByR[loc], false);
    }
    for (int start = 0; start < length; start++) {
      for (int end = start + 1; end <= length; end++) {
        for (int state = 0; state < numStates; state++) {
          if (iScore[start][end][state] > Float.NEGATIVE_INFINITY && oScore[start][end][state] > Float.NEGATIVE_INFINITY) {
            iPossibleByL[start][state] = true;
            iPossibleByR[end][state] = true;
            oPossibleByL[start][state] = true;
            oPossibleByR[end][state] = true;
          }
        }
      }
    }
    if (Test.verbose) {
      Timing.tick("done.");
    }
    return succeeded;
  }