silly
parent
b857bc96ef
commit
fa979a2fd4
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(cmake/color.cmake)
|
include(cmake/color.cmake)
|
||||||
|
|
||||||
set(BLT_VERSION 0.16.23)
|
set(BLT_VERSION 0.16.24)
|
||||||
set(BLT_TEST_VERSION 0.0.1)
|
set(BLT_TEST_VERSION 0.0.1)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
namespace blt
|
namespace blt
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename Storage, typename Consumable>
|
template<typename Storage, typename Consumable>
|
||||||
class template_consumer_base_t
|
class template_consumer_base_t
|
||||||
{
|
{
|
||||||
|
@ -79,6 +80,7 @@ namespace blt
|
||||||
{
|
{
|
||||||
//STRING, // A string of characters not $ { or }
|
//STRING, // A string of characters not $ { or }
|
||||||
IDENT, // $
|
IDENT, // $
|
||||||
|
ADD, // +
|
||||||
CURLY_OPEN, // {
|
CURLY_OPEN, // {
|
||||||
CURLY_CLOSE, // }
|
CURLY_CLOSE, // }
|
||||||
IF, // IF
|
IF, // IF
|
||||||
|
@ -143,6 +145,8 @@ namespace blt
|
||||||
return "[COMMA]";
|
return "[COMMA]";
|
||||||
case template_token_t::PERIOD:
|
case template_token_t::PERIOD:
|
||||||
return "[PERIOD]";
|
return "[PERIOD]";
|
||||||
|
case template_token_t::ADD:
|
||||||
|
return "[ADD]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +159,18 @@ namespace blt
|
||||||
|
|
||||||
enum class template_parser_failure_t
|
enum class template_parser_failure_t
|
||||||
{
|
{
|
||||||
|
SUBSTITUTION_NOT_FOUND,
|
||||||
TOKENIZER_FAILURE,
|
TOKENIZER_FAILURE,
|
||||||
NO_MATCHING_CURLY
|
NO_MATCHING_CURLY,
|
||||||
|
MISSING_IDENT_BRACES,
|
||||||
|
FUNCTION_EXPECTED_STRING,
|
||||||
|
FUNCTION_NOT_FOUND,
|
||||||
|
FUNCTION_DISCARD,
|
||||||
|
STRING_EXPECTED_CONCAT,
|
||||||
|
IF_EXPECTED_PAREN,
|
||||||
|
BOOL_EXPECTED_PAREN,
|
||||||
|
UNKNOWN_STATEMENT_ERROR,
|
||||||
|
UNKNOWN_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
struct template_token_data_t
|
struct template_token_data_t
|
||||||
|
@ -198,10 +212,15 @@ namespace blt
|
||||||
return "";
|
return "";
|
||||||
auto token = storage[getPreviousIndex()];
|
auto token = storage[getPreviousIndex()];
|
||||||
auto len = (&token.token.back() - &raw_string.front()) - last_read_index;
|
auto len = (&token.token.back() - &raw_string.front()) - last_read_index;
|
||||||
auto str = std::string_view(&raw_string[last_read_index], len);
|
auto str = std::string_view(&raw_string[lasomt_read_index], len);
|
||||||
last_read_index += len;
|
last_read_index += len;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void back()
|
||||||
|
{
|
||||||
|
current_index--;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t last_read_index = 0;
|
size_t last_read_index = 0;
|
||||||
|
@ -211,27 +230,181 @@ namespace blt
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using estring = blt::expected<std::string, template_parser_failure_t>;
|
using estring = blt::expected<std::string, template_parser_failure_t>;
|
||||||
|
using ebool = blt::expected<bool, template_parser_failure_t>;
|
||||||
|
|
||||||
template_parser_t(blt::hashmap_t<std::string, std::string>& substitutions, template_token_consumer_t& consumer):
|
template_parser_t(blt::hashmap_t<std::string, std::string>& substitutions, template_token_consumer_t& consumer):
|
||||||
substitutions(substitutions), consumer(consumer)
|
substitutions(substitutions), consumer(consumer)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
estring parse()
|
estring parse()
|
||||||
{
|
{
|
||||||
consumer.advance(2);
|
auto next = consumer.consume();
|
||||||
auto str = statement();
|
if (next.type == template_token_t::IDENT && consumer.next().type == template_token_t::CURLY_OPEN)
|
||||||
if (!str)
|
{
|
||||||
|
consumer.advance();
|
||||||
|
auto str = statement();
|
||||||
|
consumer.advance();
|
||||||
return str;
|
return str;
|
||||||
// should never occur
|
}
|
||||||
if (consumer.hasNext() && consumer.next().type != template_token_t::CURLY_CLOSE)
|
return blt::unexpected(template_parser_failure_t::MISSING_IDENT_BRACES);
|
||||||
return blt::unexpected(template_parser_failure_t::NO_MATCHING_CURLY);
|
|
||||||
consumer.advance();
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
estring statement()
|
estring statement()
|
||||||
{
|
{
|
||||||
|
auto next = consumer.consume();
|
||||||
|
if (next.type == template_token_t::STRING || next.type == template_token_t::QUOTE)
|
||||||
|
{
|
||||||
|
consumer.back();
|
||||||
|
return string();
|
||||||
|
} 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 function()
|
||||||
|
{
|
||||||
|
auto str = consumer.consume();
|
||||||
|
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 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::PAR_CLOSE)
|
||||||
|
return blt::unexpected(template_parser_failure_t::IF_EXPECTED_PAREN);
|
||||||
|
auto true_statement = statement();
|
||||||
|
estring false_statement = blt::unexpected(template_parser_failure_t::UNKNOWN_ERROR);
|
||||||
|
if (consumer.next().type == template_token_t::ELSE)
|
||||||
|
{
|
||||||
|
consumer.advance();
|
||||||
|
false_statement = statement();
|
||||||
|
}
|
||||||
|
if (bool_eval.value())
|
||||||
|
{
|
||||||
|
return true_statement;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (false_statement)
|
||||||
|
return false_statement;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
estring string()
|
||||||
|
{
|
||||||
|
auto next = consumer.consume();
|
||||||
|
if (next.type == template_token_t::STRING)
|
||||||
|
{
|
||||||
|
if (!substitutions.contains(next.token))
|
||||||
|
return blt::unexpected(template_parser_failure_t::SUBSTITUTION_NOT_FOUND);
|
||||||
|
if (consumer.next().type == template_token_t::SEMI)
|
||||||
|
{
|
||||||
|
consumer.advance();
|
||||||
|
return substitutions[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 substitutions[next.token] + str.value();
|
||||||
|
else
|
||||||
|
return str;
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return bool_expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
ebool bool_expression()
|
||||||
|
{
|
||||||
|
auto next = consumer.next();
|
||||||
|
if (next.type == template_token_t::PAR_OPEN)
|
||||||
|
return bool_statement();
|
||||||
|
consumer.advance();
|
||||||
|
if (next.type == template_token_t::NOT)
|
||||||
|
{
|
||||||
|
auto b = bool_statement();
|
||||||
|
if (b)
|
||||||
|
return !b.value();
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
} else if (next.type == template_token_t::STRING)
|
||||||
|
{
|
||||||
|
auto bool_val = next.token.empty();
|
||||||
|
next = consumer.next();
|
||||||
|
if (next.type == template_token_t::PAR_CLOSE)
|
||||||
|
return bool_val;
|
||||||
|
consumer.advance();
|
||||||
|
if (next.type == template_token_t::AND)
|
||||||
|
{
|
||||||
|
auto other_val = bool_expression();
|
||||||
|
if (!other_val)
|
||||||
|
return other_val;
|
||||||
|
return bool_val && other_val.value();
|
||||||
|
} else if (next.type == template_token_t::OR)
|
||||||
|
{
|
||||||
|
auto other_val = bool_expression();
|
||||||
|
if (!other_val)
|
||||||
|
return other_val;
|
||||||
|
return bool_val || other_val.value();
|
||||||
|
} else if (next.type == template_token_t::XOR)
|
||||||
|
{
|
||||||
|
auto other_val = bool_expression();
|
||||||
|
if (!other_val)
|
||||||
|
return other_val;
|
||||||
|
return bool_val ^ other_val.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unexpected(template_parser_failure_t::UNKNOWN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::hashmap_t<std::string, std::string>& substitutions;
|
blt::hashmap_t<std::string, std::string>& substitutions;
|
||||||
|
|
|
@ -142,6 +142,7 @@ namespace blt
|
||||||
expected& operator=(const expected& copy)
|
expected& operator=(const expected& copy)
|
||||||
{
|
{
|
||||||
v = copy.v;
|
v = copy.v;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr expected(expected&& move) noexcept: v(std::move(move.v))
|
constexpr expected(expected&& move) noexcept: v(std::move(move.v))
|
||||||
|
@ -150,6 +151,7 @@ namespace blt
|
||||||
expected& operator=(expected&& move)
|
expected& operator=(expected&& move)
|
||||||
{
|
{
|
||||||
std::swap(v, move.v);
|
std::swap(v, move.v);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5
|
Subproject commit 10368163ab1f4367d2f0685b5928b1c973ebd1ec
|
|
@ -40,6 +40,7 @@ namespace blt
|
||||||
case ',':
|
case ',':
|
||||||
case '.':
|
case '.':
|
||||||
case '|':
|
case '|':
|
||||||
|
case '+':
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -123,6 +124,9 @@ namespace blt
|
||||||
case ',':
|
case ',':
|
||||||
tokens.emplace_back(template_token_t::COMMA, level, consumer.from(current_start, current_start + 1));
|
tokens.emplace_back(template_token_t::COMMA, level, consumer.from(current_start, current_start + 1));
|
||||||
break;
|
break;
|
||||||
|
case '+':
|
||||||
|
tokens.emplace_back(template_token_t::ADD, level, consumer.from(current_start, current_start + 1));
|
||||||
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
tokens.emplace_back(template_token_t::PERIOD, level, consumer.from(current_start, current_start + 1));
|
tokens.emplace_back(template_token_t::PERIOD, level, consumer.from(current_start, current_start + 1));
|
||||||
break;
|
break;
|
||||||
|
@ -207,18 +211,25 @@ namespace blt
|
||||||
|
|
||||||
while (consumer.hasNext())
|
while (consumer.hasNext())
|
||||||
{
|
{
|
||||||
|
BLT_TRACE("Running with next %d", static_cast<int>(consumer.next().type));
|
||||||
while (consumer.hasNext(2))
|
while (consumer.hasNext(2))
|
||||||
{
|
{
|
||||||
if (consumer.next().type == template_token_t::IDENT && consumer.next().type == template_token_t::CURLY_OPEN)
|
if (consumer.next().type == template_token_t::IDENT && consumer.next(1).type == template_token_t::CURLY_OPEN)
|
||||||
{
|
{
|
||||||
|
BLT_TRACE("From Last: %s", std::string(consumer.from_last(str)).c_str());
|
||||||
return_str += consumer.from_last(str);
|
return_str += consumer.from_last(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
consumer.advance();
|
||||||
}
|
}
|
||||||
if (auto result = parser.parse())
|
if (auto result = parser.parse())
|
||||||
return_str += result.value();
|
return_str += result.value();
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (result.error() == template_parser_failure_t::FUNCTION_DISCARD)
|
||||||
|
continue;
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_str;
|
return return_str;
|
||||||
|
|
Loading…
Reference in New Issue