1 --[[--------------------------------------------------------------------
3 Gazelle: a system for building fast, reusable parsers
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 --------------------------------------------------------------------]]--
17 Queue
= {name
="Queue"}
18 function Queue
:new(init
)
19 local obj
= newobject(self
)
22 if init
then obj
:enqueue(init
) end
26 function Queue
:enqueue(val
)
27 self
.last
= self
.last
+ 1
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
39 function Queue
:isempty()
40 return self
.first
> self
.last
46 Stack
= {name
="Stack"}
47 function Stack
:new(init
)
48 local obj
= newobject(self
)
53 function Stack
:push(val
)
54 table.insert(self
.stack
, val
)
58 return table.remove(self
.stack
)
62 return self
.stack
[#self
.stack
]
65 function Stack
:contains(elem
)
66 for e
in each(self
.stack
) do
74 function Stack
:to_array()
76 for i
, val
in ipairs(self
.stack
) do
77 table.insert(arr
, val
)
86 function Set
:new(init
)
87 local obj
= newobject(self
)
90 obj
:add_collection(init
)
95 function Set
:contains(x
)
96 return self
.elements
[x
] ~= nil
100 self
.elements
[x
] = true
103 function Set
:remove(x
)
104 self
.elements
[x
] = nil
107 function Set
:add_collection(arr
)
108 for elem
in each(arr
) do
114 return pairs(self
.elements
)
117 function Set
:to_array()
119 for elem
in self
:each() do
120 table.insert(arr
, elem
)
125 function Set
:isempty()
126 return self
:count() == 0
131 for elem
in self
:each() do
137 function Set
:hash_key()
138 local arr
= self
:to_array()
140 arr
[i
] = tostring(arr
[i
])
145 str
= "" for elem
in each(arr
) do str
= str
.. elem
end
151 OrderedSet
= {name
="OrderedSet"}
152 function OrderedSet
:new(init
)
153 local obj
= newobject(self
)
154 obj
.element_offsets
= {}
157 for element
in each(init
) do
164 function OrderedSet
:add(elem
)
165 if not self
.element_offsets
[elem
] then
166 self
.element_offsets
[elem
] = #self
.elements
167 table.insert(self
.element
, elem
)
171 function OrderedSet
:offset_of(elem
)
172 return self
.element_offsets
[elem
]
175 function OrderedSet
:each()
179 if self
.elements
[i
] then
180 return self
.elements
[i
]
188 OrderedMap
= {name
="OrderedMap"}
189 function OrderedMap
:new()
190 local obj
= newobject(self
)
196 function OrderedMap
:add(key
, value
)
197 if not self
.key_offsets
[key
] then
198 self
.key_offsets
[key
] = #self
.elements
199 table.insert(self
.elements
, {key
, value
})
203 function OrderedMap
:get(key
)
204 return self
.elements
[self
.key_offsets
[key]]
[2]
207 function OrderedMap
:offset_of_key(elem
)
208 return self
.key_offsets
[elem
]
211 function OrderedMap
:each()
215 if self
.elements
[i
] then
216 return unpack(self
.elements
[i
])
224 -- The Range is *inclusive* at both ends.
225 Range
= {name
="Range"}
226 function Range
:new(low
, high
)
229 local obj
= newobject(self
)
235 function Range
.union(a
, b
)
236 if math
.max(a
.low
, b
.low
) <= (math
.min(a
.high
, b
.high
)+1) then
237 return Range
:new(math
.min(a
.low
, b
.low
), math
.max(a
.high
, b
.high
))
243 function Range
:contains(int
)
244 return (self
.low
<= int
) and (self
.high
>= int
)
247 function Range
:tostring(display_val_func
)
248 if self
.low
== self
.high
then
249 return display_val_func(self
.low
)
251 return display_val_func(self
.low
) .. "-" .. display_val_func(self
.high
)
258 -- None of the ranges may overlap.
259 IntSet
= {name
="IntSet"}
260 function IntSet
:new()
261 local obj
= newobject(self
)
267 function IntSet
:add(new_range
)
269 for range
in each(self
.list
) do
270 local union
= new_range
:union(range
)
274 table.insert(newlist
, range
)
278 table.insert(newlist
, new_range
)
282 function IntSet
:get_non_negated()
290 -- This is O(n^2) right now, and can probably
291 -- be made O(n lg n) with a little thought, but n's
292 -- are so small right now that I won't worry.
293 function IntSet
:add_intset(intset
)
294 for range
in each(intset
.list
) do
299 function IntSet
:contains(int
)
300 local obj
= self
:get_non_negated()
301 for range
in each(obj
.list
) do
302 if range
:contains(int
) then return true end
307 function IntSet
:sampleint()
308 local obj
= self
:get_non_negated()
310 if #obj
.list
== 0 then
313 return obj
.list
[1].low
317 function IntSet
:invert()
318 local new_intset
= IntSet
:new()
319 new_intset
.negated
= not self
.negated
321 table.sort(self
.list
, function (a
, b
) return a
.low
< b
.low
end)
324 for range
in each(self
.list
) do
325 if offset
<= range
.low
-1 then
326 new_intset
:add(Range
:new(offset
, range
.low
-1))
328 offset
= range
.high
+1
331 if offset
~= math
.huge
then
332 new_intset
:add(Range
:new(offset
, math
.huge
))
338 function IntSet
:each_range()
339 return each(self
:get_non_negated().list
)
342 function IntSet
:isunbounded()
343 for range
in each(self
.list
) do
344 if range
.high
== math
.huge
then
351 function IntSet
:tostring(display_val_func
)
353 if self
.negated
then str
= "^" end
355 table.sort(self
.list
, function (a
, b
) return a
.low
< b
.low
end)
357 for range
in each(self
.list
) do
364 str
= str
.. range
:tostring(display_val_func
)
370 function IntSet
:toasciistring()
371 local convert_func
= function (x
)
372 if x
== math
.huge
then
375 return string.format("\\%03o", x
)
377 return string.char(x
)
380 return self
:tostring(convert_func
)
383 function IntSet
:tointstring()
384 return self
:tostring(function (x
) return tostring(x
) end)
388 ShallowTable
= {name
="ShallowTable"}
389 function ShallowTable
:new(val
)
390 if val
== nil then return nil end
392 if not self
.cache
then
394 --setmetatable(self.cache, {__mode = "v"}) -- make values weak
399 for key
in pairs(val
) do table.insert(keys
, key
) end
401 for key
in each(keys
) do
402 if type(val
[key
]) == "table" and val
[key
].class
== fa
.NonTerm
then
403 str
= str
.. "|" .. key
.. ":NONTERM" .. tostring(val
[key
].name
)
405 str
= str
.. "|" .. key
.. ":" .. tostring(val
[key
])
409 if not self
.cache
[str
] then
410 self
.cache
[str
] = newobject(self
)
411 for k
,v
in pairs(val
) do
412 self
.cache
[str
][k
] = v
416 return self
.cache
[str
]