stamen

Static Menu Generator
git clone git://git.dimitrijedobrota.com/stamen.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

generate.cpp (4436B)


0 #include <filesystem> 1 #include <fstream> 2 #include <iostream> 3 #include <string> 4 5 #include <cemplate/cemplate.hpp> 6 #include <poafloc/poafloc.hpp> 7 8 #include "stamen/stamen.hpp" 9 10 struct arguments_t 11 { 12 std::filesystem::path config; 13 std::string nspace = "stamen"; 14 }; 15 16 namespace { 17 18 void generate_include(std::ostream& ost, 19 const stamen::Stamen& inst, 20 const arguments_t& args) 21 { 22 using namespace std::string_literals; // NOLINT 23 using namespace cemplate; // NOLINT 24 25 Program prog(ost); 26 27 const auto func_f = [&prog](const auto& pair) 28 { 29 prog.function_decl( 30 pair.first, "int", {{{"std::size_t"s, "/* unused */"s}}}); 31 }; 32 33 prog.pragma("once") 34 .line_empty() 35 .include("cstddef") 36 .include("functional") 37 .include("string") 38 .include("vector") 39 .line_empty() 40 .namespace_open(args.nspace) 41 .value(R"( 42 struct menu_t 43 { 44 using callback_f = std::function<int(std::size_t)>; 45 46 static int visit(const menu_t& menu); 47 48 struct item_t 49 { 50 std::string prompt; 51 callback_f callback; 52 }; 53 54 std::string title; 55 callback_f callback; 56 std::vector<item_t> items; 57 }; 58 59 )"); 60 61 prog.comment("generated function"); 62 std::for_each( 63 std::begin(inst.menu_lookup()), std::end(inst.menu_lookup()), func_f); 64 prog.line_empty(); 65 66 prog.comment("free function"); 67 std::for_each( 68 std::begin(inst.free_lookup()), std::end(inst.free_lookup()), func_f); 69 70 prog.namespace_close(args.nspace); 71 } 72 73 void generate_source(std::ostream& ost, 74 const stamen::Stamen& inst, 75 const arguments_t& args, 76 const std::string& include_name) 77 { 78 using namespace std::string_literals; // NOLINT 79 using namespace cemplate; // NOLINT 80 81 const auto init_f = [](const auto& menu) 82 { 83 return InitlistNode({ 84 string(menu.title()), 85 menu.code(), 86 InitlistNode(std::begin(menu.items()), 87 std::end(menu.items()), 88 [](const auto& item) -> InitlistNode 89 { 90 return { 91 string(item.prompt), 92 item.code, 93 }; 94 }), 95 }); 96 }; 97 98 Program prog(ost); 99 100 prog.include("cstddef") 101 .line_empty() 102 .includeL(include_name) 103 .line_empty() 104 .namespace_open(args.nspace); 105 106 for (const auto& [_, menu] : inst.menu_lookup()) 107 { 108 prog.function_open( 109 menu.code(), "extern int", {{{"std::size_t"s, "/* unused */"s}}}) 110 .declaration("static const menu_t", "menu", init_f(menu)) 111 .ret("menu_t::visit(menu)") 112 .function_close(menu.code()); 113 } 114 115 prog.namespace_close(args.nspace); 116 } 117 118 int parse_opt(int key, const char* arg, poafloc::Parser* parser) 119 { 120 auto* arguments = static_cast<arguments_t*>(parser->input()); 121 switch (key) 122 { 123 case 'n': 124 arguments->nspace = arg; 125 break; 126 case poafloc::ARG: 127 if (!arguments->config.empty()) 128 { 129 poafloc::failure(parser, 0, 0, "Too many arguments"); 130 poafloc::help(parser, stderr, poafloc::STD_USAGE); 131 } 132 arguments->config = arg; 133 break; 134 case poafloc::NO_ARGS: 135 poafloc::failure(parser, 0, 0, "Missing an argument"); 136 poafloc::help(parser, stderr, poafloc::STD_USAGE); 137 break; 138 default: 139 break; 140 } 141 return 0; 142 } 143 144 } // namespace 145 146 // clang-format off 147 static const poafloc::option_t options[] { 148 { nullptr, 0, nullptr, 0, "Output settings", 2}, 149 {"namespace", 'n', "name", 0, "Name of the nemespace to generate in"}, 150 { nullptr, 0, nullptr, 0, "Informational Options", -1}, 151 { nullptr}, 152 }; 153 // clang-format on 154 155 static const poafloc::arg_t arg { 156 options, 157 parse_opt, 158 "config_file", 159 "", 160 }; 161 162 int main(int argc, char* argv[]) 163 { 164 arguments_t args; 165 166 if (poafloc::parse(&arg, argc, argv, 0, &args) != 0) 167 { 168 std::cerr << "There was an error while parsing arguments"; 169 return 1; 170 } 171 172 std::ifstream ifs(args.config); 173 const stamen::Stamen inst(ifs); 174 175 const auto include_filename = args.config.stem().replace_extension(".hpp"); 176 std::ofstream include(include_filename); 177 generate_include(include, inst, args); 178 179 const auto source_filename = args.config.stem().replace_extension(".cpp"); 180 std::ofstream source(source_filename); 181 generate_source(source, inst, args, include_filename); 182 183 return 0; 184 }