From 552fe49e3894aee7f7fc5340ad1227480911bc4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Jastrze=CC=A8bski?= Date: Wed, 17 Jan 2024 23:59:52 +0000 Subject: [PATCH] refactor: simplify exact repeat --- README.md | 10 +++++----- docs/API.md | 2 +- docs/Examples.md | 4 ++-- src/__tests__/examples.test.ts | 4 ++-- src/constructs/__tests__/choice-of.test.ts | 2 +- src/constructs/__tests__/repeat.test.tsx | 10 +++++----- src/constructs/repeat.ts | 6 +++--- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 8d29ab9..5fde5d3 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ const hexColor = buildRegExp( optionally('#'), capture( choiceOf( - repeat(hexDigit, { count: 6 }), // #rrggbb - repeat(hexDigit, { count: 3 }), // #rgb + repeat(hexDigit, 6), // #rrggbb + repeat(hexDigit, 3), // #rgb ), ), endOfString, @@ -79,11 +79,11 @@ const currencyAmount = buildRegExp([ choiceOf( '$', '€', - repeat({ count: 3 }, charRange('A', 'Z')), // ISO currency code + repeat(charRange('A', 'Z'), 3), // ISO currency code ), capture( oneOrMore(digit), // Integer part - optionally(['.', repeat({ count: 2 }, digit)]), // Fractional part + optionally(['.', repeat(digit, 2)]), // Fractional part ), ]); ``` @@ -114,7 +114,7 @@ Notes: | `zeroOrMore(x)` | `x*` | Zero or more occurence of a pattern | | `oneOrMore(x)` | `x+` | One or more occurence of a pattern | | `optionally(x)` | `x?` | Zero or one occurence of a pattern | -| `repeat(x, { count: n })` | `x{n}` | Pattern repeats exact number of times | +| `repeat(x, n)` | `x{n}` | Pattern repeats exact number of times | | `repeat(x, { min: n, })` | `x{n,}` | Pattern repeats at least given number of times | | `repeat(x, { min: n, max: n2 })` | `x{n1,n2}` | Pattern repeats between n1 and n2 number of times | diff --git a/docs/API.md b/docs/API.md index 677967e..18b6cfc 100644 --- a/docs/API.md +++ b/docs/API.md @@ -73,7 +73,7 @@ function optionally( ```ts function repeat( - options: { count: number } | { min: number; max?: number }, + options: number | { min: number; max?: number }, sequence: RegexSequence, ): Repeat ``` diff --git a/docs/Examples.md b/docs/Examples.md index ae07788..7333a45 100644 --- a/docs/Examples.md +++ b/docs/Examples.md @@ -7,7 +7,7 @@ const octet = choiceOf( [digit], [charRange('1', '9'), digit], - ['1', repeat({ count: 2 }, digit)], + ['1', repeat(digit, 2)], ['2', charRange('0', '4'), digit], ['25', charRange('0', '5')] ); @@ -15,7 +15,7 @@ const octet = choiceOf( // Match const regex = buildRegExp([ startOfString, // - repeat([octet, '.'], { count: 3 }), + repeat([octet, '.'], 3), octet, endOfString, ]); diff --git a/src/__tests__/examples.test.ts b/src/__tests__/examples.test.ts index 090731f..de4b072 100644 --- a/src/__tests__/examples.test.ts +++ b/src/__tests__/examples.test.ts @@ -12,14 +12,14 @@ test('example: IPv4 address validator', () => { const octet = choiceOf( [digit], [charRange('1', '9'), digit], - ['1', repeat(digit, { count: 2 })], + ['1', repeat(digit, 2)], ['2', charRange('0', '4'), digit], ['25', charRange('0', '5')], ); const regex = buildRegExp([ startOfString, // - repeat([octet, '.'], { count: 3 }), + repeat([octet, '.'], 3), octet, endOfString, ]); diff --git a/src/constructs/__tests__/choice-of.test.ts b/src/constructs/__tests__/choice-of.test.ts index 4d2d09c..8a54634 100644 --- a/src/constructs/__tests__/choice-of.test.ts +++ b/src/constructs/__tests__/choice-of.test.ts @@ -29,7 +29,7 @@ test('`choiceOf` with sequence options', () => { test('`choiceOf` using nested regex', () => { expect(choiceOf(oneOrMore('a'), zeroOrMore('b'))).toHavePattern(/a+|b*/); - expect(choiceOf(repeat('a', { min: 1, max: 3 }), repeat('bx', { count: 5 }))).toHavePattern( + expect(choiceOf(repeat('a', { min: 1, max: 3 }), repeat('bx', 5))).toHavePattern( /a{1,3}|(?:bx){5}/, ); }); diff --git a/src/constructs/__tests__/repeat.test.tsx b/src/constructs/__tests__/repeat.test.tsx index f419647..74b0fd6 100644 --- a/src/constructs/__tests__/repeat.test.tsx +++ b/src/constructs/__tests__/repeat.test.tsx @@ -5,20 +5,20 @@ import { repeat } from '../repeat'; test('`repeat` quantifier', () => { expect(['a', repeat('b', { min: 1, max: 5 })]).toHavePattern(/ab{1,5}/); expect(['a', repeat('b', { min: 1 })]).toHavePattern(/ab{1,}/); - expect(['a', repeat('b', { count: 1 })]).toHavePattern(/ab{1}/); + expect(['a', repeat('b', 1)]).toHavePattern(/ab{1}/); - expect(['a', repeat(['a', zeroOrMore('b')], { count: 1 })]).toHavePattern(/a(?:ab*){1}/); - expect(repeat(['text', ' ', oneOrMore('d')], { count: 5 })).toHavePattern(/(?:text d+){5}/); + expect(['a', repeat(['a', zeroOrMore('b')], 1)]).toHavePattern(/a(?:ab*){1}/); + expect(repeat(['text', ' ', oneOrMore('d')], 5)).toHavePattern(/(?:text d+){5}/); }); test('`repeat` optimizes grouping for atoms', () => { - expect(repeat(digit, { count: 2 })).toHavePattern(/\d{2}/); + expect(repeat(digit, 2)).toHavePattern(/\d{2}/); expect(repeat(digit, { min: 2 })).toHavePattern(/\d{2,}/); expect(repeat(digit, { min: 1, max: 5 })).toHavePattern(/\d{1,5}/); }); test('`repeat` throws on no children', () => { - expect(() => repeat([], { count: 1 })).toThrowErrorMatchingInlineSnapshot( + expect(() => repeat([], 1)).toThrowErrorMatchingInlineSnapshot( `"\`repeat\` should receive at least one element"`, ); }); diff --git a/src/constructs/repeat.ts b/src/constructs/repeat.ts index faf7156..26a9d48 100644 --- a/src/constructs/repeat.ts +++ b/src/constructs/repeat.ts @@ -9,7 +9,7 @@ export interface Repeat extends RegexConstruct { children: RegexElement[]; } -export type RepeatOptions = { count: number } | { min: number; max?: number }; +export type RepeatOptions = number | { min: number; max?: number }; export function repeat(sequence: RegexSequence, options: RepeatOptions): Repeat { const children = ensureArray(sequence); @@ -29,10 +29,10 @@ export function repeat(sequence: RegexSequence, options: RepeatOptions): Repeat function encodeRepeat(this: Repeat): EncodeResult { const atomicNodes = encodeAtom(this.children); - if ('count' in this.options) { + if (typeof this.options === 'number') { return { precedence: 'sequence', - pattern: `${atomicNodes.pattern}{${this.options.count}}`, + pattern: `${atomicNodes.pattern}{${this.options}}`, }; }