Guest User

Untitled

a guest
Jul 26th, 2016
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.52 KB | None | 0 0
  1. local EMPTY, TERM, OR, AND = 0, 1, 2, 3
  2.  
  3. local function get_parse_tree(expression)
  4.  
  5. local Node = {}
  6. function Node.new(type, start, _end)
  7. local node = {}
  8. setmetatable(node, Node)
  9. node.__index = node
  10. node.type = type
  11. node.start = start
  12. node._end = _end
  13. node.children = {}
  14.  
  15. function node:add(child)
  16. self.children[#self.children + 1] = child
  17. end
  18.  
  19. return node
  20. end
  21.  
  22.  
  23. local ColumnVisibilityParser = {}
  24. ColumnVisibilityParser.__index = ColumnVisibilityParser
  25. function ColumnVisibilityParser.create()
  26. local obj = {}
  27. setmetatable(obj, ColumnVisibilityParser)
  28. obj.index = 0
  29. obj.parens = 0
  30. return obj
  31. end
  32.  
  33. function ColumnVisibilityParser:processTerm(start, _end, expr, expression)
  34. if start ~= _end then
  35. if expr ~= nil then
  36. error("expression needs | or &")
  37. end
  38.  
  39. return Node.new(TERM, start, _end)
  40. end
  41.  
  42. if expr == nil then
  43. error("empty term")
  44. end
  45.  
  46. return expr
  47. end
  48.  
  49. function ColumnVisibilityParser:parse(expression)
  50.  
  51. if string.len(expression) <= 0 then return nil end
  52.  
  53. local function char_at(expression, index)
  54. return expression:sub(index + 1, index + 1)
  55. end
  56.  
  57. local result = nil
  58. local expr = nil
  59. local wholeTermStart = self.index
  60. local subtermStart = self.index
  61. local subtermComplete = false
  62. local expressionLength = string.len(expression)
  63.  
  64. while (self.index <= expressionLength) do
  65. local char = char_at(expression, self.index)
  66. self.index = self.index + 1
  67.  
  68. if char == '&' then
  69. expr = self:processTerm(subtermStart, self.index - 1, expr, expression)
  70.  
  71. if result ~= nil then
  72. if result.type ~= AND then
  73. error("cannot mix & and |")
  74. end
  75. else
  76. result = Node.new(AND, wholeTermStart, wholeTermStart + 1)
  77. end
  78.  
  79. result:add(expr)
  80. expr = nil
  81. subtermStart = self.index
  82. subtermComplete = false
  83. elseif char == '|' then
  84. expr = self:processTerm(subtermStart, self.index - 1, expr, expression)
  85. if result ~= nil then
  86. if result.type ~= OR then
  87. error("cannot mix | and &")
  88. end
  89. else
  90. result = Node.new(OR, wholeTermStart, wholeTermStart + 1)
  91. end
  92.  
  93. result:add(expr)
  94. expr = nil
  95. subtermStart = self.index
  96. subtermComplete = false
  97. elseif char == '(' then
  98. self.parens = self.parens + 1
  99. if subtermStart ~= self.index - 1 or expr ~= nil then
  100. error("expression needs & or |")
  101. end
  102. expr = self:parse(expression);
  103. subtermStart = self.index;
  104. subtermComplete = false;
  105. elseif char == ')' then
  106. self.parens = self.parens - 1
  107. local child = self:processTerm(subtermStart, self.index - 1, expr, expression)
  108. if child == nil and result == nil then
  109. error("empty expression not allowed")
  110. end
  111. if result == nil then
  112. return child
  113. end
  114. if result.type == child.type then
  115. for _, child in ipairs(child.children) do
  116. result:add(child)
  117. end
  118. else
  119. result:add(child)
  120. end
  121.  
  122. result._end = self.index - 1
  123. return result
  124. elseif char == '"' then
  125. if subtermStart ~= self.index - 1 then
  126. error("expression needs & or |")
  127. end
  128.  
  129. while self.index < expressionLength and char_at(expression, self.index) ~= "\"" do
  130. if char_at(expression, self.index) == '\\' then
  131. self.index = self.index + 1
  132. if char_at(expression, self.index) ~= '\\' and char_at(expression, self.index) ~= '"' then
  133. error("invalid escaping within quotes")
  134. end
  135. end
  136. self.index = self.index + 1
  137. end
  138.  
  139. if self.index == expressionLength then
  140. error("unclosed quote")
  141. end
  142.  
  143. if subtermStart + 1 == self.index then
  144. error("empty term")
  145. end
  146.  
  147. self.index = self.index + 1
  148. subtermComplete = true
  149. else
  150. if subtermComplete then
  151. error("expression needs & or |")
  152. end
  153. -- TODO Validate chars?
  154. end
  155. end -- end while loop
  156.  
  157. local child = self:processTerm(subtermStart, self.index - 1, expr, expression)
  158.  
  159. if result ~= nil then
  160. result:add(child)
  161. result._end = self.index
  162. else
  163. result = child
  164. end
  165.  
  166. local length = #result.children
  167. if result.type ~= TERM and #result.children < 2 then
  168. error("missing term")
  169. end
  170. return result
  171. end
  172.  
  173.  
  174. local obj = {}
  175. if expression ~= nil and string.len(expression) > 0 then
  176. local parser = ColumnVisibilityParser.create()
  177. obj.node = parser:parse(expression)
  178. else
  179. obj.node = Node.new(EMPTY, 0, 0)
  180. end
  181.  
  182. return obj.node
  183. end
  184.  
  185. local function stringify(root, expression, str)
  186. if root.type == TERM then
  187. return str .. string.sub(expression, root.start + 1, root._end)
  188. else
  189. local sep = ""
  190. for _, v in pairs(root.children) do
  191. str = str .. sep
  192. local parens = v.type ~= TERM and root.type ~= v.type
  193. if parens then
  194. str = str .. '('
  195. end
  196.  
  197. str = stringify(v, expression, str)
  198.  
  199. if parens then
  200. str = str .. ')'
  201. end
  202.  
  203. if root.type == AND then
  204. sep = "&"
  205. else
  206. sep = "|"
  207. end
  208. end
  209.  
  210. return str
  211. end
  212. end
  213.  
  214. local expression = "(\"foo duh\"&bar&baz)|duh|((\"ohde argodwhy\"|ismellood)&boorps)"
  215. local node = get_parse_tree(expression)
  216.  
  217. print(stringify(node, expression, ""))
Add Comment
Please, Sign In to add comment