src/prim.bend
bend-toon-codec@0.1.0.0 · 112 lines · 16 definitions
1import Base
2import bend-toon-codec@0.1.0.0/src/json.bend as J
3import bend-toon-codec@0.1.0.0/src/num.bend as N
4import bend-toon-codec@0.1.0.0/src/head.bend as Hd
5import bend-toon-codec@0.1.0.0/src/text.bend as T
6
7
8
9
10def quoted.rest(+ok: Bool, +v: String) -> Result<&2, &2, String, J.Json>:
11 match ok:
12 case True{}:
13 Done{J.JStr{v}}
14 case False{}:
15 Fail{"unexpected characters after the closing quote"}
16
17
18def quoted.end(+r: Result<&2, &2, String, T.Cut>) -> Result<&2, &2, String, J.Json>:
19 match r:
20 case Fail{e}:
21 Fail{e}
22 case Done{T.Cut{v, rest}}:
23 quoted.rest(String.is_empty(rest), v)
24
25
26
27def lead0.ip(+ip: String) -> Bool:
28 Hd.lead(ip, 48) && Hd.at_least(ip, 2n)
29
30def lead0(+m: Maybe<&2, N.Num>) -> Bool:
31 match m:
32 case Some{N.Num{neg, ip, fp, eneg, ex}}:
33 lead0.ip(ip)
34 case None{}:
35 False{}
36
37def num.pick(+ok: Bool, +c: Maybe<&2, String>, +tok: String) -> J.Json:
38 match ok c:
39 case True{} Some{t}:
40 J.JNum{t}
41 case _ _:
42 J.JStr{tok}
43
44
45def bare.num(+tok: String) -> J.Json:
46 num.pick(Bool.not(lead0(N.split(tok))), N.canon(tok), tok)
47
48def bare.pick(+t: Bool, +f: Bool, +n: Bool, +tok: String) -> J.Json:
49 match t f n:
50 case True{} _ _:
51 J.JBool{True{}}
52 case False{} True{} _:
53 J.JBool{False{}}
54 case False{} False{} True{}:
55 J.JNull{}
56 case False{} False{} False{}:
57 bare.num(tok)
58
59def bare(+tok: String) -> J.Json:
60 bare.pick(String.eq(tok, "true"), String.eq(tok, "false"), String.eq(tok, "null"), tok)
61
62def parse.pick(+quoted: Bool, +tok: String) -> Result<&2, &2, String, J.Json>:
63 match quoted:
64 case True{}:
65 quoted.end(T.unq(Hd.drop(tok)))
66 case False{}:
67 Done{bare(tok)}
68
69
70def parse(+tok: String) -> Result<&2, &2, String, J.Json>:
71 parse.pick(Hd.lead(tok, 34), tok)
72
73def key.rest(+ok: Bool, +v: String) -> Result<&2, &2, String, String>:
74 match ok:
75 case True{}:
76 Done{v}
77 case False{}:
78 Fail{"unexpected characters after the closing quote"}
79
80def key.end(+r: Result<&2, &2, String, T.Cut>) -> Result<&2, &2, String, String>:
81 match r:
82 case Fail{e}:
83 Fail{e}
84 case Done{T.Cut{v, rest}}:
85 key.rest(String.is_empty(rest), v)
86
87def key.pick(+quoted: Bool, +tok: String) -> Result<&2, &2, String, String>:
88 match quoted:
89 case True{}:
90 key.end(T.unq(Hd.drop(tok)))
91 case False{}:
92 Done{tok}
93
94def key(+tok: String) -> Result<&2, &2, String, String>:
95 key.pick(Hd.lead(tok, 34), tok)
96
97
98def values.cons(+r: Result<&2, &2, String, J.Json>, +rest: Result<&2, &2, String, J.Json>) -> Result<&2, &2, String, J.Json>:
99 match r rest:
100 case Done{v} Done{vs}:
101 Done{J.JCons{v, vs}}
102 case Fail{e} _:
103 Fail{e}
104 case _ Fail{e}:
105 Fail{e}
106
107def values(+toks: List<&2, String>) -> Result<&2, &2, String, J.Json>:
108 match toks:
109 case Nil{}:
110 Done{J.JNil{}}
111 case Con{t, rest}:
112 values.cons(parse(String.trim(t)), values(rest))