cppast/src/refl/BuildOption.cs
2024-06-26 13:44:35 +08:00

111 lines
4.0 KiB
C#

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<string>? 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<string> PrepareFileList(List<string> 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<string>? 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;
}
}
}