diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c59ae2..4f0a2c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 0.17.4) +set(BLT_VERSION 0.17.5) set(BLT_TEST_VERSION 0.0.1) set(BLT_TARGET BLT) diff --git a/include/blt/parse/templating.h b/include/blt/parse/templating.h index 831fa33..cc9efa5 100644 --- a/include/blt/parse/templating.h +++ b/include/blt/parse/templating.h @@ -321,223 +321,19 @@ namespace blt } private: - estring statement() - { - auto next = consumer.consume(); - if (next.type == template_token_t::STRING || next.type == template_token_t::QUOTE) - { - consumer.back(); - auto str = string(); - return str; - } else if (next.type == template_token_t::FUNCTION) - { - return function(); - } else if (next.type == template_token_t::IDENT && consumer.hasNext() && consumer.next().type == template_token_t::CURLY_OPEN) - { - consumer.advance(); - auto stmt = statement(); - // should never occur - if (consumer.hasNext() && consumer.next().type != template_token_t::CURLY_CLOSE) - return blt::unexpected(template_parser_failure_t::NO_MATCHING_CURLY); - consumer.advance(); - return stmt; - } else if (next.type == template_token_t::IF) - { - return if_func(); - } - return blt::unexpected(template_parser_failure_t::UNKNOWN_STATEMENT_ERROR); - } + estring statement(); - estring function() - { - auto str = consumer.consume(); - if (consumer.next().type == template_token_t::SEMI) - consumer.advance(); - if (str.type != template_token_t::STRING) - return blt::unexpected(template_parser_failure_t::FUNCTION_EXPECTED_STRING); - if (str.token == "DISCARD") - return blt::unexpected(template_parser_failure_t::FUNCTION_DISCARD); - return blt::unexpected(template_parser_failure_t::FUNCTION_NOT_FOUND); - } + estring function(); - estring if_func() - { - // IF( - if (consumer.consume().type != template_token_t::PAR_OPEN) - return blt::unexpected(template_parser_failure_t::IF_EXPECTED_PAREN); - // (statement) - auto bool_eval = bool_statement(); - if (!bool_eval) - return blt::unexpected(bool_eval.error()); - - if (consumer.consume().type != template_token_t::CURLY_OPEN) - return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); - auto true_statement = statement(); - if (consumer.consume().type != template_token_t::CURLY_CLOSE) - return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); - - estring false_statement = blt::unexpected(template_parser_failure_t::UNKNOWN_ERROR); - bool has_false = false; - if (consumer.next().type == template_token_t::ELSE) - { - consumer.advance(); - if (consumer.consume().type != template_token_t::CURLY_OPEN) - return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); - false_statement = statement(); - if (consumer.consume().type != template_token_t::CURLY_CLOSE) - return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); - - has_false = true; - } - if (bool_eval.value()) - return true_statement; - else - { - if (has_false) - return false_statement; - return ""; - } - } + estring if_func(); - estring string() - { - auto next = consumer.consume(); - if (next.type == template_token_t::STRING) - { -// -// return blt::unexpected(template_parser_failure_t::SUBSTITUTION_NOT_FOUND); - if (consumer.next().type == template_token_t::SEMI || consumer.next().type == template_token_t::ELSE || - consumer.next().type == template_token_t::CURLY_CLOSE || consumer.next().type == template_token_t::PAR_CLOSE) - { - if (consumer.next().type == template_token_t::SEMI) - consumer.advance(); - if (!engine.contains(next.token)) - return ""; - return engine.get(next.token); - } - - if (consumer.next().type != template_token_t::ADD) - return blt::unexpected(template_parser_failure_t::STRING_EXPECTED_CONCAT); - consumer.advance(); - auto str = string(); - if (!str) - return str; - auto sub = engine.get(next.token); - if (!sub) - return sub; - return sub.value() + str.value(); - } else - { - if (consumer.next().type == template_token_t::SEMI) - { - consumer.advance(); - return std::string(next.token); - } - auto str = string(); - if (str) - return std::string(next.token) + str.value(); - else - return str; - } - } + estring string(); - ebool bool_statement() - { - auto next = consumer.next(); - if (next.type == template_token_t::PAR_OPEN) - { - consumer.advance(); - auto b = bool_statement(); - if (consumer.consume().type != template_token_t::PAR_CLOSE) - return blt::unexpected(template_parser_failure_t::BOOL_EXPECTED_PAREN); - consumer.advance(); - return b; - } - return bool_expression(); - } + ebool bool_statement(); - ebool bool_value() - { - bool b1; - auto next = consumer.next(); - bool invert = false; - // prefixes - if (next.type == template_token_t::NOT) - { - invert = true; - consumer.advance(); - next = consumer.next(); - } - if (next.type == template_token_t::PAR_OPEN) - { - auto b = bool_statement(); - if (!b) - return b; - b1 = b.value(); - } else - { - if (consumer.next().type == template_token_t::PAR_OPEN) - { - auto b = bool_statement(); - if (!b) - return b; - b1 = b.value(); - } else - { - auto b = statement(); - if (!b) - return blt::unexpected(b.error()); - b1 = !b.value().empty(); - } - } - if (invert) - b1 = !b1; - return b1; - } + ebool bool_value(); - ebool bool_expression() - { - // this whole thing is just bad. please redo. TODO - std::vector values; - while (consumer.next().type != template_token_t::CURLY_OPEN) - { - auto next = consumer.next(); - auto bv = bool_value(); - if (!bv) - return bv; - values.push_back(bv.value()); - - if (values.size() == 2) - { - auto b1 = values[0]; - auto b2 = values[1]; - values.pop_back(); - values.pop_back(); - switch (next.type) - { - case template_token_t::AND: - values.push_back(b1 && b2); - break; - case template_token_t::OR: - values.push_back(b1 || b2); - break; - case template_token_t::XOR: - values.push_back(b1 ^ b2); - break; - default: - BLT_WARN("Unexpected token '%s'", std::string(next.token).c_str()); - return blt::unexpected(template_parser_failure_t::BOOL_TYPE_NOT_FOUND); - } - } - next = consumer.next(); - if (next.type == template_token_t::CURLY_OPEN) - break; - consumer.advance(); - } - if (values.empty()) - BLT_WARN("This is not possible!"); - return values[0]; - } + ebool bool_expression(); template_engine_t& engine; template_token_consumer_t& consumer; diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 7ef2e73..1036816 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5 +Subproject commit 10368163ab1f4367d2f0685b5928b1c973ebd1ec diff --git a/src/blt/parse/templating.cpp b/src/blt/parse/templating.cpp index 54265a6..b56bef9 100644 --- a/src/blt/parse/templating.cpp +++ b/src/blt/parse/templating.cpp @@ -244,4 +244,224 @@ namespace blt return return_str; } + + template_parser_t::ebool template_parser_t::bool_expression() + { + // this whole thing is just bad. please redo. TODO + std::vector values; + while (consumer.next().type != template_token_t::CURLY_OPEN) + { + auto next = consumer.next(); + auto bv = bool_value(); + if (!bv) + return bv; + values.push_back(bv.value()); + + if (values.size() == 2) + { + auto b1 = values[0]; + auto b2 = values[1]; + values.pop_back(); + values.pop_back(); + switch (next.type) + { + case template_token_t::AND: + values.push_back(b1 && b2); + break; + case template_token_t::OR: + values.push_back(b1 || b2); + break; + case template_token_t::XOR: + values.push_back(b1 ^ b2); + break; + default: + BLT_WARN("Unexpected token '%s'", std::string(next.token).c_str()); + return blt::unexpected(template_parser_failure_t::BOOL_TYPE_NOT_FOUND); + } + } + next = consumer.next(); + if (next.type == template_token_t::CURLY_OPEN) + break; + consumer.advance(); + } + if (values.empty()) + BLT_WARN("This is not possible!"); + return values[0]; + } + + template_parser_t::ebool template_parser_t::bool_value() + { + bool b1; + auto next = consumer.next(); + bool invert = false; + // prefixes + if (next.type == template_token_t::NOT) + { + invert = true; + consumer.advance(); + next = consumer.next(); + } + if (next.type == template_token_t::PAR_OPEN) + { + auto b = bool_statement(); + if (!b) + return b; + b1 = b.value(); + } else + { + if (consumer.next().type == template_token_t::PAR_OPEN) + { + auto b = bool_statement(); + if (!b) + return b; + b1 = b.value(); + } else + { + auto b = statement(); + if (!b) + return blt::unexpected(b.error()); + b1 = !b.value().empty(); + } + } + if (invert) + b1 = !b1; + return b1; + } + + template_parser_t::ebool template_parser_t::bool_statement() + { + auto next = consumer.next(); + if (next.type == template_token_t::PAR_OPEN) + { + consumer.advance(); + auto b = bool_statement(); + if (consumer.consume().type != template_token_t::PAR_CLOSE) + return blt::unexpected(template_parser_failure_t::BOOL_EXPECTED_PAREN); + consumer.advance(); + return b; + } + return bool_expression(); + } + + template_parser_t::estring template_parser_t::string() + { + auto next = consumer.consume(); + if (next.type == template_token_t::STRING) + { +// +// return blt::unexpected(template_parser_failure_t::SUBSTITUTION_NOT_FOUND); + if (consumer.next().type == template_token_t::SEMI || consumer.next().type == template_token_t::ELSE || + consumer.next().type == template_token_t::CURLY_CLOSE || consumer.next().type == template_token_t::PAR_CLOSE) + { + if (consumer.next().type == template_token_t::SEMI) + consumer.advance(); + if (!engine.contains(next.token)) + return ""; + return engine.get(next.token); + } + + if (consumer.next().type != template_token_t::ADD) + return blt::unexpected(template_parser_failure_t::STRING_EXPECTED_CONCAT); + consumer.advance(); + auto str = string(); + if (!str) + return str; + auto sub = engine.get(next.token); + if (!sub) + return sub; + return sub.value() + str.value(); + } else + { + if (consumer.next().type == template_token_t::SEMI) + { + consumer.advance(); + return std::string(next.token); + } + auto str = string(); + if (str) + return std::string(next.token) + str.value(); + else + return str; + } + } + + template_parser_t::estring template_parser_t::if_func() + { + // IF( + if (consumer.consume().type != template_token_t::PAR_OPEN) + return blt::unexpected(template_parser_failure_t::IF_EXPECTED_PAREN); + // (statement) + auto bool_eval = bool_statement(); + if (!bool_eval) + return blt::unexpected(bool_eval.error()); + + if (consumer.consume().type != template_token_t::CURLY_OPEN) + return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); + auto true_statement = statement(); + if (consumer.consume().type != template_token_t::CURLY_CLOSE) + return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); + + estring false_statement = blt::unexpected(template_parser_failure_t::UNKNOWN_ERROR); + bool has_false = false; + if (consumer.next().type == template_token_t::ELSE) + { + consumer.advance(); + if (consumer.consume().type != template_token_t::CURLY_OPEN) + return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); + false_statement = statement(); + if (consumer.consume().type != template_token_t::CURLY_CLOSE) + return blt::unexpected(template_parser_failure_t::IF_EXPECTED_CURLY); + + has_false = true; + } + if (bool_eval.value()) + return true_statement; + else + { + if (has_false) + return false_statement; + return ""; + } + } + + template_parser_t::estring template_parser_t::function() + { + auto str = consumer.consume(); + if (consumer.next().type == template_token_t::SEMI) + consumer.advance(); + if (str.type != template_token_t::STRING) + return blt::unexpected(template_parser_failure_t::FUNCTION_EXPECTED_STRING); + if (str.token == "DISCARD") + return blt::unexpected(template_parser_failure_t::FUNCTION_DISCARD); + return blt::unexpected(template_parser_failure_t::FUNCTION_NOT_FOUND); + } + + template_parser_t::estring template_parser_t::statement() + { + auto next = consumer.consume(); + if (next.type == template_token_t::STRING || next.type == template_token_t::QUOTE) + { + consumer.back(); + auto str = string(); + return str; + } else if (next.type == template_token_t::FUNCTION) + { + return function(); + } else if (next.type == template_token_t::IDENT && consumer.hasNext() && consumer.next().type == template_token_t::CURLY_OPEN) + { + consumer.advance(); + auto stmt = statement(); + // should never occur + if (consumer.hasNext() && consumer.next().type != template_token_t::CURLY_CLOSE) + return blt::unexpected(template_parser_failure_t::NO_MATCHING_CURLY); + consumer.advance(); + return stmt; + } else if (next.type == template_token_t::IF) + { + return if_func(); + } + return blt::unexpected(template_parser_failure_t::UNKNOWN_STATEMENT_ERROR); + } + + } \ No newline at end of file