Skip to content

Commit 9b3f052

Browse files
junyersjamesr
authored andcommitted
Add support for (?<name>expr).
This follows google/re2@6148386 (and golang/go@ee61186) to some extent.
1 parent e3c736d commit 9b3f052

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

java/com/google/re2j/Parser.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,21 +1053,22 @@ private void parsePerlFlags(StringIterator t) throws PatternSyntaxException {
10531053
// support all three as well. EcmaScript 4 uses only the Python form.
10541054
//
10551055
// In both the open source world (via Code Search) and the
1056-
// Google source tree, (?P<expr>name) is the dominant form,
1057-
// so that's the one we implement. One is enough.
1056+
// Google source tree, (?P<name>expr) and (?<name>expr) are the
1057+
// dominant forms of named captures and both are supported.
10581058
String s = t.rest();
1059-
if (s.startsWith("(?P<")) {
1059+
if (s.startsWith("(?P<") || s.startsWith("(?<")) {
10601060
// Pull out name.
1061-
int end = s.indexOf('>');
1061+
int begin = s.charAt(2) == 'P' ? 4 : 3;
1062+
int end = s.indexOf('>', begin);
10621063
if (end < 0) {
10631064
throw new PatternSyntaxException(ERR_INVALID_NAMED_CAPTURE, s);
10641065
}
1065-
String name = s.substring(4, end); // "name"
1066+
String name = s.substring(begin, end); // "name"
10661067
t.skipString(name);
1067-
t.skip(5); // "(?P<>"
1068+
t.skip(begin + 1); // "(?P<>" or "(?<>"
10681069
if (!isValidCaptureName(name)) {
10691070
throw new PatternSyntaxException(
1070-
ERR_INVALID_NAMED_CAPTURE, s.substring(0, end)); // "(?P<name>"
1071+
ERR_INVALID_NAMED_CAPTURE, s.substring(0, end + 1)); // "(?P<name>" or "(?<name>"
10711072
}
10721073
// Like ordinary capture, but named.
10731074
Regexp re = op(Regexp.Op.LEFT_PAREN);

javatests/com/google/re2j/ParserTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ public boolean applies(int r) {
232232

233233
// Test named captures
234234
{"(?P<name>a)", "cap{name:lit{a}}"},
235+
{"(?<name>a)", "cap{name:lit{a}}"},
235236

236237
// Case-folded literals
237238
{"[Aa]", "litfold{A}"},
@@ -530,12 +531,20 @@ private static String runesToString(int[] runes) {
530531
"(?P<name",
531532
"(?P<x y>a)",
532533
"(?P<>a)",
534+
"(?<name>a",
535+
"(?<name>",
536+
"(?<name",
537+
"(?<x y>a)",
538+
"(?<>a)",
533539
"[a-Z]",
534540
"(?i)[a-Z]",
535541
"a{100000}",
536542
"a{100000,}",
537543
// Group names may not be repeated
538544
"(?P<foo>bar)(?P<foo>baz)",
545+
"(?P<foo>bar)(?<foo>baz)",
546+
"(?<foo>bar)(?P<foo>baz)",
547+
"(?<foo>bar)(?<foo>baz)",
539548
"\\x", // https://github.com/google/re2j/issues/103
540549
"\\xv", // https://github.com/google/re2j/issues/103
541550
};
@@ -550,6 +559,7 @@ private static String runesToString(int[] runes) {
550559
"\\Q\\\\\\\\\\E",
551560
"(?:a)",
552561
"(?P<name>a)",
562+
"(?<name>a)",
553563
};
554564

555565
private static final String[] ONLY_POSIX = {

0 commit comments

Comments
 (0)