Created
January 31, 2025 18:42
-
-
Save DrkWithT/735c73ed6a042e18840ce945b5b87f82 to your computer and use it in GitHub Desktop.
A compile time postfix expression evaluator demo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <array> | |
#include <string_view> | |
#include <utility> | |
#include <print> | |
// This was compiled and ran on Compiler Explorer: | |
// Compiler flags: -std=c++26 -Og | |
// Note: The call operator for the evaluator did not get generated at all, and the expected result of 42 was embedded in a single MOV. | |
static constexpr auto temp_limit = 10; | |
static constexpr std::string_view source = "6 4 9 * +"; | |
template <std::size_t StackLimit> | |
class CompEval { | |
private: | |
constexpr auto isSpace(char c) { | |
return c == ' ' or c == '\t' or c == '\n'; | |
}; | |
constexpr auto isDigit(char c) { | |
return c >= '0' and c <= '9'; | |
} | |
constexpr auto isOp(char c) { | |
return c == '+' or c == '-' or c == '*'; | |
} | |
constexpr auto toNum(char c) { | |
return static_cast<int>(c - '0'); | |
} | |
public: | |
constexpr CompEval() noexcept {} | |
constexpr std::pair<int, bool> operator()(std::string_view expr) { | |
std::array<int, StackLimit> stk; | |
std::fill(stk.begin(), stk.begin() + StackLimit, 0); | |
auto top = -1; | |
auto fn_push = [&](int val) { | |
top++; | |
stk[top] = val; | |
}; | |
auto fn_pop = [&]() { | |
return stk[top--]; | |
}; | |
for (const auto symbol : expr) { | |
if (isSpace(symbol)) { | |
continue; | |
} | |
if (isDigit(symbol)) { | |
fn_push(toNum(symbol)); | |
} else if (isOp(symbol)) { | |
if (symbol == '+') { | |
auto a0 = fn_pop(); | |
auto a1 = fn_pop(); | |
fn_push(a0 + a1); | |
} else if (symbol == '-') { | |
auto a0 = fn_pop(); | |
auto a1 = fn_pop(); | |
fn_push(a1 - a0); | |
} else if (symbol == '*') { | |
auto a0 = fn_pop(); | |
auto a1 = fn_pop(); | |
fn_push(a0 * a1); | |
} else { | |
return {-1, false}; // TODO: support division later? | |
} | |
} else { | |
return {-1, false}; | |
} | |
} | |
return {stk[0], true}; | |
} | |
}; | |
int main() { | |
auto ans = CompEval<10>{}(source); | |
auto [ans_val, ok] = ans; | |
std::print("Ans: {}\n", ans_val); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment