Skip to content

Instantly share code, notes, and snippets.

@DrkWithT
Created January 31, 2025 18:42
Show Gist options
  • Save DrkWithT/735c73ed6a042e18840ce945b5b87f82 to your computer and use it in GitHub Desktop.
Save DrkWithT/735c73ed6a042e18840ce945b5b87f82 to your computer and use it in GitHub Desktop.
A compile time postfix expression evaluator demo.
#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