C++: Remove named capture groups

This commit is contained in:
copilot-swe-agent[bot]
2026-07-23 10:12:01 +00:00
committed by GitHub
parent dda4b00922
commit 908764e603
4 changed files with 15 additions and 58 deletions

View File

@@ -502,13 +502,7 @@ abstract class RegExp extends StringLiteral {
}
/** Gets the name, if it has one, of the group in start,end */
string getGroupName(int start, int end) {
this.group(start, end) and
exists(int nameEnd |
this.namedGroupStart(start, nameEnd) and
result = this.getText().substring(start + 3, nameEnd - 1)
)
}
string getGroupName(int start, int end) { none() }
/** Whether the text in the range start, end is a group and can match the empty string. */
predicate zeroWidthMatch(int start, int end) {
@@ -586,8 +580,6 @@ abstract class RegExp extends StringLiteral {
private predicate groupStart(int start, int end) {
this.nonCapturingGroupStart(start, end)
or
this.namedGroupStart(start, end)
or
this.lookaheadAssertionStart(start, end)
or
this.negativeLookaheadAssertionStart(start, end)
@@ -603,7 +595,7 @@ abstract class RegExp extends StringLiteral {
private predicate nonCapturingGroupStart(int start, int end) {
this.isGroupStart(start) and
this.getChar(start + 1) = "?" and
this.getChar(start + 2) = [":", "=", "<", "!", "#"] and
this.getChar(start + 2) = [":", "=", "!", "#"] and
end = start + 3
}
@@ -614,25 +606,6 @@ abstract class RegExp extends StringLiteral {
end = start + 1
}
/**
* Matches the start of a named group, such as:
* - `(?<name>\w+)`
* - `(?'name'\w+)`
*/
private predicate namedGroupStart(int start, int end) {
this.isGroupStart(start) and
this.getChar(start + 1) = "?" and
(
this.getChar(start + 2) = "<" and
not this.getChar(start + 3) = "=" and // (?<=foo) is a positive lookbehind assertion
not this.getChar(start + 3) = "!" and // (?<!foo) is a negative lookbehind assertion
exists(int nameEnd |
nameEnd = min(int i | i > start + 3 and this.getChar(i) = ">") and
end = nameEnd + 1
)
)
}
/** Matches the start of a positive lookahead assertion, i.e. `(?=`. */
private predicate lookaheadAssertionStart(int start, int end) {
this.isGroupStart(start) and

View File

@@ -44,8 +44,6 @@
#-----| [RegExpConstant, RegExpNormalChar] b
#-----| [RegExpCharacterClassEscape] \w
#-----| [RegExpConstant, RegExpNormalChar] :
#-----| [RegExpCharacterClassEscape] \w
@@ -173,10 +171,10 @@
#-----| 0 -> [RegExpCharacterClass] [[:alpha:]]
#-----| 1 -> [RegExpCharacterClass] [[:digit:]]
#-----| [RegExpSequence] (?<qux>q+)\s+\k<qux>+
#-----| 0 -> [RegExpGroup] (?<qux>q+)
#-----| [RegExpSequence] (q+)\s+\k<q>+
#-----| 0 -> [RegExpGroup] (q+)
#-----| 1 -> [RegExpPlus] \s+
#-----| 2 -> [RegExpPlus] \k<qux>+
#-----| 2 -> [RegExpPlus] \k<q>+
#-----| [RegExpSequence] (a+)b+\1
#-----| 0 -> [RegExpGroup] (a+)
@@ -237,7 +235,7 @@
#-----| 2 -> [RegExpOpt] c?
#-----| 3 -> [RegExpConstant, RegExpNormalChar] d
#-----| [RegExpBackRef] \k<qux>
#-----| [RegExpBackRef] \k<q>
#-----| [RegExpBackRef] \1
@@ -249,15 +247,12 @@
#-----| [RegExpDot] .
#-----| [RegExpGroup] (?<qux>q+)
#-----| [RegExpGroup] (q+)
#-----| 0 -> [RegExpPlus] q+
#-----| [RegExpGroup] (a+)
#-----| 0 -> [RegExpPlus] a+
#-----| [RegExpGroup] (?<id>\w+)
#-----| 0 -> [RegExpPlus] \w+
#-----| [RegExpGroup] (?::+)
#-----| 0 -> [RegExpPlus] :+
@@ -364,8 +359,8 @@
#-----| [RegExpPlus] \s+
#-----| 0 -> [RegExpCharacterClassEscape] \s
#-----| [RegExpPlus] \k<qux>+
#-----| 0 -> [RegExpBackRef] \k<qux>
#-----| [RegExpPlus] \k<q>+
#-----| 0 -> [RegExpBackRef] \k<q>
#-----| [RegExpPlus] a+
#-----| 0 -> [RegExpConstant, RegExpNormalChar] a
@@ -373,9 +368,6 @@
#-----| [RegExpPlus] b+
#-----| 0 -> [RegExpConstant, RegExpNormalChar] b
#-----| [RegExpPlus] \w+
#-----| 0 -> [RegExpCharacterClassEscape] \w
#-----| [RegExpPlus] :+
#-----| 0 -> [RegExpConstant, RegExpNormalChar] :

View File

@@ -58,12 +58,9 @@ std::regex r_grp2("fo(o|b)ar");
std::regex r_grp3("(a|b|cd)e");
std::regex r_grp4("(?::+)\\w"); // Non-capturing group matching colons
// Named groups
std::regex r_ng1("(?<id>\\w+)");
// Backreferences
std::regex r_bref1("(a+)b+\\1");
std::regex r_bref2("(?<qux>q+)\\s+\\k<qux>+");
std::regex r_bref2("(q+)\\s+\\k<q>+");
// Two separate character classes, each containing a single POSIX bracket expression
std::regex r_posix1("[[:alpha:]][[:digit:]]");

View File

@@ -1,11 +1,10 @@
groupName
| file://:0:0:0:0 | (?<id>\\w+) | id |
| file://:0:0:0:0 | (?<qux>q+) | qux |
groupNumber
| file://:0:0:0:0 | (a+) | 1 |
| file://:0:0:0:0 | (a\|b\|cd) | 1 |
| file://:0:0:0:0 | (foo) | 1 |
| file://:0:0:0:0 | (o\|b) | 1 |
| file://:0:0:0:0 | (q+) | 1 |
term
| file://:0:0:0:0 | 0 | RegExpConstant,RegExpNormalChar |
| file://:0:0:0:0 | 0-9 | RegExpCharacterRange |
@@ -16,9 +15,6 @@ term
| file://:0:0:0:0 | !a | RegExpConstant,RegExpNormalChar |
| file://:0:0:0:0 | (?::+) | RegExpGroup |
| file://:0:0:0:0 | (?::+)\\w | RegExpSequence |
| file://:0:0:0:0 | (?<id>\\w+) | RegExpGroup |
| file://:0:0:0:0 | (?<qux>q+) | RegExpGroup |
| file://:0:0:0:0 | (?<qux>q+)\\s+\\k<qux>+ | RegExpSequence |
| file://:0:0:0:0 | (a+) | RegExpGroup |
| file://:0:0:0:0 | (a+)b+\\1 | RegExpSequence |
| file://:0:0:0:0 | (a\|b\|cd) | RegExpGroup |
@@ -27,6 +23,8 @@ term
| file://:0:0:0:0 | (foo)* | RegExpStar |
| file://:0:0:0:0 | (foo)*bar | RegExpSequence |
| file://:0:0:0:0 | (o\|b) | RegExpGroup |
| file://:0:0:0:0 | (q+) | RegExpGroup |
| file://:0:0:0:0 | (q+)\\s+\\k<q>+ | RegExpSequence |
| file://:0:0:0:0 | - | RegExpConstant,RegExpNormalChar |
| file://:0:0:0:0 | . | RegExpDot |
| file://:0:0:0:0 | . | RegExpDot |
@@ -74,8 +72,8 @@ term
| file://:0:0:0:0 | \\b!a\\B | RegExpSequence |
| file://:0:0:0:0 | \\d | RegExpCharacterClassEscape |
| file://:0:0:0:0 | \\d\\D | RegExpSequence |
| file://:0:0:0:0 | \\k<qux> | RegExpBackRef |
| file://:0:0:0:0 | \\k<qux>+ | RegExpPlus |
| file://:0:0:0:0 | \\k<q> | RegExpBackRef |
| file://:0:0:0:0 | \\k<q>+ | RegExpPlus |
| file://:0:0:0:0 | \\n | RegExpConstant,RegExpEscape |
| file://:0:0:0:0 | \\n | RegExpConstant,RegExpEscape |
| file://:0:0:0:0 | \\n\\r\\t | RegExpSequence |
@@ -89,8 +87,6 @@ term
| file://:0:0:0:0 | \\w | RegExpCharacterClassEscape |
| file://:0:0:0:0 | \\w | RegExpCharacterClassEscape |
| file://:0:0:0:0 | \\w | RegExpCharacterClassEscape |
| file://:0:0:0:0 | \\w | RegExpCharacterClassEscape |
| file://:0:0:0:0 | \\w+ | RegExpPlus |
| file://:0:0:0:0 | \\w+ | RegExpPlus |
| file://:0:0:0:0 | \\w+\\W | RegExpSequence |
| file://:0:0:0:0 | \| | RegExpConstant,RegExpNormalChar |
@@ -195,7 +191,6 @@ regExpNormalCharValue
| file://:0:0:0:0 | \\w | w |
| file://:0:0:0:0 | \\w | w |
| file://:0:0:0:0 | \\w | w |
| file://:0:0:0:0 | \\w | w |
| file://:0:0:0:0 | \| | \| |
| file://:0:0:0:0 | ] | ] |
| file://:0:0:0:0 | ] | ] |