Skip to content

Commit 62e90ef

Browse files
refactor(perf): faster checks for end nfa recursion loops
1 parent 84027b8 commit 62e90ef

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

assembly/nfa/nfa.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ export enum MatchResult {
2424
Ignore,
2525
}
2626

27+
let _stateId: u32 = 0;
28+
2729
/* eslint @typescript-eslint/no-empty-function: ["error", { "allow": ["constructors", "methods"] }] */
2830
export class State {
29-
constructor(public transitions: State[] = []) {}
31+
constructor(public transitions: State[] = [], public id: u32 = _stateId++) {}
3032

3133
matches(input: string, position: u32): MatchResult {
3234
return MatchResult.Ignore;
@@ -40,7 +42,7 @@ export class GroupStartMarkerState extends State {
4042
// captures from the path through the NFA that reaches the end are flagged
4143
flagged: bool = false;
4244

43-
constructor(next: State, public id: i32) {
45+
constructor(next: State, public groupId: i32) {
4446
super();
4547
this.transitions.push(next);
4648
}

assembly/regexp.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ import { walker as astWalker, expandRepetitions } from "./parser/walker";
99
function recursiveBacktrackingSearch(
1010
state: State,
1111
input: string,
12-
visited: State[] = [],
12+
visited: u32[] = [],
1313
position: i32 = 0
1414
): string | null {
1515
// prevent endless loops when following epsilon transitions
16-
if (visited.includes(state)) {
17-
return null;
16+
for (let i = 0, len = visited.length; i < len; i++) {
17+
if (visited[i] == state.id) {
18+
return null;
19+
}
1820
}
19-
visited.push(state);
21+
visited.push(state.id);
2022

2123
const matches = state.matches(input, position);
2224
if (matches == MatchResult.Match) {
@@ -92,11 +94,11 @@ function filterCaptures(groupMarkers: GroupStartMarkerState[]): string[] {
9294
return [];
9395
}
9496
const values = [first(groupMarkers).capture];
95-
let currrentId = first(groupMarkers).id;
97+
let currrentId = first(groupMarkers).groupId;
9698
for (let i = 0; i < groupMarkers.length; i++) {
9799
const gm = groupMarkers[i];
98-
if (gm.id != currrentId) {
99-
currrentId = gm.id;
100+
if (gm.groupId != currrentId) {
101+
currrentId = gm.groupId;
100102
values.push(gm.capture);
101103
} else {
102104
if (gm.flagged) {

0 commit comments

Comments
 (0)