@@ -3,12 +3,12 @@ local class = require("pl.class")
33local tablex = require (" pl.tablex" )
44
55local node_types = {}
6- local node_to_class
6+ local node_to_type
77local dedent
88
99local FluentNode = class ({
1010 discardable = false ,
11- mergable = false ,
11+ appendable = false ,
1212
1313 _init = function (self , node )
1414 for key , value in pairs (node ) do
@@ -24,7 +24,7 @@ local FluentNode = class({
2424 end
2525 if (node [1 ] and # node > 0 ) then
2626 self .elements = {}
27- tablex .insertvalues (self .elements , tablex .imap (node_to_class , node ))
27+ tablex .insertvalues (self .elements , tablex .imap (node_to_type , node ))
2828 end
2929 end ,
3030
@@ -33,6 +33,28 @@ local FluentNode = class({
3333 for k , v in pairs (self ) do ast [k ] = v end
3434 ast .identifier = nil
3535 return ast
36+ end ,
37+
38+ append = function (self , node )
39+ if type (self .__add ) == " function"
40+ and self .appendable
41+ and node .appendable
42+ and self :is_a (node :is_a ())
43+ then
44+ return self + node
45+ else
46+ return false
47+ end
48+ end ,
49+
50+ attach = function (self , node )
51+ if node and
52+ type (node .__mul ) == " function"
53+ then
54+ return node * self
55+ else
56+ return false
57+ end
3658 end
3759
3860 })
@@ -47,9 +69,8 @@ node_types.blank_block = class({
4769 end
4870 })
4971
50- -- TODO: can their ever be more than 1 entry?
5172node_types .Entry = function (node )
52- return node_to_class (node [1 ])
73+ return node_to_type (node [1 ])
5374end
5475
5576node_types .Junk = class ({
@@ -121,7 +142,7 @@ node_types.Pattern = class({
121142-- end
122143
123144node_types .TextElement = class ({
124- mergable = true ,
145+ appendable = true ,
125146 _base = FluentNode ,
126147 _init = function (self , node )
127148 self :super (node )
@@ -134,27 +155,42 @@ node_types.PatternElement = function (node)
134155end
135156
136157node_types .Comment = class ({
137- mergable = true ,
158+ appendable = true ,
138159 _base = FluentNode ,
139160 _init = function (self , node )
140161 self :super (node )
162+ end ,
163+ __add = function (self , node )
164+ self .content = (self .content or " " ) .. " \n " .. (node .content or " " )
165+ return self
166+ end ,
167+ __mul = function (self , node )
168+ if self :is_a (node_types .Message ) then
169+ self .comment = node
170+ return self
171+ elseif node :is_a (node_types .Message ) then
172+ node .comment = self
173+ return node
174+ end
141175 end
142176 })
143177
144178node_types .GroupComment = class ({
145- mergable = true ,
179+ appendable = true ,
146180 _base = FluentNode ,
147181 _init = function (self , node )
148182 self :super (node )
149- end
183+ end ,
184+ __add = node_types .Comment .__add
150185 })
151186
152187node_types .ResourceComment = class ({
153- mergable = true ,
188+ appendable = true ,
154189 _base = FluentNode ,
155190 _init = function (self , node )
156191 self :super (node )
157- end
192+ end ,
193+ __add = node_types .Comment .__add
158194 })
159195
160196node_types .Attribute = class ({
@@ -171,7 +207,7 @@ node_types.CommentLine = function(node)
171207 return node_types [node .id ](node )
172208end
173209
174- node_to_class = function (node )
210+ node_to_type = function (node )
175211 if type (node .id ) ~= " string" then return nil end
176212 return node_types [node .id ](node )
177213end
@@ -197,65 +233,65 @@ end
197233
198234local FluentResource = class ({
199235 type = " Resource" ,
200- idmap = {},
236+ index = {},
201237
202238 _init = function (self , ast )
203239 self .body = {}
204240 local _stash = nil
205241 local flush = function ()
206- if _stash then table.insert (self .body , _stash ) end
207- _stash = nil
242+ if _stash then
243+ self :insert (_stash )
244+ _stash = nil
245+ end
246+ return # self .body
208247 end
209248 local stash = function (node )
210249 if not _stash then
211250 _stash = node
212- elseif _stash :is_a (node :is_a ()) then
213- -- TODO: move to _add meta method
214- _stash .content = (_stash .content or " " ) .. " \n " .. (node .content or " " )
215- else
251+ elseif not _stash :append (node ) then
216252 flush ()
217253 _stash = node
218254 end
219255 end
220- -- TODO: eliminate double iteration by looking ahead?
221- local elements = tablex .imap (node_to_class , ast )
222- for _ , node in ipairs (elements ) do
223- if node .mergable then
224- stash (node )
225- elseif node :is_a (node_types .blank_block ) then
256+ for _ , leaf in ipairs (ast ) do
257+ local node = node_to_type (leaf )
258+ if node :is_a (node_types .blank_block ) then
226259 if not node .discardable then
227260 flush ()
228261 end
229- elseif node :is_a (node_types .Message ) or node :is_a (node_types .Term ) then
230- if _stash then
231- if _stash .type ~= " Comment" then
232- flush ()
233- else
234- node .comment = _stash
235- _stash = nil
236- end
237- end
238- table.insert (self .body , node )
239- if node :is_a (node_types .Message ) then
240- self .idmap [node .identifier ] = # self .body
241- end
262+ elseif node :attach (_stash ) then
263+ _stash = nil
264+ stash (node )
242265 else
243- flush ()
244- table.insert (self .body , node )
266+ stash (node )
245267 end
246268 end
247269 flush ()
248270 -- self:catch(function (self, identifier) return self:get_message(identifier) end)
249271 end ,
250272
273+ insert = function (self , node )
274+ table.insert (self .body , node )
275+ if node :is_a (node_types .Message ) then
276+ self .index [node .identifier ] = # self .body
277+ end
278+ end ,
279+
251280 get_message = function (self , identifier )
252- return self .idmap [identifier ] and self .body [self .idmap [identifier ]]
281+ return self .index [identifier ] and self .body [self .index [identifier ]]
253282 end ,
254283
255284 dump_ast = function (self )
256285 local ast = { type = " Resource" , body = {} }
257286 for _ , v in ipairs (self .body ) do table.insert (ast .body , v :dump_ast ()) end
258287 return ast
288+ end ,
289+
290+ __add = function (self , resource )
291+ for _ , node in ipairs (resource .body ) do
292+ self :insert (node )
293+ end
294+ return self
259295 end
260296
261297 })
0 commit comments