From 3384bd4c3870ccb941a8dea0ec19fe939468ac53 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 02:14:27 +0900 Subject: [PATCH 01/10] feat: add support for ES2025 duplicate named capturing groups BREAKING CHANGE: add support for ES2025 duplicate named capturing groups --- src/ast.ts | 2 +- src/ecma-versions.ts | 3 +- src/group-specifiers.ts | 104 + src/parser.ts | 18 +- src/validator.ts | 26 +- .../parser/literal/basic-valid-2015-u.json | 16 +- .../parser/literal/basic-valid-2015.json | 16 +- test/fixtures/parser/literal/basic-valid.json | 16 +- ...te-named-capturing-group-invalid-2024.json | 14 + ...te-named-capturing-group-invalid-2025.json | 14 + ...cate-named-capturing-group-valid-2025.json | 291 +++ .../named-backreferences-valid-2023.json | 8 +- .../named-capturing-group-valid-2018.json | 68 +- .../literal/test262/not-categorized.json | 196 +- ...named-groups-and-regexp-match-indices.json | 529 ++++- .../regexp-duplicate-named-groups.json | 1745 ++++++++++++++++- .../literal/test262/regexp-lookbehind.json | 148 +- ...match-indices-and-regexp-named-groups.json | 24 +- .../literal/test262/regexp-named-groups.json | 160 +- 19 files changed, 3144 insertions(+), 254 deletions(-) create mode 100644 src/group-specifiers.ts create mode 100644 test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2024.json create mode 100644 test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json create mode 100644 test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json diff --git a/src/ast.ts b/src/ast.ts index 9925265..1c32e23 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -432,7 +432,7 @@ export interface Backreference extends NodeBase { type: "Backreference" parent: Alternative | Quantifier ref: number | string - resolved: CapturingGroup + resolved: CapturingGroup[] } /** diff --git a/src/ecma-versions.ts b/src/ecma-versions.ts index 4ce2cb8..3a6b1d9 100644 --- a/src/ecma-versions.ts +++ b/src/ecma-versions.ts @@ -10,4 +10,5 @@ export type EcmaVersion = | 2022 | 2023 | 2024 -export const latestEcmaVersion = 2024 + | 2025 +export const latestEcmaVersion = 2025 diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts new file mode 100644 index 0000000..1fcdba5 --- /dev/null +++ b/src/group-specifiers.ts @@ -0,0 +1,104 @@ +/** + * Holds information for all GroupSpecifiers included in the pattern. + */ +export interface GroupSpecifiers { + /** + * @returns true if there are no GroupSpecifiers included in the pattern. + */ + isEmpty: () => boolean + clear: () => void + /** + * Called when visiting the Alternative. + * For ES2025, manage nesting with new Alternative scopes. + */ + enterAlternative: () => void + /** + * Called when leaving the Alternative. + */ + leaveAlternative: () => void + /** + * Checks whether the given group name is within the pattern. + */ + hasInPattern: (name: string) => boolean + /** + * Checks whether the given group name is within the current scope. + */ + hasInScope: (name: string) => boolean + /** + * Adds the given group name to the current scope. + */ + addToScope: (name: string) => void +} + +export class GroupSpecifiersAsES2018 implements GroupSpecifiers { + private groupName = new Set() + + public clear(): void { + this.groupName.clear() + } + + public isEmpty(): boolean { + return !this.groupName.size + } + + public hasInPattern(name: string): boolean { + return this.groupName.has(name) + } + + public hasInScope(name: string): boolean { + return this.hasInPattern(name) + } + + public addToScope(name: string): void { + this.groupName.add(name) + } + + // eslint-disable-next-line class-methods-use-this + public enterAlternative(): void { + // Prior to ES2025, it does not manage alternative scopes. + } + + // eslint-disable-next-line class-methods-use-this + public leaveAlternative(): void { + // Prior to ES2025, it does not manage alternative scopes. + } +} + +export class GroupSpecifiersAsES2025 implements GroupSpecifiers { + private groupNamesInAlternative = new Set() + private upperGroupNamesStack: Set[] = [] + + private groupNamesInPattern = new Set() + + public clear(): void { + this.groupNamesInAlternative.clear() + this.upperGroupNamesStack.length = 0 + this.groupNamesInPattern.clear() + } + + public isEmpty(): boolean { + return !this.groupNamesInPattern.size + } + + public enterAlternative(): void { + this.upperGroupNamesStack.push(this.groupNamesInAlternative) + this.groupNamesInAlternative = new Set(this.groupNamesInAlternative) + } + + public leaveAlternative(): void { + this.groupNamesInAlternative = this.upperGroupNamesStack.pop()! + } + + public hasInPattern(name: string): boolean { + return this.groupNamesInPattern.has(name) + } + + public hasInScope(name: string): boolean { + return this.groupNamesInAlternative.has(name) + } + + public addToScope(name: string): void { + this.groupNamesInAlternative.add(name) + this.groupNamesInPattern.add(name) + } +} diff --git a/src/parser.ts b/src/parser.ts index 6ba9fbc..1228093 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -36,7 +36,6 @@ type AppendableNode = const DUMMY_PATTERN: Pattern = {} as Pattern const DUMMY_FLAGS: Flags = {} as Flags -const DUMMY_CAPTURING_GROUP: CapturingGroup = {} as CapturingGroup function isClassSetOperand( node: UnicodeSetsCharacterClassElement, @@ -148,12 +147,12 @@ class RegExpParserState { for (const reference of this._backreferences) { const ref = reference.ref - const group = - typeof ref === "number" - ? this._capturingGroups[ref - 1] - : this._capturingGroups.find((g) => g.name === ref)! - reference.resolved = group - group.references.push(reference) + for (const group of typeof ref === "number" + ? [this._capturingGroups[ref - 1]] + : this._capturingGroups.filter((g) => g.name === ref)) { + reference.resolved.push(group) + group.references.push(reference) + } } } @@ -480,7 +479,7 @@ class RegExpParserState { end, raw: this.source.slice(start, end), ref, - resolved: DUMMY_CAPTURING_GROUP, + resolved: [], } parent.elements.push(node) this._backreferences.push(node) @@ -747,7 +746,7 @@ export namespace RegExpParser { strict?: boolean /** - * ECMAScript version. Default is `2024`. + * ECMAScript version. Default is `2025`. * - `2015` added `u` and `y` flags. * - `2018` added `s` flag, Named Capturing Group, Lookbehind Assertion, * and Unicode Property Escape. @@ -755,6 +754,7 @@ export namespace RegExpParser { * - `2022` added `d` flag. * - `2023` added more valid Unicode Property Escapes. * - `2024` added `v` flag. + * - `2025` added duplicate named capturing groups. */ ecmaVersion?: EcmaVersion } diff --git a/src/validator.ts b/src/validator.ts index 41901c9..8c2491e 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1,5 +1,10 @@ import type { EcmaVersion } from "./ecma-versions" import { latestEcmaVersion } from "./ecma-versions" +import type { GroupSpecifiers } from "./group-specifiers" +import { + GroupSpecifiersAsES2018, + GroupSpecifiersAsES2025, +} from "./group-specifiers" import { Reader } from "./reader" import { newRegExpSyntaxError } from "./regexp-syntax-error" import { @@ -231,7 +236,7 @@ export namespace RegExpValidator { strict?: boolean /** - * ECMAScript version. Default is `2024`. + * ECMAScript version. Default is `2025`. * - `2015` added `u` and `y` flags. * - `2018` added `s` flag, Named Capturing Group, Lookbehind Assertion, * and Unicode Property Escape. @@ -239,6 +244,7 @@ export namespace RegExpValidator { * - `2022` added `d` flag. * - `2023` added more valid Unicode Property Escapes. * - `2024` added `v` flag. + * - `2025` added duplicate named capturing groups. */ ecmaVersion?: EcmaVersion @@ -631,7 +637,7 @@ export class RegExpValidator { private _numCapturingParens = 0 - private _groupNames = new Set() + private _groupSpecifiers: GroupSpecifiers private _backreferenceNames = new Set() @@ -643,6 +649,10 @@ export class RegExpValidator { */ public constructor(options?: RegExpValidator.Options) { this._options = options ?? {} + this._groupSpecifiers = + this.ecmaVersion >= 2025 + ? new GroupSpecifiersAsES2025() + : new GroupSpecifiersAsES2018() } /** @@ -763,7 +773,7 @@ export class RegExpValidator { if ( !this._nFlag && this.ecmaVersion >= 2018 && - this._groupNames.size > 0 + !this._groupSpecifiers.isEmpty() ) { this._nFlag = true this.rewind(start) @@ -1301,7 +1311,7 @@ export class RegExpValidator { private consumePattern(): void { const start = this.index this._numCapturingParens = this.countCapturingParens() - this._groupNames.clear() + this._groupSpecifiers.clear() this._backreferenceNames.clear() this.onPatternEnter(start) @@ -1322,7 +1332,7 @@ export class RegExpValidator { this.raise(`Unexpected character '${c}'`) } for (const name of this._backreferenceNames) { - if (!this._groupNames.has(name)) { + if (!this._groupSpecifiers.hasInPattern(name)) { this.raise("Invalid named capture referenced") } } @@ -1380,7 +1390,9 @@ export class RegExpValidator { this.onDisjunctionEnter(start) do { + this._groupSpecifiers.enterAlternative() this.consumeAlternative(i++) + this._groupSpecifiers.leaveAlternative() } while (this.eat(VERTICAL_LINE)) if (this.consumeQuantifier(true)) { @@ -1846,8 +1858,8 @@ export class RegExpValidator { private consumeGroupSpecifier(): boolean { if (this.eat(QUESTION_MARK)) { if (this.eatGroupName()) { - if (!this._groupNames.has(this._lastStrValue)) { - this._groupNames.add(this._lastStrValue) + if (!this._groupSpecifiers.hasInScope(this._lastStrValue)) { + this._groupSpecifiers.addToScope(this._lastStrValue) return true } this.raise("Duplicate capture group name") diff --git a/test/fixtures/parser/literal/basic-valid-2015-u.json b/test/fixtures/parser/literal/basic-valid-2015-u.json index 5bc7306..707882a 100644 --- a/test/fixtures/parser/literal/basic-valid-2015-u.json +++ b/test/fixtures/parser/literal/basic-valid-2015-u.json @@ -1690,7 +1690,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1741,7 +1743,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -2104,7 +2108,9 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": "♻️../9" + "resolved": [ + "♻️../9" + ] } ] } @@ -2465,7 +2471,9 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": "♻️../10" + "resolved": [ + "♻️../10" + ] } ] } diff --git a/test/fixtures/parser/literal/basic-valid-2015.json b/test/fixtures/parser/literal/basic-valid-2015.json index fb85c3c..b7ac0be 100644 --- a/test/fixtures/parser/literal/basic-valid-2015.json +++ b/test/fixtures/parser/literal/basic-valid-2015.json @@ -3800,7 +3800,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3851,7 +3853,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -4444,7 +4448,9 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": "♻️../9" + "resolved": [ + "♻️../9" + ] } ] } @@ -5135,7 +5141,9 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": "♻️../10" + "resolved": [ + "♻️../10" + ] } ] } diff --git a/test/fixtures/parser/literal/basic-valid.json b/test/fixtures/parser/literal/basic-valid.json index 16341ee..e11ac90 100644 --- a/test/fixtures/parser/literal/basic-valid.json +++ b/test/fixtures/parser/literal/basic-valid.json @@ -3800,7 +3800,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3851,7 +3853,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -4444,7 +4448,9 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": "♻️../9" + "resolved": [ + "♻️../9" + ] } ] } @@ -5135,7 +5141,9 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": "♻️../10" + "resolved": [ + "♻️../10" + ] } ] } diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2024.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2024.json new file mode 100644 index 0000000..e61353f --- /dev/null +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2024.json @@ -0,0 +1,14 @@ +{ + "options": { + "strict": false, + "ecmaVersion": 2024 + }, + "patterns": { + "/(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})/": { + "error": { + "message": "Invalid regular expression: /(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})/: Duplicate capture group name", + "index": 45 + } + } + } +} \ No newline at end of file diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json new file mode 100644 index 0000000..670262f --- /dev/null +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json @@ -0,0 +1,14 @@ +{ + "options": { + "strict": false, + "ecmaVersion": 2025 + }, + "patterns": { + "/(?[0-9]{4})-(?[0-9]{2})/": { + "error": { + "message": "Invalid regular expression: /(?[0-9]{4})-(?[0-9]{2})/: Duplicate capture group name", + "index": 27 + } + } + } +} \ No newline at end of file diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json new file mode 100644 index 0000000..63ee83a --- /dev/null +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json @@ -0,0 +1,291 @@ +{ + "options": { + "strict": false, + "ecmaVersion": 2025 + }, + "patterns": { + "/(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 55, + "raw": "/(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 54, + "raw": "(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 27, + "raw": "(?[0-9]{4})-[0-9]{2}", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 18, + "raw": "(?[0-9]{4})", + "name": "year", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 17, + "raw": "[0-9]{4}", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 9, + "end": 17, + "raw": "[0-9]{4}", + "min": 4, + "max": 4, + "greedy": true, + "element": { + "type": "CharacterClass", + "parent": "♻️..", + "start": 9, + "end": 14, + "raw": "[0-9]", + "unicodeSets": false, + "negate": false, + "elements": [ + { + "type": "CharacterClassRange", + "parent": "♻️../..", + "start": 10, + "end": 13, + "raw": "0-9", + "min": { + "type": "Character", + "parent": "♻️..", + "start": 10, + "end": 11, + "raw": "0", + "value": 48 + }, + "max": { + "type": "Character", + "parent": "♻️..", + "start": 12, + "end": 13, + "raw": "9", + "value": 57 + } + } + ] + } + } + ] + } + ], + "references": [] + }, + { + "type": "Character", + "parent": "♻️../..", + "start": 18, + "end": 19, + "raw": "-", + "value": 45 + }, + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 19, + "end": 27, + "raw": "[0-9]{2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "CharacterClass", + "parent": "♻️..", + "start": 19, + "end": 24, + "raw": "[0-9]", + "unicodeSets": false, + "negate": false, + "elements": [ + { + "type": "CharacterClassRange", + "parent": "♻️../..", + "start": 20, + "end": 23, + "raw": "0-9", + "min": { + "type": "Character", + "parent": "♻️..", + "start": 20, + "end": 21, + "raw": "0", + "value": 48 + }, + "max": { + "type": "Character", + "parent": "♻️..", + "start": 22, + "end": 23, + "raw": "9", + "value": 57 + } + } + ] + } + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 28, + "end": 54, + "raw": "[0-9]{2}-(?[0-9]{4})", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 28, + "end": 36, + "raw": "[0-9]{2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "CharacterClass", + "parent": "♻️..", + "start": 28, + "end": 33, + "raw": "[0-9]", + "unicodeSets": false, + "negate": false, + "elements": [ + { + "type": "CharacterClassRange", + "parent": "♻️../..", + "start": 29, + "end": 32, + "raw": "0-9", + "min": { + "type": "Character", + "parent": "♻️..", + "start": 29, + "end": 30, + "raw": "0", + "value": 48 + }, + "max": { + "type": "Character", + "parent": "♻️..", + "start": 31, + "end": 32, + "raw": "9", + "value": 57 + } + } + ] + } + }, + { + "type": "Character", + "parent": "♻️../..", + "start": 36, + "end": 37, + "raw": "-", + "value": 45 + }, + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 37, + "end": 54, + "raw": "(?[0-9]{4})", + "name": "year", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 45, + "end": 53, + "raw": "[0-9]{4}", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 45, + "end": 53, + "raw": "[0-9]{4}", + "min": 4, + "max": 4, + "greedy": true, + "element": { + "type": "CharacterClass", + "parent": "♻️..", + "start": 45, + "end": 50, + "raw": "[0-9]", + "unicodeSets": false, + "negate": false, + "elements": [ + { + "type": "CharacterClassRange", + "parent": "♻️../..", + "start": 46, + "end": 49, + "raw": "0-9", + "min": { + "type": "Character", + "parent": "♻️..", + "start": 46, + "end": 47, + "raw": "0", + "value": 48 + }, + "max": { + "type": "Character", + "parent": "♻️..", + "start": 48, + "end": 49, + "raw": "9", + "value": 57 + } + } + ] + } + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 55, + "end": 55, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + } + } +} \ No newline at end of file diff --git a/test/fixtures/parser/literal/named-backreferences-valid-2023.json b/test/fixtures/parser/literal/named-backreferences-valid-2023.json index e1c52ef..1fa1fca 100644 --- a/test/fixtures/parser/literal/named-backreferences-valid-2023.json +++ b/test/fixtures/parser/literal/named-backreferences-valid-2023.json @@ -62,7 +62,9 @@ "end": 17, "raw": "\\k", "ref": "foo", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -143,7 +145,9 @@ "end": 17, "raw": "\\k", "ref": "foo", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } diff --git a/test/fixtures/parser/literal/named-capturing-group-valid-2018.json b/test/fixtures/parser/literal/named-capturing-group-valid-2018.json index 880c323..5f9ebd4 100644 --- a/test/fixtures/parser/literal/named-capturing-group-valid-2018.json +++ b/test/fixtures/parser/literal/named-capturing-group-valid-2018.json @@ -385,7 +385,9 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -466,7 +468,9 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -547,7 +551,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -628,7 +634,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -953,7 +961,9 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -1034,7 +1044,9 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -1115,7 +1127,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -1196,7 +1210,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -1307,7 +1323,9 @@ "end": 19, "raw": "\\k<$abc>", "ref": "$abc", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1388,7 +1406,9 @@ "end": 13, "raw": "\\k<あ>", "ref": "あ", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1469,7 +1489,9 @@ "end": 22, "raw": "\\k<\\u{20bb7}>", "ref": "𠮷", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1550,7 +1572,9 @@ "end": 32, "raw": "\\k<\\u{20bb7}>", "ref": "𠮷", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1631,7 +1655,9 @@ "end": 32, "raw": "\\k<\\uD842\\uDFB7>", "ref": "𠮷", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1712,7 +1738,9 @@ "end": 32, "raw": "\\k<\\u0061\\u0062\\u0063>", "ref": "abc", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1793,7 +1821,9 @@ "end": 32, "raw": "\\k", "ref": "abc", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1874,7 +1904,9 @@ "end": 47, "raw": "\\k<\\u{61}\\u{62}\\u{63}>", "ref": "abc", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1955,7 +1987,9 @@ "end": 15, "raw": "\\k", "ref": "a1", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } diff --git a/test/fixtures/parser/literal/test262/not-categorized.json b/test/fixtures/parser/literal/test262/not-categorized.json index 7674f27..b225cd0 100644 --- a/test/fixtures/parser/literal/test262/not-categorized.json +++ b/test/fixtures/parser/literal/test262/not-categorized.json @@ -664,7 +664,9 @@ "end": 25, "raw": "\\10", "ref": 10, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -673,7 +675,9 @@ "end": 27, "raw": "\\9", "ref": 9, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -682,7 +686,9 @@ "end": 29, "raw": "\\8", "ref": 8, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -691,7 +697,9 @@ "end": 31, "raw": "\\7", "ref": 7, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -700,7 +708,9 @@ "end": 33, "raw": "\\6", "ref": 6, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -709,7 +719,9 @@ "end": 35, "raw": "\\5", "ref": 5, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -718,7 +730,9 @@ "end": 37, "raw": "\\4", "ref": 4, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -727,7 +741,9 @@ "end": 39, "raw": "\\3", "ref": 3, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -736,7 +752,9 @@ "end": 41, "raw": "\\2", "ref": 2, - "resolved": "♻️../0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -745,7 +763,9 @@ "end": 43, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -1024,7 +1044,9 @@ "end": 24, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "Backreference", @@ -1033,7 +1055,9 @@ "end": 26, "raw": "\\2", "ref": 2, - "resolved": "♻️../0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1042,7 +1066,9 @@ "end": 28, "raw": "\\3", "ref": 3, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1051,7 +1077,9 @@ "end": 30, "raw": "\\4", "ref": 4, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1060,7 +1088,9 @@ "end": 32, "raw": "\\5", "ref": 5, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1069,7 +1099,9 @@ "end": 34, "raw": "\\6", "ref": 6, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1078,7 +1110,9 @@ "end": 36, "raw": "\\7", "ref": 7, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1087,7 +1121,9 @@ "end": 38, "raw": "\\8", "ref": 8, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1096,7 +1132,9 @@ "end": 40, "raw": "\\9", "ref": 9, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -1105,7 +1143,9 @@ "end": 43, "raw": "\\10", "ref": 10, - "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" + ] } ] } @@ -1997,7 +2037,9 @@ "end": 30, "raw": "\\9", "ref": 9, - "resolved": "♻️../8" + "resolved": [ + "♻️../8" + ] }, { "type": "Backreference", @@ -2006,7 +2048,9 @@ "end": 32, "raw": "\\9", "ref": 9, - "resolved": "♻️../8" + "resolved": [ + "♻️../8" + ] } ] } @@ -2284,7 +2328,9 @@ "end": 27, "raw": "\\8", "ref": 8, - "resolved": "♻️../7" + "resolved": [ + "♻️../7" + ] }, { "type": "Backreference", @@ -2293,7 +2339,9 @@ "end": 29, "raw": "\\8", "ref": 8, - "resolved": "♻️../7" + "resolved": [ + "♻️../7" + ] } ] } @@ -2493,7 +2541,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -2655,7 +2705,9 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "Character", @@ -2676,7 +2728,9 @@ "end": 21, "raw": "\\2", "ref": 2, - "resolved": "♻️../2/alternatives/0/elements/0" + "resolved": [ + "♻️../2/alternatives/0/elements/0" + ] }, { "type": "CapturingGroup", @@ -2823,7 +2877,9 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3018,7 +3074,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3347,7 +3405,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../0/element" + "resolved": [ + "♻️../0/element" + ] } ] } @@ -3944,7 +4004,9 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": "♻️../0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0" + ] } ] } @@ -4151,7 +4213,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "CapturingGroup", @@ -4190,7 +4254,9 @@ "end": 11, "raw": "\\2", "ref": 2, - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] } ] } @@ -4271,7 +4337,9 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -5643,7 +5711,9 @@ "end": 25, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6270,7 +6340,9 @@ "end": 17, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "Backreference", @@ -6279,7 +6351,9 @@ "end": 19, "raw": "\\2", "ref": 2, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } @@ -7087,7 +7161,9 @@ "end": 21, "raw": "\\2", "ref": 2, - "resolved": "♻️../0/alternatives/0/elements/1" + "resolved": [ + "♻️../0/alternatives/0/elements/1" + ] }, { "type": "Backreference", @@ -7096,7 +7172,9 @@ "end": 23, "raw": "\\5", "ref": 5, - "resolved": "♻️../1/alternatives/0/elements/1" + "resolved": [ + "♻️../1/alternatives/0/elements/1" + ] } ] } @@ -7400,7 +7478,9 @@ "end": 8, "raw": "\\1", "ref": 1, - "resolved": "♻️../../0" + "resolved": [ + "♻️../../0" + ] } } ] @@ -7508,7 +7588,9 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -7621,7 +7703,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -20455,7 +20539,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -20524,7 +20610,9 @@ "end": 11, "raw": "\\2", "ref": 2, - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] } ] } @@ -20575,7 +20663,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -22839,7 +22929,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Assertion", @@ -29464,7 +29556,9 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Character", @@ -29481,7 +29575,9 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Character", @@ -29498,7 +29594,9 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } diff --git a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json index 81e9e1d..287fbea 100644 --- a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json +++ b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json @@ -6,21 +6,532 @@ "options": {}, "patterns": { "/(?:(?:(?a)|(?b)|c)\\k){2}/d": { - "error": { - "message": "Invalid regular expression: /(?:(?:(?a)|(?b)|c)\\k){2}/d: Duplicate capture group name", - "index": 20 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 36, + "raw": "/(?:(?:(?a)|(?b)|c)\\k){2}/d", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "Group", + "parent": "♻️..", + "start": 1, + "end": 31, + "raw": "(?:(?:(?a)|(?b)|c)\\k)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 30, + "raw": "(?:(?a)|(?b)|c)\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 4, + "end": 25, + "raw": "(?:(?a)|(?b)|c)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 23, + "end": 24, + "raw": "c", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 23, + "end": 24, + "raw": "c", + "value": 99 + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 25, + "end": 30, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0", + "♻️../0/alternatives/1/elements/0" + ] + } + ] + } + ] + } + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 35, + "end": 36, + "raw": "d", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": true, + "unicodeSets": false + } } }, "/(?:(?a)|(?a)(?b))(?:(?c)|(?d))/d": { - "error": { - "message": "Invalid regular expression: /(?:(?a)|(?a)(?b))(?:(?c)|(?d))/d: Duplicate capture group name", - "index": 24 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 48, + "raw": "/(?:(?a)|(?a)(?b))(?:(?c)|(?d))/d", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 46, + "raw": "(?:(?a)|(?a)(?b))(?:(?c)|(?d))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 46, + "raw": "(?:(?a)|(?a)(?b))(?:(?c)|(?d))", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 1, + "end": 27, + "raw": "(?:(?a)|(?a)(?b))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 26, + "raw": "(?a)(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 12, + "end": 19, + "raw": "(?a)", + "name": "y", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + }, + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 19, + "end": 26, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 24, + "end": 25, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 24, + "end": 25, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + { + "type": "Group", + "parent": "♻️../..", + "start": 27, + "end": 46, + "raw": "(?:(?c)|(?d))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 30, + "end": 37, + "raw": "(?c)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 30, + "end": 37, + "raw": "(?c)", + "name": "z", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 35, + "end": 36, + "raw": "c", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 35, + "end": 36, + "raw": "c", + "value": 99 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 38, + "end": 45, + "raw": "(?d)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 38, + "end": 45, + "raw": "(?d)", + "name": "z", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 43, + "end": 44, + "raw": "d", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 43, + "end": 44, + "raw": "d", + "value": 100 + } + ] + } + ], + "references": [] + } + ] + } + ] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 47, + "end": 48, + "raw": "d", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": true, + "unicodeSets": false + } } }, "/(?a)|(?b)/d": { - "error": { - "message": "Invalid regular expression: /(?a)|(?b)/d: Duplicate capture group name", - "index": 14 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 18, + "raw": "/(?a)|(?b)/d", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 16, + "raw": "(?a)|(?b)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 17, + "end": 18, + "raw": "d", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": true, + "unicodeSets": false + } } } } diff --git a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json index ed7b5e0..7259126 100644 --- a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json @@ -9,27 +9,735 @@ "options": {}, "patterns": { "/(?:(?:(?a)|(?b))\\k){2}/": { - "error": { - "message": "Invalid regular expression: /(?:(?:(?a)|(?b))\\k){2}/: Duplicate capture group name", - "index": 20 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 33, + "raw": "/(?:(?:(?a)|(?b))\\k){2}/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 32, + "raw": "(?:(?:(?a)|(?b))\\k){2}", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 32, + "raw": "(?:(?:(?a)|(?b))\\k){2}", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 1, + "end": 32, + "raw": "(?:(?:(?a)|(?b))\\k){2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "Group", + "parent": "♻️..", + "start": 1, + "end": 29, + "raw": "(?:(?:(?a)|(?b))\\k)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 28, + "raw": "(?:(?a)|(?b))\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 4, + "end": 23, + "raw": "(?:(?a)|(?b))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 23, + "end": 28, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0", + "♻️../0/alternatives/1/elements/0" + ] + } + ] + } + ] + } + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 33, + "end": 33, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } }, "/(?:(?:(?a)|(?b)|c)\\k){2}/": { - "error": { - "message": "Invalid regular expression: /(?:(?:(?a)|(?b)|c)\\k){2}/: Duplicate capture group name", - "index": 20 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 35, + "raw": "/(?:(?:(?a)|(?b)|c)\\k){2}/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "elements": [ + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 1, + "end": 34, + "raw": "(?:(?:(?a)|(?b)|c)\\k){2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "Group", + "parent": "♻️..", + "start": 1, + "end": 31, + "raw": "(?:(?:(?a)|(?b)|c)\\k)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 30, + "raw": "(?:(?a)|(?b)|c)\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 4, + "end": 25, + "raw": "(?:(?a)|(?b)|c)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 15, + "end": 22, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 20, + "end": 21, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 23, + "end": 24, + "raw": "c", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 23, + "end": 24, + "raw": "c", + "value": 99 + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 25, + "end": 30, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0", + "♻️../0/alternatives/1/elements/0" + ] + } + ] + } + ] + } + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 35, + "end": 35, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } }, "/(?:(?a)|(?b))\\k/": { - "error": { - "message": "Invalid regular expression: /(?:(?a)|(?b))\\k/: Duplicate capture group name", - "index": 17 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 26, + "raw": "/(?:(?a)|(?b))\\k/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 25, + "raw": "(?:(?a)|(?b))\\k", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 25, + "raw": "(?:(?a)|(?b))\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 1, + "end": 20, + "raw": "(?:(?a)|(?b))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 19, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 12, + "end": 19, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [ + "♻️../../../../../1" + ] + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 20, + "end": 25, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0", + "♻️../0/alternatives/1/elements/0" + ] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 26, + "end": 26, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } }, "/(?:(?a)|(?a)(?b))(?:(?c)|(?d))/": { - "error": { - "message": "Invalid regular expression: /(?:(?a)|(?a)(?b))(?:(?c)|(?d))/: Duplicate capture group name", - "index": 24 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 47, + "raw": "/(?:(?a)|(?a)(?b))(?:(?c)|(?d))/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 46, + "raw": "(?:(?a)|(?a)(?b))(?:(?c)|(?d))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 46, + "raw": "(?:(?a)|(?a)(?b))(?:(?c)|(?d))", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 1, + "end": 27, + "raw": "(?:(?a)|(?a)(?b))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 4, + "end": 11, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 9, + "end": 10, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 26, + "raw": "(?a)(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 12, + "end": 19, + "raw": "(?a)", + "name": "y", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 17, + "end": 18, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + }, + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 19, + "end": 26, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 24, + "end": 25, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 24, + "end": 25, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + { + "type": "Group", + "parent": "♻️../..", + "start": 27, + "end": 46, + "raw": "(?:(?c)|(?d))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 30, + "end": 37, + "raw": "(?c)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 30, + "end": 37, + "raw": "(?c)", + "name": "z", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 35, + "end": 36, + "raw": "c", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 35, + "end": 36, + "raw": "c", + "value": 99 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 38, + "end": 45, + "raw": "(?d)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 38, + "end": 45, + "raw": "(?d)", + "name": "z", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 43, + "end": 44, + "raw": "d", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 43, + "end": 44, + "raw": "d", + "value": 100 + } + ] + } + ], + "references": [] + } + ] + } + ] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 47, + "end": 47, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } }, "/(?x)|(?:zy\\k)/": { @@ -129,7 +837,9 @@ "end": 19, "raw": "\\k", "ref": "a", - "resolved": "♻️../../../../../../../0/elements/0" + "resolved": [ + "♻️../../../../../../../0/elements/0" + ] } ] } @@ -157,70 +867,631 @@ } }, "/(?a)|(?b)/": { - "error": { - "message": "Invalid regular expression: /(?a)|(?b)/: Duplicate capture group name", - "index": 14 - } - }, - "/(?a)|(?b)/g": { - "error": { - "message": "Invalid regular expression: /(?a)|(?b)/g: Duplicate capture group name", - "index": 14 - } - }, - "/(?b)|(?a)/": { - "error": { - "message": "Invalid regular expression: /(?b)|(?a)/: Duplicate capture group name", - "index": 14 - } - }, - "/(?b)|(?a)/g": { - "error": { - "message": "Invalid regular expression: /(?b)|(?a)/g: Duplicate capture group name", - "index": 14 - } - }, - "/(?a)(?a)|(?b)(?b)/": { - "error": { - "message": "Invalid regular expression: /(?a)(?a)|(?b)(?b)/: Duplicate capture group name", - "index": 21 - } - }, - "/[ab]/": { "ast": { "type": "RegExpLiteral", "parent": null, "start": 0, - "end": 6, - "raw": "/[ab]/", + "end": 17, + "raw": "/(?a)|(?b)/", "pattern": { "type": "Pattern", "parent": "♻️..", "start": 1, - "end": 5, - "raw": "[ab]", + "end": 16, + "raw": "(?a)|(?b)", "alternatives": [ { "type": "Alternative", "parent": "♻️../..", "start": 1, - "end": 5, - "raw": "[ab]", + "end": 8, + "raw": "(?a)", "elements": [ { - "type": "CharacterClass", + "type": "CapturingGroup", "parent": "♻️../..", "start": 1, - "end": 5, - "raw": "[ab]", - "unicodeSets": false, - "negate": false, - "elements": [ + "end": 8, + "raw": "(?a)", + "name": "x", + "alternatives": [ { - "type": "Character", + "type": "Alternative", "parent": "♻️../..", - "start": 2, - "end": 3, + "start": 6, + "end": 7, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 17, + "end": 17, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/(?a)|(?b)/g": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 18, + "raw": "/(?a)|(?b)/g", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 16, + "raw": "(?a)|(?b)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 17, + "end": 18, + "raw": "g", + "global": true, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/(?b)|(?a)/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 17, + "raw": "/(?b)|(?a)/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 16, + "raw": "(?b)|(?a)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 17, + "end": 17, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/(?b)|(?a)/g": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 18, + "raw": "/(?b)|(?a)/g", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 16, + "raw": "(?b)|(?a)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 9, + "end": 16, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 14, + "end": 15, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 17, + "end": 18, + "raw": "g", + "global": true, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/(?a)(?a)|(?b)(?b)/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 31, + "raw": "/(?a)(?a)|(?b)(?b)/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 30, + "raw": "(?a)(?a)|(?b)(?b)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 15, + "raw": "(?a)(?a)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 1, + "end": 8, + "raw": "(?a)", + "name": "y", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 6, + "end": 7, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + }, + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 8, + "end": 15, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 13, + "end": 14, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 13, + "end": 14, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 16, + "end": 30, + "raw": "(?b)(?b)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 16, + "end": 23, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + }, + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 23, + "end": 30, + "raw": "(?b)", + "name": "y", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 28, + "end": 29, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 28, + "end": 29, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 31, + "end": 31, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/[ab]/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 6, + "raw": "/[ab]/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 5, + "raw": "[ab]", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 5, + "raw": "[ab]", + "elements": [ + { + "type": "CharacterClass", + "parent": "♻️../..", + "start": 1, + "end": 5, + "raw": "[ab]", + "unicodeSets": false, + "negate": false, + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 2, + "end": 3, "raw": "a", "value": 97 }, @@ -256,15 +1527,361 @@ } }, "/^(?:(?x)|(?y)|z)\\k$/": { - "error": { - "message": "Invalid regular expression: /^(?:(?x)|(?y)|z)\\k$/: Duplicate capture group name", - "index": 18 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 30, + "raw": "/^(?:(?x)|(?y)|z)\\k$/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 29, + "raw": "^(?:(?x)|(?y)|z)\\k$", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 29, + "raw": "^(?:(?x)|(?y)|z)\\k$", + "elements": [ + { + "type": "Assertion", + "parent": "♻️../..", + "start": 1, + "end": 2, + "raw": "^", + "kind": "start" + }, + { + "type": "Group", + "parent": "♻️../..", + "start": 2, + "end": 23, + "raw": "(?:(?x)|(?y)|z)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 5, + "end": 12, + "raw": "(?x)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 5, + "end": 12, + "raw": "(?x)", + "name": "a", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 10, + "end": 11, + "raw": "x", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 10, + "end": 11, + "raw": "x", + "value": 120 + } + ] + } + ], + "references": [ + "♻️../../../../../2" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 13, + "end": 20, + "raw": "(?y)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 13, + "end": 20, + "raw": "(?y)", + "name": "a", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 18, + "end": 19, + "raw": "y", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 18, + "end": 19, + "raw": "y", + "value": 121 + } + ] + } + ], + "references": [ + "♻️../../../../../2" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "z", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "z", + "value": 122 + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 23, + "end": 28, + "raw": "\\k", + "ref": "a", + "resolved": [ + "♻️../1/alternatives/0/elements/0", + "♻️../1/alternatives/1/elements/0" + ] + }, + { + "type": "Assertion", + "parent": "♻️../..", + "start": 28, + "end": 29, + "raw": "$", + "kind": "end" + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 30, + "end": 30, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } }, "/^(?:(?x)|(?y)|z){2}\\k$/": { - "error": { - "message": "Invalid regular expression: /^(?:(?x)|(?y)|z){2}\\k$/: Duplicate capture group name", - "index": 18 + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 33, + "raw": "/^(?:(?x)|(?y)|z){2}\\k$/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 32, + "raw": "^(?:(?x)|(?y)|z){2}\\k$", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 32, + "raw": "^(?:(?x)|(?y)|z){2}\\k$", + "elements": [ + { + "type": "Assertion", + "parent": "♻️../..", + "start": 1, + "end": 2, + "raw": "^", + "kind": "start" + }, + { + "type": "Quantifier", + "parent": "♻️../..", + "start": 2, + "end": 26, + "raw": "(?:(?x)|(?y)|z){2}", + "min": 2, + "max": 2, + "greedy": true, + "element": { + "type": "Group", + "parent": "♻️..", + "start": 2, + "end": 23, + "raw": "(?:(?x)|(?y)|z)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 5, + "end": 12, + "raw": "(?x)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 5, + "end": 12, + "raw": "(?x)", + "name": "a", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 10, + "end": 11, + "raw": "x", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 10, + "end": 11, + "raw": "x", + "value": 120 + } + ] + } + ], + "references": [ + "♻️../../../../../../2" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 13, + "end": 20, + "raw": "(?y)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 13, + "end": 20, + "raw": "(?y)", + "name": "a", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 18, + "end": 19, + "raw": "y", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 18, + "end": 19, + "raw": "y", + "value": 121 + } + ] + } + ], + "references": [ + "♻️../../../../../../2" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "z", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 21, + "end": 22, + "raw": "z", + "value": 122 + } + ] + } + ] + } + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 26, + "end": 31, + "raw": "\\k", + "ref": "a", + "resolved": [ + "♻️../1/element/alternatives/0/elements/0", + "♻️../1/element/alternatives/1/elements/0" + ] + }, + { + "type": "Assertion", + "parent": "♻️../..", + "start": 31, + "end": 32, + "raw": "$", + "kind": "end" + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 33, + "end": 33, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } } } } diff --git a/test/fixtures/parser/literal/test262/regexp-lookbehind.json b/test/fixtures/parser/literal/test262/regexp-lookbehind.json index a6bc9f9..bf35d3d 100644 --- a/test/fixtures/parser/literal/test262/regexp-lookbehind.json +++ b/test/fixtures/parser/literal/test262/regexp-lookbehind.json @@ -431,7 +431,9 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -440,7 +442,9 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/0" + ] }, { "type": "Backreference", @@ -449,7 +453,9 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -566,7 +572,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../../../../../0" + "resolved": [ + "♻️../../../../../../../../../0" + ] }, { "type": "Backreference", @@ -575,7 +583,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../../../../../0" + "resolved": [ + "♻️../../../../../../../../../0" + ] } ] } @@ -697,7 +707,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../../../../../0" + "resolved": [ + "♻️../../../../../../../../../0" + ] }, { "type": "Backreference", @@ -706,7 +718,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../../../../../0" + "resolved": [ + "♻️../../../../../../../../../0" + ] } ] } @@ -814,7 +828,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -823,7 +839,9 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -832,7 +850,9 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -943,7 +963,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -952,7 +974,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -961,7 +985,9 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -3042,7 +3068,9 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/0" + ] } ] } @@ -3127,7 +3155,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] }, { "type": "Character", @@ -3270,7 +3300,9 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] } ] }, @@ -3677,7 +3709,9 @@ "end": 17, "raw": "\\1", "ref": 1, - "resolved": "♻️../0/alternatives/0/elements/0" + "resolved": [ + "♻️../0/alternatives/0/elements/0" + ] } ] } @@ -4054,7 +4088,9 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -5047,7 +5083,9 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -5183,7 +5221,9 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -5293,7 +5333,9 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -7035,7 +7077,9 @@ "end": 10, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../3" + "resolved": [ + "♻️../../../../../3" + ] } ] } @@ -7074,7 +7118,9 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] } ] } @@ -7837,7 +7883,9 @@ "end": 9, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../3" + "resolved": [ + "♻️../../../../../3" + ] } ] } @@ -7892,7 +7940,9 @@ "end": 16, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] } ] } @@ -9441,7 +9491,9 @@ "end": 16, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../../../../../0/alternatives/0/elements/0" + ] } ] } @@ -9623,7 +9675,9 @@ "end": 20, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/0" + ] } ] } @@ -9848,7 +9902,9 @@ "end": 27, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/0" + ] } ] } @@ -10081,7 +10137,9 @@ "end": 27, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0/alternatives/0/elements/0" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/0" + ] } ] } @@ -10223,7 +10281,9 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] }, { "type": "Backreference", @@ -10232,7 +10292,9 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../0/alternatives/0/elements/1" + "resolved": [ + "♻️../../../../../0/alternatives/0/elements/1" + ] }, { "type": "Backreference", @@ -10241,7 +10303,9 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -10335,7 +10399,9 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../.." + "resolved": [ + "♻️../../../.." + ] } ] } @@ -10432,7 +10498,9 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../.." + "resolved": [ + "♻️../../../.." + ] } ] } @@ -11719,7 +11787,9 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] }, { "type": "Quantifier", @@ -11878,7 +11948,9 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] }, { "type": "Quantifier", @@ -12037,7 +12109,9 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] }, { "type": "Quantifier", diff --git a/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json b/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json index ceeba4c..a33c97c 100644 --- a/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json @@ -617,7 +617,9 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "Backreference", @@ -626,7 +628,9 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Backreference", @@ -635,7 +639,9 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -776,7 +782,9 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "Backreference", @@ -785,7 +793,9 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Backreference", @@ -794,7 +804,9 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } diff --git a/test/fixtures/parser/literal/test262/regexp-named-groups.json b/test/fixtures/parser/literal/test262/regexp-named-groups.json index 001ecda..bc5242d 100644 --- a/test/fixtures/parser/literal/test262/regexp-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-named-groups.json @@ -169,7 +169,9 @@ "end": 18, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -198,7 +200,9 @@ "end": 22, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] } ] } @@ -329,7 +333,9 @@ "end": 18, "raw": "\\1", "ref": 1, - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -358,7 +364,9 @@ "end": 22, "raw": "\\2", "ref": 2, - "resolved": "♻️../../../../../1" + "resolved": [ + "♻️../../../../../1" + ] } ] } @@ -474,7 +482,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "Backreference", @@ -483,7 +493,9 @@ "end": 15, "raw": "\\2", "ref": 2, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } @@ -594,7 +606,9 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] }, { "type": "Backreference", @@ -603,7 +617,9 @@ "end": 15, "raw": "\\2", "ref": 2, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } @@ -3624,7 +3640,9 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "Backreference", @@ -3633,7 +3651,9 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Backreference", @@ -3642,7 +3662,9 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3783,7 +3805,9 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "Backreference", @@ -3792,7 +3816,9 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "Backreference", @@ -3801,7 +3827,9 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -3991,7 +4019,9 @@ "end": 11, "raw": "\\k", "ref": "a", - "resolved": "♻️../../../.." + "resolved": [ + "♻️../../../.." + ] }, { "type": "CharacterSet", @@ -4089,7 +4119,9 @@ "end": 11, "raw": "\\k", "ref": "a", - "resolved": "♻️../../../.." + "resolved": [ + "♻️../../../.." + ] }, { "type": "CharacterSet", @@ -4638,7 +4670,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -4747,7 +4781,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -4856,7 +4892,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] }, @@ -5002,7 +5040,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] }, @@ -5857,7 +5897,9 @@ "end": 14, "raw": "\\k", "ref": "b", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -5946,7 +5988,9 @@ "end": 14, "raw": "\\k", "ref": "b", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6035,7 +6079,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6124,7 +6170,9 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6205,7 +6253,9 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "CapturingGroup", @@ -6244,7 +6294,9 @@ "end": 25, "raw": "\\k", "ref": "b", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6325,7 +6377,9 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": "♻️../2" + "resolved": [ + "♻️../2" + ] }, { "type": "CapturingGroup", @@ -6364,7 +6418,9 @@ "end": 25, "raw": "\\k", "ref": "b", - "resolved": "♻️../0" + "resolved": [ + "♻️../0" + ] } ] } @@ -6514,7 +6570,9 @@ "end": 25, "raw": "\\k", "ref": "dog", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -6669,7 +6727,9 @@ "end": 25, "raw": "\\k", "ref": "dog", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -8207,7 +8267,9 @@ "end": 21, "raw": "\\k<狗>", "ref": "狗", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -8362,7 +8424,9 @@ "end": 21, "raw": "\\k<狗>", "ref": "狗", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -9325,7 +9389,9 @@ "end": 31, "raw": "\\k<𝓓𝓸𝓰>", "ref": "𝓓𝓸𝓰", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -9480,7 +9546,9 @@ "end": 31, "raw": "\\k<𝓓𝓸𝓰>", "ref": "𝓓𝓸𝓰", - "resolved": "♻️../../../../../0" + "resolved": [ + "♻️../../../../../0" + ] } ] } @@ -12494,7 +12562,9 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -12903,7 +12973,9 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -12952,7 +13024,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } @@ -13003,7 +13077,9 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", @@ -13052,7 +13128,9 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] } ] } @@ -13103,7 +13181,9 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": "♻️../1" + "resolved": [ + "♻️../1" + ] }, { "type": "CapturingGroup", From 32084567cea96be56312b1ae07a4bdc5bed4c396 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 14:13:29 +0900 Subject: [PATCH 02/10] add test cases and fix --- src/group-specifiers.ts | 48 +++++++++++++++++-- src/validator.ts | 6 ++- ...te-named-capturing-group-invalid-2025.json | 18 +++++++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts index 1fcdba5..e7d7415 100644 --- a/src/group-specifiers.ts +++ b/src/group-specifiers.ts @@ -7,6 +7,11 @@ export interface GroupSpecifiers { */ isEmpty: () => boolean clear: () => void + /** + * Called when visiting the Disjunction. + * For ES2025, manage nesting with new Disjunction scopes. + */ + enterDisjunction: () => void /** * Called when visiting the Alternative. * For ES2025, manage nesting with new Alternative scopes. @@ -16,6 +21,10 @@ export interface GroupSpecifiers { * Called when leaving the Alternative. */ leaveAlternative: () => void + /** + * Called when leaving the Disjunction. + */ + leaveDisjunction: () => unknown /** * Checks whether the given group name is within the pattern. */ @@ -53,6 +62,11 @@ export class GroupSpecifiersAsES2018 implements GroupSpecifiers { this.groupName.add(name) } + // eslint-disable-next-line class-methods-use-this + public enterDisjunction(): void { + // Prior to ES2025, it does not manage disjunction scopes. + } + // eslint-disable-next-line class-methods-use-this public enterAlternative(): void { // Prior to ES2025, it does not manage alternative scopes. @@ -62,17 +76,26 @@ export class GroupSpecifiersAsES2018 implements GroupSpecifiers { public leaveAlternative(): void { // Prior to ES2025, it does not manage alternative scopes. } + + // eslint-disable-next-line class-methods-use-this + public leaveDisjunction(): void { + // Prior to ES2025, it does not manage disjunction scopes. + } } export class GroupSpecifiersAsES2025 implements GroupSpecifiers { + private groupNamesInDisjunction = new Set() + private groupNamesInDisjunctionStack: Set[] = [] private groupNamesInAlternative = new Set() - private upperGroupNamesStack: Set[] = [] + private groupNamesInAlternativeStack: Set[] = [] private groupNamesInPattern = new Set() public clear(): void { + this.groupNamesInDisjunction.clear() + this.groupNamesInDisjunctionStack.length = 0 this.groupNamesInAlternative.clear() - this.upperGroupNamesStack.length = 0 + this.groupNamesInAlternativeStack.length = 0 this.groupNamesInPattern.clear() } @@ -80,13 +103,29 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { return !this.groupNamesInPattern.size } + public enterDisjunction(): void { + this.groupNamesInDisjunctionStack.push(this.groupNamesInDisjunction) + this.groupNamesInDisjunction = new Set() + } + public enterAlternative(): void { - this.upperGroupNamesStack.push(this.groupNamesInAlternative) + this.groupNamesInAlternativeStack.push(this.groupNamesInAlternative) this.groupNamesInAlternative = new Set(this.groupNamesInAlternative) } public leaveAlternative(): void { - this.groupNamesInAlternative = this.upperGroupNamesStack.pop()! + for (const groupName of this.groupNamesInAlternative) { + this.groupNamesInDisjunction.add(groupName) + } + this.groupNamesInAlternative = this.groupNamesInAlternativeStack.pop()! + } + + public leaveDisjunction(): void { + for (const groupName of this.groupNamesInDisjunction) { + this.groupNamesInAlternative.add(groupName) + this.groupNamesInPattern.add(groupName) + } + this.groupNamesInDisjunction = this.groupNamesInDisjunctionStack.pop()! } public hasInPattern(name: string): boolean { @@ -99,6 +138,5 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { public addToScope(name: string): void { this.groupNamesInAlternative.add(name) - this.groupNamesInPattern.add(name) } } diff --git a/src/validator.ts b/src/validator.ts index 8c2491e..08fbc41 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1388,11 +1388,10 @@ export class RegExpValidator { const start = this.index let i = 0 + this._groupSpecifiers.enterDisjunction() this.onDisjunctionEnter(start) do { - this._groupSpecifiers.enterAlternative() this.consumeAlternative(i++) - this._groupSpecifiers.leaveAlternative() } while (this.eat(VERTICAL_LINE)) if (this.consumeQuantifier(true)) { @@ -1402,6 +1401,7 @@ export class RegExpValidator { this.raise("Lone quantifier brackets") } this.onDisjunctionLeave(start, this.index) + this._groupSpecifiers.leaveDisjunction() } /** @@ -1415,11 +1415,13 @@ export class RegExpValidator { private consumeAlternative(i: number): void { const start = this.index + this._groupSpecifiers.enterAlternative() this.onAlternativeEnter(start, i) while (this.currentCodePoint !== -1 && this.consumeTerm()) { // do nothing. } this.onAlternativeLeave(start, this.index, i) + this._groupSpecifiers.leaveAlternative() } /** diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json index 670262f..93b2394 100644 --- a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json @@ -9,6 +9,24 @@ "message": "Invalid regular expression: /(?[0-9]{4})-(?[0-9]{2})/: Duplicate capture group name", "index": 27 } + }, + "/(?:(?a)|(?b))(?c)/": { + "error": { + "message": "Invalid regular expression: /(?:(?a)|(?b))(?c)/: Duplicate capture group name", + "index": 25 + } + }, + "/(?:(?:(?a)|(?b)))(?c)/": { + "error": { + "message": "Invalid regular expression: /(?:(?:(?a)|(?b)))(?c)/: Duplicate capture group name", + "index": 29 + } + }, + "/(?:(?:(?a)|(?b))|(?:))(?c)/": { + "error": { + "message": "Invalid regular expression: /(?:(?:(?a)|(?b))|(?:))(?c)/: Duplicate capture group name", + "index": 34 + } } } } \ No newline at end of file From 803019aaf4297c1b8793196b254a16d9dac09362 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 14:32:03 +0900 Subject: [PATCH 03/10] add test cases --- ...cate-named-capturing-group-valid-2025.json | 426 ++++++++++++++++++ 1 file changed, 426 insertions(+) diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json index 63ee83a..5f72cc4 100644 --- a/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json @@ -286,6 +286,432 @@ "unicodeSets": false } } + }, + "/(?:(?:(?a)\\k|(?b)\\k)|(?:))\\k/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 45, + "raw": "/(?:(?:(?a)\\k|(?b)\\k)|(?:))\\k/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 44, + "raw": "(?:(?:(?a)\\k|(?b)\\k)|(?:))\\k", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 44, + "raw": "(?:(?:(?a)\\k|(?b)\\k)|(?:))\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 1, + "end": 39, + "raw": "(?:(?:(?a)\\k|(?b)\\k)|(?:))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 33, + "raw": "(?:(?a)\\k|(?b)\\k)", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 4, + "end": 33, + "raw": "(?:(?a)\\k|(?b)\\k)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 7, + "end": 19, + "raw": "(?a)\\k", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 7, + "end": 14, + "raw": "(?a)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "value": 97 + } + ] + } + ], + "references": [ + "♻️../1", + "♻️../../../1/elements/1", + "♻️../../../../../../../../../1" + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 14, + "end": 19, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0", + "♻️../../../1/elements/0" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 20, + "end": 32, + "raw": "(?b)\\k", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 20, + "end": 27, + "raw": "(?b)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 25, + "end": 26, + "raw": "b", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 25, + "end": 26, + "raw": "b", + "value": 98 + } + ] + } + ], + "references": [ + "♻️../../../0/elements/1", + "♻️../1", + "♻️../../../../../../../../../1" + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 27, + "end": 32, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../../../0/elements/0", + "♻️../0" + ] + } + ] + } + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 34, + "end": 38, + "raw": "(?:)", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 34, + "end": 38, + "raw": "(?:)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 37, + "end": 37, + "raw": "", + "elements": [] + } + ] + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 39, + "end": 44, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0", + "♻️../0/alternatives/0/elements/0/alternatives/1/elements/0" + ] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 45, + "end": 45, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } + }, + "/(?:(?:(?a\\k)|(?b\\k))|(?:))\\k/": { + "ast": { + "type": "RegExpLiteral", + "parent": null, + "start": 0, + "end": 45, + "raw": "/(?:(?:(?a\\k)|(?b\\k))|(?:))\\k/", + "pattern": { + "type": "Pattern", + "parent": "♻️..", + "start": 1, + "end": 44, + "raw": "(?:(?:(?a\\k)|(?b\\k))|(?:))\\k", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 1, + "end": 44, + "raw": "(?:(?:(?a\\k)|(?b\\k))|(?:))\\k", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 1, + "end": 39, + "raw": "(?:(?:(?a\\k)|(?b\\k))|(?:))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 4, + "end": 33, + "raw": "(?:(?a\\k)|(?b\\k))", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 4, + "end": 33, + "raw": "(?:(?a\\k)|(?b\\k))", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 7, + "end": 19, + "raw": "(?a\\k)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 7, + "end": 19, + "raw": "(?a\\k)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 12, + "end": 18, + "raw": "a\\k", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 12, + "end": 13, + "raw": "a", + "value": 97 + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 13, + "end": 18, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../../../..", + "♻️../../../../../../../1/elements/0" + ] + } + ] + } + ], + "references": [ + "♻️alternatives/0/elements/1", + "♻️../../../1/elements/0/alternatives/0/elements/1", + "♻️../../../../../../../../../1" + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 20, + "end": 32, + "raw": "(?b\\k)", + "elements": [ + { + "type": "CapturingGroup", + "parent": "♻️../..", + "start": 20, + "end": 32, + "raw": "(?b\\k)", + "name": "x", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 25, + "end": 31, + "raw": "b\\k", + "elements": [ + { + "type": "Character", + "parent": "♻️../..", + "start": 25, + "end": 26, + "raw": "b", + "value": 98 + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 26, + "end": 31, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../../../../../../../0/elements/0", + "♻️../../../.." + ] + } + ] + } + ], + "references": [ + "♻️../../../0/elements/0/alternatives/0/elements/1", + "♻️alternatives/0/elements/1", + "♻️../../../../../../../../../1" + ] + } + ] + } + ] + } + ] + }, + { + "type": "Alternative", + "parent": "♻️../..", + "start": 34, + "end": 38, + "raw": "(?:)", + "elements": [ + { + "type": "Group", + "parent": "♻️../..", + "start": 34, + "end": 38, + "raw": "(?:)", + "alternatives": [ + { + "type": "Alternative", + "parent": "♻️../..", + "start": 37, + "end": 37, + "raw": "", + "elements": [] + } + ] + } + ] + } + ] + }, + { + "type": "Backreference", + "parent": "♻️../..", + "start": 39, + "end": 44, + "raw": "\\k", + "ref": "x", + "resolved": [ + "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0", + "♻️../0/alternatives/0/elements/0/alternatives/1/elements/0" + ] + } + ] + } + ] + }, + "flags": { + "type": "Flags", + "parent": "♻️..", + "start": 45, + "end": 45, + "raw": "", + "global": false, + "ignoreCase": false, + "multiline": false, + "unicode": false, + "sticky": false, + "dotAll": false, + "hasIndices": false, + "unicodeSets": false + } + } } } } \ No newline at end of file From 3711614ace06331a31fb6a0ec8d3f63a508a6225 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 14:46:38 +0900 Subject: [PATCH 04/10] refactor --- src/group-specifiers.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts index e7d7415..cb7a088 100644 --- a/src/group-specifiers.ts +++ b/src/group-specifiers.ts @@ -114,16 +114,12 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { } public leaveAlternative(): void { - for (const groupName of this.groupNamesInAlternative) { - this.groupNamesInDisjunction.add(groupName) - } this.groupNamesInAlternative = this.groupNamesInAlternativeStack.pop()! } public leaveDisjunction(): void { for (const groupName of this.groupNamesInDisjunction) { this.groupNamesInAlternative.add(groupName) - this.groupNamesInPattern.add(groupName) } this.groupNamesInDisjunction = this.groupNamesInDisjunctionStack.pop()! } @@ -138,5 +134,7 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { public addToScope(name: string): void { this.groupNamesInAlternative.add(name) + this.groupNamesInDisjunction.add(name) + this.groupNamesInPattern.add(name) } } From b74101b78d890982b6118629ae11c2dad88977fb Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 15:00:34 +0900 Subject: [PATCH 05/10] fix --- src/group-specifiers.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts index cb7a088..51f16cf 100644 --- a/src/group-specifiers.ts +++ b/src/group-specifiers.ts @@ -118,10 +118,12 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { } public leaveDisjunction(): void { - for (const groupName of this.groupNamesInDisjunction) { + const child = this.groupNamesInDisjunction + this.groupNamesInDisjunction = this.groupNamesInDisjunctionStack.pop()! + for (const groupName of child) { + this.groupNamesInDisjunction.add(groupName) this.groupNamesInAlternative.add(groupName) } - this.groupNamesInDisjunction = this.groupNamesInDisjunctionStack.pop()! } public hasInPattern(name: string): boolean { From eb3552ab7ca682a130b5d734a385f8d1fbcf88f4 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sun, 14 Apr 2024 22:41:30 +0900 Subject: [PATCH 06/10] update ast types --- src/ast.ts | 13 +- src/parser.ts | 21 +- .../parser/literal/basic-valid-2015-u.json | 20 +- .../parser/literal/basic-valid-2015.json | 20 +- test/fixtures/parser/literal/basic-valid.json | 20 +- ...cate-named-capturing-group-valid-2025.json | 6 + .../named-backreferences-valid-2023.json | 10 +- .../named-capturing-group-valid-2018.json | 85 +++--- .../literal/test262/not-categorized.json | 245 +++++++----------- ...named-groups-and-regexp-match-indices.json | 1 + .../regexp-duplicate-named-groups.json | 10 +- .../literal/test262/regexp-lookbehind.json | 185 ++++++------- ...match-indices-and-regexp-named-groups.json | 30 +-- .../literal/test262/regexp-named-groups.json | 200 ++++++-------- 14 files changed, 368 insertions(+), 498 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index 1c32e23..6628567 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -428,12 +428,23 @@ export interface Character extends NodeBase { * The backreference. * E.g. `\1`, `\k` */ -export interface Backreference extends NodeBase { +export type Backreference = AmbiguousBackreference | UnambiguousBackreference +interface BaseBackreference extends NodeBase { type: "Backreference" parent: Alternative | Quantifier ref: number | string + ambiguous: boolean + resolved: CapturingGroup | CapturingGroup[] +} +export interface AmbiguousBackreference extends BaseBackreference { + ref: string + ambiguous: true resolved: CapturingGroup[] } +export interface UnambiguousBackreference extends BaseBackreference { + ambiguous: false + resolved: CapturingGroup +} /** * The flags. diff --git a/src/parser.ts b/src/parser.ts index 1228093..61522af 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -36,6 +36,7 @@ type AppendableNode = const DUMMY_PATTERN: Pattern = {} as Pattern const DUMMY_FLAGS: Flags = {} as Flags +const DUMMY_CAPTURING_GROUP: CapturingGroup = {} as CapturingGroup function isClassSetOperand( node: UnicodeSetsCharacterClassElement, @@ -147,10 +148,19 @@ class RegExpParserState { for (const reference of this._backreferences) { const ref = reference.ref - for (const group of typeof ref === "number" - ? [this._capturingGroups[ref - 1]] - : this._capturingGroups.filter((g) => g.name === ref)) { - reference.resolved.push(group) + const groups = + typeof ref === "number" + ? [this._capturingGroups[ref - 1]] + : this._capturingGroups.filter((g) => g.name === ref) + if (groups.length === 1) { + const group = groups[0] + reference.ambiguous = false + reference.resolved = group + } else { + reference.ambiguous = true + reference.resolved = groups + } + for (const group of groups) { group.references.push(reference) } } @@ -479,7 +489,8 @@ class RegExpParserState { end, raw: this.source.slice(start, end), ref, - resolved: [], + ambiguous: false, + resolved: DUMMY_CAPTURING_GROUP, } parent.elements.push(node) this._backreferences.push(node) diff --git a/test/fixtures/parser/literal/basic-valid-2015-u.json b/test/fixtures/parser/literal/basic-valid-2015-u.json index 707882a..963494d 100644 --- a/test/fixtures/parser/literal/basic-valid-2015-u.json +++ b/test/fixtures/parser/literal/basic-valid-2015-u.json @@ -1690,9 +1690,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1743,9 +1742,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -2108,9 +2106,8 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": [ - "♻️../9" - ] + "ambiguous": false, + "resolved": "♻️../9" } ] } @@ -2471,9 +2468,8 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": [ - "♻️../10" - ] + "ambiguous": false, + "resolved": "♻️../10" } ] } diff --git a/test/fixtures/parser/literal/basic-valid-2015.json b/test/fixtures/parser/literal/basic-valid-2015.json index b7ac0be..ed988e9 100644 --- a/test/fixtures/parser/literal/basic-valid-2015.json +++ b/test/fixtures/parser/literal/basic-valid-2015.json @@ -3800,9 +3800,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -3853,9 +3852,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -4448,9 +4446,8 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": [ - "♻️../9" - ] + "ambiguous": false, + "resolved": "♻️../9" } ] } @@ -5141,9 +5138,8 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": [ - "♻️../10" - ] + "ambiguous": false, + "resolved": "♻️../10" } ] } diff --git a/test/fixtures/parser/literal/basic-valid.json b/test/fixtures/parser/literal/basic-valid.json index e11ac90..e8b04da 100644 --- a/test/fixtures/parser/literal/basic-valid.json +++ b/test/fixtures/parser/literal/basic-valid.json @@ -3800,9 +3800,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -3853,9 +3852,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -4448,9 +4446,8 @@ "end": 34, "raw": "\\10", "ref": 10, - "resolved": [ - "♻️../9" - ] + "ambiguous": false, + "resolved": "♻️../9" } ] } @@ -5141,9 +5138,8 @@ "end": 37, "raw": "\\11", "ref": 11, - "resolved": [ - "♻️../10" - ] + "ambiguous": false, + "resolved": "♻️../10" } ] } diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json index 5f72cc4..de6bca9 100644 --- a/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-valid-2025.json @@ -375,6 +375,7 @@ "end": 19, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0", "♻️../../../1/elements/0" @@ -428,6 +429,7 @@ "end": 32, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../../../0/elements/0", "♻️../0" @@ -474,6 +476,7 @@ "end": 44, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0", "♻️../0/alternatives/0/elements/0/alternatives/1/elements/0" @@ -579,6 +582,7 @@ "end": 18, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../../../..", "♻️../../../../../../../1/elements/0" @@ -632,6 +636,7 @@ "end": 31, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../../../../../../../0/elements/0", "♻️../../../.." @@ -687,6 +692,7 @@ "end": 44, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0", "♻️../0/alternatives/0/elements/0/alternatives/1/elements/0" diff --git a/test/fixtures/parser/literal/named-backreferences-valid-2023.json b/test/fixtures/parser/literal/named-backreferences-valid-2023.json index 1fa1fca..051c04b 100644 --- a/test/fixtures/parser/literal/named-backreferences-valid-2023.json +++ b/test/fixtures/parser/literal/named-backreferences-valid-2023.json @@ -62,9 +62,8 @@ "end": 17, "raw": "\\k", "ref": "foo", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -145,9 +144,8 @@ "end": 17, "raw": "\\k", "ref": "foo", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } diff --git a/test/fixtures/parser/literal/named-capturing-group-valid-2018.json b/test/fixtures/parser/literal/named-capturing-group-valid-2018.json index 5f9ebd4..169b435 100644 --- a/test/fixtures/parser/literal/named-capturing-group-valid-2018.json +++ b/test/fixtures/parser/literal/named-capturing-group-valid-2018.json @@ -385,9 +385,8 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -468,9 +467,8 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -551,9 +549,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -634,9 +631,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -961,9 +957,8 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -1044,9 +1039,8 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -1127,9 +1121,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -1210,9 +1203,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -1323,9 +1315,8 @@ "end": 19, "raw": "\\k<$abc>", "ref": "$abc", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1406,9 +1397,8 @@ "end": 13, "raw": "\\k<あ>", "ref": "あ", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1489,9 +1479,8 @@ "end": 22, "raw": "\\k<\\u{20bb7}>", "ref": "𠮷", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1572,9 +1561,8 @@ "end": 32, "raw": "\\k<\\u{20bb7}>", "ref": "𠮷", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1655,9 +1643,8 @@ "end": 32, "raw": "\\k<\\uD842\\uDFB7>", "ref": "𠮷", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1738,9 +1725,8 @@ "end": 32, "raw": "\\k<\\u0061\\u0062\\u0063>", "ref": "abc", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1821,9 +1807,8 @@ "end": 32, "raw": "\\k", "ref": "abc", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1904,9 +1889,8 @@ "end": 47, "raw": "\\k<\\u{61}\\u{62}\\u{63}>", "ref": "abc", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1987,9 +1971,8 @@ "end": 15, "raw": "\\k", "ref": "a1", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } diff --git a/test/fixtures/parser/literal/test262/not-categorized.json b/test/fixtures/parser/literal/test262/not-categorized.json index b225cd0..75600ff 100644 --- a/test/fixtures/parser/literal/test262/not-categorized.json +++ b/test/fixtures/parser/literal/test262/not-categorized.json @@ -664,9 +664,8 @@ "end": 25, "raw": "\\10", "ref": 10, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -675,9 +674,8 @@ "end": 27, "raw": "\\9", "ref": 9, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -686,9 +684,8 @@ "end": 29, "raw": "\\8", "ref": 8, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -697,9 +694,8 @@ "end": 31, "raw": "\\7", "ref": 7, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -708,9 +704,8 @@ "end": 33, "raw": "\\6", "ref": 6, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -719,9 +714,8 @@ "end": 35, "raw": "\\5", "ref": 5, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -730,9 +724,8 @@ "end": 37, "raw": "\\4", "ref": 4, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -741,9 +734,8 @@ "end": 39, "raw": "\\3", "ref": 3, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -752,9 +744,8 @@ "end": 41, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -763,9 +754,8 @@ "end": 43, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -1044,9 +1034,8 @@ "end": 24, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "Backreference", @@ -1055,9 +1044,8 @@ "end": 26, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1066,9 +1054,8 @@ "end": 28, "raw": "\\3", "ref": 3, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1077,9 +1064,8 @@ "end": 30, "raw": "\\4", "ref": 4, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1088,9 +1074,8 @@ "end": 32, "raw": "\\5", "ref": 5, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1099,9 +1084,8 @@ "end": 34, "raw": "\\6", "ref": 6, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1110,9 +1094,8 @@ "end": 36, "raw": "\\7", "ref": 7, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1121,9 +1104,8 @@ "end": 38, "raw": "\\8", "ref": 8, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1132,9 +1114,8 @@ "end": 40, "raw": "\\9", "ref": 9, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -1143,9 +1124,8 @@ "end": 43, "raw": "\\10", "ref": 10, - "resolved": [ - "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0/alternatives/0/elements/0" } ] } @@ -2037,9 +2017,8 @@ "end": 30, "raw": "\\9", "ref": 9, - "resolved": [ - "♻️../8" - ] + "ambiguous": false, + "resolved": "♻️../8" }, { "type": "Backreference", @@ -2048,9 +2027,8 @@ "end": 32, "raw": "\\9", "ref": 9, - "resolved": [ - "♻️../8" - ] + "ambiguous": false, + "resolved": "♻️../8" } ] } @@ -2328,9 +2306,8 @@ "end": 27, "raw": "\\8", "ref": 8, - "resolved": [ - "♻️../7" - ] + "ambiguous": false, + "resolved": "♻️../7" }, { "type": "Backreference", @@ -2339,9 +2316,8 @@ "end": 29, "raw": "\\8", "ref": 8, - "resolved": [ - "♻️../7" - ] + "ambiguous": false, + "resolved": "♻️../7" } ] } @@ -2541,9 +2517,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -2705,9 +2680,8 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "Character", @@ -2728,9 +2702,8 @@ "end": 21, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../2/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../2/alternatives/0/elements/0" }, { "type": "CapturingGroup", @@ -2877,9 +2850,8 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -3074,9 +3046,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -3405,9 +3376,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0/element" - ] + "ambiguous": false, + "resolved": "♻️../0/element" } ] } @@ -4004,9 +3974,8 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0" } ] } @@ -4213,9 +4182,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "CapturingGroup", @@ -4254,9 +4222,8 @@ "end": 11, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" } ] } @@ -4337,9 +4304,8 @@ "end": 6, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -5711,9 +5677,8 @@ "end": 25, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6340,9 +6305,8 @@ "end": 17, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "Backreference", @@ -6351,9 +6315,8 @@ "end": 19, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } @@ -7161,9 +7124,8 @@ "end": 21, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../0/alternatives/0/elements/1" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/1" }, { "type": "Backreference", @@ -7172,9 +7134,8 @@ "end": 23, "raw": "\\5", "ref": 5, - "resolved": [ - "♻️../1/alternatives/0/elements/1" - ] + "ambiguous": false, + "resolved": "♻️../1/alternatives/0/elements/1" } ] } @@ -7478,9 +7439,8 @@ "end": 8, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../0" - ] + "ambiguous": false, + "resolved": "♻️../../0" } } ] @@ -7588,9 +7548,8 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -7703,9 +7662,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -20539,9 +20497,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -20610,9 +20567,8 @@ "end": 11, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" } ] } @@ -20663,9 +20619,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -22929,9 +22884,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Assertion", @@ -29556,9 +29510,8 @@ "end": 9, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Character", @@ -29575,9 +29528,8 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Character", @@ -29594,9 +29546,8 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } diff --git a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json index 287fbea..44383fd 100644 --- a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json +++ b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups-and-regexp-match-indices.json @@ -160,6 +160,7 @@ "end": 30, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0", "♻️../0/alternatives/1/elements/0" diff --git a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json index 7259126..1bafeb6 100644 --- a/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-duplicate-named-groups.json @@ -146,6 +146,7 @@ "end": 28, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0", "♻️../0/alternatives/1/elements/0" @@ -332,6 +333,7 @@ "end": 30, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0", "♻️../0/alternatives/1/elements/0" @@ -478,6 +480,7 @@ "end": 25, "raw": "\\k", "ref": "x", + "ambiguous": true, "resolved": [ "♻️../0/alternatives/0/elements/0", "♻️../0/alternatives/1/elements/0" @@ -837,9 +840,8 @@ "end": 19, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../../../../../../../0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../0/elements/0" } ] } @@ -1666,6 +1668,7 @@ "end": 28, "raw": "\\k", "ref": "a", + "ambiguous": true, "resolved": [ "♻️../1/alternatives/0/elements/0", "♻️../1/alternatives/1/elements/0" @@ -1850,6 +1853,7 @@ "end": 31, "raw": "\\k", "ref": "a", + "ambiguous": true, "resolved": [ "♻️../1/element/alternatives/0/elements/0", "♻️../1/element/alternatives/1/elements/0" diff --git a/test/fixtures/parser/literal/test262/regexp-lookbehind.json b/test/fixtures/parser/literal/test262/regexp-lookbehind.json index bf35d3d..0cfaf0d 100644 --- a/test/fixtures/parser/literal/test262/regexp-lookbehind.json +++ b/test/fixtures/parser/literal/test262/regexp-lookbehind.json @@ -431,9 +431,8 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -442,9 +441,8 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/0" }, { "type": "Backreference", @@ -453,9 +451,8 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -572,9 +569,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../../../0" }, { "type": "Backreference", @@ -583,9 +579,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../../../0" } ] } @@ -707,9 +702,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../../../0" }, { "type": "Backreference", @@ -718,9 +712,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../../../0" } ] } @@ -828,9 +821,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -839,9 +831,8 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -850,9 +841,8 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -963,9 +953,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -974,9 +963,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -985,9 +973,8 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -3068,9 +3055,8 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/0" } ] } @@ -3155,9 +3141,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" }, { "type": "Character", @@ -3300,9 +3285,8 @@ "end": 10, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" } ] }, @@ -3709,9 +3693,8 @@ "end": 17, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../0/alternatives/0/elements/0" } ] } @@ -4088,9 +4071,8 @@ "end": 12, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -5083,9 +5065,8 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -5221,9 +5202,8 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -5333,9 +5313,8 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -7077,9 +7056,8 @@ "end": 10, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../3" - ] + "ambiguous": false, + "resolved": "♻️../../../../../3" } ] } @@ -7118,9 +7096,8 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" } ] } @@ -7883,9 +7860,8 @@ "end": 9, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../3" - ] + "ambiguous": false, + "resolved": "♻️../../../../../3" } ] } @@ -7940,9 +7916,8 @@ "end": 16, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" } ] } @@ -9491,9 +9466,8 @@ "end": 16, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../../../../../0/alternatives/0/elements/0" } ] } @@ -9675,9 +9649,8 @@ "end": 20, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/0" } ] } @@ -9902,9 +9875,8 @@ "end": 27, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/0" } ] } @@ -10137,9 +10109,8 @@ "end": 27, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/0" } ] } @@ -10281,9 +10252,8 @@ "end": 15, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" }, { "type": "Backreference", @@ -10292,9 +10262,8 @@ "end": 17, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../0/alternatives/0/elements/1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0/alternatives/0/elements/1" }, { "type": "Backreference", @@ -10303,9 +10272,8 @@ "end": 19, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -10399,9 +10367,8 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../.." - ] + "ambiguous": false, + "resolved": "♻️../../../.." } ] } @@ -10498,9 +10465,8 @@ "end": 7, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../.." - ] + "ambiguous": false, + "resolved": "♻️../../../.." } ] } @@ -11787,9 +11753,8 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" }, { "type": "Quantifier", @@ -11948,9 +11913,8 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" }, { "type": "Quantifier", @@ -12109,9 +12073,8 @@ "end": 14, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" }, { "type": "Quantifier", diff --git a/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json b/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json index a33c97c..32f9930 100644 --- a/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-match-indices-and-regexp-named-groups.json @@ -617,9 +617,8 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "Backreference", @@ -628,9 +627,8 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Backreference", @@ -639,9 +637,8 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -782,9 +779,8 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "Backreference", @@ -793,9 +789,8 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Backreference", @@ -804,9 +799,8 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } diff --git a/test/fixtures/parser/literal/test262/regexp-named-groups.json b/test/fixtures/parser/literal/test262/regexp-named-groups.json index bc5242d..5e03c4b 100644 --- a/test/fixtures/parser/literal/test262/regexp-named-groups.json +++ b/test/fixtures/parser/literal/test262/regexp-named-groups.json @@ -169,9 +169,8 @@ "end": 18, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -200,9 +199,8 @@ "end": 22, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" } ] } @@ -333,9 +331,8 @@ "end": 18, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -364,9 +361,8 @@ "end": 22, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../../../../../1" - ] + "ambiguous": false, + "resolved": "♻️../../../../../1" } ] } @@ -482,9 +478,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "Backreference", @@ -493,9 +488,8 @@ "end": 15, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } @@ -606,9 +600,8 @@ "end": 13, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" }, { "type": "Backreference", @@ -617,9 +610,8 @@ "end": 15, "raw": "\\2", "ref": 2, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } @@ -3640,9 +3632,8 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "Backreference", @@ -3651,9 +3642,8 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Backreference", @@ -3662,9 +3652,8 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -3805,9 +3794,8 @@ "end": 27, "raw": "\\k", "ref": "c", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "Backreference", @@ -3816,9 +3804,8 @@ "end": 32, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "Backreference", @@ -3827,9 +3814,8 @@ "end": 37, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -4019,9 +4005,8 @@ "end": 11, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../../../.." - ] + "ambiguous": false, + "resolved": "♻️../../../.." }, { "type": "CharacterSet", @@ -4119,9 +4104,8 @@ "end": 11, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../../../.." - ] + "ambiguous": false, + "resolved": "♻️../../../.." }, { "type": "CharacterSet", @@ -4670,9 +4654,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -4781,9 +4764,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -4892,9 +4874,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] }, @@ -5040,9 +5021,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] }, @@ -5897,9 +5877,8 @@ "end": 14, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -5988,9 +5967,8 @@ "end": 14, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6079,9 +6057,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6170,9 +6147,8 @@ "end": 11, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6253,9 +6229,8 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "CapturingGroup", @@ -6294,9 +6269,8 @@ "end": 25, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6377,9 +6351,8 @@ "end": 13, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../2" - ] + "ambiguous": false, + "resolved": "♻️../2" }, { "type": "CapturingGroup", @@ -6418,9 +6391,8 @@ "end": 25, "raw": "\\k", "ref": "b", - "resolved": [ - "♻️../0" - ] + "ambiguous": false, + "resolved": "♻️../0" } ] } @@ -6570,9 +6542,8 @@ "end": 25, "raw": "\\k", "ref": "dog", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -6727,9 +6698,8 @@ "end": 25, "raw": "\\k", "ref": "dog", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -8267,9 +8237,8 @@ "end": 21, "raw": "\\k<狗>", "ref": "狗", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -8424,9 +8393,8 @@ "end": 21, "raw": "\\k<狗>", "ref": "狗", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -9389,9 +9357,8 @@ "end": 31, "raw": "\\k<𝓓𝓸𝓰>", "ref": "𝓓𝓸𝓰", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -9546,9 +9513,8 @@ "end": 31, "raw": "\\k<𝓓𝓸𝓰>", "ref": "𝓓𝓸𝓰", - "resolved": [ - "♻️../../../../../0" - ] + "ambiguous": false, + "resolved": "♻️../../../../../0" } ] } @@ -12562,9 +12528,8 @@ "end": 3, "raw": "\\1", "ref": 1, - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -12973,9 +12938,8 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -13024,9 +12988,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } @@ -13077,9 +13040,8 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", @@ -13128,9 +13090,8 @@ "end": 20, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" } ] } @@ -13181,9 +13142,8 @@ "end": 6, "raw": "\\k", "ref": "a", - "resolved": [ - "♻️../1" - ] + "ambiguous": false, + "resolved": "♻️../1" }, { "type": "CapturingGroup", From bf0ea8e845756958b6fbae092006e129ffaf7e47 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 15 Apr 2024 10:34:23 +0900 Subject: [PATCH 07/10] add test case --- .../duplicate-named-capturing-group-invalid-2025.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json index 93b2394..4ef7058 100644 --- a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json @@ -10,6 +10,12 @@ "index": 27 } }, + "/(?a)|(?b)(?c)/": { + "error": { + "message": "Invalid regular expression: /(?a)|(?b)(?c)/: Duplicate capture group name", + "index": 21 + } + }, "/(?:(?a)|(?b))(?c)/": { "error": { "message": "Invalid regular expression: /(?:(?a)|(?b))(?c)/: Duplicate capture group name", From 44db75abd304589ae3759b303fe5a43060eb968b Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 15 Apr 2024 11:41:19 +0900 Subject: [PATCH 08/10] add test case --- .../duplicate-named-capturing-group-invalid-2025.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json index 4ef7058..40c68ad 100644 --- a/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json +++ b/test/fixtures/parser/literal/duplicate-named-capturing-group-invalid-2025.json @@ -22,6 +22,12 @@ "index": 25 } }, + "/(?a)(?:(?b)|(?c))/": { + "error": { + "message": "Invalid regular expression: /(?a)(?:(?b)|(?c))/: Duplicate capture group name", + "index": 16 + } + }, "/(?:(?:(?a)|(?b)))(?c)/": { "error": { "message": "Invalid regular expression: /(?:(?:(?a)|(?b)))(?c)/: Duplicate capture group name", From 06d7dff627bdbe42aac3fa537473b93de317d432 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 15 Apr 2024 19:59:56 +0900 Subject: [PATCH 09/10] refactor --- src/group-specifiers.ts | 48 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts index 51f16cf..61caf15 100644 --- a/src/group-specifiers.ts +++ b/src/group-specifiers.ts @@ -84,18 +84,18 @@ export class GroupSpecifiersAsES2018 implements GroupSpecifiers { } export class GroupSpecifiersAsES2025 implements GroupSpecifiers { - private groupNamesInDisjunction = new Set() - private groupNamesInDisjunctionStack: Set[] = [] - private groupNamesInAlternative = new Set() - private groupNamesInAlternativeStack: Set[] = [] + private groupNamesAddedInDisjunction = new Set() + private groupNamesAddedInUpperDisjunctionStack: Set[] = [] + private groupNamesInScope = new Set() + private groupNamesInUpperScopeStack: Set[] = [] private groupNamesInPattern = new Set() public clear(): void { - this.groupNamesInDisjunction.clear() - this.groupNamesInDisjunctionStack.length = 0 - this.groupNamesInAlternative.clear() - this.groupNamesInAlternativeStack.length = 0 + this.groupNamesAddedInDisjunction.clear() + this.groupNamesAddedInUpperDisjunctionStack.length = 0 + this.groupNamesInScope.clear() + this.groupNamesInUpperScopeStack.length = 0 this.groupNamesInPattern.clear() } @@ -104,25 +104,31 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { } public enterDisjunction(): void { - this.groupNamesInDisjunctionStack.push(this.groupNamesInDisjunction) - this.groupNamesInDisjunction = new Set() + this.groupNamesAddedInUpperDisjunctionStack.push( + this.groupNamesAddedInDisjunction, + ) + // Clear groupNamesAddedInDisjunction to store the groupName added in this Disjunction. + this.groupNamesAddedInDisjunction = new Set() } public enterAlternative(): void { - this.groupNamesInAlternativeStack.push(this.groupNamesInAlternative) - this.groupNamesInAlternative = new Set(this.groupNamesInAlternative) + this.groupNamesInUpperScopeStack.push(this.groupNamesInScope) + this.groupNamesInScope = new Set(this.groupNamesInScope) } public leaveAlternative(): void { - this.groupNamesInAlternative = this.groupNamesInAlternativeStack.pop()! + this.groupNamesInScope = this.groupNamesInUpperScopeStack.pop()! } public leaveDisjunction(): void { - const child = this.groupNamesInDisjunction - this.groupNamesInDisjunction = this.groupNamesInDisjunctionStack.pop()! - for (const groupName of child) { - this.groupNamesInDisjunction.add(groupName) - this.groupNamesInAlternative.add(groupName) + const groupNamesAddedInDisjunction = this.groupNamesAddedInDisjunction + this.groupNamesAddedInDisjunction = + this.groupNamesAddedInUpperDisjunctionStack.pop()! + for (const groupName of groupNamesAddedInDisjunction) { + // Adds the groupName added in Disjunction to groupNamesInScope. + this.groupNamesInScope.add(groupName) + // Adds the groupName added in Disjunction to the upper Disjunction. + this.groupNamesAddedInDisjunction.add(groupName) } } @@ -131,12 +137,12 @@ export class GroupSpecifiersAsES2025 implements GroupSpecifiers { } public hasInScope(name: string): boolean { - return this.groupNamesInAlternative.has(name) + return this.groupNamesInScope.has(name) } public addToScope(name: string): void { - this.groupNamesInAlternative.add(name) - this.groupNamesInDisjunction.add(name) + this.groupNamesInScope.add(name) + this.groupNamesAddedInDisjunction.add(name) this.groupNamesInPattern.add(name) } } From d7f0d662424b6cd6a7fcad5f628ca20f25cf6813 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Wed, 17 Apr 2024 09:18:48 +0900 Subject: [PATCH 10/10] refactor to be more consistent with acorn impl --- src/group-specifiers.ts | 117 +++++++++++++++++++++++----------------- src/validator.ts | 3 +- 2 files changed, 69 insertions(+), 51 deletions(-) diff --git a/src/group-specifiers.ts b/src/group-specifiers.ts index 61caf15..e26329b 100644 --- a/src/group-specifiers.ts +++ b/src/group-specifiers.ts @@ -16,11 +16,7 @@ export interface GroupSpecifiers { * Called when visiting the Alternative. * For ES2025, manage nesting with new Alternative scopes. */ - enterAlternative: () => void - /** - * Called when leaving the Alternative. - */ - leaveAlternative: () => void + enterAlternative: (index: number) => void /** * Called when leaving the Disjunction. */ @@ -40,7 +36,7 @@ export interface GroupSpecifiers { } export class GroupSpecifiersAsES2018 implements GroupSpecifiers { - private groupName = new Set() + private readonly groupName = new Set() public clear(): void { this.groupName.clear() @@ -72,77 +68,100 @@ export class GroupSpecifiersAsES2018 implements GroupSpecifiers { // Prior to ES2025, it does not manage alternative scopes. } - // eslint-disable-next-line class-methods-use-this - public leaveAlternative(): void { - // Prior to ES2025, it does not manage alternative scopes. - } - // eslint-disable-next-line class-methods-use-this public leaveDisjunction(): void { // Prior to ES2025, it does not manage disjunction scopes. } } -export class GroupSpecifiersAsES2025 implements GroupSpecifiers { - private groupNamesAddedInDisjunction = new Set() - private groupNamesAddedInUpperDisjunctionStack: Set[] = [] - private groupNamesInScope = new Set() - private groupNamesInUpperScopeStack: Set[] = [] +/** + * Track disjunction structure to determine whether a duplicate + * capture group name is allowed because it is in a separate branch. + */ +class BranchID { + public readonly parent: BranchID | null + private readonly base: BranchID + public constructor(parent: BranchID | null, base: BranchID | null) { + // Parent disjunction branch + this.parent = parent + // Identifies this set of sibling branches + this.base = base ?? this + } + + /** + * A branch is separate from another branch if they or any of + * their parents are siblings in a given disjunction + */ + public separatedFrom(other: BranchID): boolean { + if (this.base === other.base && this !== other) { + return true + } + if (other.parent && this.separatedFrom(other.parent)) { + return true + } + return this.parent?.separatedFrom(other) ?? false + } + + public child() { + return new BranchID(this, null) + } + + public sibling() { + return new BranchID(this.parent, this.base) + } +} - private groupNamesInPattern = new Set() +export class GroupSpecifiersAsES2025 implements GroupSpecifiers { + private branchID = new BranchID(null, null) + private readonly groupNames = new Map() public clear(): void { - this.groupNamesAddedInDisjunction.clear() - this.groupNamesAddedInUpperDisjunctionStack.length = 0 - this.groupNamesInScope.clear() - this.groupNamesInUpperScopeStack.length = 0 - this.groupNamesInPattern.clear() + this.branchID = new BranchID(null, null) + this.groupNames.clear() } public isEmpty(): boolean { - return !this.groupNamesInPattern.size + return !this.groupNames.size } public enterDisjunction(): void { - this.groupNamesAddedInUpperDisjunctionStack.push( - this.groupNamesAddedInDisjunction, - ) - // Clear groupNamesAddedInDisjunction to store the groupName added in this Disjunction. - this.groupNamesAddedInDisjunction = new Set() + this.branchID = this.branchID.child() } - public enterAlternative(): void { - this.groupNamesInUpperScopeStack.push(this.groupNamesInScope) - this.groupNamesInScope = new Set(this.groupNamesInScope) - } - - public leaveAlternative(): void { - this.groupNamesInScope = this.groupNamesInUpperScopeStack.pop()! + public enterAlternative(index: number): void { + if (index === 0) { + return + } + this.branchID = this.branchID.sibling() } public leaveDisjunction(): void { - const groupNamesAddedInDisjunction = this.groupNamesAddedInDisjunction - this.groupNamesAddedInDisjunction = - this.groupNamesAddedInUpperDisjunctionStack.pop()! - for (const groupName of groupNamesAddedInDisjunction) { - // Adds the groupName added in Disjunction to groupNamesInScope. - this.groupNamesInScope.add(groupName) - // Adds the groupName added in Disjunction to the upper Disjunction. - this.groupNamesAddedInDisjunction.add(groupName) - } + this.branchID = this.branchID.parent! } public hasInPattern(name: string): boolean { - return this.groupNamesInPattern.has(name) + return this.groupNames.has(name) } public hasInScope(name: string): boolean { - return this.groupNamesInScope.has(name) + const branches = this.groupNames.get(name) + if (!branches) { + return false + } + for (const branch of branches) { + if (!branch.separatedFrom(this.branchID)) { + return true + } + } + return false } public addToScope(name: string): void { - this.groupNamesInScope.add(name) - this.groupNamesAddedInDisjunction.add(name) - this.groupNamesInPattern.add(name) + const branches = this.groupNames.get(name) + if (branches) { + branches.push(this.branchID) + return + } + this.groupNames.set(name, [this.branchID]) } } diff --git a/src/validator.ts b/src/validator.ts index 08fbc41..72c5439 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1415,13 +1415,12 @@ export class RegExpValidator { private consumeAlternative(i: number): void { const start = this.index - this._groupSpecifiers.enterAlternative() + this._groupSpecifiers.enterAlternative(i) this.onAlternativeEnter(start, i) while (this.currentCodePoint !== -1 && this.consumeTerm()) { // do nothing. } this.onAlternativeLeave(start, this.index, i) - this._groupSpecifiers.leaveAlternative() } /**