/** * Returns all but the first matcher from a sequence or True if there is only a single * matcher in the sequence. */ static Matcher tail(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> ms = matcher.<SeqMatcher>as().matchers(); return SeqMatcher.create(ms.subList(1, ms.size())); } else { return TrueMatcher.INSTANCE; } }
/** Create a new instance. */ static Matcher create(Matcher... matchers) { switch (matchers.length) { case 0: return TrueMatcher.INSTANCE; case 1: return matchers[0]; default: return new SeqMatcher(matchers); } }
/** Create a new instance. */ static Matcher create(List<Matcher> matchers) { return create(matchers.toArray(new Matcher[] {})); }
/** Returns the first matcher from a sequence. */ static Matcher head(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> ms = matcher.<SeqMatcher>as().matchers(); return ms.get(0); } else { return matcher; } }
/** Create a new instance. */ static Matcher create(List<Matcher> matchers) { return create(matchers.toArray(new Matcher[] {})); }
/** Returns the first matcher from a sequence. */ static Matcher head(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> ms = matcher.<SeqMatcher>as().matchers(); return ms.get(0); } else { return matcher; } }
/** * Returns all but the first matcher from a sequence or True if there is only a single * matcher in the sequence. */ static Matcher tail(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> ms = matcher.<SeqMatcher>as().matchers(); return SeqMatcher.create(ms.subList(1, ms.size())); } else { return TrueMatcher.INSTANCE; } }
@Override public Matcher mergeNext(Matcher after) { if (after instanceof TrueMatcher) { return this; } List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { ms.add(SeqMatcher.create(m, after)); } return OrMatcher.create(ms); }
/** * If a sequence contains an explicit false matcher then the whole sequence will never match * and can be treated as false. */ static Matcher sequenceWithFalseIsFalse(Matcher matcher) { if (matcher instanceof SeqMatcher) { for (Matcher m : matcher.<SeqMatcher>as().matchers()) { if (m instanceof FalseMatcher) { return FalseMatcher.INSTANCE; } } } return matcher; }
/** Create a new instance. */ static Matcher create(Matcher... matchers) { switch (matchers.length) { case 0: return TrueMatcher.INSTANCE; case 1: return matchers[0]; default: return new SeqMatcher(matchers); } }
/** * The true matcher is sometimes used as a placeholder while parsing. For sequences it isn't * needed and it is faster to leave them out. */ static Matcher removeTrueInSequence(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { if (!(m instanceof TrueMatcher)) { ms.add(m); } } return SeqMatcher.create(ms); } return matcher; }
@Override public Matcher rewriteEnd(Function<Matcher, Matcher> f) { List<Matcher> ms = new ArrayList<>(); for (int i = 0; i < matchers.length - 1; ++i) { ms.add(matchers[i]); } ms.add(matchers[matchers.length - 1].rewriteEnd(f)); return f.apply(SeqMatcher.create(ms)); }
/** * If a sequence contains an explicit false matcher then the whole sequence will never match * and can be treated as false. */ static Matcher sequenceWithFalseIsFalse(Matcher matcher) { if (matcher instanceof SeqMatcher) { for (Matcher m : matcher.<SeqMatcher>as().matchers()) { if (m instanceof FalseMatcher) { return FalseMatcher.INSTANCE; } } } return matcher; }
/** * The true matcher is sometimes used as a placeholder while parsing. For sequences it isn't * needed and it is faster to leave them out. */ static Matcher removeTrueInSequence(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { if (!(m instanceof TrueMatcher)) { ms.add(m); } } return SeqMatcher.create(ms); } return matcher; }
@Override public Matcher mergeNext(Matcher after) { if (after instanceof TrueMatcher) { return this; } Matcher m = (next instanceof TrueMatcher) ? after : SeqMatcher.create(next, after); return new ZeroOrMoreMatcher(repeated, m); }
/** * If a start anchor is followed by a repeated any match, then the start anchor can be removed * as it will not change the result ({@code "^.*" => ".*"}). */ static Matcher removeStartFollowedByMatchAny(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); if (matchers.size() == 2 && matchers.get(0) instanceof StartMatcher && matchers.get(1) instanceof ZeroOrMoreMatcher) { ZeroOrMoreMatcher zm = matchers.get(1).as(); if (zm.repeated() instanceof AnyMatcher) { return zm; } } } return matcher; }
/** * Since we do not need to capture the contents, nested sequences can be simplified to * a just a simple sequence. For example, {@code "a(b.*c)d" => "ab.*cd"}. */ static Matcher flattenNestedSequences(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { if (m instanceof SeqMatcher) { ms.addAll(m.<SeqMatcher>as().matchers()); } else { ms.add(m); } } return SeqMatcher.create(ms); } return matcher; }
@Override public Matcher mergeNext(Matcher after) { if (after instanceof TrueMatcher) { return this; } List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { ms.add(SeqMatcher.create(m, after)); } return OrMatcher.create(ms); }
/** * If a start anchor is followed by a repeated any match, then the start anchor can be removed * as it will not change the result ({@code "^.*" => ".*"}). */ static Matcher removeStartFollowedByMatchAny(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); if (matchers.size() == 2 && matchers.get(0) instanceof StartMatcher && matchers.get(1) instanceof ZeroOrMoreMatcher) { ZeroOrMoreMatcher zm = matchers.get(1).as(); if (zm.repeated() instanceof AnyMatcher) { return zm; } } } return matcher; }
/** * Since we do not need to capture the contents, nested sequences can be simplified to * a just a simple sequence. For example, {@code "a(b.*c)d" => "ab.*cd"}. */ static Matcher flattenNestedSequences(Matcher matcher) { if (matcher instanceof SeqMatcher) { List<Matcher> matchers = matcher.<SeqMatcher>as().matchers(); List<Matcher> ms = new ArrayList<>(); for (Matcher m : matchers) { if (m instanceof SeqMatcher) { ms.addAll(m.<SeqMatcher>as().matchers()); } else { ms.add(m); } } return SeqMatcher.create(ms); } return matcher; }