static bool flexMatchIC_debug; static bool flexMatchIC(S pat, S s) { ret flexMatchIC(pat, s, null); } static bool flexMatchIC(S pat, S s, Matches m) { L tokpat = codeTokens(javaTok(pat)); L tokfull = joinBrackets(javaTok(s)); L tok = codeTokens(tokfull); new BitSet bla; if (!flexMatchIC_impl(tokpat, 0, tok, 0, bla)) ret false; if (m != null) { new L l; for (int i = 1; i < l(tokfull); i += 2) { if (bla.get(i/2)) { int j = i; while (j < l(tokfull) && bla.get(j/2)) j += 2; l.add(join(subList(tokfull, i, j-1))); i = j-2; } } m.m = toStringArray(l); } ret true; } static bool flexMatchIC_impl(L pat, int ipat, L tok, int itok, BitSet bla) { if (flexMatchIC_debug) print("flexMatchIC " + structure(subList(pat, ipat)) + " " + structure(subList(tok, itok)) + " " + structure(bla)); if (ipat >= l(pat)) ret itok >= l(tok); S t = pat.get(ipat); if (eq(t, "*")) if (itok >= l(tok)) // nothing to consume - just advance in pattern ret flexMatchIC_impl(pat, ipat+1, tok, itok, bla); else { // something to consume - try both continuing and ending to fill "*" bla.set(itok); if (flexMatchIC_impl(pat, ipat, tok, itok+1, bla) || flexMatchIC_impl(pat, ipat+1, tok, itok+1, bla)) ret true; // success, leave mark bla.clear(itok); // fail, undo marking ret false; } if (itok >= l(tok)) { if (flexMatchIC_debug) print("too much pattern"); ret false; } if (neqic(tok.get(itok), t)) { if (flexMatchIC_debug) print("mismatch"); ret false; } // ok, consume and proceed ret flexMatchIC_impl(pat, ipat+1, tok, itok+1, bla); }