function debug_to_string(v) if type(v) == "nil" or type(v) == "number" or type(v) == "string" or type(v) =="boolean" then return tostring(v) elseif type(v) == "table" then local s = "{" for key, value in pairs(v) do s = s .. debug_to_string(key) .. ": " .. debug_to_string(value) .. ", " end return s .. "}" end end function debug_print(v) print(debug_to_string(v)) print() end function has(t, k) return rawget(t, k) end function create_tree(node) local traverse = function(self, node) if type(node) == "table" then if has(node, "tag") then coroutine.yield(node) self.traverse(self, node.value) else for key, value in pairs(node) do self.traverse(self, value) end end end end local successor = function(self) local continues, node = coroutine.resume(self.co) self.node = node return continues end local begin = function(self) local co = coroutine.create(self.traverse) local continues, node = coroutine.resume(co, self, node) return ({ node = node, co = co, succ = successor }) end local find = function(self, compare) local it = self:begin() while true do local node = it.node if compare(node) then return node elseif not it:succ() then break end end return nil end return ({ traverse = traverse, begin = begin, find = find, node = node }) end local tree = create_tree({tag = "html", value = { {tag = "head", value = { {tag = "title", attr = {name = "yank it!"}, value = "sample page"} }}, {tag = "body", attr = {name = "insert in there!"} , value = { {tag = "p", value = "Hello,"}, {tag = "p", value = "world!"} }} }}) yank = tree:find(function(value) return value and value.attr and value.attr.name == "yank it!" end) to = tree:find(function(value) return value and value.attr and value.attr.name == "insert in there!" end) debug_print(tree.node) debug_print(yank) debug_print(to) table.insert(to.value, yank) debug_print(tree.node)
Standard input is empty
{tag: html, value: {1: {tag: head, value: {1: {value: sample page, attr: {name: yank it!, }, tag: title, }, }, }, 2: {value: {1: {tag: p, value: Hello,, }, 2: {tag: p, value: world!, }, }, attr: {name: insert in there!, }, tag: body, }, }, } {value: sample page, attr: {name: yank it!, }, tag: title, } {value: {1: {tag: p, value: Hello,, }, 2: {tag: p, value: world!, }, }, attr: {name: insert in there!, }, tag: body, } {tag: html, value: {1: {tag: head, value: {1: {value: sample page, attr: {name: yank it!, }, tag: title, }, }, }, 2: {value: {1: {tag: p, value: Hello,, }, 2: {tag: p, value: world!, }, 3: {value: sample page, attr: {name: yank it!, }, tag: title, }, }, attr: {name: insert in there!, }, tag: body, }, }, }