Skip to content

refactor: rename types #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# API

## Builder

### `buildRegex()` function

```ts
function buildRegex(sequence: RegexSequence): RegExp;

function buildRegex(
flags: {
global?: boolean;
ignoreCase?: boolean;
multiline?: boolean;
hasIndices?: boolean;
sticky?: boolean;
},
sequence: RegexSequence
): RegExp;
```

## Components

### `capture()` component

Captures, also known as capturing groups, are used to extract and store parts of the matched string for later use.

```ts
function capture(
sequence: RegexSequence
): Capture
```

### `choiceOf()` component

```ts
function choiceOf(
...alternatives: RegexSequence[]
): ChoiceOf {
```

The `choiceOf` (alternation) construct is used to match one out of several possible sequences. It functions similarly to a logical OR operator in programming. It can match simple string options as well as complex patterns.

Example: `choiceOf("color", "colour")` matches either `color` or `colour` pattern.

## Quantifiers

### `zeroOrMore()` component

```ts
function zeroOrMore(
sequence: RegexSequence,
): ZeroOrMore
```

### `oneOrMore()` component

```ts
function oneOrMore(
sequence: RegexSequence,
): OneOrMore
```

### `optionally()` component

```ts
function optionally(
sequence: RegexSequence,
): Optionally
```

### `repeat()` component

```ts
function repeat(
options: { count: number } | { min: number; max?: number },
sequence: RegexSequence,
): Repeat
```

## Character classes

Character classes are a set of characters that match any one of the characters in the set.

### Common character classess

```ts
const any: CharacterClass;
const word: CharacterClass;
const digit: CharacterClass;
const whitespace: CharacterClass;
```

* `any` matches any character except newline characters.
* `word` matches any word character (alphanumeric & underscore).
* `digit` matches any digit.
* `whitespace` matches any whitespace character (spaces, tabs, line breaks).

### `anyOf()` component

```ts
function anyOf(
characters: string,
): CharacterClass
```

The `anyOf` class matches any character present in the `character` string.

Example: `anyOf('aeiou')` will match either `a`, `e`, `i` `o` or `u` characters.

### `characterRange()` component

```ts
function characterRange(
start: string,
end: string,
): CharacterClass
```

The `characterRange` class matches any character present in the range from `start` to `end` (inclusive).

Examples:
* `characterRange('a', 'z')` will match all lowercase characters from `a` to `z`.
* `characterRange('A', 'Z')` will match all uppercase characters from `a` to `z`.
* `characterRange('0', '9')` will match all digit characters from `0` to `9`.

### `characterClass()` component

```ts
function characterClass(
...elements: CharacterClass[],
): CharacterClass
```

The `characterClass` component creates a new character class that includes all passed character classes.

Example:
* `characterClass(characterRange('a', 'f'), digit)` will match all lowercase hex digits (`0` to `9` and `a` to `f`).
* `characterClass(characterRange('a', 'z'), digit, anyOf("._-"))` will match any digit, lowercase latin lettet from `a` to `z`, and either of `.`, `_`, and `-` characters.

### `inverted()` component

```ts
function inverted(
element: CharacterClass,
): CharacterClass
```

The `inverted` component creates a new character class that matches any character that is not present in the passed character class.

Examples:
* `inverted(digit)` matches any character that is not a digit
* `inverted(anyOf('aeiou'))` matches any character that is not a lowercase vowel.



## Anchors

Anchors are special characters or sequences that specify positions in the input string, rather than matching specific characters.

### Line start and end

```ts
const startOfString: Anchor; // Regex: ^
const endOfString: Anchor; // Regex: $
```

The `startOfString` (regex: `^`) matches the start of a string (or line, if multiline mode is enabled).

The `endOfString` (regex: `$`) matches the end of a string (or line, if multiline mode is enabled).
4 changes: 2 additions & 2 deletions src/components/anchors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { EncodeOutput } from '../encoder/types';
import type { RegexElement } from '../types';
import type { RegexEncodable } from '../types';

export interface Anchor extends RegexElement {
export interface Anchor extends RegexEncodable {
type: 'anchor';
symbol: string;
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/capture.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { encodeSequence } from '../encoder/encoder';
import type { EncodeOutput } from '../encoder/types';
import { asNodeArray } from '../utils/nodes';
import type { RegexElement, RegexNode, RegexSequence } from '../types';
import type { RegexElement, RegexEncodable, RegexSequence } from '../types';

export interface Capture extends RegexElement {
export interface Capture extends RegexEncodable {
type: 'capture';
children: RegexNode[];
children: RegexElement[];
}

export function capture(sequence: RegexSequence): Capture {
Expand Down
6 changes: 3 additions & 3 deletions src/components/choice-of.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { encodeSequence } from '../encoder/encoder';
import type { EncodeOutput } from '../encoder/types';
import { asNodeArray } from '../utils/nodes';
import type { RegexElement, RegexNode, RegexSequence } from '../types';
import type { RegexElement, RegexEncodable, RegexSequence } from '../types';

export interface ChoiceOf extends RegexElement {
export interface ChoiceOf extends RegexEncodable {
type: 'choiceOf';
alternatives: RegexNode[][];
alternatives: RegexElement[][];
}

export function choiceOf(...alternatives: RegexSequence[]): ChoiceOf {
Expand Down
14 changes: 7 additions & 7 deletions src/components/quantifiers.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { encodeAtom } from '../encoder/encoder';
import type { EncodeOutput } from '../encoder/types';
import { asNodeArray } from '../utils/nodes';
import type { RegexElement, RegexNode, RegexSequence } from '../types';
import type { RegexElement, RegexEncodable, RegexSequence } from '../types';

export interface OneOrMore extends RegexElement {
export interface OneOrMore extends RegexEncodable {
type: 'oneOrMore';
children: RegexNode[];
children: RegexElement[];
}

export interface Optionally extends RegexElement {
export interface Optionally extends RegexEncodable {
type: 'optionally';
children: RegexNode[];
children: RegexElement[];
}

export interface ZeroOrMore extends RegexElement {
export interface ZeroOrMore extends RegexEncodable {
type: 'zeroOrMore';
children: RegexNode[];
children: RegexElement[];
}

export function oneOrMore(sequence: RegexSequence): OneOrMore {
Expand Down
6 changes: 3 additions & 3 deletions src/components/repeat.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { encodeAtom } from '../encoder/encoder';
import type { EncodeOutput } from '../encoder/types';
import { asNodeArray } from '../utils/nodes';
import type { RegexElement, RegexNode, RegexSequence } from '../types';
import type { RegexElement, RegexEncodable, RegexSequence } from '../types';

export interface Repeat extends RegexElement {
export interface Repeat extends RegexEncodable {
type: 'repeat';
options: RepeatOptions;
children: RegexNode[];
children: RegexElement[];
}

export type RepeatOptions = { count: number } | { min: number; max?: number };
Expand Down
8 changes: 4 additions & 4 deletions src/encoder/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { RegexNode } from '../types';
import type { RegexElement } from '../types';
import { escapeText } from '../utils/text';
import type { EncodeOutput } from './types';

export function encodeSequence(nodes: RegexNode[]): EncodeOutput {
export function encodeSequence(nodes: RegexElement[]): EncodeOutput {
const encodedNodes = nodes.map((n) => encodeNode(n));
return concatSequence(encodedNodes);
}

export function encodeAtom(nodes: RegexNode[]): EncodeOutput {
export function encodeAtom(nodes: RegexElement[]): EncodeOutput {
return asAtom(encodeSequence(nodes));
}

function encodeNode(node: RegexNode): EncodeOutput {
function encodeNode(node: RegexElement): EncodeOutput {
if (typeof node === 'string') {
return encodeText(node);
}
Expand Down
15 changes: 12 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import type { EncodeOutput } from './encoder/types';

export type RegexSequence = RegexNode | RegexNode[];
/**
* Sequence of `RegexElements` that can be encoded into a regular expression.
*/
export type RegexSequence = RegexElement[] | RegexElement;

export type RegexNode = RegexElement | string;
/**
* Represents a result of calling a regex component (`RegexEncodable`) or a string to be matched literally.
*/
export type RegexElement = RegexEncodable | string;

export interface RegexElement {
/**
* Represents result of calling a regex componen.
*/
export interface RegexEncodable {
type: string;
encode(): EncodeOutput;
}
4 changes: 2 additions & 2 deletions src/utils/nodes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RegexNode, RegexSequence } from '../types';
import type { RegexElement, RegexSequence } from '../types';

export function asNodeArray(sequence: RegexSequence): RegexNode[] {
export function asNodeArray(sequence: RegexSequence): RegexElement[] {
return Array.isArray(sequence) ? sequence : [sequence];
}
10 changes: 5 additions & 5 deletions test-utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { buildRegex } from '../src/builders';
import type { RegexElement, RegexNode } from '../src/types';
import type { RegexElement, RegexEncodable } from '../src/types';

export function isRegexNode(node: unknown): node is RegexNode {
return typeof node === 'string' || isRegexElement(node);
export function isRegexElement(node: unknown): node is RegexElement {
return typeof node === 'string' || isRegexEncodable(node);
}

export function isRegexElement(element: unknown): element is RegexElement {
export function isRegexEncodable(element: unknown): element is RegexEncodable {
return (
typeof element === 'object' &&
element !== null &&
Expand All @@ -14,7 +14,7 @@ export function isRegexElement(element: unknown): element is RegexElement {
);
}

export function asRegExp(regex: RegExp | RegexNode | RegexNode[]) {
export function asRegExp(regex: RegExp | RegexElement | RegexElement[]) {
if (regex instanceof RegExp) {
return regex;
}
Expand Down