blob: e0a1a5c05765ae94416a55099759e0b761d0ee69 (
plain)
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
|
(.module:
[lux (#- char)
["%" data/text/format (#+ format)]
["_" test (#+ Test)]
[abstract
[monad (#+ Monad do)]
{[0 #spec]
[/
["$." equivalence]
["$." codec]]}]
[control
pipe
["E" try]
["p" parser
["</>" xml]]]
[data
["." name]
["." maybe]
["." text ("#@." equivalence)]
[number
["n" nat]]
[collection
["." dictionary]
["." list ("#@." functor)]]]
[math
["r" random (#+ Random) ("#@." monad)]]]
{1
["." / (#+ XML)]})
(def: char-range
Text
(format "_"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
(def: char
(Random Nat)
(do {! r.monad}
[idx (|> r.nat (:: ! map (n.% (text.size char-range))))]
(wrap (maybe.assume (text.nth idx char-range)))))
(def: (size bottom top)
(-> Nat Nat (Random Nat))
(let [constraint (|>> (n.% top) (n.max bottom))]
(r@map constraint r.nat)))
(def: (text bottom top)
(-> Nat Nat (Random Text))
(do r.monad
[size (..size bottom top)]
(r.text ..char size)))
(def: xml-identifier^
(Random Name)
(r.and (..text 0 10)
(..text 1 10)))
(def: #export xml
(Random XML)
(r.rec (function (_ xml)
(r.or (..text 1 10)
(do r.monad
[size (..size 0 2)]
($_ r.and
xml-identifier^
(r.dictionary name.hash size xml-identifier^ (..text 0 10))
(r.list size xml)))))))
(def: #export test
Test
(<| (_.context (%.name (name-of /.XML)))
($_ _.and
($equivalence.spec /.equivalence ..xml)
($codec.spec /.equivalence /.codec ..xml)
(do {! r.monad}
[text (..text 1 10)
num-children (|> r.nat (:: ! map (n.% 5)))
children (r.list num-children (..text 1 10))
tag xml-identifier^
attribute xml-identifier^
value (..text 1 10)
#let [node (#/.Node tag
(dictionary.put attribute value /.attrs)
(list@map (|>> #/.Text) children))]]
($_ _.and
(_.test "Can parse text."
(E.default #0
(do E.monad
[output (</>.run </>.text
(#/.Text text))]
(wrap (text@= text output)))))
(_.test "Can parse attributes."
(E.default #0
(do E.monad
[output (</>.run (p.before </>.ignore
(</>.attribute attribute))
node)]
(wrap (text@= value output)))))
(_.test "Can parse nodes."
(E.default #0
(do E.monad
[_ (</>.run (p.before </>.ignore
(</>.node tag))
node)]
(wrap #1))))
(_.test "Can parse children."
(E.default #0
(do E.monad
[outputs (</>.run (</>.children (p.some </>.text)) node)]
(wrap (:: (list.equivalence text.equivalence) =
children
outputs)))))
))
)))
|