diff options
Diffstat (limited to 'Source/tools/bindingGen/main.cs')
-rw-r--r-- | Source/tools/bindingGen/main.cs | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/Source/tools/bindingGen/main.cs b/Source/tools/bindingGen/main.cs new file mode 100644 index 0000000..cf78f89 --- /dev/null +++ b/Source/tools/bindingGen/main.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Text.RegularExpressions; +using System.IO; + +namespace bindingGen +{ + /// <summary> + /// 输入目录,在目录下生成./binding目录,存放导出的binding代码 + /// </summary> + class Program + { + // {0} 文件名 + // {1} 第一个名称空间 + // {2} 第二个名称空间 + // {3} 内容 + static string output = @"#include ""../{0}.h"" + +using namespace std; + +namespace {1} +{{ + namespace {2} + {{ + {3} + }} +}} +"; + + // {0} 类名 + // {1} 内容 + static string registry = @" + LUAX_REGISTRY({0}) + {{ +{1} + }} +"; + + // {0} 类名 + // {1} 内容 + static string postprocess = @" + LUAX_POSTPROCESS({0}) + {{ +{1} + }} +"; + + // {0} 类名 + // {1} 去掉_的函数名 + // {2} 小写的类名 + static string method = @" + // {2}:{1}() + LUAX_IMPL_METHOD({0}, _{1}) + {{ + LUAX_PREPARE(L, {0}); + + }} +"; + // {0} 类名 + // {1} 去掉_的函数名 + static string method_new = @" + // {0}.{1}() + LUAX_IMPL_METHOD({0}, _{1}) + {{ + LUAX_STATE(L); + + }} +"; + + static string make_register_methods(MatchCollection methods) + { + if (methods.Count == 0) + return ""; + string register_methods = ""; + register_methods += "\t\t\tLUAX_REGISTER_METHODS(state,\n"; + int maxlen = 0; + foreach(var m in methods) + { + string method = m.ToString(); + if (method.Count() > maxlen) + maxlen = method.Count(); + } + for(int i = 0; i < methods.Count; ++i) + { + Match m = methods[i]; + string method = m.ToString(); + register_methods += "\t\t\t\t"; + register_methods += "{ "; + register_methods += ('"' + method.Substring(1, method.Count() - 1) + "\",").PadRight(maxlen + 3, ' '); + register_methods += method.PadRight(maxlen + 1, ' '); + register_methods += "}"; + if (i != methods.Count - 1) + register_methods += ','; + register_methods += '\n'; + } + register_methods += "\t\t\t);"; + return register_methods; + } + + static string make_impl_methods(MatchCollection mc, string cname) + { + if (mc.Count == 0) + return ""; + + string methods = ""; + + foreach(var m in mc) + { + string name = m.ToString(); + if(name != "_New") + { + methods += String.Format(method, cname, name.Substring(1, name.Count() - 1), cname.ToLower()); + } + else + { + methods += String.Format(method_new, cname, name.Substring(1, name.Count() - 1)); + } + } + + return methods; + } + + static string make_register_enum(MatchCollection mc, string src) + { + if (mc.Count == 0) + return ""; + + string reg_enum_l = @"(?<=enum\s"; + string reg_enum_r = @"[\s\n]*\{((?!\{)[\s\S])*)[A-Z_]+(?=\s*,)"; + string enums = ""; + + foreach(var m in mc) + { + string name = m.ToString(); + enums += "\t\t\tLUAX_REGISTER_ENUM(state, "; + enums += "\"E" + name + "\",\n"; + MatchCollection values = Regex.Matches(src, reg_enum_l + name + reg_enum_r); + string[] enames = new string[values.Count]; + string[] keys = new string[values.Count]; + int maxEname = 0, maxKey = 0; + for (int i = 0; i < values.Count; ++i) + { + enames[i] = values[i].ToString(); + keys[i] = enames[i].Substring(enames[i].LastIndexOf('_') + 1, enames[i].Count() - enames[i].LastIndexOf('_') -1); + if (enames[i].Count() > maxEname) maxEname = enames[i].Count(); + if (keys[i].Count() > maxKey) maxKey = keys[i].Count(); + } + for(int i = 0; i < values.Count; ++i) + { + enums += "\t\t\t\t{ "; + enums += ('"' + keys[i] + "\",").PadRight(maxKey + 4); + enums += enames[i].PadRight(maxEname + 1); + enums += "}"; + if (i != values.Count - 1) + enums += ","; + enums += "\n"; + } + enums += "\t\t\t);\n"; + } + return enums; + } + + /// <summary> + /// 用法: + /// bindingGen <目录> + /// </summary> + /// <param name="args"></param> + static void Main(string[] args) + { + if (args.Length < 1) + return; + + string dir = args[0]; + + Console.WriteLine("源目录: " + dir); + + if (!Directory.Exists(dir)) + return; + + string reg_class = @"(?<=Portable\<)[0-9a-zA-Z]+(?=\>)"; + string reg_methods = @"(?<=LUAX_DECL_METHOD\()[0-9a-zA-Z_]+(?=\))"; + string reg_enums = @"(?<=LUAX_DECL_ENUM\()[0-9a-zA-Z_]+(?=\))"; + string reg_namespace = @"(?<=namespace\s)[0-9a-zA-Z]+(?=[\s\n]*)"; + + if(!Directory.Exists(dir + "/binding")) + { + Directory.CreateDirectory(dir + "/binding"); + } + + string[] files = Directory.GetFiles(dir); + for(int i = 0; i < files.Count(); ++i) + { + string file = files[i]; + if (!File.Exists(file)) + continue; + file = file.Replace('\\', '/'); + string name = file.Substring(file.LastIndexOf('/') + 1, file.LastIndexOf('.') - file.LastIndexOf('/') - 1); + string bindingFile = dir + "/binding/_" + name + ".cpp"; + if (File.Exists(bindingFile)) + continue; + string code = File.ReadAllText(file); + // + Match m = Regex.Match(code, reg_class); + if (!m.Success) + continue; + string className = m.ToString(); + MatchCollection mc = Regex.Matches(code, reg_namespace); + // 应该两个名称空间 + if(mc.Count != 2) + { + Console.WriteLine("Error: 源文件没有两个名称空间 " + file); + continue; + } + string namespace1 = mc[0].ToString(); + string namespace2 = mc[1].ToString(); + // 名称空间内的内容 + string content = ""; + mc = Regex.Matches(code, reg_methods); + content += String.Format(registry, className, make_register_methods(mc)); + mc = Regex.Matches(code, reg_enums); + content += String.Format(postprocess, className, make_register_enum(mc, code)); + mc = Regex.Matches(code, reg_methods); + content += make_impl_methods(mc, className); + string binding = String.Format(output, name, namespace1, namespace2, content); + Console.WriteLine("输出: "+bindingFile); + File.WriteAllText(bindingFile, binding); + } + + } + } +} |