Skip to content

Commit 33e8203

Browse files
authored
fix: error in expression with nested expression (#143)
1 parent 97c3ce6 commit 33e8203

File tree

3 files changed

+593
-11
lines changed

3 files changed

+593
-11
lines changed

src/parser.ts

+13-11
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ class RegExpParserState {
5858

5959
private _node: AppendableNode = DUMMY_PATTERN
6060

61-
private _expressionBuffer: ClassIntersection | ClassSubtraction | null =
62-
null
61+
private _expressionBufferMap = new Map<
62+
CharacterClass | ExpressionCharacterClass,
63+
ClassIntersection | ClassSubtraction
64+
>()
6365

6466
private _flags: Flags = DUMMY_FLAGS
6567

@@ -538,16 +540,14 @@ class RegExpParserState {
538540
node.raw = this.source.slice(start, end)
539541
this._node = parent
540542

541-
const expression = this._expressionBuffer
542-
if (
543-
expression?.parent !== (node as unknown as ExpressionCharacterClass)
544-
) {
543+
const expression = this._expressionBufferMap.get(node)
544+
if (!expression) {
545545
return
546546
}
547547
if (node.elements.length > 0) {
548548
throw new Error("UnknownError")
549549
}
550-
this._expressionBuffer = null
550+
this._expressionBufferMap.delete(node)
551551

552552
// Replace with ExpressionCharacterClass.
553553
const newNode: ExpressionCharacterClass = {
@@ -614,7 +614,8 @@ class RegExpParserState {
614614
}
615615
// Replace the last two elements.
616616
const right = parent.elements.pop()
617-
const left = this._expressionBuffer ?? parent.elements.pop()
617+
const left =
618+
this._expressionBufferMap.get(parent) ?? parent.elements.pop()
618619
if (
619620
!left ||
620621
!right ||
@@ -637,7 +638,7 @@ class RegExpParserState {
637638
}
638639
left.parent = node
639640
right.parent = node
640-
this._expressionBuffer = node
641+
this._expressionBufferMap.set(parent, node)
641642
}
642643

643644
public onClassSubtraction(start: number, end: number): void {
@@ -647,7 +648,8 @@ class RegExpParserState {
647648
}
648649
// Replace the last two elements.
649650
const right = parent.elements.pop()
650-
const left = this._expressionBuffer ?? parent.elements.pop()
651+
const left =
652+
this._expressionBufferMap.get(parent) ?? parent.elements.pop()
651653
if (
652654
!left ||
653655
!right ||
@@ -670,7 +672,7 @@ class RegExpParserState {
670672
}
671673
left.parent = node
672674
right.parent = node
673-
this._expressionBuffer = node
675+
this._expressionBufferMap.set(parent, node)
674676
}
675677

676678
public onClassStringDisjunctionEnter(start: number): void {

test/fixtures/parser/literal/class-set-expression-intersection-valid-2024.json

+290
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,296 @@
23312331
"unicodeSets": true
23322332
}
23332333
}
2334+
},
2335+
"/[a&&b&&[c&&d&&e]]/v": {
2336+
"ast": {
2337+
"type": "RegExpLiteral",
2338+
"parent": null,
2339+
"start": 0,
2340+
"end": 20,
2341+
"raw": "/[a&&b&&[c&&d&&e]]/v",
2342+
"pattern": {
2343+
"type": "Pattern",
2344+
"parent": "♻️..",
2345+
"start": 1,
2346+
"end": 18,
2347+
"raw": "[a&&b&&[c&&d&&e]]",
2348+
"alternatives": [
2349+
{
2350+
"type": "Alternative",
2351+
"parent": "♻️../..",
2352+
"start": 1,
2353+
"end": 18,
2354+
"raw": "[a&&b&&[c&&d&&e]]",
2355+
"elements": [
2356+
{
2357+
"type": "ExpressionCharacterClass",
2358+
"parent": "♻️../..",
2359+
"start": 1,
2360+
"end": 18,
2361+
"raw": "[a&&b&&[c&&d&&e]]",
2362+
"negate": false,
2363+
"expression": {
2364+
"type": "ClassIntersection",
2365+
"parent": "♻️..",
2366+
"start": 2,
2367+
"end": 17,
2368+
"raw": "a&&b&&[c&&d&&e]",
2369+
"left": {
2370+
"type": "ClassIntersection",
2371+
"parent": "♻️..",
2372+
"start": 2,
2373+
"end": 6,
2374+
"raw": "a&&b",
2375+
"left": {
2376+
"type": "Character",
2377+
"parent": "♻️..",
2378+
"start": 2,
2379+
"end": 3,
2380+
"raw": "a",
2381+
"value": 97
2382+
},
2383+
"right": {
2384+
"type": "Character",
2385+
"parent": "♻️..",
2386+
"start": 5,
2387+
"end": 6,
2388+
"raw": "b",
2389+
"value": 98
2390+
}
2391+
},
2392+
"right": {
2393+
"type": "ExpressionCharacterClass",
2394+
"parent": "♻️..",
2395+
"start": 8,
2396+
"end": 17,
2397+
"raw": "[c&&d&&e]",
2398+
"negate": false,
2399+
"expression": {
2400+
"type": "ClassIntersection",
2401+
"parent": "♻️..",
2402+
"start": 9,
2403+
"end": 16,
2404+
"raw": "c&&d&&e",
2405+
"left": {
2406+
"type": "ClassIntersection",
2407+
"parent": "♻️..",
2408+
"start": 9,
2409+
"end": 13,
2410+
"raw": "c&&d",
2411+
"left": {
2412+
"type": "Character",
2413+
"parent": "♻️..",
2414+
"start": 9,
2415+
"end": 10,
2416+
"raw": "c",
2417+
"value": 99
2418+
},
2419+
"right": {
2420+
"type": "Character",
2421+
"parent": "♻️..",
2422+
"start": 12,
2423+
"end": 13,
2424+
"raw": "d",
2425+
"value": 100
2426+
}
2427+
},
2428+
"right": {
2429+
"type": "Character",
2430+
"parent": "♻️..",
2431+
"start": 15,
2432+
"end": 16,
2433+
"raw": "e",
2434+
"value": 101
2435+
}
2436+
}
2437+
}
2438+
}
2439+
}
2440+
]
2441+
}
2442+
]
2443+
},
2444+
"flags": {
2445+
"type": "Flags",
2446+
"parent": "♻️..",
2447+
"start": 19,
2448+
"end": 20,
2449+
"raw": "v",
2450+
"global": false,
2451+
"ignoreCase": false,
2452+
"multiline": false,
2453+
"unicode": false,
2454+
"sticky": false,
2455+
"dotAll": false,
2456+
"hasIndices": false,
2457+
"unicodeSets": true
2458+
}
2459+
}
2460+
},
2461+
"/[a&&b&&[c--d--[e&&f&&g]]]/v": {
2462+
"ast": {
2463+
"type": "RegExpLiteral",
2464+
"parent": null,
2465+
"start": 0,
2466+
"end": 28,
2467+
"raw": "/[a&&b&&[c--d--[e&&f&&g]]]/v",
2468+
"pattern": {
2469+
"type": "Pattern",
2470+
"parent": "♻️..",
2471+
"start": 1,
2472+
"end": 26,
2473+
"raw": "[a&&b&&[c--d--[e&&f&&g]]]",
2474+
"alternatives": [
2475+
{
2476+
"type": "Alternative",
2477+
"parent": "♻️../..",
2478+
"start": 1,
2479+
"end": 26,
2480+
"raw": "[a&&b&&[c--d--[e&&f&&g]]]",
2481+
"elements": [
2482+
{
2483+
"type": "ExpressionCharacterClass",
2484+
"parent": "♻️../..",
2485+
"start": 1,
2486+
"end": 26,
2487+
"raw": "[a&&b&&[c--d--[e&&f&&g]]]",
2488+
"negate": false,
2489+
"expression": {
2490+
"type": "ClassIntersection",
2491+
"parent": "♻️..",
2492+
"start": 2,
2493+
"end": 25,
2494+
"raw": "a&&b&&[c--d--[e&&f&&g]]",
2495+
"left": {
2496+
"type": "ClassIntersection",
2497+
"parent": "♻️..",
2498+
"start": 2,
2499+
"end": 6,
2500+
"raw": "a&&b",
2501+
"left": {
2502+
"type": "Character",
2503+
"parent": "♻️..",
2504+
"start": 2,
2505+
"end": 3,
2506+
"raw": "a",
2507+
"value": 97
2508+
},
2509+
"right": {
2510+
"type": "Character",
2511+
"parent": "♻️..",
2512+
"start": 5,
2513+
"end": 6,
2514+
"raw": "b",
2515+
"value": 98
2516+
}
2517+
},
2518+
"right": {
2519+
"type": "ExpressionCharacterClass",
2520+
"parent": "♻️..",
2521+
"start": 8,
2522+
"end": 25,
2523+
"raw": "[c--d--[e&&f&&g]]",
2524+
"negate": false,
2525+
"expression": {
2526+
"type": "ClassSubtraction",
2527+
"parent": "♻️..",
2528+
"start": 9,
2529+
"end": 24,
2530+
"raw": "c--d--[e&&f&&g]",
2531+
"left": {
2532+
"type": "ClassSubtraction",
2533+
"parent": "♻️..",
2534+
"start": 9,
2535+
"end": 13,
2536+
"raw": "c--d",
2537+
"left": {
2538+
"type": "Character",
2539+
"parent": "♻️..",
2540+
"start": 9,
2541+
"end": 10,
2542+
"raw": "c",
2543+
"value": 99
2544+
},
2545+
"right": {
2546+
"type": "Character",
2547+
"parent": "♻️..",
2548+
"start": 12,
2549+
"end": 13,
2550+
"raw": "d",
2551+
"value": 100
2552+
}
2553+
},
2554+
"right": {
2555+
"type": "ExpressionCharacterClass",
2556+
"parent": "♻️..",
2557+
"start": 15,
2558+
"end": 24,
2559+
"raw": "[e&&f&&g]",
2560+
"negate": false,
2561+
"expression": {
2562+
"type": "ClassIntersection",
2563+
"parent": "♻️..",
2564+
"start": 16,
2565+
"end": 23,
2566+
"raw": "e&&f&&g",
2567+
"left": {
2568+
"type": "ClassIntersection",
2569+
"parent": "♻️..",
2570+
"start": 16,
2571+
"end": 20,
2572+
"raw": "e&&f",
2573+
"left": {
2574+
"type": "Character",
2575+
"parent": "♻️..",
2576+
"start": 16,
2577+
"end": 17,
2578+
"raw": "e",
2579+
"value": 101
2580+
},
2581+
"right": {
2582+
"type": "Character",
2583+
"parent": "♻️..",
2584+
"start": 19,
2585+
"end": 20,
2586+
"raw": "f",
2587+
"value": 102
2588+
}
2589+
},
2590+
"right": {
2591+
"type": "Character",
2592+
"parent": "♻️..",
2593+
"start": 22,
2594+
"end": 23,
2595+
"raw": "g",
2596+
"value": 103
2597+
}
2598+
}
2599+
}
2600+
}
2601+
}
2602+
}
2603+
}
2604+
]
2605+
}
2606+
]
2607+
},
2608+
"flags": {
2609+
"type": "Flags",
2610+
"parent": "♻️..",
2611+
"start": 27,
2612+
"end": 28,
2613+
"raw": "v",
2614+
"global": false,
2615+
"ignoreCase": false,
2616+
"multiline": false,
2617+
"unicode": false,
2618+
"sticky": false,
2619+
"dotAll": false,
2620+
"hasIndices": false,
2621+
"unicodeSets": true
2622+
}
2623+
}
23342624
}
23352625
}
23362626
}

0 commit comments

Comments
 (0)