(Regexp re)
| 104 | // push pushes the regexp re onto the parse stack and returns the regexp. |
| 105 | // Returns null for a CHAR_CLASS that can be merged with the top-of-stack. |
| 106 | private Regexp push(Regexp re) { |
| 107 | if (re.op == Regexp.Op.CHAR_CLASS && re.runes.length == 2 && re.runes[0] == re.runes[1]) { |
| 108 | // Collapse range [x-x] -> single rune x. |
| 109 | if (maybeConcat(re.runes[0], flags & ~RE2.FOLD_CASE)) { |
| 110 | return null; |
| 111 | } |
| 112 | re.op = Regexp.Op.LITERAL; |
| 113 | re.runes = new int[] {re.runes[0]}; |
| 114 | re.flags = flags & ~RE2.FOLD_CASE; |
| 115 | } else if ((re.op == Regexp.Op.CHAR_CLASS |
| 116 | && re.runes.length == 4 |
| 117 | && re.runes[0] == re.runes[1] |
| 118 | && re.runes[2] == re.runes[3] |
| 119 | && Unicode.simpleFold(re.runes[0]) == re.runes[2] |
| 120 | && Unicode.simpleFold(re.runes[2]) == re.runes[0]) |
| 121 | || (re.op == Regexp.Op.CHAR_CLASS |
| 122 | && re.runes.length == 2 |
| 123 | && re.runes[0] + 1 == re.runes[1] |
| 124 | && Unicode.simpleFold(re.runes[0]) == re.runes[1] |
| 125 | && Unicode.simpleFold(re.runes[1]) == re.runes[0])) { |
| 126 | // Case-insensitive rune like [Aa] or [Δδ]. |
| 127 | if (maybeConcat(re.runes[0], flags | RE2.FOLD_CASE)) { |
| 128 | return null; |
| 129 | } |
| 130 | |
| 131 | // Rewrite as (case-insensitive) literal. |
| 132 | re.op = Regexp.Op.LITERAL; |
| 133 | re.runes = new int[] {re.runes[0]}; |
| 134 | re.flags = flags | RE2.FOLD_CASE; |
| 135 | } else { |
| 136 | // Incremental concatenation. |
| 137 | maybeConcat(-1, 0); |
| 138 | } |
| 139 | |
| 140 | stack.add(re); |
| 141 | return re; |
| 142 | } |
| 143 | |
| 144 | // maybeConcat implements incremental concatenation |
| 145 | // of literal runes into string nodes. The parser calls this |
no test coverage detected