code: public void expandSymbol(int symbol) {
          int prod, maxProd;
          int ofs, maxOfs;
          int ofs2, maxOfs2;
          int i, j;
          boolean found;
          int count, nextCount;
          IntArrayList next;
          int[][] expand;
          List<int[]> expandLst;
          int right;
  
          maxProd = getProductionCount();
  
          // make an array of the expand prods to easily index them;
          // storing the indexes instead is difficult because the indexes
          // max change
          expandLst = new ArrayList<int[]>();
          for (prod = 0; prod < maxProd; prod++) {
              if (getLeft(prod) == symbol) {
                  expandLst.add(getProduction(prod));
              }
          }
          expand = new int[expandLst.size()][];
          expandLst.toArray(expand);
  
          for (prod = maxProd - 1; prod >= 0; prod--) {
              maxOfs = getLength(prod);
              found = false;
              nextCount = 1;
              for (ofs = 0; ofs < maxOfs; ofs++) {
                  if (getRight(prod, ofs) == symbol) {
                      found = true;
                      nextCount *= expand.length;
                  }
              }
              if (found) {
                  // testing found is an optimization
                  for (i = 0; i < nextCount; i++) {
                      count = i;
                      next = new IntArrayList();
                      next.add(getLeft(prod));
                      for (ofs = 0; ofs < maxOfs; ofs++) {
                          right = getRight(prod, ofs);
                          if (right == symbol) {
                              j = count % expand.length;
                              maxOfs2 = expand[j].length;
                              for (ofs2 = 1; ofs2 < maxOfs2; ofs2++) {
                                  next.add(expand[j][ofs2]);
                              }
                              count /= expand.length;
                          } else {
                              next.add(right);
                          }
                      }
                      if (count != 0) {
                          throw new RuntimeException();
                      }
                      addProduction(prod + 1, next.toArray());
                  }
                  removeProduction(prod);
              }
          }
      }
docs: expansion is not performed recurively