]> Cypherpunks.ru repositories - gostls13.git/commitdiff
regexp/syntax: accept (?<name>...) syntax as valid capture
authorMauri de Souza Meneguzzo <mauri870@gmail.com>
Sat, 29 Jul 2023 20:26:00 +0000 (20:26 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 31 Jul 2023 19:52:57 +0000 (19:52 +0000)
Currently the only named capture supported by regexp is (?P<name>a).

The syntax (?<name>a) is also widely used and there is currently an effort from
 the Rust regex and RE2 teams to also accept this syntax.

Fixes #58458

Change-Id: If22d44d3a5c4e8133ec68238ab130c151ca7c5c5
GitHub-Last-Rev: 31b50e6ab40cfb0f36df6f570525657d4680017f
GitHub-Pull-Request: golang/go#61624
Reviewed-on: https://go-review.googlesource.com/c/go/+/513838
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/regexp/syntax/doc.go
src/regexp/syntax/parse.go
src/regexp/syntax/parse_test.go

index f6a4b43f7aebb1796b75da85eccb169ad401577d..eb8a971c734874d7ee5f7c4648a287999ad6be1c 100644 (file)
@@ -56,6 +56,7 @@ Grouping:
 
        (re)           numbered capturing group (submatch)
        (?P<name>re)   named & numbered capturing group (submatch)
+       (?<name>re)    named & numbered capturing group (submatch)
        (?:re)         non-capturing group
        (?flags)       set flags within current group; non-capturing
        (?flags:re)    set flags during re; non-capturing
index accee9ab089edc1c78a9b7ed3eb00d6a0cc4167b..a4ccfe3bdbc75ddcb69378b99f454f015ca5681a 100644 (file)
@@ -1159,9 +1159,18 @@ func (p *parser) parsePerlFlags(s string) (rest string, err error) {
        // support all three as well. EcmaScript 4 uses only the Python form.
        //
        // In both the open source world (via Code Search) and the
-       // Google source tree, (?P<expr>name) is the dominant form,
-       // so that's the one we implement. One is enough.
-       if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
+       // Google source tree, (?P<expr>name) and (?<expr>name) are the
+       // dominant forms of named captures and both are supported.
+       startsWithP := len(t) > 4 && t[2] == 'P' && t[3] == '<'
+       startsWithName := len(t) > 3 && t[2] == '<'
+
+       if startsWithP || startsWithName {
+               // position of expr start
+               exprStartPos := 4
+               if startsWithName {
+                       exprStartPos = 3
+               }
+
                // Pull out name.
                end := strings.IndexRune(t, '>')
                if end < 0 {
@@ -1171,8 +1180,8 @@ func (p *parser) parsePerlFlags(s string) (rest string, err error) {
                        return "", &Error{ErrInvalidNamedCapture, s}
                }
 
-               capture := t[:end+1] // "(?P<name>"
-               name := t[4:end]     // "name"
+               capture := t[:end+1]        // "(?P<name>" or "(?<name>"
+               name := t[exprStartPos:end] // "name"
                if err = checkUTF8(name); err != nil {
                        return "", err
                }
index 67e3c5622a0fef2d4793c76b9bce70603edd21bd..d7999046e0eaaa643a9dc29bb947954f1bb61653 100644 (file)
@@ -160,6 +160,7 @@ var parseTests = []parseTest{
 
        // Test named captures
        {`(?P<name>a)`, `cap{name:lit{a}}`},
+       {`(?<name>a)`, `cap{name:lit{a}}`},
 
        // Case-folded literals
        {`[Aa]`, `litfold{A}`},
@@ -482,6 +483,11 @@ var invalidRegexps = []string{
        `(?P<name`,
        `(?P<x y>a)`,
        `(?P<>a)`,
+       `(?<name>a`,
+       `(?<name>`,
+       `(?<name`,
+       `(?<x y>a)`,
+       `(?<>a)`,
        `[a-Z]`,
        `(?i)[a-Z]`,
        `\Q\E*`,