Skip to content

Commit 538e2c9

Browse files
committed
refactor: self code review
1 parent a39946d commit 538e2c9

File tree

3 files changed

+116
-82
lines changed

3 files changed

+116
-82
lines changed

src/constructs/__tests__/capture.test.tsx

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { capture, oneOrMore } from '../..';
1+
import {
2+
any,
3+
anyOf,
4+
buildRegExp,
5+
capture,
6+
digit,
7+
inverted,
8+
oneOrMore,
9+
reference,
10+
word,
11+
wordBoundary,
12+
} from '../..';
213

314
test('`capture` pattern', () => {
415
expect(capture('a')).toEqualRegex(/(a)/);
@@ -12,3 +23,97 @@ test('`capture` matching', () => {
1223
expect(['a', capture('b')]).toMatchGroups('ab', ['ab', 'b']);
1324
expect(['a', capture('b'), capture('c')]).toMatchGroups('abc', ['abc', 'b', 'c']);
1425
});
26+
27+
test('named `capture` pattern', () => {
28+
expect(capture('a', { ref: 'xyz' })).toEqualRegex('(?<xyz>a)');
29+
expect(capture('abc', { ref: 'xyz' })).toEqualRegex('(?<xyz>abc)');
30+
expect(capture(oneOrMore('abc'), { ref: 'xyz' })).toEqualRegex('(?<xyz>(?:abc)+)');
31+
expect(oneOrMore(capture('abc', { ref: 'xyz' }))).toEqualRegex('(?<xyz>abc)+');
32+
});
33+
34+
test('named `capture` matching', () => {
35+
expect(capture('b', { ref: 'x1' })).toMatchGroups('ab', ['b', 'b']);
36+
expect(capture('b', { ref: 'x1' })).toMatchNamedGroups('ab', { x1: 'b' });
37+
38+
expect(['a', capture('b', { ref: 'x1' })]).toMatchGroups('ab', ['ab', 'b']);
39+
expect(['a', capture('b', { ref: 'x1' })]).toMatchNamedGroups('ab', { x1: 'b' });
40+
41+
expect([capture('a'), capture('b', { ref: 'x1' }), capture('c', { ref: 'x2' })]).toMatchGroups(
42+
'abc',
43+
['abc', 'a', 'b', 'c'],
44+
);
45+
expect([
46+
capture('a'),
47+
capture('b', { ref: 'x1' }),
48+
capture('c', { ref: 'x2' }),
49+
]).toMatchNamedGroups('abc', { x1: 'b', x2: 'c' });
50+
});
51+
52+
// Should have `ref0` as name.
53+
const firstRef = reference();
54+
55+
test('`reference` pattern', () => {
56+
expect([firstRef]).toEqualRegex(/\k<ref0>/);
57+
expect([reference('xyz')]).toEqualRegex(/\k<xyz>/);
58+
expect([capture(any, { ref: firstRef }), ' ', firstRef]).toEqualRegex('(?<ref0>.) \\k<ref0>');
59+
60+
const otherRef = reference('r123');
61+
expect(['xx', capture(any, { ref: otherRef }), ' ', otherRef, 'xx']).toEqualRegex(
62+
'xx(?<r123>.) \\k<r123>xx',
63+
);
64+
});
65+
66+
test('`reference` matching basic case', () => {
67+
const ref = reference();
68+
expect([capture(word, { ref }), ref]).toMatchString('aa');
69+
expect([capture(digit, { ref }), ref]).toMatchString('11');
70+
71+
expect([capture(any, { ref }), ref]).not.toMatchString('ab');
72+
73+
expect([capture(digit, { ref }), ref]).not.toMatchString('1a');
74+
expect([capture(digit, { ref }), ref]).not.toMatchString('a1');
75+
});
76+
77+
test('`reference` matching HTML attributes', () => {
78+
const quoteRef = reference('quote');
79+
const quote = anyOf('"\'');
80+
const htmlAttributeRegex = buildRegExp([
81+
wordBoundary,
82+
capture(oneOrMore(word), { ref: 'name' }),
83+
'=',
84+
capture(quote, { ref: quoteRef }),
85+
capture(oneOrMore(inverted(quote)), { ref: 'value' }),
86+
quoteRef,
87+
]);
88+
89+
expect(htmlAttributeRegex).toMatchNamedGroups('a="b"', {
90+
name: 'a',
91+
quote: '"',
92+
value: 'b',
93+
});
94+
expect(htmlAttributeRegex).toMatchNamedGroups('aa="bbb"', {
95+
name: 'aa',
96+
quote: '"',
97+
value: 'bbb',
98+
});
99+
expect(htmlAttributeRegex).toMatchNamedGroups(`aa='bbb'`, {
100+
name: 'aa',
101+
quote: `'`,
102+
value: 'bbb',
103+
});
104+
expect(htmlAttributeRegex).toMatchNamedGroups('<input type="number" />', {
105+
quote: '"',
106+
name: 'type',
107+
value: 'number',
108+
});
109+
expect(htmlAttributeRegex).toMatchNamedGroups(`<input type='number' />`, {
110+
quote: "'",
111+
name: 'type',
112+
value: 'number',
113+
});
114+
115+
expect(htmlAttributeRegex).not.toMatchString(`aa="bbb'`);
116+
expect(htmlAttributeRegex).not.toMatchString(`aa='bbb"`);
117+
expect(htmlAttributeRegex).not.toMatchString(`<input type='number" />`);
118+
expect(htmlAttributeRegex).not.toMatchString(`<input type="number' />`);
119+
});

src/constructs/__tests__/references.test.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/constructs/capture.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ export interface CaptureOptions {
1313
ref?: Reference | string;
1414
}
1515

16-
/**
17-
* Reference to a capturing group.
18-
*/
1916
export interface Reference extends RegexConstruct {
2017
type: 'reference';
2118
name: string;
2219
}
2320

21+
/**
22+
* Capturing group.
23+
*
24+
* Captures the matched text and allows it to be referenced later both in the match results as well
25+
* as in the regex itself (@see Reference).
26+
*/
2427
export function capture(sequence: RegexSequence, options?: CaptureOptions): Capture {
2528
return {
2629
type: 'capture',
@@ -32,6 +35,9 @@ export function capture(sequence: RegexSequence, options?: CaptureOptions): Capt
3235

3336
let counter = 0;
3437

38+
/**
39+
* Reference to a capturing group.
40+
*/
3541
export function reference(name?: string): Reference {
3642
return {
3743
type: 'reference',
@@ -58,7 +64,7 @@ function encodeCapture(this: Capture): EncodeResult {
5864

5965
function encodeReference(this: Reference): EncodeResult {
6066
return {
61-
precedence: 'sequence',
67+
precedence: 'atom',
6268
pattern: `\\k<${this.name}>`,
6369
};
6470
}

0 commit comments

Comments
 (0)