1 --[[--------------------------------------------------------------------
3 Gazelle: a system for building fast, reusable parsers
7 Miscellaneous algorithms that don't belong anywhere else.
9 Copyright (c) 2007-2008 Joshua Haberman. See LICENSE for details.
11 --------------------------------------------------------------------]]--
13 function newobject(class
)
15 setmetatable(obj
, class
)
21 -- each(foo): returns an iterator; if the object supports the each method,
22 -- call that, otherwise return an iterator for a plain array.
23 function each(array_or_eachable_obj
)
24 if array_or_eachable_obj
.class
then
25 return array_or_eachable_obj
:each()
27 local array
= array_or_eachable_obj
31 if array
[i
] then return array
[i
] else return nil end
36 function table_shallow_eql(tbl1
, tbl2
)
37 for k
,v
in pairs(tbl1
) do
38 if tbl1
[k
] ~= tbl2
[k
] then return false end
40 for k
,v
in pairs(tbl2
) do
41 if tbl1
[k
] ~= tbl2
[k
] then return false end
46 function table_copy(t
, max_depth
)
48 for k
, v
in pairs(t
) do
49 if max_depth
> 1 and type(v
) == "table" then
50 v
= table_copy(v
, max_depth
- 1)
57 function table_shallow_copy(t
)
58 return table_copy(t
, 1)
61 function get_common_prefix_len(arrays
)
63 while common_len
<= #arrays
[1] do
64 local elem
= arrays
[1][common_len
+1]
65 for array
in each(arrays
) do
66 if array
[common_len
+1] ~= elem
then
70 common_len
= common_len
+ 1
76 function get_unique_table_for(val
)
77 local string_table
= {}
78 for entry
in each(val
) do table.insert(string_table
, tostring(entry
)) end
79 local str
= table.concat(string_table
, "\136")
80 if not cache
[str
] then
81 cache
[str
] = table_shallow_copy(val
)
86 function depth_first_traversal(obj
, children_func
)
87 local seen
= Set
:new
{obj
}
88 local stack
= Stack
:new()
90 depth_first_traversal_helper(obj
, children_func
, stack
, seen
)
94 function depth_first_traversal_helper(obj
, children_func
, stack
, seen
)
95 local children
= children_func(obj
, stack
) or {}
96 for child
in each(children
) do
97 if not seen
:contains(child
) then
100 depth_first_traversal_helper(child
, children_func
, stack
, seen
)
106 -- all ints within each IntSet are assumed to be equivalent.
107 -- Given this, return a new list of IntSets, where each IntSet
108 -- returned is considered equivalent across ALL IntSets.
109 function equivalence_classes(int_sets
)
114 for int_set
in each(int_sets
) do
115 if int_set
.negated
then int_set
= int_set
:invert() end
116 for range
in each(int_set
.list
) do
117 table.insert(events
, {range
.low
, BEGIN
, int_set
})
118 table.insert(events
, {range
.high
+1, END
, int_set
})
122 local cmp_events
= function(a
, b
)
124 return b
[2] < a
[2] -- END events should go before BEGIN events
130 table.sort(events
, cmp_events
)
132 local nested_regions
= Set
:new()
133 local last_offset
= nil
135 for event
in each(events
) do
136 local offset
, event_type
, int_set
= unpack(event
)
138 if last_offset
and last_offset
< offset
and (not nested_regions
:isempty()) then
139 local hk
= nested_regions
:hash_key()
140 classes
[hk
] = classes
[hk
] or IntSet
:new()
141 classes
[hk
]:add(Range
:new(last_offset
, offset
-1))
144 if event_type
== BEGIN
then
145 nested_regions
:add(int_set
)
147 nested_regions
:remove(int_set
)
153 for hk
, int_set
in pairs(classes
) do
154 table.insert(ret
, int_set
)
159 function str_join(list
, separator
)
161 for i
, string in ipairs(list
) do
164 str
= str
.. separator
170 function table_contains(table, element
)
171 for i
, table_element
in pairs(table) do
172 if element
== table_element
then
179 function clamp_table(tab
, len
)
180 local my_table
= table_shallow_copy(tab
)
181 while #my_table
> len
do
182 table.remove(my_table
)