diff --git a/test/Regex.java b/test/Regex.java index 16b50745fa..b26105e1ed 100644 --- a/test/Regex.java +++ b/test/Regex.java @@ -81,5 +81,7 @@ public class Regex { expectMatch("\\078", "\0078"); expectSplit("(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)", "a + b * x", "a", " + ", "b", " * ", "x"); + expectMatch("[0-9[def]]", "f"); + expectNoMatch("[a-z&&[^d-f]]", "f"); } } diff --git a/test/regex/CharacterMatcher.java b/test/regex/CharacterMatcher.java index b5b99a75cb..fd8109622c 100644 --- a/test/regex/CharacterMatcher.java +++ b/test/regex/CharacterMatcher.java @@ -98,6 +98,17 @@ class CharacterMatcher { this.inversePattern = inversePattern; } + private void intersect(CharacterMatcher other) { + boolean inversePattern = this.inversePattern && other.inversePattern; + if ((map.length > other.map.length) ^ inversePattern) { + map = java.util.Arrays.copyOf(map, other.map.length); + } + for (int i = 0; i < map.length; ++ i) { + map[i] = (matches((char)i) && other.matches((char)i)) ^ inversePattern; + } + this.inversePattern = inversePattern; + } + static class Parser { private final char[] description; private int offset; @@ -248,8 +259,28 @@ class CharacterMatcher { } else { matcher.setMatch(previous); } - } else if (c == '&' || c == '[') { - unsupported("operation"); + } else if (c == '[') { + Parser parser = new Parser(description); + CharacterMatcher other = parser.parseClass(offset - 1); + if (other == null) { + unsupported("invalid merge"); + } + matcher.merge(other); + offset = parser.getEndOffset(); + previous = -1; + } else if (c == '&') { + if (offset + 2 > description.length || description[offset] != '&' + || description[offset + 1] != '[') { + unsupported("operation"); + } + Parser parser = new Parser(description); + CharacterMatcher other = parser.parseClass(offset + 1); + if (other == null) { + unsupported("invalid intersection"); + } + matcher.intersect(other); + offset = parser.getEndOffset(); + previous = -1; } else if (c == ']') { break; } else {