Skip to content

Commit d343563

Browse files
committed
feat: support for modifier
1 parent 9f383cd commit d343563

21 files changed

+1107
-74
lines changed

scripts/update-fixtures.ts

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ for (const filename of Object.keys(Visitor.fixturesData)) {
5353
onExpressionCharacterClassEnter: enter,
5454
onFlagsEnter: enter,
5555
onGroupEnter: enter,
56+
onModifierFlagsEnter: enter,
57+
onModifiersEnter: enter,
5658
onPatternEnter: enter,
5759
onQuantifierEnter: enter,
5860
onRegExpLiteralEnter: enter,
@@ -71,6 +73,8 @@ for (const filename of Object.keys(Visitor.fixturesData)) {
7173
onExpressionCharacterClassLeave: leave,
7274
onFlagsLeave: leave,
7375
onGroupLeave: leave,
76+
onModifierFlagsLeave: leave,
77+
onModifiersLeave: leave,
7478
onPatternLeave: leave,
7579
onQuantifierLeave: leave,
7680
onRegExpLiteralLeave: leave,

src/ast.ts

+24
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type BranchNode =
1717
| ExpressionCharacterClass
1818
| Group
1919
| LookaroundAssertion
20+
| Modifiers
2021
| Pattern
2122
| Quantifier
2223
| RegExpLiteral
@@ -31,6 +32,7 @@ export type LeafNode =
3132
| Character
3233
| CharacterSet
3334
| Flags
35+
| ModifierFlags
3436

3537
/**
3638
* The type which includes all atom nodes.
@@ -122,6 +124,7 @@ export interface Alternative extends NodeBase {
122124
export interface Group extends NodeBase {
123125
type: "Group"
124126
parent: Alternative | Quantifier
127+
modifiers: Modifiers | null
125128
alternatives: Alternative[]
126129
}
127130

@@ -432,6 +435,27 @@ export interface Backreference extends NodeBase {
432435
resolved: CapturingGroup
433436
}
434437

438+
/**
439+
* The modifiers.
440+
*/
441+
export interface Modifiers extends NodeBase {
442+
type: "Modifiers"
443+
parent: Group
444+
add: ModifierFlags | null
445+
remove: ModifierFlags | null
446+
}
447+
448+
/**
449+
* The modifier flags.
450+
*/
451+
export interface ModifierFlags extends NodeBase {
452+
type: "ModifierFlags"
453+
parent: Modifiers
454+
dotAll: boolean
455+
ignoreCase: boolean
456+
multiline: boolean
457+
}
458+
435459
/**
436460
* The flags.
437461
*/

src/parser.ts

+83
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
UnicodeSetsCharacterClass,
2020
ExpressionCharacterClass,
2121
StringAlternative,
22+
Modifiers,
2223
} from "./ast"
2324
import type { EcmaVersion } from "./ecma-versions"
2425
import { latestEcmaVersion } from "./ecma-versions"
@@ -32,6 +33,7 @@ type AppendableNode =
3233
| ClassStringDisjunction
3334
| Group
3435
| LookaroundAssertion
36+
| Modifiers
3537
| Pattern
3638
| StringAlternative
3739

@@ -203,6 +205,7 @@ class RegExpParserState {
203205
start,
204206
end: start,
205207
raw: "",
208+
modifiers: null,
206209
alternatives: [],
207210
}
208211
parent.elements.push(this._node)
@@ -219,6 +222,85 @@ class RegExpParserState {
219222
this._node = node.parent
220223
}
221224

225+
public onModifiersEnter(start: number): void {
226+
const parent = this._node
227+
if (parent.type !== "Group") {
228+
throw new Error("UnknownError")
229+
}
230+
231+
this._node = {
232+
type: "Modifiers",
233+
parent,
234+
start,
235+
end: start,
236+
raw: "",
237+
add: null,
238+
remove: null,
239+
}
240+
parent.modifiers = this._node
241+
}
242+
243+
public onModifiersLeave(start: number, end: number): void {
244+
const node = this._node
245+
if (node.type !== "Modifiers" || node.parent.type !== "Group") {
246+
throw new Error("UnknownError")
247+
}
248+
249+
node.end = end
250+
node.raw = this.source.slice(start, end)
251+
this._node = node.parent
252+
}
253+
254+
public onAddModifiers(
255+
start: number,
256+
end: number,
257+
{
258+
ignoreCase,
259+
multiline,
260+
dotAll,
261+
}: { ignoreCase: boolean; multiline: boolean; dotAll: boolean },
262+
): void {
263+
const parent = this._node
264+
if (parent.type !== "Modifiers") {
265+
throw new Error("UnknownError")
266+
}
267+
parent.add = {
268+
type: "ModifierFlags",
269+
parent,
270+
start,
271+
end,
272+
raw: this.source.slice(start, end),
273+
ignoreCase,
274+
multiline,
275+
dotAll,
276+
}
277+
}
278+
279+
public onRemoveModifiers(
280+
start: number,
281+
end: number,
282+
{
283+
ignoreCase,
284+
multiline,
285+
dotAll,
286+
}: { ignoreCase: boolean; multiline: boolean; dotAll: boolean },
287+
): void {
288+
const parent = this._node
289+
if (parent.type !== "Modifiers") {
290+
throw new Error("UnknownError")
291+
}
292+
parent.remove = {
293+
type: "ModifierFlags",
294+
parent,
295+
start,
296+
end,
297+
raw: this.source.slice(start, end),
298+
ignoreCase,
299+
multiline,
300+
dotAll,
301+
}
302+
}
303+
222304
public onCapturingGroupEnter(start: number, name: string | null): void {
223305
const parent = this._node
224306
if (parent.type !== "Alternative") {
@@ -754,6 +836,7 @@ export namespace RegExpParser {
754836
* - `2022` added `d` flag.
755837
* - `2023` added more valid Unicode Property Escapes.
756838
* - `2024` added `v` flag.
839+
* - `202x` added modifier.
757840
*/
758841
ecmaVersion?: EcmaVersion
759842
}

0 commit comments

Comments
 (0)