code: public Map<Integer, PrefixSet> firsts(int k) {
          IntBitSet terminals;
          IntBitSet nonterminals;
          Map<Integer, PrefixSet> result;
          PrefixSet first;
          int oldSize;
          boolean modified;
          Concat concat;
  
          result = new HashMap<Integer, PrefixSet>();
          terminals = new IntBitSet();
          nonterminals = new IntBitSet();
          getTerminals(terminals);
          getNonterminals(nonterminals);
          for (int symbol = terminals.first(); symbol != -1; symbol = terminals.next(symbol)) {
              result.put(symbol, PrefixSet.one(symbol));
          }
          for (int symbol = nonterminals.first(); symbol != -1; symbol = nonterminals.next(symbol)) {
              result.put(symbol, new PrefixSet());
          }
          do {
              modified = false;
              for (int p = 0; p < getProductionCount(); p++) {
                  first = result.get(getLeft(p));
                  oldSize = first.size();
                  concat = new Concat(k);
                  for (int ofs = 0, length = getLength(p); ofs < length; ofs++) {
                      if (concat.with(result.get(getRight(p, ofs)))) {
                          break;
                      }
                  }
                  first.addAll(concat.result());
                  if (first.size() != oldSize) {
                      modified = true;
                  }
              }
          } while (modified);
          for (int symbol = nonterminals.first(); symbol != -1; symbol = nonterminals.next(symbol)) {
              if (result.get(symbol).size() == 0) {
                  throw new IllegalStateException("" + symbol);
              }
          }
          return result;
      }
docs: --