-
Notifications
You must be signed in to change notification settings - Fork 2
/
parser-4.test.ts
45 lines (34 loc) · 1.2 KB
/
parser-4.test.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
// Parses expressions using [parser-4.ts](./parser-4.ts).
import * as Z from "./parser-4.js"
const Expression: Z.Parser<number> = Z.deferred(() =>
Z.any(Level1, Parenthesized),
)
const Number = Z.regex(/^\d+(?:\.+\d+)?(?:e[+-]?\d+)?/).map((value) =>
parseFloat(value[0]),
)
const Parenthesized = Z.sequence(
Z.text("("),
Z.OptionalWhitespace,
Expression,
Z.OptionalWhitespace,
Z.text(")"),
).key(2)
const Atom = Z.any(Number, Parenthesized)
const Multiplication = Z.sequence(Z.text("*"), Z.OptionalWhitespace, Atom)
const Division = Z.sequence(Z.text("/"), Z.OptionalWhitespace, Atom)
const Level2 = Z.sequence(
Number,
Z.OptionalWhitespace,
Z.sepBy(Z.any(Multiplication, Division), Z.OptionalWhitespace),
).map(([number, , mappers]) =>
mappers.reduce((a, [type, , b]) => (type == "*" ? a * b : a / b), number),
)
const Addition = Z.sequence(Z.text("+"), Z.OptionalWhitespace, Level2)
const Subtraction = Z.sequence(Z.text("-"), Z.OptionalWhitespace, Level2)
const Level1 = Z.sequence(
Number,
Z.OptionalWhitespace,
Z.sepBy(Z.any(Addition, Subtraction), Z.OptionalWhitespace),
).map(([number, , mappers]) =>
mappers.reduce((a, [type, , b]) => (type == "+" ? a + b : a - b), number),
)