-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMetaEvaluator.mpp
More file actions
68 lines (60 loc) · 2.5 KB
/
MetaEvaluator.mpp
File metadata and controls
68 lines (60 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
export module CppUtils.Language.MetaEvaluator;
import std;
import CppUtils.String;
import CppUtils.Language.AST;
export namespace CppUtils::Language
{
struct MetaEvaluator
{
using Cursor = String::Cursor<std::string_view>;
[[nodiscard]] inline constexpr auto exists(Type::Token instruction) const noexcept -> bool
{
const auto range = scopes | std::views::reverse;
auto it = std::ranges::find_if(range, [instruction](const auto scope) -> bool { return scope.get().exists(instruction); });
return it != std::ranges::end(range);
}
[[nodiscard]] inline constexpr auto operator()(
Cursor& cursor,
const ASTNode& instruction = ASTNode{Type::hash("main")})
-> std::expected<void, std::string_view>
{
using namespace String::Literals;
if (instruction.value == "call"_token)
{
if (std::empty(instruction.nodes)) [[unlikely]]
return std::unexpected{R"(Missing argument in the "call" instruction)"};
if (auto it = functions.find(instruction.nodes.front().value); it != std::cend(functions))
return it->second(cursor, instruction.nodes.front(), *this);
else [[unlikely]]
return std::unexpected{"Unknown function"};
}
auto grammar = [this, instruction]() -> std::reference_wrapper<ASTNode> {
const auto range = scopes | std::views::reverse;
auto it = std::ranges::find_if(range, [instruction](const auto scope) -> bool { return scope.get().exists(instruction.value); });
return it != std::ranges::end(range) ? *it : scopes.front();
}();
if (not grammar.get().exists(instruction.value)) [[unlikely]]
return std::unexpected{"Unknown lexeme"};
auto lexemes = std::ref(grammar.get()[instruction.value].nodes);
for (auto instructionPosition = 0uz; not exit and instructionPosition < std::size(lexemes.get()); ++instructionPosition)
{
const auto& lexeme = lexemes.get()[instructionPosition];
if (auto result = operator()(cursor, lexeme); not result) [[unlikely]]
return result;
if (not grammar.get().exists(instruction.value)) [[unlikely]]
return {};
lexemes = std::ref(grammar.get()[instruction.value].nodes);
}
exit = false;
return {};
}
[[nodiscard]] inline auto getScope() -> ASTNode&
{
return scopes.back().get();
}
std::unordered_map<Type::Token, std::function<std::expected<void, std::string_view>(Cursor&, const ASTNode&, MetaEvaluator&)>> functions;
ASTNode rootAst = {0uz, {ASTNode{Type::hash("main")}}};
std::vector<std::reference_wrapper<ASTNode>> scopes = {std::ref(rootAst)};
bool exit = false;
};
}