Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for modifier #83

Merged
merged 9 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scripts/update-fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ for (const filename of Object.keys(Visitor.fixturesData)) {
onExpressionCharacterClassEnter: enter,
onFlagsEnter: enter,
onGroupEnter: enter,
onModifierFlagsEnter: enter,
onModifiersEnter: enter,
onPatternEnter: enter,
onQuantifierEnter: enter,
onRegExpLiteralEnter: enter,
Expand All @@ -71,6 +73,8 @@ for (const filename of Object.keys(Visitor.fixturesData)) {
onExpressionCharacterClassLeave: leave,
onFlagsLeave: leave,
onGroupLeave: leave,
onModifierFlagsLeave: leave,
onModifiersLeave: leave,
onPatternLeave: leave,
onQuantifierLeave: leave,
onRegExpLiteralLeave: leave,
Expand Down
33 changes: 33 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type BranchNode =
| ExpressionCharacterClass
| Group
| LookaroundAssertion
| Modifiers
| Pattern
| Quantifier
| RegExpLiteral
Expand All @@ -31,6 +32,7 @@ export type LeafNode =
| Character
| CharacterSet
| Flags
| ModifierFlags

/**
* The type which includes all atom nodes.
Expand Down Expand Up @@ -122,6 +124,7 @@ export interface Alternative extends NodeBase {
export interface Group extends NodeBase {
type: "Group"
parent: Alternative | Quantifier
modifiers: Modifiers | null
alternatives: Alternative[]
}

Expand Down Expand Up @@ -446,6 +449,36 @@ export interface UnambiguousBackreference extends BaseBackreference {
resolved: CapturingGroup
}

/**
* The modifiers.
*/
export interface Modifiers extends NodeBase {
type: "Modifiers"
parent: Group
/**
* The add modifier flags.
*/
add: ModifierFlags
/**
* The remove modifier flags.
*
* `null` means no remove modifier flags. e.g. `(?ims:x)`
* The reason for `null` is that there is no position where the remove modifier flags appears. Must be behind the minus mark.
*/
remove: ModifierFlags | null
}

/**
* The modifier flags.
*/
export interface ModifierFlags extends NodeBase {
type: "ModifierFlags"
parent: Modifiers
dotAll: boolean
ignoreCase: boolean
multiline: boolean
}

/**
* The flags.
*/
Expand Down
88 changes: 86 additions & 2 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
UnicodeSetsCharacterClass,
ExpressionCharacterClass,
StringAlternative,
Modifiers,
} from "./ast"
import type { EcmaVersion } from "./ecma-versions"
import { latestEcmaVersion } from "./ecma-versions"
Expand All @@ -31,6 +32,7 @@ type AppendableNode =
| ClassStringDisjunction
| Group
| LookaroundAssertion
| Modifiers
| Pattern
| StringAlternative

Expand Down Expand Up @@ -205,14 +207,17 @@ class RegExpParserState {
throw new Error("UnknownError")
}

this._node = {
const group: Group = {
type: "Group",
parent,
start,
end: start,
raw: "",
modifiers: null,
alternatives: [],
}

this._node = group
parent.elements.push(this._node)
}

Expand All @@ -227,6 +232,85 @@ class RegExpParserState {
this._node = node.parent
}

public onModifiersEnter(start: number): void {
const parent = this._node
if (parent.type !== "Group") {
throw new Error("UnknownError")
}

this._node = {
type: "Modifiers",
parent,
start,
end: start,
raw: "",
add: null as never, // Set in onAddModifiers.
remove: null,
}
parent.modifiers = this._node
}

public onModifiersLeave(start: number, end: number): void {
const node = this._node
if (node.type !== "Modifiers" || node.parent.type !== "Group") {
throw new Error("UnknownError")
}

node.end = end
node.raw = this.source.slice(start, end)
this._node = node.parent
}

public onAddModifiers(
start: number,
end: number,
{
ignoreCase,
multiline,
dotAll,
}: { ignoreCase: boolean; multiline: boolean; dotAll: boolean },
): void {
const parent = this._node
if (parent.type !== "Modifiers") {
throw new Error("UnknownError")
}
parent.add = {
type: "ModifierFlags",
parent,
start,
end,
raw: this.source.slice(start, end),
ignoreCase,
multiline,
dotAll,
}
}

public onRemoveModifiers(
start: number,
end: number,
{
ignoreCase,
multiline,
dotAll,
}: { ignoreCase: boolean; multiline: boolean; dotAll: boolean },
): void {
const parent = this._node
if (parent.type !== "Modifiers") {
throw new Error("UnknownError")
}
parent.remove = {
type: "ModifierFlags",
parent,
start,
end,
raw: this.source.slice(start, end),
ignoreCase,
multiline,
dotAll,
}
}

public onCapturingGroupEnter(start: number, name: string | null): void {
const parent = this._node
if (parent.type !== "Alternative") {
Expand Down Expand Up @@ -765,7 +849,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.
* - `2025` added duplicate named capturing groups, modifiers.
*/
ecmaVersion?: EcmaVersion
}
Expand Down
Loading
Loading