using CommandLine; using CppAst; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; namespace refl { [Verb("build",HelpText = "Generate custom code based on the parsed AST.")] internal class CmdBuildOption { [Value(0, MetaName = "", Required = true, Min = 2, HelpText = "Input file(s) for parsing.")] public IEnumerable? InputFiles { get; set; } [Option('o', "output", Required = true, HelpText = "Output file for generated code.")] public string Output { get; set; } = ""; [Option('t', "template", Required = true, HelpText = "the code template need to render")] public string Template { get; set; } = ""; [Option('i', "include", Required = false, HelpText = "link to the include dir")] public string IncludeDir { get; set; } = ""; [Option('m', "macros", Required = false, HelpText = "add the macros file")] public string MacroFile { get; set; } = ""; [Option('d', "define", Required = false, HelpText = "define a macro on the command line")] public string Define { get; set; } = ""; [Option('v', "verbose", Required = false, HelpText = "output compile info")] public bool Verbose { get; set; } = false; [Option('h', "help", HelpText = "Display this help message.")] public bool Help { get; set; } = false; static string InputFile = "cpp_input.h"; static CppParserOptions MakeParserOptions(CmdBuildOption opt) { var parse = new CppParserOptions { AdditionalArguments = { "-std=c++20" }, //ParseTokenAttributes = true, //ParseCommentAttribute = true, }; if (!string.IsNullOrWhiteSpace(opt.Define)) { var defines = opt.Define.Split(";"); foreach (var def in defines) { parse.Defines.Add(def); } } if (!string.IsNullOrWhiteSpace(opt.IncludeDir)) { var links = opt.IncludeDir.Split(";"); foreach (var ink in links) { parse.IncludeFolders.Add(ink); } } return parse; } public static List PrepareFileList(List file_list) { StringBuilder code = new StringBuilder(); foreach (var file in file_list) { string fileContent = File.ReadAllText(file); code.AppendLine(fileContent.Replace("#include", "//#include")); } file_list.Clear(); file_list.Add(InputFile); File.WriteAllText(InputFile, code.ToString()); return file_list; } public static int CMD_CheckBuildOption(CmdBuildOption opt) { if(opt.InputFiles == null || !Gen.InitTemplate(opt.Template)) { return -1; } var parse_opt = MakeParserOptions(opt); List? file_list = null; if (Path.Exists(opt.MacroFile)) { file_list = opt.InputFiles.ToList(); file_list[0] = opt.MacroFile; } else { file_list = opt.InputFiles.Skip(1).ToList(); } var compilation = CppAst.CppParser.ParseFiles(PrepareFileList(file_list), parse_opt); if (opt.Verbose) { // Print diagnostic messages foreach (var message in compilation.Diagnostics.Messages) if (message.Type.Equals(CppLogMessageType.Error)) Console.WriteLine(message); } var module = ModuleMeta.ParseCompileInfo(compilation); Gen gen = new Gen(); gen.GenCppMeta(module, opt.Output.ToLower()); if (opt.Verbose) { Console.WriteLine("gen success!"); } return 0; } } }