52 lines
1.5 KiB
C++

#include "expr.hh"
#include "../tokenizer.hh"
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
#include <sstream>
std::string AstPrinter::print(const Expression &expr) {
return std::visit([this](auto &&node) -> std::string {
using T = std::decay_t<decltype(node)>;
if constexpr(std::is_same_v<T, Binary>) {
return parenthesize(node.op.lexeme, {node.left, node.right});
} else if constexpr(std::is_same_v<T, Grouping>) {
return parenthesize("group", {node.expression});
} else if constexpr(std::is_same_v<T, Literal>) {
switch (node.value.type) {
case ObjectType::NIL:
return "nil";
case ObjectType::IDENTIFIER:
case ObjectType::STRING_LIT: {
std::string value = std::get<std::string>(node.value.value);
return value;
}
case ObjectType::NUMBER: {
double value = std::get<double>(node.value.value);
return std::to_string(value);
}
}
} else if constexpr(std::is_same_v<T, Unary>) {
return parenthesize(node.op.lexeme, {node.right});
}
return "";
}, expr);
}
std::string AstPrinter::parenthesize(const std::string &name, std::vector<Expression> exprs) {
std::stringstream ss{};
ss << '(' << name;
for (auto &expr : exprs) {
std::string value = std::visit([this](auto &&node) -> std::string {
return print(node);
}, expr);
ss << ' ' << value;
}
ss << ')';
return ss.str();
}