Skip to content

Commit 95056b1

Browse files
committed
feat: support for modifier
1 parent 3cb60cc commit 95056b1

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

@@ -435,6 +438,27 @@ export interface Backreference extends NodeBase {
435438
resolved: CapturingGroup
436439
}
437440

441+
/**
442+
* The modifiers.
443+
*/
444+
export interface Modifiers extends NodeBase {
445+
type: "Modifiers"
446+
parent: Group
447+
add: ModifierFlags | null
448+
remove: ModifierFlags | null
449+
}
450+
451+
/**
452+
* The modifier flags.
453+
*/
454+
export interface ModifierFlags extends NodeBase {
455+
type: "ModifierFlags"
456+
parent: Modifiers
457+
dotAll: boolean
458+
ignoreCase: boolean
459+
multiline: boolean
460+
}
461+
438462
/**
439463
* The flags.
440464
*/

src/parser.ts

+83
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
UnicodeSetsCharacterClass,
1919
ExpressionCharacterClass,
2020
StringAlternative,
21+
Modifiers,
2122
} from "./ast"
2223
import type { EcmaVersion } from "./ecma-versions"
2324
import { latestEcmaVersion } from "./ecma-versions"
@@ -31,6 +32,7 @@ type AppendableNode =
3132
| ClassStringDisjunction
3233
| Group
3334
| LookaroundAssertion
35+
| Modifiers
3436
| Pattern
3537
| StringAlternative
3638

@@ -202,6 +204,7 @@ class RegExpParserState {
202204
start,
203205
end: start,
204206
raw: "",
207+
modifiers: null,
205208
alternatives: [],
206209
}
207210
parent.elements.push(this._node)
@@ -218,6 +221,85 @@ class RegExpParserState {
218221
this._node = node.parent
219222
}
220223

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

0 commit comments

Comments
 (0)