From 0d72d35229fe5d9d967bb38d679c71f89cd31d0e Mon Sep 17 00:00:00 2001 From: Andreas Tsouchlos Date: Sun, 21 Nov 2021 16:53:14 +0100 Subject: [PATCH] Implemented ast_node_T; parse_string now returns an actual AST; Moved functions to new files --- inc/{utility.h => ConstString.h} | 14 +-- inc/Logger.h | 4 +- inc/format.h | 61 +++++++++++ inc/{parsing.h => parse.h} | 176 +++++++++++++------------------ inc/parse_types.h | 61 +++++++++++ src/main.cpp | 23 ---- 6 files changed, 199 insertions(+), 140 deletions(-) rename inc/{utility.h => ConstString.h} (69%) create mode 100644 inc/format.h rename inc/{parsing.h => parse.h} (72%) create mode 100644 inc/parse_types.h diff --git a/inc/utility.h b/inc/ConstString.h similarity index 69% rename from inc/utility.h rename to inc/ConstString.h index db8d382..31f6a68 100644 --- a/inc/utility.h +++ b/inc/ConstString.h @@ -1,18 +1,10 @@ -#ifndef LOGGER_UTILITY_H -#define LOGGER_UTILITY_H +#ifndef LOGGER_CONSTSTRING_H +#define LOGGER_CONSTSTRING_H namespace detail { -constexpr std::size_t const_pow(std::size_t base, int exponent) { - if (exponent == 0) - return 1; - else - return base * const_pow(base, exponent -1); -} - - template class ConstString { public: @@ -40,4 +32,4 @@ ConstString(const char (&)[N]) -> ConstString; } // namespace detail -#endif // LOGGER_UTILITY_H +#endif // LOGGER_CONSTSTRING_H diff --git a/inc/Logger.h b/inc/Logger.h index 72dbaf3..0347564 100644 --- a/inc/Logger.h +++ b/inc/Logger.h @@ -6,8 +6,8 @@ #include #include -#include -#include +#include +#include /* diff --git a/inc/format.h b/inc/format.h new file mode 100644 index 0000000..3977b02 --- /dev/null +++ b/inc/format.h @@ -0,0 +1,61 @@ +#ifndef LOGGER_FORMAT_H +#define LOGGER_FORMAT_H + + +#include "parse.h" + + +namespace detail { + + +template +constexpr int get_output_len() { + constexpr auto parse_result = parse_string(); + static_assert(parse_result.is_valid, "Syntax error in log string"); + + unsigned result = 0; + + for (const auto& ast_node : parse_result.value) { + if (ast_node.is_char()) + ++result; + else + result += ast_node.get_node().length; + } + + return result; +} + +template +constexpr bool is_valid_type() { + // TODO + return true; +} + +template +constexpr std::array format_arg(T arg) { + static_assert(is_valid_type(), "Invalid argument type"); + + std::array result; + + for (auto& c : result) + c = 'f'; + + return result; +} + + +} // namespace detail + + +template +std::array()> format(args_t... args) { + constexpr auto parse_result = detail::parse_string(); + static_assert(parse_result.is_valid); + + std::array()> result; + + return result; +} + + +#endif // LOGGER_FORMAT_H diff --git a/inc/parsing.h b/inc/parse.h similarity index 72% rename from inc/parsing.h rename to inc/parse.h index 20fc553..3d9c93e 100644 --- a/inc/parsing.h +++ b/inc/parse.h @@ -1,31 +1,9 @@ -#ifndef LOGGER_PARSING_H -#define LOGGER_PARSING_H +#ifndef LOGGER_PARSE_H +#define LOGGER_PARSE_H -#include - - -namespace detail { - - -enum class FormatType { s, c, b, B, d, o, x, X, a, A, e, E, f, F, g, G, p }; - -template -struct parse_result_t { - bool is_valid = false; - unsigned new_index = 0; - value_t value; -}; - -struct fmt_node_t { - bool has_zero_padding = false; - int length = 6; - int precision = 2; - FormatType type = FormatType::s; -}; - -template -using string_result_t = std::array; +#include "ConstString.h" +#include "parse_types.h" // clang-format off @@ -60,6 +38,63 @@ using string_result_t = std::array; // clang-format on +namespace detail { + + +/* + * + * Functions to determine the size of data structures + * + */ + + +template +constexpr unsigned count_braces() { + unsigned result = 0; + + for (unsigned i = 0; i < s.size(); ++i) { + if (s[i] == '{') + ++result; + } + + return result; +} + +template +constexpr unsigned strlen_braces() { + unsigned result = 0; + + bool brace_open = false; + for (unsigned i = 0; i < s.size(); ++i) { + if (!brace_open) { + if (s[i] == '{') { + brace_open = true; + ++result; + } + } else { + ++result; + if (s[i] == '}') { + brace_open = false; + } + } + } + + return result; +} + +template +constexpr int get_ast_len() { + return (s.size() - strlen_braces() + count_braces()); +} + + +/* + * + * Parsing functions + * + */ + + template constexpr bool is_digit(ConstString s, unsigned i) { return (s[i] > 47) && (s[i] < 58); @@ -200,47 +235,14 @@ constexpr parse_result_t parse_braces(unsigned i) { } template -constexpr unsigned count_braces() { - unsigned result = 0; - - for (unsigned i = 0; i < s.size(); ++i) { - if (s[i] == '{') - ++result; - } - - return result; -} - -template -constexpr unsigned len_braces() { - unsigned result = 0; - - bool brace_open = false; - for (unsigned i = 0; i < s.size(); ++i) { - if (!brace_open) { - if (s[i] == '{') { - brace_open = true; - ++result; - } - } else { - ++result; - if (s[i] == '}') { - brace_open = false; - } - } - } - - return result; -} - -template -constexpr parse_result_t()>> parse_string() { - parse_result_t()>> result; +constexpr parse_result_t()>> parse_string() { + parse_result_t()>> result; result.is_valid = true; - unsigned format_node_pos = 0; + unsigned ast_position = 0; - for (unsigned i = 0; i < s.size(); ++i) { + unsigned i = 0; + while (i < s.size()) { if (s[i] == '{') { ++i; @@ -248,57 +250,23 @@ constexpr parse_result_t()>> parse_string() { if (!is_valid) { return {false, i, {}}; } - i = new_i; - result.value[format_node_pos++] = format_node; + i = new_i; + result.value[ast_position++].set_node(format_node); } else if (s[i] == '}') { return {false, i, {}}; + } else { + result.value[ast_position++].set_char(s[i]); + ++i; } } return result; } -template -constexpr int get_output_len() { - constexpr auto parse_result = parse_string(); - static_assert(parse_result.is_valid, "Syntax error in log string"); - - unsigned result = s.size() - len_braces(); - - for (const auto& fmt_node : parse_result.value) { - result += fmt_node.length; - } - - return result; -} - } // namespace detail -template -std::array()> format(args_t...) { - std::array()> result; - constexpr auto parse_result = detail::parse_string(); - static_assert(parse_result.is_valid); - - std::cout << "Total computed length: " << result.size() << std::endl; - - for (const auto& format_node : parse_result.value) { - std::cout << "\tFormat Node:" << std::endl; - std::cout << "\t\thas_zero_padding:\t" << format_node.has_zero_padding - << std::endl; - std::cout << "\t\tlength:\t\t\t\t" << format_node.length << std::endl; - std::cout << "\t\tprecision:\t\t\t" << format_node.precision - << std::endl; - std::cout << "\t\ttype:\t\t\t\t" << static_cast(format_node.type) - << std::endl; - } - - return result; -} - - -#endif // LOGGER_PARSING_H +#endif // LOGGER_PARSE_H diff --git a/inc/parse_types.h b/inc/parse_types.h new file mode 100644 index 0000000..31930b9 --- /dev/null +++ b/inc/parse_types.h @@ -0,0 +1,61 @@ +#ifndef LOGGER_PARSE_TYPES_H +#define LOGGER_PARSE_TYPES_H + + +enum class FormatType { s, c, b, B, d, o, x, X, a, A, e, E, f, F, g, G, p }; + + +template +struct parse_result_t { + bool is_valid = false; + unsigned new_index = 0; + value_t value; +}; + + +struct fmt_node_t { + bool has_zero_padding = false; + int length = 6; + int precision = 2; + FormatType type = FormatType::s; +}; + + +class ast_node_t { +public: + constexpr ast_node_t() { + } + + constexpr void set_char(char c) { + m_c = c; + m_is_char = true; + } + constexpr void set_node(fmt_node_t node) { + m_node = node; + m_is_char = false; + } + + constexpr char get_char() const { + return m_c; + } + constexpr fmt_node_t get_node() const { + return m_node; + } + + constexpr bool is_char() const { + return m_is_char; + } + +private: + bool m_is_char = false; + + char m_c = 'c'; + fmt_node_t m_node; +}; + + +template +using string_result_t = std::array; + + +#endif //LOGGER_PARSE_TYPES_H diff --git a/src/main.cpp b/src/main.cpp index 341fe54..7a526b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,36 +8,13 @@ public: void write(char c) { std::cout << c; } -private: }; int main() { -/* Uart uart; - - Logger logger(uart); - logger.log<"Test:{}">(1, 2, 3); - - std::cout << std::endl; - - */ - constexpr detail::ConstString s{"Test: {:16.8f} {:03.5} {:08.2}"}; const auto formatted = format(3.4, "abc", 8.98754); -/* - constexpr detail::ConstString s = "{:8.14c}"; - - constexpr auto result = detail::parse_fmt_string(2); - - std::cout << "Is valid: " << result.is_valid << std::endl << std::endl; - - std::cout << "\tresult.has_zero_padding: " << result.result.has_zero_padding << std::endl; - std::cout << "\tresult.length: " << result.result.length << std::endl; - std::cout << "\tresult.precision: " << result.result.precision << std::endl; - std::cout << "\tresult.type: " << static_cast(result.result.type) << std::endl; -*/ - return 0; } \ No newline at end of file