NfaMatcher { public Set<String> matchPartial(List<T> args) { Set<State> clist = new HashSet<>(); compile(); addState(clist, start); for (T arg : args) { Set<State> nlist = new HashSet<>(); clist.stream() .filter(s -> !Objects.equals(State.Match, s.c) && !Objects.equals(State.Split, s.c)) .filter(s -> matcher.apply(arg, s.c)) .forEach(s -> addState(nlist, s.out)); clist = nlist; } return clist.stream() .filter(s -> !Objects.equals(State.Match, s.c) && !Objects.equals(State.Split, s.c)) .map(s -> s.c) .collect(Collectors.toSet()); } NfaMatcher(String regexp, BiFunction<T, String, Boolean> matcher); void compile(); boolean match(List<T> args); Set<String> matchPartial(List<T> args);  }
@Test public void testPartial() { assertEquals(asSet("C1", "C2", "C3", "C4", "C5"), matchPartial("(C1 | C2 | C3)* C4? C5+", "--opt1=a")); assertEquals(asSet("C5"), matchPartial("(C1 | C2 | C3)* C4? C5+", "--opt1=a", "--myopt")); }
@Test public void testPartial2() { assertEquals(asSet("C3"), matchPartial(" ( C1 ( C2 ( C3 ) | C4 | C5 ) ) ", "--opt1", "--opt2")); }