Skip to content

Commit

Permalink
fix: make globals static so that they don't pollute downstream librar…
Browse files Browse the repository at this point in the history
…ies (#42)

Also reorganized top level `let`s into static variables.
  • Loading branch information
Willem Wyndham authored May 4, 2021
1 parent 4dc21b0 commit debec10
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# prettier doesn't support decorators on functions :-(
assembly/char.ts
assembly/char.ts
assembly/nfa/types.ts
8 changes: 8 additions & 0 deletions asconfig.empty.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"options": {
"runtime": "stub",
"textFile": "build/empty.wat",
"debug": true
},
"entries": ["assembly/__tests__/empty.ts"]
}
1 change: 1 addition & 0 deletions assembly/__tests__/empty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import * as regex from "..";
5 changes: 5 additions & 0 deletions assembly/__tests__/empty.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(module
(memory $0 0)
(table $0 1 funcref)
(export "memory" (memory $0))
)
2 changes: 2 additions & 0 deletions assembly/char.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-ignore
@lazy
export const enum Char {
None = -1,
HorizontalTab = 0x09,
Expand Down
25 changes: 15 additions & 10 deletions assembly/nfa/matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ const enum MatcherType {
CharacterSet,
CharacterClass,
}

let _flags: Flags;

export class Matcher {
@lazy static _flags: Flags;

constructor(readonly type: MatcherType) {}

matches(code: u32): bool {
Expand Down Expand Up @@ -47,20 +46,23 @@ export class Matcher {
node: CharacterClassNode,
flags: Flags
): CharacterClassMatcher {
_flags = flags;
Matcher._flags = flags;
const matchers = node.expressions.map<Matcher>((exp) => {
switch (exp.type) {
case NodeType.CharacterRange:
return Matcher.fromCharacterRangeNode(
exp as CharacterRangeNode,
_flags
Matcher._flags
);
case NodeType.Character:
return Matcher.fromCharacterNode(exp as CharacterNode, _flags);
return Matcher.fromCharacterNode(
exp as CharacterNode,
Matcher._flags
);
case NodeType.CharacterSet:
return Matcher.fromCharacterClassNode(
exp as CharacterSetNode,
_flags
Matcher._flags
);
default:
throw new Error("unsupported node type within character set");
Expand Down Expand Up @@ -93,9 +95,12 @@ export class CharacterMatcher extends Matcher {
}
}

const LOWERCASE_LETTERS = new Range(Char.a, Char.z);
const UPPERCASE_LETTERS = new Range(Char.A, Char.Z);
const UPPER_LOWER_OFFSET = Char.a - Char.A;
// @ts-ignore
@lazy const LOWERCASE_LETTERS = new Range(Char.a, Char.z);
// @ts-ignore
@lazy const UPPERCASE_LETTERS = new Range(Char.A, Char.Z);
// @ts-ignore
@lazy const UPPER_LOWER_OFFSET = Char.a - Char.A;

export class CharacterRangeMatcher extends Matcher {
private ranges: Range[];
Expand Down
20 changes: 8 additions & 12 deletions assembly/nfa/nfa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,15 @@ import {
import { Char } from "../char";
import { Matcher } from "./matcher";
import { Flags } from "../regexp";

export enum MatchResult {
// a match has occurred - which is a signal to consume a character
Match,
// a match failed, abort this regex
Fail,
// this state doesn't preform a match
Ignore,
}

let _stateId: u32 = 0;
import { MatchResult } from "./types";

/* eslint @typescript-eslint/no-empty-function: ["error", { "allow": ["constructors", "methods"] }] */
export class State {
constructor(public transitions: State[] = [], public id: u32 = _stateId++) {}
@lazy static _stateId: u32 = 0;
constructor(
public transitions: State[] = [],
public id: u32 = State._stateId++
) {}

matches(input: string, position: u32): MatchResult {
return MatchResult.Ignore;
Expand Down Expand Up @@ -253,3 +247,5 @@ class AutomataFactor {
}
}
}

export { MatchResult } from "./types";
10 changes: 10 additions & 0 deletions assembly/nfa/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @ts-ignore
@lazy
export enum MatchResult {
// a match has occurred - which is a signal to consume a character
Match,
// a match failed, abort this regex
Fail,
// this state doesn't preform a match
Ignore,
}
13 changes: 6 additions & 7 deletions assembly/parser/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ export const enum NodeType {
Group,
}

const emptyNodeArray = new Array<Node>();

export abstract class Node {
@lazy static readonly emptyArray: Node[] = new Array<Node>();
constructor(public type: NodeType) {}

children(): Node[] {
return emptyNodeArray;
return Node.emptyArray;
}

abstract clone(): Node;
Expand All @@ -37,7 +36,7 @@ export class AST extends Node {
}

children(): Node[] {
return this.body != null ? [this.body as Node] : emptyNodeArray;
return this.body != null ? [this.body as Node] : Node.emptyArray;
}

clone(): Node {
Expand Down Expand Up @@ -210,17 +209,17 @@ export class AlternationNode extends Node {
}
}

let _id = 0;

export class GroupNode extends Node {
@lazy static _id: i32 = 0;

constructor(
public expression: Node,
public capturing: bool,
public id: i32 = -1
) {
super(NodeType.Group);
if (id == -1) {
this.id = _id++;
this.id = GroupNode._id++;
}
}

Expand Down
11 changes: 7 additions & 4 deletions assembly/parser/walker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ export function walker(ast: AST, visitor: (node: NodeVisitor) => void): void {
}
}

// range quantifiers are implemented via 'expansion', which significantly
// increases the size of the AST. This imposes a hard limit to prevent
// memory-related issues
const QUANTIFIER_LIMIT = 1000;
/**
range quantifiers are implemented via 'expansion', which significantly
increases the size of the AST. This imposes a hard limit to prevent
memory-related issues
*/
// @ts-ignore
@lazy const QUANTIFIER_LIMIT = 1000;

function parentAsConcatNode(visitor: NodeVisitor): ConcatenationNode {
let concatNode: ConcatenationNode | null = null;
Expand Down
9 changes: 4 additions & 5 deletions assembly/regexp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ export class Match {
}
}

let gm = new Array<GroupStartMarkerState>();

export class Flags {
global: bool = false;
ignoreCase: bool = false;
Expand Down Expand Up @@ -112,6 +110,7 @@ function lastCapturesForGroup(groupMarkers: GroupStartMarkerState[]): string[] {
}

export class RegExp {
@lazy static gm: GroupStartMarkerState[] = new Array<GroupStartMarkerState>();
lastIndex: i32 = 0;
private flags: Flags;
private nfa: Automata;
Expand All @@ -136,16 +135,16 @@ export class RegExp {
this.nfa = Automata.toNFA(ast, flags);

// find all the group marker states
gm = new Array<GroupStartMarkerState>();
RegExp.gm = new Array<GroupStartMarkerState>();
nfaWalker(this.nfa.start, (state) => {
if (state instanceof GroupStartMarkerState) {
const startMarker = state as GroupStartMarkerState;
if (startMarker.capturing) {
gm.push(state as GroupStartMarkerState);
RegExp.gm.push(state as GroupStartMarkerState);
}
}
});
this.groupMarkers = gm;
this.groupMarkers = RegExp.gm;

this.flags = flags;
}
Expand Down
Loading

0 comments on commit debec10

Please sign in to comment.