-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCalc.ts
82 lines (67 loc) · 2.2 KB
/
Calc.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// type Calc<T> = Eval<Parse<Lex<T>>>;
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type Unfold<T extends string> = T extends "" ? [] : [T];
type Lex<T, Prev extends string = ""> = T extends ""
? Unfold<Prev>
: T extends `+${infer Rest}`
? [...Unfold<Prev>, "+", ...Lex<Rest>]
: T extends `*${infer Rest}`
? [...Unfold<Prev>, "*", ...Lex<Rest>]
: T extends `(${infer Rest}`
? [...Unfold<Prev>, "(", ...Lex<Rest>]
: T extends `)${infer Rest}`
? [...Unfold<Prev>, ")", ...Lex<Rest>]
: T extends ` ${infer Rest}`
? [...Unfold<Prev>, ...Lex<Rest>]
: T extends `${infer First}${infer Rest}`
? First extends Digit
? Lex<Rest, `${Prev}${First}`>
: never
: never;
type AsPeano<T, Acc extends 0[] = []> = T extends `${Acc["length"]}`
? Acc
: AsPeano<T, [0, ...Acc]>;
type AsNum<T extends any[]> = T["length"];
type PNumber<T> = T extends [infer Num, ...infer Rest]
? [AsPeano<Num>, Rest]
: never;
type PGroup<T> = T extends ["(", ...infer Rest]
? PSum<Rest> extends [infer Inner, [")", ...infer Rest2]]
? [Inner, Rest2]
: never
: never;
type PFactor<T> = T extends [infer First, ...infer _]
? First extends "("
? PGroup<T>
: PNumber<T>
: never;
type PMult<T> = PFactor<T> extends [infer Left, infer Rest]
? Rest extends ["*", ...infer Rest2]
? PMult<Rest2> extends [infer Right, infer Rest3]
? [["*", Left, Right], Rest3]
: never
: [Left, Rest]
: never;
type PSum<T> = PMult<T> extends [infer Left, infer Rest]
? Rest extends ["+", ...infer Rest2]
? PSum<Rest2> extends [infer Right, infer Rest3]
? [["+", Left, Right], Rest3]
: never
: [Left, Rest]
: never;
type Parse<T> = PSum<T> extends [infer Value, []] ? Value : never;
type Sum<A extends 0[], B extends 0[]> = [...A, ...B];
type Prod<A extends 0[], B extends any[]> = B extends []
? []
: B extends [0, ...infer Rest]
? Sum<A, Prod<A, Rest>>
: never;
type Eval<T> = T extends 0[]
? T
: T extends ["+", infer Left, infer Right]
? Sum<Eval<Left>, Eval<Right>>
: T extends ["*", infer Left, infer Right]
? Prod<Eval<Left>, Eval<Right>>
: never;
type Calc<T> = AsNum<Eval<Parse<Lex<T>>>>;
type Result = Calc<"10 * 4 + 2 * 5">;