StringSearcher { public String findAndReplace(String src, ReplacementSelector<? super MATCHRESULT> replacer) { StringMatchIterator<MATCHRESULT> it = searchString(src); StringReplaceAppendable dest=null; int doneTo=0; while(it.hasNext()) { MATCHRESULT mr = it.next(); int s = it.matchStartPosition(); int e = it.matchEndPosition(); if (dest == null) { dest = new StringReplaceAppendable(src); } if (doneTo < s) { dest.append(src, doneTo, s); } doneTo = replacer.apply(dest, mr, src, s, e); if (doneTo <= 0) { doneTo = e; } else { if (doneTo <= s) { throw new IndexOutOfBoundsException("Replacer tried to rescan matched string"); } it.reposition(doneTo); } } if (dest != null) { if (doneTo < src.length()) { dest.append(src, doneTo, src.length()); } return dest.toString(); } else { return src; } } StringSearcher(DfaState<MATCHRESULT> matcher,
            DfaState<?> reverseFinder); @SuppressWarnings("unchecked") StringMatchIterator<MATCHRESULT> searchString(String src); String findAndReplace(String src, ReplacementSelector<? super MATCHRESULT> replacer);  }
@Test public void test() throws Exception { DfaBuilder<JavaToken> builder = new DfaBuilder<>(); for (JavaToken tok : JavaToken.values()) { builder.addPattern(tok.m_pattern, tok); } StringSearcher<JavaToken> searcher = builder.buildStringSearcher(null); String instr = _readResource("SearcherTestInput.txt"); String want = _readResource("SearcherTestOutput.txt"); String have = searcher.findAndReplace(instr, StringSearcherTest::tokenReplace); Assert.assertEquals(want, have); }