Skip to content

Commit 4a16993

Browse files
committed
refactor: numeric precedence
1 parent d218336 commit 4a16993

14 files changed

+33
-35
lines changed

src/constructs/anchors.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,31 @@ import type { EncodedRegex } from '../types';
44
* Start of string anchor. Matches the start of of string. In `multiline` mode, also matches immediately following a newline.
55
*/
66
export const startOfString: EncodedRegex = {
7-
precedence: 'atom',
7+
precedence: 0,
88
pattern: '^',
99
};
1010

1111
/**
1212
* End of string anchor. Matches the end of a string. In `multiline` mode, also matches immediately preceding a newline.
1313
*/
1414
export const endOfString: EncodedRegex = {
15-
precedence: 'atom',
15+
precedence: 0,
1616
pattern: '$',
1717
};
1818

1919
/**
2020
* Word boundary anchor. Matches the position where one side is a word character (alphanumeric or underscore) and the other side is a non-word character (anything else).
2121
*/
2222
export const wordBoundary: EncodedRegex = {
23-
precedence: 'atom',
23+
precedence: 0,
2424
pattern: '\\b',
2525
};
2626

2727
/**
2828
* Non-word boundary anchor. Matches the position where both sides are word characters.
2929
*/
3030
export const nonWordBoundary: EncodedRegex = {
31-
precedence: 'atom',
31+
precedence: 0,
3232
pattern: '\\B',
3333
};
3434

src/constructs/capture.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ export function capture(sequence: RegexSequence, options?: CaptureOptions): Enco
2121
const name = options?.name;
2222
if (name) {
2323
return {
24-
precedence: 'atom',
24+
precedence: 0,
2525
pattern: `(?<${name}>${encode(sequence).pattern})`,
2626
};
2727
}
2828

2929
return {
30-
precedence: 'atom',
30+
precedence: 0,
3131
pattern: `(${encode(sequence).pattern})`,
3232
};
3333
}
@@ -43,7 +43,7 @@ export function capture(sequence: RegexSequence, options?: CaptureOptions): Enco
4343
*/
4444
export function ref(name: string): Reference {
4545
return {
46-
precedence: 'atom',
46+
precedence: 0,
4747
pattern: `\\k<${name}>`,
4848
name,
4949
};

src/constructs/char-class.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function encodeCharClass(
8181
isNegated?: boolean,
8282
): EncodedRegex {
8383
return {
84-
precedence: 'atom',
84+
precedence: 0,
8585
pattern: `[${isNegated ? '^' : ''}${this.elements.join('')}]`,
8686
};
8787
}

src/constructs/char-escape.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import type { CharacterEscape, EncodedRegex } from '../types';
55
* Specifically this one is NOT a character escape.
66
*/
77
export const any: EncodedRegex = {
8-
precedence: 'atom',
8+
precedence: 0,
99
pattern: '.',
1010
};
1111

1212
/**
1313
* Matches any digit (0-9).
1414
*/
1515
export const digit: CharacterEscape = {
16-
precedence: 'atom',
16+
precedence: 0,
1717
pattern: '\\d',
1818
elements: ['\\d'],
1919
};
@@ -22,7 +22,7 @@ export const digit: CharacterEscape = {
2222
* Matches any non-digit (0-9) character.
2323
*/
2424
export const nonDigit: CharacterEscape = {
25-
precedence: 'atom',
25+
precedence: 0,
2626
pattern: '\\D',
2727
elements: ['\\D'],
2828
};
@@ -31,7 +31,7 @@ export const nonDigit: CharacterEscape = {
3131
* Matches any word character (alphanumeric or underscore).
3232
*/
3333
export const word: CharacterEscape = {
34-
precedence: 'atom',
34+
precedence: 0,
3535
pattern: '\\w',
3636
elements: ['\\w'],
3737
};
@@ -40,7 +40,7 @@ export const word: CharacterEscape = {
4040
* Matches any non-word (alphanumeric or underscore) character.
4141
*/
4242
export const nonWord: CharacterEscape = {
43-
precedence: 'atom',
43+
precedence: 0,
4444
pattern: '\\W',
4545
elements: ['\\W'],
4646
};
@@ -49,7 +49,7 @@ export const nonWord: CharacterEscape = {
4949
* Matches any whitespace character (space, tab, newline, etc.).
5050
*/
5151
export const whitespace: CharacterEscape = {
52-
precedence: 'atom',
52+
precedence: 0,
5353
pattern: '\\s',
5454
elements: ['\\s'],
5555
};
@@ -58,7 +58,7 @@ export const whitespace: CharacterEscape = {
5858
* Matches any non-whitespace (space, tab, newline, etc.) character.
5959
*/
6060
export const nonWhitespace: CharacterEscape = {
61-
precedence: 'atom',
61+
precedence: 0,
6262
pattern: '\\S',
6363
elements: ['\\S'],
6464
};

src/constructs/choice-of.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function choiceOf(...alternatives: RegexSequence[]): EncodedRegex {
1818
}
1919

2020
return {
21-
precedence: 'disjunction',
21+
precedence: 2,
2222
pattern: encodedAlternatives.map((n) => n.pattern).join('|'),
2323
};
2424
}

src/constructs/lookahead.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { EncodedRegex, RegexSequence } from '../types';
1717
*/
1818
export function lookahead(sequence: RegexSequence): EncodedRegex {
1919
return {
20-
precedence: 'atom',
20+
precedence: 0,
2121
pattern: `(?=${encode(sequence).pattern})`,
2222
};
2323
}

src/constructs/lookbehind.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { EncodedRegex, RegexSequence } from '../types';
1717
*/
1818
export function lookbehind(sequence: RegexSequence): EncodedRegex {
1919
return {
20-
precedence: 'atom',
20+
precedence: 0,
2121
pattern: `(?<=${encode(sequence).pattern})`,
2222
};
2323
}

src/constructs/negative-lookahead.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { EncodedRegex, RegexSequence } from '../types';
1717
*/
1818
export function negativeLookahead(sequence: RegexSequence): EncodedRegex {
1919
return {
20-
precedence: 'atom',
20+
precedence: 0,
2121
pattern: `(?!${encode(sequence).pattern})`,
2222
};
2323
}

src/constructs/negative-lookbehind.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { EncodedRegex, RegexSequence } from '../types';
1717
*/
1818
export function negativeLookbehind(sequence: RegexSequence): EncodedRegex {
1919
return {
20-
precedence: 'atom',
20+
precedence: 0,
2121
pattern: `(?<!${encode(sequence).pattern})`,
2222
};
2323
}

src/constructs/quantifiers.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export interface QuantifierOptions {
1515
export function zeroOrMore(sequence: RegexSequence, options?: QuantifierOptions): EncodedRegex {
1616
const elements = ensureElements(sequence);
1717
return {
18-
precedence: 'sequence',
18+
precedence: 1,
1919
pattern: `${encodeAtomic(elements)}*${options?.greedy === false ? '?' : ''}`,
2020
};
2121
}
@@ -29,7 +29,7 @@ export function zeroOrMore(sequence: RegexSequence, options?: QuantifierOptions)
2929
export function oneOrMore(sequence: RegexSequence, options?: QuantifierOptions): EncodedRegex {
3030
const elements = ensureElements(sequence);
3131
return {
32-
precedence: 'sequence',
32+
precedence: 1,
3333
pattern: `${encodeAtomic(elements)}+${options?.greedy === false ? '?' : ''}`,
3434
};
3535
}
@@ -43,7 +43,7 @@ export function oneOrMore(sequence: RegexSequence, options?: QuantifierOptions):
4343
export function optional(sequence: RegexSequence, options?: QuantifierOptions): EncodedRegex {
4444
const elements = ensureElements(sequence);
4545
return {
46-
precedence: 'sequence',
46+
precedence: 1,
4747
pattern: `${encodeAtomic(elements)}?${options?.greedy === false ? '?' : ''}`,
4848
};
4949
}

src/constructs/repeat.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ export function repeat(sequence: RegexSequence, options: RepeatOptions): Encoded
2222

2323
if (typeof options === 'number') {
2424
return {
25-
precedence: 'sequence',
25+
precedence: 1,
2626
pattern: `${encodeAtomic(elements)}{${options}}`,
2727
};
2828
}
2929

3030
return {
31-
precedence: 'sequence',
31+
precedence: 1,
3232
pattern: `${encodeAtomic(elements)}{${options.min},${options?.max ?? ''}}${
3333
options.greedy === false ? '?' : ''
3434
}`,

src/constructs/unicode.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function unicodeChar(codePoint: number): CharacterEscape {
2323
: `\\u{${codePoint.toString(16)}}`; // 1-6 digit hex (requires unicode-aware mode)
2424

2525
return {
26-
precedence: 'atom',
26+
precedence: 0,
2727
pattern: escape,
2828
elements: [escape],
2929
};
@@ -50,7 +50,7 @@ export function unicodeProperty(property: string, value?: string): CharacterEsca
5050
const escape = `\\p{${property}${value ? `=${value}` : ''}}`;
5151

5252
return {
53-
precedence: 'atom',
53+
precedence: 0,
5454
pattern: escape,
5555
elements: [escape],
5656
};

src/encoder.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@ export function encode(sequence: RegexSequence): EncodedRegex {
1010
}
1111

1212
return {
13-
precedence: 'sequence',
14-
pattern: encoded
15-
.map((n) => (n.precedence === 'disjunction' ? encodeAtomic(n) : n.pattern))
16-
.join(''),
13+
precedence: 1,
14+
pattern: encoded.map((n) => (n.precedence === 2 ? encodeAtomic(n) : n.pattern)).join(''),
1715
};
1816
}
1917

2018
export function encodeAtomic(sequence: RegexSequence): string {
2119
const encoded = encode(sequence);
22-
return encoded.precedence === 'atom' ? encoded.pattern : `(?:${encoded.pattern})`;
20+
return encoded.precedence === 0 ? encoded.pattern : `(?:${encoded.pattern})`;
2321
}
2422

2523
function encodeElement(element: RegexElement): EncodedRegex {
@@ -51,7 +49,7 @@ function encodeText(text: string): EncodedRegex {
5149

5250
return {
5351
// Optimize for single character case
54-
precedence: text.length === 1 ? 'atom' : 'sequence',
52+
precedence: text.length === 1 ? 0 : 1,
5553
pattern: escapeText(text),
5654
};
5755
}
@@ -61,7 +59,7 @@ function encodeRegExp(regexp: RegExp): EncodedRegex {
6159

6260
return {
6361
// Encode at safe precedence
64-
precedence: isAtomicPattern(pattern) ? 'atom' : 'disjunction',
62+
precedence: isAtomicPattern(pattern) ? 0 : 2,
6563
pattern,
6664
};
6765
}

src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface EncodedRegex {
2828
/**
2929
* Precedence of given regex pattern.
3030
*/
31-
export type EncodePrecedence = 'atom' | 'sequence' | 'disjunction';
31+
export type EncodePrecedence = 0 | 1 | 2;
3232

3333
/**
3434
* Regex patter that can be encoded by calling the `encode` method.

0 commit comments

Comments
 (0)