1if not modules then modules = { } end modules ['node-ser'] = {
2 version = 1.001,
3 comment = "companion to node-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11local type, tostring = type, tostring
12local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize
13local formatters, format, rep = string.formatters, string.format, string.rep
14
15local allocate = utilities.storage.allocate
16
17local context = context
18local nodes = nodes
19
20local getfields = nodes.fields
21local isnode = nodes.isnode
22local nodecodes = nodes.nodecodes
23local subtypes = nodes.subtypes
24local tonode = nodes.tonode
25local tonut = nodes.tonut
26
27local hlist_code <const> = nodecodes.hlist
28local vlist_code <const> = nodecodes.vlist
29
30local f_char = formatters["%U"]
31local f_attr = formatters["<attribute : %i>"]
32local f_recurse = formatters["<recursive : %i>"]
33
34
35
36
37local canbezero = {
38 integer = true,
39 dimension = true,
40 number = true,
41}
42
43local canbelist = {
44 attribute = "<attribute>",
45 node = "<node>",
46 token = "<token>",
47 node_list = "<nodes>",
48 token_list = "<tokens>",
49}
50
51local canbeignored = {
52 prev = "<node>"
53}
54
55local canbechar = {
56 char = true,
57 smallchar = true,
58 largechar = true,
59}
60
61local fieldtypes = table.setmetatableindex(function(t,k)
62 local v = getfields(k,true) or false
63 t[k] = v
64 return v
65end)
66
67nodes.fieldtypes = fieldtypes
68
69
70
71local function astable(n)
72 n = tonode(n)
73 if n then
74 local id = n.id
75 local fields = fieldtypes[id]
76 if fields then
77 local subtype = n.subtype
78 local result = { }
79 for field, fieldtype in sortedhash(fields) do
80 local value = n[field]
81 if value then
82 if field == "subtype" then
83
84 elseif canbeignored[field] then
85 value = nil
86 elseif canbezero[fieldtype] and value == 0 then
87 value = nil
88 elseif canbelist[fieldtype] then
89 value = canbelist[fieldtype]
90 end
91 if value then
92 result[field] = value
93 end
94 end
95 end
96 id = nodecodes[id]
97 result.id = id
98 if subtype then
99 local subtypes = subtypes[id]
100 if subtypes then
101 result.subtype = subtypes[subtype]
102 end
103 end
104 return result
105 end
106 end
107end
108
109nodes.astable = astable
110
111setinspector("node",function(v) if isnode(v) then printtable(astable(v),tostring(v)) return true end end)
112
113local function to_table(n,flat,verbose,noattributes,done)
114 local d = tonut(n)
115 if done[d] then
116 return f_recurse(d)
117 else
118 done[d] = true
119 local fields = fieldtypes[n.id]
120 if fields then
121 local result = { }
122 for field, fieldtype in sortedhash(fields) do
123 local value = n[field]
124 if value then
125 if fieldtype == "attribute" then
126 if noattributes then
127 result[value] = canbeignored[value]
128 else
129 result[value] = to_table(value,flat,verbose,noattributes,done)
130 end
131 elseif canbeignored[field] then
132 result[value] = canbeignored[value]
133 elseif not verbose and canbezero[fieldtype] and value == 0 then
134 value = nil
135 elseif canbelist[fieldtype] then
136 if flat then
137 result[value] = canbelist[value]
138 else
139 result[value] = to_table(value,flat,verbose,noattributes,done)
140 end
141 end
142 if value then
143 result[field] = value
144 end
145 end
146 end
147 if verbose then
148 local id = result.id
149 if id then
150 id = nodecodes[id]
151 result.id = id
152 local subtype = result.subtype
153 if subtype then
154 local subtypes = subtypes[id]
155 if subtypes then
156 result.subtype = subtypes[subtype]
157 end
158 end
159 end
160 for k, v in next, canbechar do
161 local v = result[k]
162 if v then
163 result[k] = f_char(v)
164 end
165 end
166 end
167 return result
168 end
169 end
170end
171
172local function totable(n,flat,verbose,noattributes)
173 if n then
174 local d = { }
175 if flat then
176 local t, tn = { }, 0
177 while n do
178 tn = tn + 1
179 local nt = to_table(n,flat,verbose,noattributes,d)
180 t[tn] = nt
181 nt.next = nil
182 nt.prev = nil
183 n = n.next
184 end
185 done = nil
186 return t
187 else
188 local t = to_table(n,flat,verbose,noattributes,d)
189 local n = n.next
190 if n then
191 t.next = totable(n,flat,verbose,noattributes,d)
192 end
193 return t
194 end
195 else
196 return { }
197 end
198end
199
200nodes.totable = function(n,...) return totable(tonode(n),...) end
201nodes.totree = function(n) return totable(tonode(n),true,true,true) end
202
203local function key(k)
204 return ((type(k) == "number") and "["..k.."]") or k
205end
206
207function nodes.serialize(root,flat,verbose,noattributes,name)
208 return serialize(totable(tonode(root),flat,verbose,noattributes),name)
209end
210
211function nodes.serializebox(n,flat,verbose,noattributes,name)
212 return serialize(totable(tex.box[n],flat,verbose,noattributes),name)
213end
214
215function nodes.visualizebox(n,flat,verbose,noattributes,name)
216 context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name)
217end
218
219function nodes.list(head,n)
220 head = tonode(head)
221 if not n then
222 context.starttyping(true)
223 end
224 while head do
225 local id = head.id
226 context(rep(" ",n or 0) .. tostring(head) .. "\n")
227 if id == hlist_code or id == vlist_code then
228 nodes.list(head.list,(n or 0)+1)
229 end
230 head = head.next
231 end
232 if not n then
233 context.stoptyping(true)
234 end
235end
236
237function nodes.print(head,n)
238 head = tonode(head)
239 while head do
240 local id = head.id
241 logs.writer(string.formatters["%w%S"],n or 0,head)
242 if id == hlist_code or id == vlist_code then
243 nodes.print(head.list,(n or 0)+1)
244 end
245 head = head.next
246 end
247end
248
249
250
251local function apply(n,action)
252 while n do
253 action(n)
254 local id = n.id
255 if id == hlist_code or id == vlist_code then
256 apply(n.list,action)
257 end
258 n = n.next
259 end
260end
261
262nodes.apply = apply
263
264local nuts = nodes.nuts
265local getid = nuts.getid
266local getlist = nuts.getlist
267local getnext = nuts.getnext
268
269local function apply(n,action)
270 while n do
271 action(n)
272 local id = getid(n)
273 if id == hlist_code or id == vlist_code then
274 local list = getlist(n,action)
275 if list then
276 apply(list,action)
277 end
278 end
279 n = getnext(n)
280 end
281end
282
283nuts.apply = apply
284 |