1 --[[--------------------------------------------------------------------
5 Implementations of useful data structures that we use often.
6 Most of these are just useful interfaces around Lua's tables.
8 Copyright (c) 2007 Joshua Haberman. See LICENSE for details.
10 --------------------------------------------------------------------]]--
15 Queue
= {name
="Queue"}
16 function Queue
:new(init
)
17 local obj
= newobject(self
)
20 if init
then obj
:enqueue(init
) end
24 function Queue
:enqueue(val
)
25 self
.last
= self
.last
+ 1
29 function Queue
:dequeue()
30 if self
:isempty() then error("Tried to dequeue an empty queue") end
31 local val
= self
[self
.first
]
32 self
[self
.first
] = nil
33 self
.first
= self
.first
+ 1
37 function Queue
:isempty()
38 return self
.first
> self
.last
44 Stack
= {name
="Stack"}
45 function Stack
:new(init
)
46 local obj
= newobject(self
)
51 function Stack
:push(val
)
52 table.insert(self
.stack
, val
)
56 return table.remove(self
.stack
)
60 return self
.stack
[#self
.stack
]
63 function Stack
:contains(elem
)
64 for e
in each(self
.stack
) do
72 function Stack
:to_array()
74 for i
, val
in ipairs(self
.stack
) do
75 table.insert(arr
, val
)
84 function Set
:new(init
)
85 local obj
= newobject(self
)
88 obj
:add_collection(init
)
93 function Set
:contains(x
)
94 return self
.elements
[x
] ~= nil
98 self
.elements
[x
] = true
101 function Set
:remove(x
)
102 self
.elements
[x
] = nil
105 function Set
:add_collection(arr
)
106 for elem
in each(arr
) do
112 return pairs(self
.elements
)
115 function Set
:to_array()
117 for elem
in self
:each() do
118 table.insert(arr
, elem
)
123 function Set
:isempty()
124 return self
:count() == 0
129 for elem
in self
:each() do
135 function Set
:hash_key()
136 local arr
= self
:to_array()
138 arr
[i
] = tostring(arr
[i
])
143 str
= "" for elem
in each(arr
) do str
= str
.. elem
end
149 -- The Range is *inclusive* at both ends.
150 Range
= {name
="Range"}
151 function Range
:new(low
, high
)
154 local obj
= newobject(self
)
160 function Range
.union(a
, b
)
161 if math
.max(a
.low
, b
.low
) <= (math
.min(a
.high
, b
.high
)+1) then
162 return Range
:new(math
.min(a
.low
, b
.low
), math
.max(a
.high
, b
.high
))
168 function Range
:contains(int
)
169 return (self
.low
<= int
) and (self
.high
>= int
)
172 function Range
:tostring(display_val_func
)
173 if self
.low
== self
.high
then
174 return display_val_func(self
.low
)
176 return display_val_func(self
.low
) .. "-" .. display_val_func(self
.high
)
183 -- None of the ranges may overlap.
184 IntSet
= {name
="IntSet"}
185 function IntSet
:new()
186 local obj
= newobject(self
)
192 function IntSet
:add(new_range
)
194 for range
in each(self
.list
) do
195 local union
= new_range
:union(range
)
199 table.insert(newlist
, range
)
203 table.insert(newlist
, new_range
)
207 function IntSet
:get_non_negated()
215 -- This is O(n^2) right now, and can probably
216 -- be made O(n lg n) with a little thought, but n's
217 -- are so small right now that I won't worry.
218 function IntSet
:add_intset(intset
)
219 for range
in each(intset
.list
) do
224 function IntSet
:contains(int
)
225 local obj
= self
:get_non_negated()
226 for range
in each(obj
.list
) do
227 if range
:contains(int
) then return true end
232 function IntSet
:sampleint()
233 local obj
= self
:get_non_negated()
235 if #obj
.list
== 0 then
238 return obj
.list
[1].low
242 function IntSet
:invert()
243 local new_intset
= IntSet
:new()
244 new_intset
.negated
= not self
.negated
246 table.sort(self
.list
, function (a
, b
) return a
.low
< b
.low
end)
249 for range
in each(self
.list
) do
250 if offset
<= range
.low
-1 then
251 new_intset
:add(Range
:new(offset
, range
.low
-1))
253 offset
= range
.high
+1
256 if offset
~= math
.huge
then
257 new_intset
:add(Range
:new(offset
, math
.huge
))
263 function IntSet
:each_range()
264 return each(self
:get_non_negated().list
)
267 function IntSet
:isunbounded()
268 for range
in each(self
.list
) do
269 if range
.high
== math
.huge
then
276 function IntSet
:tostring(display_val_func
)
278 if self
.negated
then str
= "^" end
280 table.sort(self
.list
, function (a
, b
) return a
.low
< b
.low
end)
282 for range
in each(self
.list
) do
289 str
= str
.. range
:tostring(display_val_func
)
295 function IntSet
:toasciistring()
296 local convert_func
= function (x
)
297 if x
== math
.huge
then
300 return string.format("\\%03o", x
)
302 return string.char(x
)
305 return self
:tostring(convert_func
)
308 function IntSet
:tointstring()
309 return self
:tostring(function (x
) return tostring(x
) end)
313 ShallowTable
= {name
="ShallowTable"}
314 function ShallowTable
:new(val
)
315 if val
== nil then return nil end
317 if not self
.cache
then
319 --setmetatable(self.cache, {__mode = "v"}) -- make values weak
324 for key
in pairs(val
) do table.insert(keys
, key
) end
326 for key
in each(keys
) do
327 if type(val
[key
]) == "table" and val
[key
].class
== fa
.NonTerm
then
328 str
= str
.. "|" .. key
.. ":NONTERM" .. tostring(val
[key
].name
)
330 str
= str
.. "|" .. key
.. ":" .. tostring(val
[key
])
334 if not self
.cache
[str
] then
335 self
.cache
[str
] = newobject(self
)
336 for k
,v
in pairs(val
) do
337 self
.cache
[str
][k
] = v
341 return self
.cache
[str
]