1-- tolua: container abstract class
2-- Written by Waldemar Celes
3-- TeCGraf/PUC-Rio
4-- Jul 1998
5-- $Id$
6
7-- This code is free software; you can redistribute it and/or modify it.
8-- The software provided hereunder is on an "as is" basis, and
9-- the author has no obligation to provide maintenance, support, updates,
10-- enhancements, or modifications.
11
12
13-- Container class
14-- Represents a container of features to be bound
15-- to lua.
16classContainer =
17{
18 curr = nil,
19 _base = classFeature,
20}
21settag(classContainer,tolua_tag)
22
23-- output tags
24function classContainer:decltag ()
25 push(self)
26 local i=1
27 while self[i] do
28  self[i]:decltag()
29  i = i+1
30 end
31 pop()
32end
33
34
35-- write support code
36function classContainer:supcode ()
37 push(self)
38 local i=1
39 while self[i] do
40  self[i]:supcode()
41  i = i+1
42 end
43 pop()
44end
45
46
47-- Internal container constructor
48function _Container (self)
49 self._base = classContainer
50 settag(self,tolua_tag)
51 self.n = 0
52 self.typedefs = {n=0}
53 self.lnames = {}
54 return self
55end
56
57-- push container
58function push (t)
59 classContainer.curr = t
60end
61
62-- pop container
63function pop ()
64 classContainer.curr = classContainer.curr.parent
65end
66
67-- append to current container
68function append (t)
69 return classContainer.curr:append(t)
70end
71
72-- append typedef to current container
73function appendtypedef (t)
74 return classContainer.curr:appendtypedef(t)
75end
76
77-- substitute typedef
78function findtypedef (type)
79 return classContainer.curr:findtypedef(type)
80end
81
82-- check if is typedef
83function istypedef (type)
84 return classContainer.curr:istypedef(type)
85end
86
87-- append feature to container
88function classContainer:append (t)
89 self.n = self.n + 1
90 self[self.n] = t
91 t.parent = self
92end
93
94-- append typedef
95function classContainer:appendtypedef (t)
96 self.typedefs.n = self.typedefs.n + 1
97 self.typedefs[self.typedefs.n] = t
98end
99
100-- determine lua function name overload
101function classContainer:overload (lname)
102 if not self.lnames[lname] then
103  self.lnames[lname] = 0
104 else
105  self.lnames[lname] = self.lnames[lname] + 1
106 end
107 return format("%02d",self.lnames[lname])
108end
109
110function classContainer:findtypedef (type)
111 local env = self
112 while env do
113  if env.typedefs then
114   local i=1
115   while env.typedefs[i] do
116    if env.typedefs[i].utype == type then
117	 local mod1,type1 = env.typedefs[i].mod,env.typedefs[i].type
118         local mod2,type2 = findtypedef(type1)
119         return mod2..' '..mod1,type2
120	end
121	i = i+1
122   end
123  end
124  env = env.parent
125 end
126 return '',type
127end
128
129function classContainer:istypedef (type)
130 local env = self
131 while env do
132  if env.typedefs then
133   local i=1
134   while env.typedefs[i] do
135    if env.typedefs[i].utype == type then
136         return 1
137        end
138        i = i+1
139   end
140  end
141  env = env.parent
142 end
143 return nil
144end
145
146-- parse chunk
147function classContainer:doparse (s)
148
149 -- try module
150 do
151  local b,e,name,body = strfind(s,"^%s*module%s%s*([_%w][_%w]*)%s*(%b{})%s*")
152  if b then
153   _curr_code = strsub(s,b,e)
154   Module(name,body)
155   return strsub(s,e+1)
156  end
157 end
158
159 -- try define
160 do
161  local b,e,name = strfind(s,"^%s*#define%s%s*([^%s]*)[^\n]*\n%s*")
162  if b then
163   _curr_code = strsub(s,b,e)
164   Define(name)
165   return strsub(s,e+1)
166  end
167 end
168
169 -- try enumerates
170 do
171  local b,e,body = strfind(s,"^%s*enum[^{]*(%b{})%s*;?%s*")
172  if b then
173   _curr_code = strsub(s,b,e)
174   Enumerate(body)
175   return strsub(s,e+1)
176  end
177 end
178
179 do
180  local b,e,body,name = strfind(s,"^%s*typedef%s%s*enum[^{]*(%b{})%s*([%w_][^%s]*)%s*;%s*")
181  if b then
182   _curr_code = strsub(s,b,e)
183   Enumerate(body)
184   Typedef("int "..name)
185   return strsub(s,e+1)
186  end
187 end
188
189 -- try operator
190 do
191  local b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&]*operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
192  if b then
193   _curr_code = strsub(s,b,e)
194   Operator(decl,kind,arg,const)
195   return strsub(s,e+1)
196  end
197 end
198
199 -- try function
200 do
201  local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
202  if not b then
203   -- try a single letter function name
204   b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
205  end
206  if b then
207   _curr_code = strsub(s,b,e)
208   Function(decl,arg,const)
209   return strsub(s,e+1)
210  end
211 end
212
213 -- try inline function
214 do
215  local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*%b{}%s*")
216  if not b then
217   -- try a single letter function name
218   b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*%b{}%s*")
219  end
220  if b then
221   _curr_code = strsub(s,b,e)
222   Function(decl,arg,const)
223   return strsub(s,e+1)
224  end
225 end
226
227 -- try class
228 do
229  local b,e,name,base,body = strfind(s,"^%s*class%s*([_%w][_%w]*)%s*(.-)%s*(%b{})%s*;%s*")
230  if not b then
231   b,e,name,base,body = strfind(s,"^%s*struct%s*([_%w][_%w]*)%s*(.-)%s*(%b{})%s*;%s*")
232   if not b then
233    base = ''
234    b,e,body,name = strfind(s,"^%s*typedef%s%s*struct%s%s*[_%w]*%s*(%b{})%s*([_%w][_%w]*)%s*;%s*")
235   end
236  end
237  if b then
238   if base ~= '' then
239    local b,e
240	b,e,base = strfind(base,".-([_%w][_%w]*)$")
241   end
242   _curr_code = strsub(s,b,e)
243   Class(name,base,body)
244   return strsub(s,e+1)
245  end
246 end
247
248 -- try typedef
249 do
250  local b,e,types = strfind(s,"^%s*typedef%s%s*(.-)%s*;%s*")
251  if b then
252   _curr_code = strsub(s,b,e)
253   Typedef(types)
254   return strsub(s,e+1)
255  end
256 end
257
258 -- try variable
259 do
260  local b,e,decl = strfind(s,"^%s*([_%w][_@%s%w%d%*&]*[_%w%d])%s*;%s*")
261  if b then
262   _curr_code = strsub(s,b,e)
263   Variable(decl)
264   return strsub(s,e+1)
265  end
266 end
267
268 -- try array
269 do
270  local b,e,decl = strfind(s,"^%s*([_%w][][_@%s%w%d%*&]*[]_%w%d])%s*;%s*")
271  if b then
272   _curr_code = strsub(s,b,e)
273   Array(decl)
274   return strsub(s,e+1)
275  end
276 end
277
278 -- try code
279 do
280  local b,e,code = strfind(s,"^%s*(%b\1\2)")
281  if b then
282   Code(strsub(code,2,-2))
283   return strsub(s,e+1)
284  end
285 end
286
287 -- try verbatim
288 do
289  local b,e,line = strfind(s,"^%s*%$(.-\n)")
290  if b then
291   Verbatim(line)
292   return strsub(s,e+1)
293  end
294 end
295
296 -- no matching
297 if gsub(s,"%s%s*","") ~= "" then
298  _curr_code = s
299  error("#parse error")
300 else
301  return ""
302 end
303end
304
305function classContainer:parse (s)
306 while s ~= '' do
307  s = self:doparse(s)
308 end
309end
310
311
312