This repository has been archived by the owner on May 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.ns
122 lines (110 loc) · 3.02 KB
/
parser.ns
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
external record-fix(a : top) : top :=
"{ [key in keyof a]: a[key] }"
external record-empty : top :=
"{ }"
external record-singleton(key : string, value : top) : top :=
"{ [k in key]: value }"
external record-merge(a : top, b : top) : top :=
"(a & b)"
external space : string :=
'" " | "\\n"'
enum unit :=
| mk-unit
enum result(a : top) :=
| ok(value : a, rest : string)
| fail
def parse-string(str : string, s : string) : result(unit) :=
match s with
| <.str, s> := ok(unit, mk-unit, s)
| _ := fail(unit)
end
def parse-space(s : string) : result(unit) :=
match s with
| <.space, s> := parse-space(s)
| _ := ok(unit, mk-unit, s)
end
def parse-name(s : string) : result(string) :=
match s with
| <name, ":", s> := ok(string, name, <":", s>)
| _ := fail(string)
end
mutual
def parse-type(s : string) : result(top) :=
match s with
| <"number", s> := ok(top, number, s)
| <"string", s> := ok(top, string, s)
| <"boolean", s> := ok(top, boolean, s)
| _ := parse-record(s)
end
def parse-field(s : string) : result(top) :=
match parse-name(s) with
| fail(string) := fail(top)
| ok(string, (name : string), s) :=
match parse-string(": ", s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
match parse-type(s) with
| fail(top) := fail(top)
| ok(top, type_, s) :=
ok(top, record-singleton(name, type_), s)
end
end
end
def parse-fields(s : string) : result(top) :=
match parse-field(s) with
| fail(top) := ok(top, record-empty, s)
| ok(top, field, s) :=
match parse-string(",", s) with
| fail(unit) := ok(top, field, s)
| ok(unit, mk-unit, s) :=
match parse-space(s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
match parse-fields(s) with
| fail(top) := fail(top)
| ok(top, fields, s) :=
ok(top, record-merge(field, fields), s)
end
end
end
end
def parse-record(s : string) : result(top) :=
match parse-string("{", s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
match parse-space(s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
match parse-fields(s) with
| fail(top) := fail(top)
| ok(top, fields, s) :=
match parse-space(s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
match parse-string("}", s) with
| fail(unit) := fail(top)
| ok(unit, mk-unit, s) :=
ok(top, record-fix(fields), s)
end
end
end
end
end
end
def run-type-result(result : result(top)) : top :=
match result with
| ok(top, value, "") := value
| _ := bottom
end
def result-number : top :=
run-type-result(parse-type("number"))
def result-record : top :=
run-type-result(
parse-type(
< "{\n"
, " a: number, e: boolean,\n"
, " b: { c: string, d: string } \n"
, " }"
>
)
)