cemplate

Simple C++ template engine
git clone git://git.dimitrijedobrota.com/cemplate.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

cemplate.cpp (4865B)


1 #include <format> 2 #include <iostream> 3 4 #include "cemplate/cemplate.hpp" 5 6 namespace 7 { 8 9 void warning(const std::string& message, const std::string& addition) // NOLINT 10 { 11 std::cerr << "Warning: " << message; 12 if (!addition.empty()) { 13 std::cerr << " - " + addition; 14 } 15 std::cerr << '\n' << std::flush; 16 } 17 18 } // namespace 19 20 namespace cemplate 21 { 22 23 std::string string(const std::string& value) 24 { 25 return std::format(R"("{}")", value); 26 } 27 28 std::string call(s_t func, l_t args) 29 { 30 return std::format( 31 "{}({})", func, join(std::begin(args), std::end(args), ", ")); 32 } 33 34 std::string template_def(s_t var, l_t params) 35 { 36 return std::format( 37 "{}<{}>", var, join(std::begin(params), std::end(params), ", ")); 38 } 39 40 Program& Program::line_empty() 41 { 42 m_ost << "\n"; 43 return *this; 44 } 45 46 Program& Program::line_value(s_t value) 47 { 48 m_ost << indent() << value; 49 return *this; 50 } 51 52 Program& Program::value(s_t value) 53 { 54 m_ost << value; 55 return *this; 56 } 57 58 Program& Program::pragma(s_t value) 59 { 60 m_ost << std::format("#pragma {}\n", value); 61 return *this; 62 } 63 64 Program& Program::include(s_t header) 65 { 66 m_ost << std::format("#include <{}>\n", header); 67 return *this; 68 } 69 70 Program& Program::includeL(s_t header) 71 { 72 m_ost << std::format("#include \"{}\"\n", header); 73 return *this; 74 } 75 76 Program& Program::comment(s_t value) 77 { 78 m_ost << std::format("{}// {}\n", indent(), value); 79 return *this; 80 } 81 82 Program& Program::multilineComment(l_t values) 83 { 84 m_ost << std::format( 85 "{}/* {}\n*/\n", 86 indent(), 87 join(std::begin(values), std::end(values), "\n" + indent() + " ")); 88 return *this; 89 } 90 91 Program& Program::call(s_t func, s_t args) 92 { 93 m_ost << std::format("{}{}({});\n", indent(), func, args); 94 return *this; 95 } 96 97 Program& Program::call(s_t func, l_t args) 98 { 99 const std::string val = join(std::begin(args), std::end(args), ", "); 100 return call(func, val); 101 } 102 103 Program& Program::ret(s_t value) 104 { 105 m_ost << std::format("{}return {};\n", indent(), value); 106 return *this; 107 } 108 109 Program& Program::declaration(s_t type, s_t name, s_t value) 110 { 111 m_ost << std::format("{}{} {} = {};\n", indent(), type, name, value); 112 return *this; 113 } 114 115 Program& Program::declaration(s_t type, s_t name, i_t value) 116 { 117 m_ost << std::format("{}{} {} = {{\n{}{}}};\n", 118 indent(), 119 type, 120 name, 121 value.format(m_indent + 1), 122 indent()); 123 return *this; 124 } 125 126 Program& Program::require(s_t value) 127 { 128 m_ost << std::format( 129 "{}requires {}\n", ::cemplate::indent(m_indent + 1), value); 130 return *this; 131 } 132 133 Program& Program::template_decl(l_t params) 134 { 135 m_ost << std::format("{}template <{}>\n", 136 indent(), 137 join(std::begin(params), std::end(params), ", ")); 138 return *this; 139 } 140 141 Program& Program::function_decl(s_t name, s_t ret, l_t params) 142 { 143 m_ost << std::format("{} {}({});\n", 144 ret, 145 name, 146 join(std::begin(params), std::end(params), ", ")); 147 return *this; 148 } 149 150 std::string InitlistNode::format(uint64_t lvl) const 151 { 152 const auto eval = []<typename T>(const T& val, std::uint64_t llvl) 153 { 154 if constexpr (std::is_same_v<T, std::string>) { 155 return std::format("{}{},\n", indent(llvl), val); 156 } else { 157 return std::format( 158 "{}{{\n{}{}}},\n", indent(llvl), val.format(llvl + 1), indent(llvl)); 159 } 160 }; 161 162 std::string res; 163 164 for (const auto& elem : m_values) { 165 std::visit([&](const auto& val) { res += eval(val, lvl + 1); }, 166 elem.value()); 167 } 168 169 return res; 170 } 171 172 Program& Program::function_open(s_t name, s_t ret, l_t params) 173 { 174 if (!m_function_last.empty()) { 175 warning("opening, but function is not closed", m_function_last); 176 } 177 178 m_function_last = name; 179 m_indent++; 180 m_ost << std::format("{} {}({})\n{{\n", 181 ret, 182 name, 183 join(std::begin(params), std::end(params), ", ")); 184 return *this; 185 } 186 187 Program& Program::function_close(s_t name) 188 { 189 if (m_function_last != name) { 190 warning("closing, but function is not closed", m_function_last); 191 } 192 193 m_function_last.clear(); 194 m_indent--; 195 m_ost << "}\n\n"; 196 return *this; 197 } 198 199 Program& Program::namespace_open(s_t name) 200 { 201 if (m_namespace_seen.contains(name)) { 202 warning("nesting namespaces of the same name", name); 203 } 204 205 m_namespace_seen.insert(name); 206 m_namespace_stack.push(name); 207 208 m_ost << std::format("namespace {}\n{{\n\n", name); 209 return *this; 210 } 211 212 Program& Program::namespace_close(s_t name) 213 { 214 if (m_namespace_stack.empty() || m_namespace_stack.top() != name) { 215 warning("closing unproper namespace", name); 216 } 217 218 m_namespace_seen.erase(name); 219 m_namespace_stack.pop(); 220 m_ost << std::format("\n}} // namespace {}\n\n", name); 221 return *this; 222 } 223 224 } // namespace cemplate