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)


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