mirror of
https://github.com/cimgui/cimgui.git
synced 2025-08-10 20:08:31 +01:00
more robust parsing of enum values
This commit is contained in:
@@ -93,6 +93,26 @@ local function str_split(str, pat)
|
|||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
local function strsplit(str, pat)
|
||||||
|
local t = {}
|
||||||
|
local t2 = {}
|
||||||
|
local fpat = "(.-)" .. pat
|
||||||
|
local last_end = 1
|
||||||
|
local s, e, cap, cap2 = str:find(fpat, 1)
|
||||||
|
while s do
|
||||||
|
table.insert(t,cap)
|
||||||
|
table.insert(t2,cap2)
|
||||||
|
last_end = e+1
|
||||||
|
s, e, cap, cap2 = str:find(fpat, last_end)
|
||||||
|
end
|
||||||
|
if last_end <= #str then
|
||||||
|
cap = str:sub(last_end)
|
||||||
|
table.insert(t, cap)
|
||||||
|
elseif str:sub(-1)==pat then
|
||||||
|
table.insert(t, "")
|
||||||
|
end
|
||||||
|
return t,t2
|
||||||
|
end
|
||||||
local function split_comment(line)
|
local function split_comment(line)
|
||||||
local comment = line:match("(%s*//.*)") or ""
|
local comment = line:match("(%s*//.*)") or ""
|
||||||
line = line:gsub("%s*//.*","")
|
line = line:gsub("%s*//.*","")
|
||||||
@@ -112,23 +132,101 @@ local function clean_spaces(cad)
|
|||||||
cad = cad:gsub("%s*([%(%),=:])%s*","%1") --not spaces with ( , ) or ( = ) or ( : )
|
cad = cad:gsub("%s*([%(%),=:])%s*","%1") --not spaces with ( , ) or ( = ) or ( : )
|
||||||
return cad
|
return cad
|
||||||
end
|
end
|
||||||
function strsplit(str, pat)
|
|
||||||
local t = {}
|
------------------------------------
|
||||||
local fpat = "(.-)" .. pat
|
local function parse_enum_value(value, allenums)
|
||||||
local last_end = 1
|
local function clean(val)
|
||||||
local s, e, cap = str:find(fpat, 1)
|
if type(val)=="string" then
|
||||||
while s do
|
return clean_spaces(val)
|
||||||
table.insert(t,cap)
|
else
|
||||||
last_end = e+1
|
return val
|
||||||
s, e, cap = str:find(fpat, last_end)
|
end
|
||||||
end
|
end
|
||||||
if last_end <= #str then
|
|
||||||
cap = str:sub(last_end)
|
if type(value)=="number" then
|
||||||
table.insert(t, cap)
|
return value
|
||||||
elseif str:sub(-1)==pat then
|
elseif type(value)=="string" then
|
||||||
table.insert(t, "")
|
--numbers
|
||||||
end
|
local numval = tonumber(value)
|
||||||
return t
|
if numval then return numval end
|
||||||
|
--already in allenums
|
||||||
|
if allenums[clean(value)] then return allenums[clean(value)] end
|
||||||
|
--must be several and operators
|
||||||
|
--precedence order (hope not ())
|
||||||
|
assert(not value:match("[%(%)]"))
|
||||||
|
local several,seps = strsplit(value,"([<>&|~]+)")
|
||||||
|
--M.prtable(t.value,several,seps)
|
||||||
|
assert(#seps+1==#several)
|
||||||
|
|
||||||
|
local i = 1
|
||||||
|
local ik = 1
|
||||||
|
local sepk = {"~","<<",">>","&","^","|"}
|
||||||
|
while(#seps>0) do
|
||||||
|
local sep = sepk[ik]
|
||||||
|
local v = seps[i]
|
||||||
|
if sep==v then
|
||||||
|
if v=="~" then
|
||||||
|
local val = clean(several[i+1])
|
||||||
|
if allenums[val] then val = allenums[val] end
|
||||||
|
assert(several[i]==" " or several[i]=="")
|
||||||
|
several[i] = bit.bnot(val)
|
||||||
|
table.remove(several,i+1)
|
||||||
|
table.remove(seps,i)
|
||||||
|
elseif v=="<<" then
|
||||||
|
local val1 = clean(several[i])
|
||||||
|
local val2 = clean(several[i+1])
|
||||||
|
if allenums[val1] then val1 = allenums[val1] end
|
||||||
|
if allenums[val2] then val2 = allenums[val2] end
|
||||||
|
several[i] = bit.lshift(val1,val2)
|
||||||
|
table.remove(several,i+1)
|
||||||
|
table.remove(seps,i)
|
||||||
|
elseif v==">>" then
|
||||||
|
local val1 = clean(several[i])
|
||||||
|
local val2 = clean(several[i+1])
|
||||||
|
if allenums[val1] then val1 = allenums[val1] end
|
||||||
|
if allenums[val2] then val2 = allenums[val2] end
|
||||||
|
several[i] = bit.rshift(val1,val2)
|
||||||
|
table.remove(several,i+1)
|
||||||
|
table.remove(seps,i)
|
||||||
|
elseif v=="&" then
|
||||||
|
local val1 = clean(several[i])
|
||||||
|
local val2 = clean(several[i+1])
|
||||||
|
if allenums[val1] then val1 = allenums[val1] end
|
||||||
|
if allenums[val2] then val2 = allenums[val2] end
|
||||||
|
several[i] = bit.band(val1,val2)
|
||||||
|
table.remove(several,i+1)
|
||||||
|
table.remove(seps,i)
|
||||||
|
elseif v=="^" then
|
||||||
|
error"^ operator still not done"
|
||||||
|
elseif v=="|" then
|
||||||
|
local val1 = clean(several[i])
|
||||||
|
local val2 = clean(several[i+1])
|
||||||
|
if allenums[val1] then val1 = allenums[val1] end
|
||||||
|
if allenums[val2] then val2 = allenums[val2] end
|
||||||
|
several[i] = bit.bor(val1,val2)
|
||||||
|
table.remove(several,i+1)
|
||||||
|
table.remove(seps,i)
|
||||||
|
else
|
||||||
|
error("unknown operator "..v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if i>#seps then
|
||||||
|
ik = ik + 1 --next operator
|
||||||
|
if ik > #sepk then break end
|
||||||
|
i = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #seps>0 then
|
||||||
|
print("value",value)
|
||||||
|
M.prtable(several,seps)
|
||||||
|
end
|
||||||
|
assert(#seps==0)
|
||||||
|
assert(type(several[1])=="number")
|
||||||
|
return several[1]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
local function save_data(filename,...)
|
local function save_data(filename,...)
|
||||||
@@ -1043,22 +1141,7 @@ function M.Parser()
|
|||||||
--first calc_value in enums
|
--first calc_value in enums
|
||||||
for enumname,enum in pairs(outtab.enums) do
|
for enumname,enum in pairs(outtab.enums) do
|
||||||
for i,t in ipairs(enum) do
|
for i,t in ipairs(enum) do
|
||||||
local val = tonumber(t.value)
|
t.calc_value = parse_enum_value(t.value,allenums)
|
||||||
if val then
|
|
||||||
t.calc_value = val
|
|
||||||
elseif t.value:match"<<" then
|
|
||||||
local v1,v2 = t.value:match("(%d+)%s*<<%s*(%d+)")
|
|
||||||
t.calc_value = bit.lshift(v1,v2)
|
|
||||||
elseif t.value:match"|" then --or several enums
|
|
||||||
local ens = t.value
|
|
||||||
ens = strsplit(ens,"|")
|
|
||||||
for i,v in ipairs(ens) do ens[i] = allenums[clean_spaces(v)] end
|
|
||||||
t.calc_value = bit.bor(unpack(ens))
|
|
||||||
elseif allenums[t.value] then
|
|
||||||
t.calc_value = allenums[t.value]
|
|
||||||
else
|
|
||||||
print("Error unknown value in enums",t.value)
|
|
||||||
end
|
|
||||||
assert(t.calc_value)
|
assert(t.calc_value)
|
||||||
allenums[t.name] = t.calc_value
|
allenums[t.name] = t.calc_value
|
||||||
end
|
end
|
||||||
|
@@ -605,82 +605,18 @@ local cstructsstr = outpre..table.concat(outtab,"")..outpost..(extra or "")
|
|||||||
local cfuncsstr = func_header_generate(parser1i)
|
local cfuncsstr = func_header_generate(parser1i)
|
||||||
save_data("./output/cimgui_internal.h",cimgui_header,"#ifdef CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n",cstructsstr,"\n#endif\n")--,cfuncsstr)
|
save_data("./output/cimgui_internal.h",cimgui_header,"#ifdef CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n",cstructsstr,"\n#endif\n")--,cfuncsstr)
|
||||||
copyfile("./output/cimgui_internal.h", "../cimgui_internal.h")
|
copyfile("./output/cimgui_internal.h", "../cimgui_internal.h")
|
||||||
--local structs_and_enums_table_i = parser1i:gen_structs_and_enums_table()
|
|
||||||
--save_data("./output/structs_and_enums_i.lua",serializeTableF(structs_and_enums_table_i))
|
|
||||||
--]=]
|
--]=]
|
||||||
----------- add only ImGuiContext from imgui_internal.h to parser1
|
---------- generate now structs_and_enums_i
|
||||||
--[=[
|
---[=[
|
||||||
local parser1i = parseImGuiHeader([[../imgui/imgui_internal.h]],{[[imgui_internal]],[[imstb_textedit]]})
|
save_data([[../imgui/temp.h]],[[#include "imgui.h"
|
||||||
|
#include "imgui_internal.h"]])
|
||||||
|
local parser1i = parseImGuiHeader([[../imgui/temp.h]],{[[imgui]],[[imgui_internal]],[[imstb_textedit]]})
|
||||||
|
os.remove([[../imgui/temp.h]])
|
||||||
parser1i:do_parse()
|
parser1i:do_parse()
|
||||||
local p1isten = parser1i:gen_structs_and_enums_table()
|
local structs_and_enums_table_i = parser1i:gen_structs_and_enums_table()
|
||||||
--parser1i:printItems()
|
save_data("./output/structs_and_enums_i.lua",serializeTableF(structs_and_enums_table_i))
|
||||||
print"typedefs_table---------------------------"
|
|
||||||
cpp2ffi.prtable(parser1i.typedefs_table)
|
|
||||||
print"typedefs_table end---------------------------"
|
|
||||||
local needed = {ImGuiContext = {type = "ImGuiContext", kind = "structs", order = parser1i.order["ImGuiContext"]}}
|
|
||||||
local seen = {}
|
|
||||||
local function RecurseNeeded(Ini,IniKind,level)
|
|
||||||
--if level > 5 then return end
|
|
||||||
if seen[Ini] then return end
|
|
||||||
seen[Ini] = true
|
|
||||||
print("RecurseNeeded",Ini,IniKind,level)
|
|
||||||
for i,v in ipairs(p1isten[IniKind][Ini]) do
|
|
||||||
--if not v.type then print("nil type in",Ini,IniKind) end
|
|
||||||
--dont want pointers
|
|
||||||
local type = v.type:match"([^%*]+)"
|
|
||||||
--ImVector out
|
|
||||||
if type:match"ImVector_" then type=type:match"ImVector_(.+)" end
|
|
||||||
|
|
||||||
local kind = p1isten.enums[type] and "enums" or p1isten.structs[type] and "structs" or nil
|
|
||||||
if kind=="structs" then
|
|
||||||
if not needed[type] then RecurseNeeded(type,kind,level+1) end
|
|
||||||
needed[type] = {type = type, kind = kind, order = parser1i.order[type]}
|
|
||||||
elseif kind=="enums" then
|
|
||||||
needed[type] = {type = type, kind = kind, order = parser1i.order[type]}
|
|
||||||
elseif parser1i.typedefs_table[type] then
|
|
||||||
needed[type] = {type = type, kind = "typedef", order = parser1i.order[type]}
|
|
||||||
elseif parser1i.vardefs[type] then
|
|
||||||
needed[type] = {type = type, kind = "vardef", order = parser1i.order[type]}
|
|
||||||
elseif not cpp2ffi.c_types[type] then
|
|
||||||
print("RecurseNeded failed",type)
|
|
||||||
--error"failed recurse"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
RecurseNeeded("ImGuiContext","structs",0)
|
|
||||||
|
|
||||||
|
|
||||||
local ordered_needed = {}
|
|
||||||
for k,v in pairs(needed) do
|
|
||||||
table.insert(ordered_needed,v)
|
|
||||||
end
|
|
||||||
table.sort(ordered_needed, function(a,b) return a.order < b.order end)
|
|
||||||
|
|
||||||
print"needed are-----------------------"
|
|
||||||
for i,vv in ipairs(ordered_needed) do
|
|
||||||
print(vv.order,vv.type,vv.kind)
|
|
||||||
local v = parser1i.itemsarr[vv.order]
|
|
||||||
|
|
||||||
--if v.item:match"^[%s\n\r]*struct%s*ImGuiContext" then
|
|
||||||
if vv.kind=="structs" then
|
|
||||||
--add enum keyword where necessary
|
|
||||||
--print"setting enum keyword------------------------"
|
|
||||||
local newitem = ""
|
|
||||||
for line in v.item:gmatch("([^\n]+)") do
|
|
||||||
local typen = line:match"^%s*(%S+)"
|
|
||||||
if p1isten.enums[typen] then
|
|
||||||
print("add enum",typen)
|
|
||||||
newitem = newitem.."\nenum"..line
|
|
||||||
else
|
|
||||||
newitem = newitem.."\n"..line
|
|
||||||
end
|
|
||||||
end
|
|
||||||
v.item = newitem
|
|
||||||
end
|
|
||||||
table.insert(parser1.itemsarr,v)
|
|
||||||
end
|
|
||||||
--]=]
|
--]=]
|
||||||
|
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
save_data("./output/overloads.txt",parser1.overloadstxt)
|
save_data("./output/overloads.txt",parser1.overloadstxt)
|
||||||
@@ -782,6 +718,7 @@ end
|
|||||||
local json = require"json"
|
local json = require"json"
|
||||||
save_data("./output/definitions.json",json.encode(json_prepare(parser1.defsT)))
|
save_data("./output/definitions.json",json.encode(json_prepare(parser1.defsT)))
|
||||||
save_data("./output/structs_and_enums.json",json.encode(structs_and_enums_table))
|
save_data("./output/structs_and_enums.json",json.encode(structs_and_enums_table))
|
||||||
|
save_data("./output/structs_and_enums_i.json",json.encode(structs_and_enums_table_i))
|
||||||
save_data("./output/typedefs_dict.json",json.encode(parser1.typedefs_dict))
|
save_data("./output/typedefs_dict.json",json.encode(parser1.typedefs_dict))
|
||||||
if parser2 then
|
if parser2 then
|
||||||
save_data("./output/impl_definitions.json",json.encode(json_prepare(parser2.defsT)))
|
save_data("./output/impl_definitions.json",json.encode(json_prepare(parser2.defsT)))
|
||||||
|
Reference in New Issue
Block a user