tolua读入pkg文件调用classContainer:parse去解析代码s,通过classContainer:doparse去循环处理代码中的每一行
function classContainer:parse (s)
--self.curr_member_access = nil
while s ~= '' do
s = self:doparse(s)
methodisvirtual = false
end
end
在doparse中传入的s进行解析
function classContainer:doparse (s)
--print ("parse "..s)
-- try the parser hook
do
local sub = parser_hook(s)
if sub then
return sub
end
end
-- try the null statement
do
local b,e,code = string.find(s, "^%s*;")
if b then
return strsub(s,e+1)
end
end
-- try empty verbatim line
do
local b,e,code = string.find(s, "^%s*$\n")
if b then
return strsub(s,e+1)
end
end
-- todo lua code / C code / extern 等等
在doparse中对传入的s 应用各种模式去匹配,然后进行处理,用function的代码来叙述
-- try function
do
--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*")
local b,e,decl,arg,const,virt = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)%s*(=?%s*0?)%s*;%s*")
if not b then
-- try function with template
b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w]%b<>)%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
end
if not b then
-- try a single letter function name
b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
end
if not b then
-- try function pointer
b,e,decl,arg,const = strfind(s,"^%s*([^%(;\n]+%b())%s*(%b())%s*;%s*")
if b then
decl = string.gsub(decl, "%(%s*%*([^%)]*)%s*%)", " %1 ")
end
end
if b then
if virt and string.find(virt, "[=0]") then
if self.flags then
self.flags.pure_virtual = true
end
end
_curr_code = strsub(s,b,e)
Function(decl,arg,const)
return strsub(s,e+1)
end
end
-- try inline function
do
local b,e,decl,arg,const = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)[^;{]*%b{}%s*;?%s*")
--local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w>])%s*(%b())%s*(c?o?n?s?t?)[^;]*%b{}%s*;?%s*")
if not b then
-- try a single letter function name
b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?).-%b{}%s*;?%s*")
end
if b then
_curr_code = strsub(s,b,e)
Function(decl,arg,const)
return strsub(s,e+1)
end
end
代码对函数可能出现的情况分别用了不同的模式去匹配,如果匹配成功调用Function去产生一个新的函数对象
-- Internal constructor
function _Function (t)
setmetatable(t,classFunction)
if t.const ~= 'const' and t.const ~= '' then
error("#invalid 'const' specification")
end
append(t)
if t:inclass() then
--print ('t.name is '..t.name..', parent.name is '..t.parent.name)
if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
t.name = 'new'
t.lname = 'new'
t.parent._new = true
t.type = t.parent.name
t.ptr = '*'
elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
t.name = 'delete'
t.lname = 'delete'
t.parent._delete = true
end
end
t.cname = t:cfuncname("tolua")..t:overload(t)
return t
end
-- Constructor
-- Expects three strings: one representing the function declaration,
-- another representing the argument list, and the third representing
-- the "const" or empty string.
function Function (d,a,c)
--local t = split(strsub(a,2,-2),',') -- eliminate braces
--local t = split_params(strsub(a,2,-2))
if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
return nil
end
local i=1
local l = {n=0}
a = string.gsub(a, "%s*([%(%)])%s*", "%1")
local t,strip,last = strip_pars(strsub(a,2,-2));
if strip then
--local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
local ns = join(t, ",", 1, last-1)
ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
--ns = strip_defaults(ns)
local f = Function(d, ns, c)
for i=1,last do
t[i] = string.gsub(t[i], "=.*$", "")
end
end
while t[i] do
l.n = l.n+1
l[l.n] = Declaration(t[i],'var',true)
i = i+1
end
local f = Declaration(d,'func')
f.args = l
f.const = c
return _Function(f)
end
调用declaration去声明一个函数的对象,继续调用_Function,其中在_Function中会去调用append方法,添加到classContainer的curr中去
function append (t)
return classContainer.curr:append(t)
end
这样不断遍历,就把需要解析的代码分割成了不同的对象实体,再去对每个对象实体,进行解析,就从pkg->cpp的转化了