fork download
  1. function debug_to_string(v)
  2. if type(v) == "nil" or type(v) == "number" or type(v) == "string" or type(v) =="boolean" then
  3. return tostring(v)
  4. elseif type(v) == "table" then
  5. local s = "{"
  6. for key, value in pairs(v) do
  7. s = s .. debug_to_string(key) .. ": " .. debug_to_string(value) .. ", "
  8. end
  9. return s .. "}"
  10. end
  11. end
  12.  
  13. function debug_print(v)
  14. print(debug_to_string(v))
  15. print()
  16. end
  17.  
  18. function has(t, k)
  19. return rawget(t, k)
  20. end
  21.  
  22. function create_tree(node)
  23. local traverse = function(self, node)
  24. if type(node) == "table" then
  25. if has(node, "tag") then
  26. coroutine.yield(node)
  27. self.traverse(self, node.value)
  28. else
  29. for key, value in pairs(node) do
  30. self.traverse(self, value)
  31. end
  32. end
  33. end
  34. end
  35.  
  36. local successor = function(self)
  37. local continues, node = coroutine.resume(self.co)
  38. self.node = node
  39. return continues
  40. end
  41.  
  42. local begin = function(self)
  43. local co = coroutine.create(self.traverse)
  44. local continues, node = coroutine.resume(co, self, node)
  45. return ({
  46. node = node,
  47. co = co,
  48. succ = successor
  49. })
  50. end
  51.  
  52. local find = function(self, compare)
  53. local it = self:begin()
  54. while true do
  55. local node = it.node
  56. if compare(node) then
  57. return node
  58. elseif not it:succ() then
  59. break
  60. end
  61. end
  62. return nil
  63. end
  64.  
  65. return ({
  66. traverse = traverse,
  67. begin = begin,
  68. find = find,
  69. node = node
  70. })
  71. end
  72.  
  73. local tree = create_tree({tag = "html", value = {
  74. {tag = "head", value = {
  75. {tag = "title", attr = {name = "yank it!"}, value = "sample page"}
  76. }},
  77. {tag = "body", attr = {name = "insert in there!"} , value = {
  78. {tag = "p", value = "Hello,"},
  79. {tag = "p", value = "world!"}
  80. }}
  81. }})
  82.  
  83. yank = tree:find(function(value)
  84. return value and value.attr and value.attr.name == "yank it!"
  85. end)
  86.  
  87. to = tree:find(function(value)
  88. return value and value.attr and value.attr.name == "insert in there!"
  89. end)
  90. debug_print(tree.node)
  91.  
  92. debug_print(yank)
  93. debug_print(to)
  94. table.insert(to.value, yank)
  95. debug_print(tree.node)
Success #stdin #stdout 0s 2836KB
stdin
Standard input is empty
stdout
{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, }, }, }