private void initializeChart(List sentence) {
    int boundary = wordNumberer.number(Lexicon.BOUNDARY);

    for (int start = 0; start + 1 <= length; start++) {
      if (Test.maxSpanForTags > 1) { // only relevant for parsing single words as multiple input tokens.
        // note we don't look for "words" including the end symbol!
        for (int end = start + 1; (end < length - 1 && end - start <= Test.maxSpanForTags) || (start + 1 == end); end++) {
          StringBuilder word = new StringBuilder();
          //wsg: Feb 2010 - Appears to support character-level parsing
          for (int i = start; i < end; i++) {
            if (sentence.get(i) instanceof HasWord) {
              HasWord cl = (HasWord) sentence.get(i);
              word.append(cl.word());
            } else {
              word.append(sentence.get(i).toString());
            }
          }
          for (int state = 0; state < numStates; state++) {
            float iS = iScore[start][end][state];
            if (iS == Float.NEGATIVE_INFINITY && isTag[state]) {
              IntTaggedWord itw = new IntTaggedWord(wordNumberer.number(word), Numberer.translate(stateSpace, "tags", state));
              iScore[start][end][state] = lex.score(itw, start);
              if (iScore[start][end][state] > Float.NEGATIVE_INFINITY) {
                narrowRExtent[start][state] = start + 1;
                narrowLExtent[end][state] = end - 1;
                wideRExtent[start][state] = start + 1;
                wideLExtent[end][state] = end - 1;
              }
            }
          }
        }

      } else { // "normal" chart initialization of the [start,start+1] cell

        int word = words[start];
        int end = start + 1;
        Arrays.fill(tags[start], false);
        
        //Force tags
        String trueTagStr = null;
        if (sentence.get(start) instanceof HasTag) {
          trueTagStr = ((HasTag) sentence.get(start)).tag();
          if ("".equals(trueTagStr)) {
            trueTagStr = null;
          }
        }
        
        //Word context (e.g., morphosyntactic info)
        String wordContextStr = null;
        if(sentence.get(start) instanceof HasContext) {
          wordContextStr = ((HasContext) sentence.get(start)).current();
          if("".equals(wordContextStr))
            wordContextStr = null;
        }
        
        boolean assignedSomeTag = false;

        if ( ! floodTags || word == boundary) {
          // in this case we generate the taggings in the lexicon,
          // which may itself be tagging flexibly or using a strict lexicon.
          if (dumpTagging) {
            EncodingPrintWriter.err.println("Normal tagging " + Numberer.getGlobalNumberer("words").object(word) + " [" + word + "]", "UTF-8");
          }
          for (Iterator<IntTaggedWord> taggingI = lex.ruleIteratorByWord(word, start, wordContextStr); taggingI.hasNext(); ) {
            IntTaggedWord tagging = taggingI.next();
            int state = Numberer.translate("tags", stateSpace, tagging.tag);
            if (trueTagStr != null) { // if word was supplied with a POS tag, skip all taggings not basicCategory() compatible with supplied tag.
              if ((!Test.forceTagBeginnings && !tlp.basicCategory(tagging.tagString()).equals(trueTagStr)) ||
                  (Test.forceTagBeginnings &&  !tagging.tagString().startsWith(trueTagStr))) {
                if (dumpTagging) {
                  EncodingPrintWriter.err.println("  Skipping " + tagging + " as it doesn't match trueTagStr: " + trueTagStr, "UTF-8");
                }
                continue;
              }
            }
            // try {
            float lexScore = lex.score(tagging, start); // score the cell according to P(word|tag) in the lexicon
            if (lexScore > Float.NEGATIVE_INFINITY) {
              assignedSomeTag = true;
              iScore[start][end][state] = lexScore;
              narrowRExtent[start][state] = end;
              narrowLExtent[end][state] = start;
              wideRExtent[start][state] = end;
              wideLExtent[end][state] = start;
            }
            // } catch (Exception e) {
            // e.printStackTrace();
            // System.out.println("State: " + state + " tags " + Numberer.getGlobalNumberer("tags").object(tagging.tag));
            // }
            int tag = tagging.tag;
            tags[start][tag] = true;
            if (dumpTagging) {
              EncodingPrintWriter.err.println("Word pos " + start + " tagging " + tagging + " score " + iScore[start][end][state] + " [state " + Numberer.object("states", state) + " = " + state + "]", "UTF-8");
            }
            //if (start == length-2 && tagging.parent == puncTag)
            //  lastIsPunc = true;
          }
        } // end if ( ! floodTags || word == boundary)

        if ( ! assignedSomeTag) {
          // If you got here, either you were using forceTags (gold tags)
          // and the gold tag was not seen with that word in the training data
          // or we are in floodTags=true (recovery parse) mode
          // Here, we give words all tags for
          // which the lexicon score is not -Inf, not just seen or
          // specified taggings
          if (dumpTagging) {
            EncodingPrintWriter.err.println("Forced FlexiTagging " + Numberer.getGlobalNumberer("words").object(word), "UTF-8");
          }
          for (int state = 0; state < numStates; state++) {
            if (isTag[state] && iScore[start][end][state] == Float.NEGATIVE_INFINITY) {
              if (trueTagStr != null) {
                String tagString = (String) stateNumberer.object(state);
                if ( ! tlp.basicCategory(tagString).equals(trueTagStr)) {
                  continue;
                }
              }

              float lexScore = lex.score(new IntTaggedWord(word, Numberer.translate(stateSpace, "tags", state)), start);
              if (lexScore > Float.NEGATIVE_INFINITY) {
                iScore[start][end][state] = lexScore;
                narrowRExtent[start][state] = end;
                narrowLExtent[end][state] = start;
                wideRExtent[start][state] = end;
                wideLExtent[end][state] = start;
              }
              if (dumpTagging) {
                EncodingPrintWriter.err.println("Word pos " + start + " tagging " + (new IntTaggedWord(word, Numberer.translate(stateSpace, "tags", state))) + " score " + iScore[start][start + 1][state]  + " [state " + Numberer.object("states", state) + " = " + state + "]", "UTF-8");
              }
            }
          }
        } // end if ! assignedSomeTag

        // tag multi-counting
        if (op.dcTags) {
          for (int state = 0; state < numStates; state++) {
            if (isTag[state]) {
              iScore[start][end][state] *= (1.0 + Test.depWeight);
            }
          }
        }

        if (floodTags && (!Test.noRecoveryTagging) && ! (word == boundary)) {
          // if parse failed because of tag coverage, we put in all tags with
          // a score of -1000, by fiat.  You get here from the invocation of
          // parse(ls) inside parse(ls) *after* floodTags has been turned on.
          // Search above for "floodTags = true".
          if (dumpTagging) {
            EncodingPrintWriter.err.println("Flooding tags for " + Numberer.getGlobalNumberer("words").object(word), "UTF-8");
          }
          for (int state = 0; state < numStates; state++) {
            if (isTag[state] && iScore[start][end][state] == Float.NEGATIVE_INFINITY) {
              iScore[start][end][state] = -1000.0f;
              narrowRExtent[start][state] = end;
              narrowLExtent[end][state] = start;
              wideRExtent[start][state] = end;
              wideLExtent[end][state] = start;
            }
          }
        }

        // Apply unary rules in diagonal cells of chart
        if (spillGuts) {
          tick("Terminal Unary...");
        }
        for (int state = 0; state < numStates; state++) {
          float iS = iScore[start][end][state];
          if (iS == Float.NEGATIVE_INFINITY) {
            continue;
          }
          UnaryRule[] unaries = ug.closedRulesByChild(state);
          for (UnaryRule ur : unaries) {
            int parentState = ur.parent;
            float pS = ur.score;
            float tot = iS + pS;
            if (tot > iScore[start][end][parentState]) {
              iScore[start][end][parentState] = tot;
              narrowRExtent[start][parentState] = end;
              narrowLExtent[end][parentState] = start;
              wideRExtent[start][parentState] = end;
              wideLExtent[end][parentState] = start;
            }
          }
        }
        if (spillGuts) {
          tick("Next word...");
        }
      }
    }
  }