code: private static MutableFst makeFilter(WriteableSymbolTable table, Semiring semiring, String eps1, String eps2) {
  
      MutableFst filter = new MutableFst(semiring, table, table);
  
      // State 0
      MutableState s0 = filter.newStartState();
      s0.setFinalWeight(semiring.one());
      MutableState s1 = filter.newState();
      s1.setFinalWeight(semiring.one());
      MutableState s2 = filter.newState();
      s2.setFinalWeight(semiring.one());
  
      filter.addArc(s0, eps2, eps1, s0, semiring.one());
      filter.addArc(s0, eps1, eps1, s1, semiring.one());
      filter.addArc(s0, eps2, eps2, s2, semiring.one());
      // self loops
      filter.addArc(s1, eps1, eps1, s1, semiring.one());
      filter.addArc(s2, eps2, eps2, s2, semiring.one());
      for (ObjectIntCursor<String> cursor : table) {
        int i = cursor.value;
        String key = cursor.key;
        if (key.equals(Fst.EPS) || key.equals(eps1) || key.equals(eps2)) {
          continue;
        }
        filter.addArc(s0, i, i, s0, semiring.one());
        filter.addArc(s1, i, i, s0, semiring.one());
        filter.addArc(s2, i, i, s0, semiring.one());
      }
      return filter;
    }
docs: Get a filter to use for avoiding multiple epsilon paths in the resulting Fst
  
  See: M. Mohri, "Weighted automata algorithms", Handbook of Weighted Automata. Springer, pp. 213-250, 2009.
  
  @param table    the filter's input/output symbols
  @param semiring the semiring to use in the operation