case 2: if (alternatives.get(1) instanceof Empty) { // (?:a|) -> a? return new Repetition(alternatives.get(0), 0, 1, true); } else if (alternatives.get(0) instanceof Empty) { return new Repetition(alternatives.get(1), 0, 1, false);
@Override protected void appendSourceCode(StringBuilder sb) { int bodyStart = sb.length(); appendBodySourceCode(sb); int bodyEnd = sb.length(); int bodyLen = bodyEnd - bodyStart; int expandedMin = min - expanded; int expandedMax = max == Integer.MAX_VALUE ? max : max - expanded; int suffixLen = suffixLen(min, max); int expandedSuffixLen = suffixLen(expandedMin, expandedMax); if (bodyLen * expanded + expandedSuffixLen < suffixLen && !body.hasCapturingGroup()) {
case 2: if (alternatives.get(1) instanceof Empty) { // (?:a|) -> a? return new Repetition(alternatives.get(0), 0, 1, true); } else if (alternatives.get(0) instanceof Empty) { return new Repetition(alternatives.get(1), 0, 1, false);
@Override protected void appendSourceCode(StringBuilder sb) { int bodyStart = sb.length(); appendBodySourceCode(sb); int bodyEnd = sb.length(); int bodyLen = bodyEnd - bodyStart; int expandedMin = min - expanded; int expandedMax = max == Integer.MAX_VALUE ? max : max - expanded; int suffixLen = suffixLen(min, max); int expandedSuffixLen = suffixLen(expandedMin, expandedMax); if (bodyLen * expanded + expandedSuffixLen < suffixLen && !body.hasCapturingGroup()) {
@Override public RegExpTree simplify(String flags) { RegExpTree body = this.body.simplify(flags); if (max == 0 && !body.hasCapturingGroup()) { return Empty.INSTANCE; } if (body instanceof Empty || NEVER_MATCHES.equals(body)) { return body; } int min = this.min; int max = this.max; if (body instanceof Repetition) { Repetition rbody = (Repetition) body; if (rbody.greedy == greedy) { long lmin = ((long) min) * rbody.min; long lmax = ((long) max) * rbody.max; if (lmin < Integer.MAX_VALUE) { body = rbody.body; min = (int) lmin; max = lmax >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) lmax; } } } if (min == 1 && max == 1) { return body; } boolean greedy = this.greedy || min == max; return body.equals(this.body) && min == this.min && max == this.max && greedy == this.greedy ? this : new Repetition(body, min, max, greedy).simplify(flags); }
@Override public RegExpTree simplify(String flags) { RegExpTree body = this.body.simplify(flags); if (max == 0 && !body.hasCapturingGroup()) { return Empty.INSTANCE; } if (body instanceof Empty || NEVER_MATCHES.equals(body)) { return body; } int min = this.min; int max = this.max; if (body instanceof Repetition) { Repetition rbody = (Repetition) body; if (rbody.greedy == greedy) { long lmin = ((long) min) * rbody.min; long lmax = ((long) max) * rbody.max; if (lmin < Integer.MAX_VALUE) { body = rbody.body; min = (int) lmin; max = lmax >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) lmax; } } } if (min == 1 && max == 1) { return body; } boolean greedy = this.greedy || min == max; return body.equals(this.body) && min == this.min && max == this.max && greedy == this.greedy ? this : new Repetition(body, min, max, greedy).simplify(flags); }
private static int suffixLen(int min, int max) { // This mirrors the branches that renders a suffix in appendSourceCode below. if (max == Integer.MAX_VALUE) { switch (min) { case 0: // * case 1: // + return 1; default: return 3 + numDecimalDigits(min); // {3,} } } if (min == 0 && max == 1) { return 1; // ? } if (min == max) { if (min == 1) { return 0; // No suffix needed for {1}. } return 2 + numDecimalDigits(min); // {4} } return 3 + numDecimalDigits(min) + numDecimalDigits(max); // {2,7} }
private static int suffixLen(int min, int max) { // This mirrors the branches that renders a suffix in appendSourceCode below. if (max == Integer.MAX_VALUE) { switch (min) { case 0: // * case 1: // + return 1; default: return 3 + numDecimalDigits(min); // {3,} } } if (min == 0 && max == 1) { return 1; // ? } if (min == max) { if (min == 1) { return 0; // No suffix needed for {1}. } return 2 + numDecimalDigits(min); // {4} } return 3 + numDecimalDigits(min) + numDecimalDigits(max); // {2,7} }