Many changes to get RTNs and IntFAs properly emitted into bytecode again.
[gazelle.git] / compiler / data_structures.lua
blobf60e6a005b1d52f540042f7b41975c2c10285772
1 --[[--------------------------------------------------------------------
3 Gazelle: a system for building fast, reusable parsers
5 data_structures.lua
7 Implementations of useful data structures that we use often.
8 Most of these are just useful interfaces around Lua's tables.
10 Copyright (c) 2007 Joshua Haberman. See LICENSE for details.
12 --------------------------------------------------------------------]]--
14 require "misc"
16 -- Queue
17 Queue = {name="Queue"}
18 function Queue:new(init)
19 local obj = newobject(self)
20 obj.first = 0
21 obj.last = -1
22 if init then obj:enqueue(init) end
23 return obj
24 end
26 function Queue:enqueue(val)
27 self.last = self.last + 1
28 self[self.last] = val
29 end
31 function Queue:dequeue()
32 if self:isempty() then error("Tried to dequeue an empty queue") end
33 local val = self[self.first]
34 self[self.first] = nil
35 self.first = self.first + 1
36 return val
37 end
39 function Queue:isempty()
40 return self.first > self.last
41 end
42 -- class Queue
45 -- Stack
46 Stack = {name="Stack"}
47 function Stack:new(init)
48 local obj = newobject(self)
49 obj.stack = {}
50 return obj
51 end
53 function Stack:push(val)
54 table.insert(self.stack, val)
55 end
57 function Stack:pop()
58 return table.remove(self.stack)
59 end
61 function Stack:top()
62 return self.stack[#self.stack]
63 end
65 function Stack:isempty()
66 return #self.stack == 0
67 end
69 function Stack:dup()
70 local new_stack = newobject(Stack)
71 new_stack.stack = table_shallow_copy(self.stack)
72 return new_stack
73 end
75 function Stack:contains(elem)
76 for e in each(self.stack) do
77 if elem == e then
78 return true
79 end
80 end
81 return false
82 end
84 function Stack:to_array()
85 local arr = {}
86 for i, val in ipairs(self.stack) do
87 table.insert(arr, val)
88 end
89 return arr
90 end
91 -- class Stack
94 -- Set
95 Set = {name="Set"}
96 function Set:new(init)
97 local obj = newobject(self)
98 obj.elements = {}
99 if init then
100 obj:add_collection(init)
102 return obj
105 function Set:contains(x)
106 return self.elements[x] ~= nil
109 function Set:add(x)
110 self.elements[x] = true
113 function Set:remove(x)
114 self.elements[x] = nil
117 function Set:add_collection(arr)
118 for elem in each(arr) do
119 self:add(elem)
123 function Set:each()
124 return pairs(self.elements)
127 function Set:to_array()
128 local arr = {}
129 for elem in self:each() do
130 table.insert(arr, elem)
132 return arr
135 function Set:isempty()
136 return self:count() == 0
139 function Set:dup()
140 local new_set = newobject(Set)
141 new_set.elements = table_shallow_copy(self.elements)
142 return new_set
145 function Set:count()
146 local i = 0
147 for elem in self:each() do
148 i = i + 1
150 return i
153 function Set:hash_key()
154 local arr = self:to_array()
155 for i=1,#arr do
156 arr[i] = tostring(arr[i])
159 table.sort(arr)
161 str = "" for elem in each(arr) do str = str .. elem end
162 return str
164 -- class Set
166 -- OrderedSet
167 OrderedSet = {name="OrderedSet"}
168 function OrderedSet:new(init)
169 local obj = newobject(self)
170 obj.element_offsets = {}
171 obj.elements = {}
172 if init then
173 for element in each(init) do
174 obj:add(element)
177 return obj
180 function OrderedSet:add(elem)
181 if not self.element_offsets[elem] then
182 table.insert(self.elements, elem)
183 self.element_offsets[elem] = #self.elements
187 function OrderedSet:count()
188 return #self.elements
191 function OrderedSet:offset_of(elem)
192 return self.element_offsets[elem]
195 function OrderedSet:element_at(pos)
196 return self.elements[pos]
199 function OrderedSet:sort(sort_func)
200 table.sort(self.elements, sort_func)
201 self.element_offsets = {}
202 for i, element in ipairs(self.elements) do
203 self.element_offsets[element] = i
207 function OrderedSet:each()
208 local i = 0
209 return function ()
210 i = i + 1
211 if self.elements[i] then
212 return self.elements[i]
213 else
214 return nil
219 -- OrderedMap
220 OrderedMap = {name="OrderedMap"}
221 function OrderedMap:new()
222 local obj = newobject(self)
223 obj.key_offsets = {}
224 obj.elements = {}
225 return obj
228 function OrderedMap:add(key, value)
229 if not self.key_offsets[key] then
230 table.insert(self.elements, {key, value})
231 self.key_offsets[key] = #self.elements
235 function OrderedMap:get(key)
236 return self.elements[self.key_offsets[key]][2]
239 function OrderedMap:offset_of_key(elem)
240 return self.key_offsets[elem]
243 function OrderedMap:count()
244 return #self.elements
247 function OrderedMap:each()
248 local i = 0
249 return function ()
250 i = i + 1
251 if self.elements[i] then
252 return unpack(self.elements[i])
253 else
254 return nil
259 -- Range
260 -- The Range is *inclusive* at both ends.
261 Range = {name="Range"}
262 function Range:new(low, high)
263 assert(low <= high)
265 local obj = newobject(self)
266 obj.low = low
267 obj.high = high
268 return obj
271 function Range.union(a, b)
272 if math.max(a.low, b.low) <= (math.min(a.high, b.high)+1) then
273 return Range:new(math.min(a.low, b.low), math.max(a.high, b.high))
274 else
275 return nil
279 function Range:contains(int)
280 return (self.low <= int) and (self.high >= int)
283 function Range:tostring(display_val_func)
284 if self.low == self.high then
285 return display_val_func(self.low)
286 else
287 return display_val_func(self.low) .. "-" .. display_val_func(self.high)
290 -- class Range
293 -- IntSet
294 -- None of the ranges may overlap.
295 IntSet = {name="IntSet"}
296 function IntSet:new()
297 local obj = newobject(self)
298 obj.list = {}
299 obj.negated = false
300 return obj
303 function IntSet:add(new_range)
304 local newlist = {}
305 for range in each(self.list) do
306 local union = new_range:union(range)
307 if union then
308 new_range = union
309 else
310 table.insert(newlist, range)
314 table.insert(newlist, new_range)
315 self.list = newlist
318 function IntSet:get_non_negated()
319 if self.negated then
320 return self:invert()
321 else
322 return self
326 -- This is O(n^2) right now, and can probably
327 -- be made O(n lg n) with a little thought, but n's
328 -- are so small right now that I won't worry.
329 function IntSet:add_intset(intset)
330 for range in each(intset.list) do
331 self:add(range)
335 function IntSet:contains(int)
336 local obj = self:get_non_negated()
337 for range in each(obj.list) do
338 if range:contains(int) then return true end
340 return false
343 function IntSet:sampleint()
344 local obj = self:get_non_negated()
346 if #obj.list == 0 then
347 return nil
348 else
349 return obj.list[1].low
353 function IntSet:invert()
354 local new_intset = IntSet:new()
355 new_intset.negated = not self.negated
357 table.sort(self.list, function (a, b) return a.low < b.low end)
358 local offset = 0
360 for range in each(self.list) do
361 if offset <= range.low-1 then
362 new_intset:add(Range:new(offset, range.low-1))
364 offset = range.high+1
367 if offset ~= math.huge then
368 new_intset:add(Range:new(offset, math.huge))
371 return new_intset
374 function IntSet:each_range()
375 return each(self:get_non_negated().list)
378 function IntSet:isunbounded()
379 for range in each(self.list) do
380 if range.high == math.huge then
381 return true
384 return false
387 function IntSet:tostring(display_val_func)
388 local str = ""
389 if self.negated then str = "^" end
391 table.sort(self.list, function (a, b) return a.low < b.low end)
392 local first = true
393 for range in each(self.list) do
394 if first then
395 first = false
396 else
397 str = str .. ","
400 str = str .. range:tostring(display_val_func)
403 return str
406 function IntSet:toasciistring()
407 local convert_func = function (x)
408 if x == math.huge then
409 return "del"
410 elseif x < 33 then
411 return string.format("\\%03o", x)
412 else
413 return string.char(x)
416 return self:tostring(convert_func)
419 function IntSet:tointstring()
420 return self:tostring(function (x) return tostring(x) end)
422 -- class IntSet
424 ShallowTable = {name="ShallowTable"}
425 function ShallowTable:new(val)
426 if val == nil then return nil end
428 if not self.cache then
429 self.cache = {}
430 --setmetatable(self.cache, {__mode = "v"}) -- make values weak
433 local str = ""
434 local keys = {}
435 for key in pairs(val) do table.insert(keys, key) end
436 table.sort(keys)
437 for key in each(keys) do
438 if type(val[key]) == "table" and val[key].class == fa.NonTerm then
439 str = str .. "|" .. key .. ":NONTERM" .. tostring(val[key].name)
440 else
441 str = str .. "|" .. key .. ":" .. tostring(val[key])
445 if not self.cache[str] then
446 self.cache[str] = newobject(self)
447 for k,v in pairs(val) do
448 self.cache[str][k] = v
452 return self.cache[str]
455 -- vim:et:sts=2:sw=2