fmt/ylex.bend
cswap-bend-cli@0.1.0.0 · 231 lines · 38 definitions
1import Base
2import cswap-bend-cli@0.1.0.0/json.bend as Json
3
4
5
6
7
8def JR() -> Type:
9 Result<&2, &2, String, Json.Json>
10
11def ge(+c: U32, lo: U32) -> Bool:
12 U32.is_ge(c, lo)
13
14def between(+c: U32, lo: U32, hi: U32) -> Bool:
15 U32.is_ge(c, lo) && U32.is_le(c, hi)
16
17def is_digit(+c: U32) -> Bool:
18 between(c, 48, 57)
19
20def is_space(+c: U32) -> Bool:
21 U32.is_eq(c, 32)
22
23
24
25type NS is Data:
26 NStart{}
27 NMinus{}
28 NZero{}
29 NInt{}
30 NDot{}
31 NFrac{}
32 NExp{}
33 NESign{}
34 NEDig{}
35 NBad{}
36
37def ns.lead(+c: U32) -> NS:
38 Bool.pick(NS, U32.is_eq(c, 48), NZero{}, Bool.pick(NS, between(c, 49, 57), NInt{}, NBad{}))
39
40def ns.start(+c: U32) -> NS:
41 Bool.pick(NS, U32.is_eq(c, 45), NMinus{}, ns.lead(c))
42
43def ns.tail(+c: U32) -> NS:
44 Bool.pick(NS, U32.is_eq(c, 46), NDot{}, Bool.pick(NS, U32.is_eq(c, 101) || U32.is_eq(c, 69), NExp{}, NBad{}))
45
46def ns.int(+c: U32) -> NS:
47 Bool.pick(NS, is_digit(c), NInt{}, ns.tail(c))
48
49def ns.frac(+c: U32) -> NS:
50 Bool.pick(NS, is_digit(c), NFrac{}, Bool.pick(NS, U32.is_eq(c, 101) || U32.is_eq(c, 69), NExp{}, NBad{}))
51
52def ns.exp(+c: U32) -> NS:
53 Bool.pick(NS, U32.is_eq(c, 43) || U32.is_eq(c, 45), NESign{}, Bool.pick(NS, is_digit(c), NEDig{}, NBad{}))
54
55def ns.digits(+c: U32, next: NS) -> NS:
56 Bool.pick(NS, is_digit(c), next, NBad{})
57
58def ns.step(s: NS, +c: U32) -> NS:
59 match s:
60 case NStart{}:
61 ns.start(c)
62 case NMinus{}:
63 ns.lead(c)
64 case NZero{}:
65 ns.tail(c)
66 case NInt{}:
67 ns.int(c)
68 case NDot{}:
69 ns.digits(c, NFrac{})
70 case NFrac{}:
71 ns.frac(c)
72 case NExp{}:
73 ns.exp(c)
74 case NESign{}:
75 ns.digits(c, NEDig{})
76 case NEDig{}:
77 ns.digits(c, NEDig{})
78 case NBad{}:
79 NBad{}
80
81def ns.run(s: String, st: NS) -> NS:
82 match s:
83 case SNil{}:
84 st
85 case SCon{Chr{c}, t}:
86 ns.run(t, ns.step(st, c))
87
88def ns.accept(s: NS) -> Bool:
89 match s:
90 case NZero{}:
91 True{}
92 case NInt{}:
93 True{}
94 case NFrac{}:
95 True{}
96 case NEDig{}:
97 True{}
98 case _:
99 False{}
100
101
102def is_number(s: String) -> Bool:
103 ns.accept(ns.run(s, NStart{}))
104
105
106
107def word_is(+low: String, w: String) -> Bool:
108 String.eq(low, w)
109
110def is_null_word(+low: String) -> Bool:
111 String.is_empty(low) || word_is(low, "~") || word_is(low, "null")
112
113def is_bool_word(+low: String) -> Bool:
114 word_is(low, "true") || word_is(low, "false")
115
116
117def reserved(+low: String) -> Bool:
118 is_null_word(low) || is_bool_word(low) || word_is(low, "yes") || word_is(low, "no") || word_is(low, "on") || word_is(low, "off") || word_is(low, "y") || word_is(low, "n")
119
120
121def resolve.low(+low: String, +s: String) -> Json.Json:
122 Bool.pick(Json.Json, is_null_word(low), Json.JNull{},
123 Bool.pick(Json.Json, word_is(low, "true"), Json.JBool{True{}},
124 Bool.pick(Json.Json, word_is(low, "false"), Json.JBool{False{}},
125 Bool.pick(Json.Json, is_number(s), Json.JNum{s}, Json.JStr{s}))))
126
127def resolve(+s: String) -> Json.Json:
128 resolve.low(String.to_lower(s), s)
129
130
131
132
133
134def bad_first(+c: U32) -> Bool:
135 U32.is_eq(c, 45) || U32.is_eq(c, 63) || U32.is_eq(c, 58) || U32.is_eq(c, 44) || U32.is_eq(c, 91) || U32.is_eq(c, 93) || U32.is_eq(c, 123) || U32.is_eq(c, 125)
136 || U32.is_eq(c, 35) || U32.is_eq(c, 38) || U32.is_eq(c, 42) || U32.is_eq(c, 33) || U32.is_eq(c, 124) || U32.is_eq(c, 62) || U32.is_eq(c, 39) || U32.is_eq(c, 34)
137 || U32.is_eq(c, 37) || U32.is_eq(c, 64) || U32.is_eq(c, 96) || U32.is_eq(c, 43) || U32.is_eq(c, 46) || U32.is_eq(c, 126) || U32.is_eq(c, 61) || U32.is_eq(c, 60)
138 || is_digit(c) || is_space(c)
139
140def bad_char(+c: U32) -> Bool:
141 U32.is_lt(c, 32) || between(c, 127, 159) || between(c, 8232, 8233) || U32.is_eq(c, 65279)
142
143
144def rest_ok(s: String, +prev: U32) -> Bool:
145 match s:
146 case SNil{}:
147 Bool.not(U32.is_eq(prev, 58)) && Bool.not(is_space(prev))
148 case SCon{Chr{+c}, t}:
149 Bool.not(bad_char(c)) && Bool.not(U32.is_eq(prev, 58) && is_space(c)) && Bool.not(is_space(prev) && U32.is_eq(c, 35)) && rest_ok(t, c)
150
151def first_ok(s: String) -> Bool:
152 match s:
153 case SNil{}:
154 False{}
155 case SCon{Chr{+c}, t}:
156 Bool.not(bad_first(c)) && Bool.not(bad_char(c)) && rest_ok(t, c)
157
158def plain_ok(+s: String) -> Bool:
159 first_ok(s) && Bool.not(reserved(String.to_lower(s)))
160
161
162
163def dq.pick(done: Bool, n: Nat, rest: Maybe<&2, Nat>) -> Maybe<&2, Nat>:
164 match done:
165 case True{}:
166 Some{n}
167 case False{}:
168 rest
169
170
171
172def dq.end(s: String, +n: Nat, +esc: Bool) -> Maybe<&2, Nat>:
173 match s:
174 case SNil{}:
175 None{}
176 case SCon{Chr{+c}, t}:
177 dq.pick(Bool.not(esc) && U32.is_eq(c, 34), Nat.add(n, 1n), dq.end(t, Nat.add(n, 1n), Bool.not(esc) && U32.is_eq(c, 92)))
178
179def sq.eos(prevq: Bool, n: Nat) -> Maybe<&2, Nat>:
180 match prevq:
181 case True{}:
182 Some{n}
183 case False{}:
184 None{}
185
186def sq.pick(done: Bool, n: Nat, rest: Maybe<&2, Nat>) -> Maybe<&2, Nat>:
187 match done:
188 case True{}:
189 Some{n}
190 case False{}:
191 rest
192
193
194
195def sq.end(s: String, +n: Nat, +prevq: Bool) -> Maybe<&2, Nat>:
196 match s:
197 case SNil{}:
198 sq.eos(prevq, n)
199 case SCon{Chr{+c}, t}:
200 sq.pick(prevq && Bool.not(U32.is_eq(c, 39)), n, sq.end(t, Nat.add(n, 1n), Bool.not(prevq) && U32.is_eq(c, 39)))
201
202def first_code(s: String) -> U32:
203 match s:
204 case SNil{}:
205 0
206 case SCon{Chr{c}, t}:
207 c
208
209def tl.plus(m: Maybe<&2, Nat>) -> Maybe<&2, Nat>:
210 match m:
211 case None{}:
212 None{}
213 case Some{n}:
214 Some{Nat.add(n, 1n)}
215
216def tl.pick(isd: Bool, iss: Bool, d: Maybe<&2, Nat>, s: Maybe<&2, Nat>) -> Maybe<&2, Nat>:
217 match isd iss:
218 case True{} _:
219 d
220 case False{} True{}:
221 s
222 case False{} False{}:
223 None{}
224
225def token_len.q(+s: String, +c: U32) -> Maybe<&2, Nat>:
226 tl.pick(U32.is_eq(c, 34), U32.is_eq(c, 39), tl.plus(dq.end(String.drop(s, 1n), 0n, False{})), tl.plus(sq.end(String.drop(s, 1n), 0n, False{})))
227
228
229
230def token_len(+s: String) -> Maybe<&2, Nat>:
231 token_len.q(s, first_code(s))