-
Notifications
You must be signed in to change notification settings - Fork 0
/
json.ts
104 lines (92 loc) · 2.58 KB
/
json.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import {
ParseResult,
Parser,
Either,
Left,
OneOrMore,
Optional,
Pair,
Right,
Sequence,
ZeroOrMore,
} from "./combinators.ts";
import { isNumeric, Item, Match } from "./simple.ts";
const WhiteSpace = new Item()
.pred((ch) => ch === " ")
.map((_) => null);
const WhiteSpaces = new ZeroOrMore(WhiteSpace);
function SpaceSurrounded(match: string) {
return new Sequence(WhiteSpaces, new Match(match), WhiteSpaces);
}
class JsonObject extends Parser<Record<string, unknown>> {
parse(input: string): ParseResult<Record<string, unknown>> {
const Num = new OneOrMore(new Item().pred(isNumeric))
.map((value) => parseInt(value.join("")));
const QuotedString = new Either(new Match('"'), new Match("'"))
.flat_map((delimiter) =>
new Left(
new ZeroOrMore(new Item().pred((c) => c != delimiter)),
new Match(delimiter as string),
)
)
.map((value) => value.join(""));
const Bool = new Either(new Match("true"), new Match("false"));
class PArray extends Parser<unknown[]> {
parse(input: string): ParseResult<unknown[]> {
return new Right(
SpaceSurrounded("["),
new Left(
new Optional(new Pair(
new ZeroOrMore(
new Left(
new Either(Num, Bool, QuotedString, this, new JsonObject()),
SpaceSurrounded(","),
),
),
new Either(Num, Bool, QuotedString, this, new JsonObject()),
)
.map(([elems, end_elem]) => {
elems.push(end_elem);
return elems;
})),
SpaceSurrounded("]"),
),
)
.map((value) => value || [])
.parse(input);
}
}
const JsonPair = new Pair(
QuotedString,
new Right(
SpaceSurrounded(":"),
new Either(Num, Bool, QuotedString, new PArray(), this).inspect(),
),
);
return new Right(
SpaceSurrounded("{"),
new Left(
new Optional(new Pair(
new ZeroOrMore(
new Left(JsonPair, SpaceSurrounded(",")),
),
JsonPair,
).map(([pairs, end_pair]) => {
pairs.push(end_pair);
return pairs;
}))
.map((pairs) => pairs || []),
SpaceSurrounded("}"),
),
)
.map((pairs) => {
const jsonData: Record<string, unknown> = {};
for (const [key, value] of pairs) {
jsonData[key] = value;
}
return jsonData;
})
.parse(input);
}
}
export { JsonObject }