52 lines
1.5 KiB
C++
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();
|
|
}
|