private Matcher repeat(Matcher matcher) { int start = current; advance(c -> c != '}'); String[] numbers = tokens.subSequence(start, current - 1).toString().split(","); int min = Integer.parseInt(numbers[0]); int max = (numbers.length > 1) ? Integer.parseInt(numbers[1]) : min; return new RepeatMatcher(matcher, min, max); }
private Matcher repeat(Matcher matcher) { int start = current; advance(c -> c != '}'); String[] numbers = tokens.subSequence(start, current - 1).toString().split(","); int min = Integer.parseInt(numbers[0]); int max = (numbers.length > 1) ? Integer.parseInt(numbers[1]) : min; return new RepeatMatcher(matcher, min, max); }
@SuppressWarnings("PMD.AvoidBranchingStatementAsLastInLoop") private void advance(IntPredicate condition) { while (!isAtEnd() && condition.test(advance())) { continue; // loop is just used to advance the position } } }
@SuppressWarnings("PMD.AvoidBranchingStatementAsLastInLoop") private void advance(IntPredicate condition) { while (!isAtEnd() && condition.test(advance())) { continue; // loop is just used to advance the position } } }
private Matcher group() { if (peek() == '?') { advance(); char c = advance(); switch (c) { case '<': // Named capturing group advance(v -> v != '>'); if (isAtEnd()) { throw error("unclosed name for capturing group"); } return groupExpr(); case ':': // Non-capturing group return groupExpr(); case '=': return new PositiveLookaheadMatcher(expr()); case '!': return new NegativeLookaheadMatcher(expr()); default: throw unsupported("inline flags"); } } else { return groupExpr(); } }
private Matcher term() { List<Matcher> matchers = new ArrayList<>(); while (!isAtEnd() && peek() != ')' && peek() != '|') { char c = advance(); switch (c) { case '\\':
private Matcher term() { List<Matcher> matchers = new ArrayList<>(); while (!isAtEnd() && peek() != ')' && peek() != '|') { char c = advance(); switch (c) { case '\\':
private Matcher group() { if (peek() == '?') { advance(); char c = advance(); switch (c) { case '<': // Named capturing group advance(v -> v != '>'); if (isAtEnd()) { throw error("unclosed name for capturing group"); } return groupExpr(); case ':': // Non-capturing group return groupExpr(); case '=': return new PositiveLookaheadMatcher(expr()); case '!': return new NegativeLookaheadMatcher(expr()); default: throw unsupported("inline flags"); } } else { return groupExpr(); } }
boolean invert = peek() == '^'; if (invert) { advance(); set = AsciiSet.all(); char c = advance(); set = update(set, AsciiSet.fromPattern(Character.toString(c)), invert); char c = advance(); switch (c) { case '[': case '&': if (peek() == '&') { advance(); if (peek() == '[') { advance(); set = set.intersection(charClass()); } else if (peek() != ']') { tmp = namedCharClass(); if (tmp == null) { c = advance(); rangeStart = true; set = update(set, AsciiSet.fromPattern(Character.toString(c)), invert); if (rangeStart && peek() != ']') { if (peek() == '\\') { advance();
private Matcher escape() { char c = peek(); if (c == 'Q') { return quotation(); } else if (c == 'c') { throw unsupported("control character"); } else if (Constants.DIGIT.contains(c) || c == 'k') { throw unsupported("back references"); } else { AsciiSet set = namedCharClass(); if (set == null) { advance(); return new CharSeqMatcher(String.valueOf(c)); } else { return new CharClassMatcher(set); } } }
boolean invert = peek() == '^'; if (invert) { advance(); set = AsciiSet.all(); char c = advance(); set = update(set, AsciiSet.fromPattern(Character.toString(c)), invert); char c = advance(); switch (c) { case '[': case '&': if (peek() == '&') { advance(); if (peek() == '[') { advance(); set = set.intersection(charClass()); } else if (peek() != ']') { tmp = namedCharClass(); if (tmp == null) { c = advance(); rangeStart = true; set = update(set, AsciiSet.fromPattern(Character.toString(c)), invert); if (rangeStart && peek() != ']') { if (peek() == '\\') { advance();
private Matcher meta(Matcher matcher) { int start = current - 1; advance(c -> META.contains((char) c)); --current; String quantifier = tokens.subSequence(start, current).toString(); switch (quantifier) { case "?": // Makes repeat reluctant if (matcher instanceof RepeatMatcher) { return matcher; } case "??": case "?+": return OrMatcher.create(matcher, TrueMatcher.INSTANCE); case "*": case "*?": return new ZeroOrMoreMatcher(matcher, term()); case "*+": return new RepeatMatcher(matcher, 0, Integer.MAX_VALUE); case "+": case "+?": return SeqMatcher.create(matcher, new ZeroOrMoreMatcher(matcher, term())); case "++": return SeqMatcher.create(matcher, new RepeatMatcher(matcher, 1, Integer.MAX_VALUE)); default: throw new IllegalArgumentException("unknown quantifier: " + quantifier); } }
private Matcher escape() { char c = peek(); if (c == 'Q') { return quotation(); } else if (c == 'c') { throw unsupported("control character"); } else if (Constants.DIGIT.contains(c) || c == 'k') { throw unsupported("back references"); } else { AsciiSet set = namedCharClass(); if (set == null) { advance(); return new CharSeqMatcher(String.valueOf(c)); } else { return new CharClassMatcher(set); } } }
private Matcher meta(Matcher matcher) { int start = current - 1; advance(c -> META.contains((char) c)); --current; String quantifier = tokens.subSequence(start, current).toString(); switch (quantifier) { case "?": // Makes repeat reluctant if (matcher instanceof RepeatMatcher) { return matcher; } case "??": case "?+": return OrMatcher.create(matcher, TrueMatcher.INSTANCE); case "*": case "*?": return new ZeroOrMoreMatcher(matcher, term()); case "*+": return new RepeatMatcher(matcher, 0, Integer.MAX_VALUE); case "+": case "+?": return SeqMatcher.create(matcher, new ZeroOrMoreMatcher(matcher, term())); case "++": return SeqMatcher.create(matcher, new RepeatMatcher(matcher, 1, Integer.MAX_VALUE)); default: throw new IllegalArgumentException("unknown quantifier: " + quantifier); } }
@SuppressWarnings("PMD.MissingBreakInSwitch") private AsciiSet namedCharClass() { boolean invert = false; char c = advance(); switch (c) { case 'd': return Constants.DIGIT; case 'D': return Constants.DIGIT.invert(); case 's': return Constants.SPACE; case 'S': return Constants.SPACE.invert(); case 'w': return Constants.WORD_CHARS; case 'W': return Constants.WORD_CHARS.invert(); case 'h': case 'H': throw unsupported("horizontal whitespace class"); case 'v': case 'V': throw unsupported("vertical whitespace class"); case 'P': invert = true; case 'p': return newNamedCharSet(name(), invert); default: --current; return null; } }
@SuppressWarnings("PMD.MissingBreakInSwitch") private AsciiSet namedCharClass() { boolean invert = false; char c = advance(); switch (c) { case 'd': return Constants.DIGIT; case 'D': return Constants.DIGIT.invert(); case 's': return Constants.SPACE; case 'S': return Constants.SPACE.invert(); case 'w': return Constants.WORD_CHARS; case 'W': return Constants.WORD_CHARS.invert(); case 'h': case 'H': throw unsupported("horizontal whitespace class"); case 'v': case 'V': throw unsupported("vertical whitespace class"); case 'P': invert = true; case 'p': return newNamedCharSet(name(), invert); default: --current; return null; } }