Skip to content

Commit 86e5306

Browse files
committed
feat(parser): add char ranges
1 parent 6625821 commit 86e5306

File tree

4 files changed

+114
-29
lines changed

4 files changed

+114
-29
lines changed

src/internals/parser/Parser.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import {
1010
_,
1111
} from "../core/Core";
1212
import { Match } from "../match/Match";
13+
import { CharToNumber } from "../strings/impl/chars";
1314
import { Strings } from "../strings/Strings";
1415
import { Tuples } from "../tuples/Tuples";
15-
16+
import { GreaterThanOrEqual, LessThanOrEqual } from "../numbers/impl/compare";
1617
export namespace Parser {
1718
/**
1819
* A parser is a function that takes static parameters and a string input
@@ -498,6 +499,44 @@ export namespace Parser {
498499
: InputError<this["arg0"]>;
499500
}
500501

502+
/**
503+
* Parser that matches a single character between the given characters.
504+
* @param start - the start of the range
505+
* @param end - the end of the range
506+
* @returns an Ok type if the parser matches or an error
507+
*
508+
* @example
509+
* ```ts
510+
* type T0 = Call<CharRange<"a", "z">, "a">;
511+
* // ^? type T0 = Ok< "a", "" >
512+
* type T1 = Call<CharRange<"a", "z">, "z">;
513+
* // ^? type T1 = Ok< "z", "" >
514+
* type T2 = Call<CharRange<"a", "z">, "A">;
515+
* // ^? type T2 = Error<{ message: "Expected 'range('a', 'z')' - Received 'A'"; cause: "";}>
516+
* ```
517+
*/
518+
export interface CharRange<start extends string, end extends string>
519+
extends ParserFn {
520+
name: "range";
521+
params: [start, end];
522+
return: this["arg0"] extends infer Input extends string
523+
? Input extends `${infer Head}${infer Tail}`
524+
? [CharToNumber<start>, CharToNumber<Head>, CharToNumber<end>] extends [
525+
infer S extends number,
526+
infer H extends number,
527+
infer E extends number
528+
]
529+
? [GreaterThanOrEqual<H, S>, LessThanOrEqual<H, E>] extends [
530+
true,
531+
true
532+
]
533+
? Ok<Head, Tail>
534+
: Err<this, Input>
535+
: Err<this, Input>
536+
: Err<this, Input>
537+
: InputError<this["arg0"]>;
538+
}
539+
501540
/**
502541
* Parser that matches a single character that is an alphanumeric character.
503542
* @returns an Ok type if the parser matches or an error

src/internals/strings/Strings.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Std } from "../std/Std";
33
import { Tuples } from "../tuples/Tuples";
44
import * as H from "../helpers";
55
import * as Impl from "./impl/strings";
6-
import { Functions } from "../functions/Functions";
76

87
export namespace Strings {
98
export type Stringifiable =
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// prettier-ignore
2+
export type ascii = {
3+
" ": 32; "!": 33; '"': 34; "#": 35; $: 36; "%": 37; "&": 38; "'": 39;
4+
"(": 40; ")": 41; "*": 42; "+": 43; ",": 44; "-": 45; ".": 46; "/": 47; "0": 48; "1": 49;
5+
"2": 50; "3": 51; "4": 52; "5": 53; "6": 54; "7": 55; "8": 56; "9": 57; ":": 58; ";": 59;
6+
"<": 60; "=": 61; ">": 62; "?": 63; "@": 64; A: 65; B: 66; C: 67; D: 68; E: 69;
7+
F: 70; G: 71; H: 72; I: 73; J: 74; K: 75; L: 76; M: 77; N: 78; O: 79;
8+
P: 80; Q: 81; R: 82; S: 83; T: 84; U: 85; V: 86; W: 87; X: 88; Y: 89;
9+
Z: 90; "[": 91; "\\": 92; "]": 93; "^": 94; _: 95; "`": 96; a: 97; b: 98; c: 99;
10+
d: 100; e: 101; f: 102; g: 103; h: 104; i: 105; j: 106; k: 107; l: 108; m: 109;
11+
n: 110; o: 111; p: 112; q: 113; r: 114; s: 115; t: 116; u: 117; v: 118; w: 119;
12+
x: 120; y: 121; z: 122; "{": 123; "|": 124; "}": 125; "~": 126;
13+
é: 130; â: 131; ä: 132; à: 133; å: 134; ç: 135; ê: 136; ë: 137; è: 138; ï: 139;
14+
î: 140; ì: 141; Ä: 142; Å: 143; É: 144; æ: 145; Æ: 146; ô: 147; ö: 148; ò: 149;
15+
û: 150; ù: 151; ÿ: 152; Ö: 153; Ü: 154; ø: 155; "£": 156; Ø: 157; "×": 158; ƒ: 159;
16+
á: 160; í: 161; ó: 162; ú: 163; ñ: 164; Ñ: 165; ª: 166; º: 167; "¿": 168; "®": 169;
17+
"½": 171; "¼": 172; "¡": 173; "«": 174; "»": 175; "░": 176; "▒": 177; "▓": 178; "│": 179;
18+
"┤": 180; Á: 181; Â: 182; À: 183; "©": 184; "╣": 185; "║": 186; "╗": 187; "╝": 188; "¢": 189;
19+
"¥": 190; "┐": 191; "└": 192; "┴": 193; "┬": 194; "├": 195; "─": 196; "┼": 197; ã: 198; Ã: 199;
20+
"╚": 200; "╔": 201; "╩": 202; "╦": 203; "╠": 204; "═": 205; "╬": 206; "¤": 207; ð: 208; Ð: 209;
21+
Ê: 210; Ë: 211; È: 212; ı: 213; Í: 214; Î: 215; Ï: 216; "┘": 217; "┌": 218; "█": 219;
22+
"▄": 220; "¦": 221; Ì: 222; "▀": 223; Ó: 224; ß: 225; Ô: 226; Ò: 227; õ: 228; Õ: 229;
23+
µ: 230; þ: 231; Þ: 232; Ú: 233; Û: 234; Ù: 235; ý: 236; Ý: 237; "¯": 238; "´": 239;
24+
"¬": 240; "±": 241; "‗": 242; "¾": 243; "¶": 244; "§": 245; "÷": 246; "¸": 247; "°": 248; "¨": 249;
25+
"•": 250; "¹": 251; "³": 252; "²": 253; "■": 254;
26+
};
27+
28+
// prettier-ignore
29+
export type toNextAscii = [
30+
"", "", "", "", "", "","", "", "","", "", "","", "", "","", "", "","", "", "","", "", "","", "", "","", "", "", "",
31+
" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/",
32+
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
33+
"@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
34+
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_",
35+
"`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
36+
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "", "", "",
37+
"é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å", "É", "æ",
38+
"Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "ø", "£", "Ø", "×", "ƒ", "á", "í",
39+
"ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "®", "", "½", "¼", "¡", "«", "»", "░", "▒",
40+
"▓", "│", "┤", "Á", "Â", "À", "©", "", "╣", "║", "╗", "╝", "¢", "¥", "┐", "└",
41+
"┴", "┬", "├", "─", "┼", "ã", "Ã", "╚", "╔", "╩", "╦", "╠", "═", "╬", "¤", "ð",
42+
"Ð", "Ê", "Ë", "È", "ı", "Í", "Î", "Ï", "┘", "┌", "█", "▄", "¦", "Ì", "▀", "Ó",
43+
"ß", "Ô", "Ò", "õ", "Õ", "µ", "þ", "Þ", "Ú", "Û", "Ù", "ý", "Ý", "¯", "´",
44+
"¬", "±", "‗", "¾", "¶", "§", "÷", "¸", "°", "¨", "•", "¹", "³", "²", "■"
45+
];
46+
47+
export type toPrevAscii = ["", "", ...toNextAscii];
48+
49+
export type toAscii = ["", ...toNextAscii];
50+
51+
export type CharToNumber<T extends string> = T extends keyof ascii
52+
? ascii[T]
53+
: 0;
54+
55+
export type NumberToChar<T extends number> = T extends keyof toNextAscii
56+
? toAscii[T]
57+
: "";
58+
59+
export type CharNext<T extends string> = T extends keyof ascii
60+
? toNextAscii[ascii[T]]
61+
: "";
62+
63+
export type CharPrev<T extends string> = T extends keyof ascii
64+
? toPrevAscii[ascii[T]]
65+
: "";
66+
67+
export type CharRange<
68+
start extends string,
69+
end extends string,
70+
acc extends string[] = []
71+
> = start extends end
72+
? [...acc, start]
73+
: CharRange<CharNext<start>, end, [...acc, start]>;

src/internals/strings/impl/compare.ts

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,7 @@ import { Call2 } from "../../core/Core";
22
import { Numbers } from "../../numbers/Numbers";
33
import { StringToTuple } from "./split";
44
import { Equal as _Equal } from "../../helpers";
5-
6-
// prettier-ignore
7-
type ascii = {
8-
" ": 32; "!": 33; '"': 34; "#": 35; $: 36; "%": 37; "&": 38; "'": 39;
9-
"(": 40; ")": 41; "*": 42; "+": 43; ",": 44; "-": 45; ".": 46; "/": 47; "0": 48; "1": 49;
10-
"2": 50; "3": 51; "4": 52; "5": 53; "6": 54; "7": 55; "8": 56; "9": 57; ":": 58; ";": 59;
11-
"<": 60; "=": 61; ">": 62; "?": 63; "@": 64; A: 65; B: 66; C: 67; D: 68; E: 69;
12-
F: 70; G: 71; H: 72; I: 73; J: 74; K: 75; L: 76; M: 77; N: 78; O: 79;
13-
P: 80; Q: 81; R: 82; S: 83; T: 84; U: 85; V: 86; W: 87; X: 88; Y: 89;
14-
Z: 90; "[": 91; "\\": 92; "]": 93; "^": 94; _: 95; "`": 96; a: 97; b: 98; c: 99;
15-
d: 100; e: 101; f: 102; g: 103; h: 104; i: 105; j: 106; k: 107; l: 108; m: 109;
16-
n: 110; o: 111; p: 112; q: 113; r: 114; s: 115; t: 116; u: 117; v: 118; w: 119;
17-
x: 120; y: 121; z: 122; "{": 123; "|": 124; "}": 125; "~": 126;
18-
é: 130; â: 131; ä: 132; à: 133; å: 134; ç: 135; ê: 136; ë: 137; è: 138; ï: 139;
19-
î: 140; ì: 141; Ä: 142; Å: 143; É: 144; æ: 145; Æ: 146; ô: 147; ö: 148; ò: 149;
20-
û: 150; ù: 151; ÿ: 152; Ö: 153; Ü: 154; ø: 155; "£": 156; Ø: 157; "×": 158; ƒ: 159;
21-
á: 160; í: 161; ó: 162; ú: 163; ñ: 164; Ñ: 165; ª: 166; º: 167; "¿": 168; "®": 169;
22-
"½": 171; "¼": 172; "¡": 173; "«": 174; "»": 175; "░": 176; "▒": 177; "▓": 178; "│": 179;
23-
"┤": 180; Á: 181; Â: 182; À: 183; "©": 184; "╣": 185; "║": 186; "╗": 187; "╝": 188; "¢": 189;
24-
"¥": 190; "┐": 191; "└": 192; "┴": 193; "┬": 194; "├": 195; "─": 196; "┼": 197; ã: 198; Ã: 199;
25-
"╚": 200; "╔": 201; "╩": 202; "╦": 203; "╠": 204; "═": 205; "╬": 206; "¤": 207; ð: 208; Ð: 209;
26-
Ê: 210; Ë: 211; È: 212; ı: 213; Í: 214; Î: 215; Ï: 216; "┘": 217; "┌": 218; "█": 219;
27-
"▄": 220; "¦": 221; Ì: 222; "▀": 223; Ó: 224; ß: 225; Ô: 226; Ò: 227; õ: 228; Õ: 229;
28-
µ: 230; þ: 231; Þ: 232; Ú: 233; Û: 234; Ù: 235; ý: 236; Ý: 237; "¯": 238; "´": 239;
29-
"¬": 240; "±": 241; "‗": 242; "¾": 243; "¶": 244; "§": 245; "÷": 246; "¸": 247; "°": 248; "¨": 249;
30-
"•": 250; "¹": 251; "³": 252; "²": 253; "■": 254;
31-
};
5+
import { ascii } from "./chars";
326

337
type CharacterCompare<
348
Char1 extends string,

0 commit comments

Comments
 (0)