diff options
author | chai <chaifix@163.com> | 2019-08-07 21:08:47 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-08-07 21:08:47 +0800 |
commit | 0c391fdbce5a079cf03e483eb6174dd47806163d (patch) | |
tree | b06cd7a9d0ae0d9bb9e82f3dcb786dfce11f8628 /Build/tools/bindingGen/main.cs | |
parent | 9686368e58e25cbd6dc37d686bdd2be3f80486d6 (diff) |
*misc
Diffstat (limited to 'Build/tools/bindingGen/main.cs')
-rw-r--r-- | Build/tools/bindingGen/main.cs | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/Build/tools/bindingGen/main.cs b/Build/tools/bindingGen/main.cs new file mode 100644 index 0000000..f58b846 --- /dev/null +++ b/Build/tools/bindingGen/main.cs @@ -0,0 +1,282 @@ +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; +using namespace Luax; + +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}); + + return 0; + }} +"; + // {0} 类名 + // {1} 去掉_的函数名 + static string method_new = @" + // {0}.{1}() + LUAX_IMPL_METHOD({0}, _{1}) + {{ + LUAX_STATE(L); + + return 0; + }} +"; + + 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 int IndexOfChar(string str, char c, int n) + { + int j = 0; + for (int i = 0; i < str.Count(); ++i) + { + char ch = str[i]; + if (ch == c) + { + if (j == n) + return i; + ++j; + } + } + return -1; + } + + 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])*\s)[A-Z_0-9]+(?=[\s\=,]+)"; + string enums = ""; + + // 尝试查找下划线索引号,如果没有,代表这个枚举字符串全部都是key + string reg_under_line_l = @"(?<=LUAX_DECL_ENUM\s*\(\s*"; + string reg_under_line_r = @"\s*,\s*)[0-9]+(?=\s*\))"; + + 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 underline_index = -1; + Match underline = Regex.Match(src, reg_under_line_l + name + reg_under_line_r); + if (underline.Success) + { + underline_index = int.Parse(underline.ToString()); + } + int maxEname = 0, maxKey = 0; + for (int i = 0; i < values.Count; ++i) + { + enames[i] = values[i].ToString(); + if(underline_index != -1) + { + int start = IndexOfChar(enames[i], '_', underline_index) + 1; + keys[i] = enames[i].Substring(start, enames[i].Count() - start); + } + else + { + // 表明全部都是key + keys[i] = enames[i]; + } + 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_abclass = @"(?<=LUAX_DECL_ABSTRACT_FACTORY\s*\(\s*)[0-9a-zA-Z]+(?=\s*\))"; + string reg_methods = @"(?<=LUAX_DECL_METHOD\()[0-9a-zA-Z_]+(?=\))"; + string reg_enums = @"(?<=LUAX_DECL_ENUM\()[0-9a-zA-Z_]+(?=\s*[\),]+)"; + 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); + string className = ""; + if (m.Success) + { + className = m.ToString(); + } + if (!m.Success) + { + // 抽象类,不会继承Portable模板 + Match abstract_m = Regex.Match(code, reg_abclass); + if (!abstract_m.Success) + continue; + className = abstract_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); + } + } + } +} |