58 lines
1.8 KiB
C++
58 lines
1.8 KiB
C++
#include "printer.hh"
|
|
#include "expr.hh"
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
std::string AstPrinter::print(const Expr &expr) {
|
|
switch (expr.type) {
|
|
case ExprType::BINARY: {
|
|
std::shared_ptr<_Binary> binary = std::get<std::shared_ptr<_Binary>>(expr.value);
|
|
assert(binary != nullptr);
|
|
return parenthesize(binary->op.lexeme, {&binary->left, &binary->right});
|
|
}
|
|
case ExprType::GROUPING: {
|
|
std::shared_ptr<_Grouping> group = std::get<std::shared_ptr<_Grouping>>(expr.value);
|
|
assert(group != nullptr);
|
|
return parenthesize("group", {&group->expr});
|
|
}
|
|
case ExprType::LITERAL: {
|
|
std::shared_ptr<_Literal> literal = std::get<std::shared_ptr<_Literal>>(expr.value);
|
|
assert(literal != nullptr);
|
|
switch (literal->value.type) {
|
|
case ObjectType::NIL:
|
|
return "nil";
|
|
case ObjectType::BOOL: {
|
|
bool value = std::get<bool>(literal->value.value);
|
|
return (value ? "true" : "false");
|
|
}
|
|
case ObjectType::IDENTIFIER:
|
|
case ObjectType::STRING_LIT: {
|
|
std::string value = std::get<std::string>(literal->value.value);
|
|
return value;
|
|
}
|
|
case ObjectType::NUMBER: {
|
|
double value = std::get<double>(literal->value.value);
|
|
return std::to_string(value);
|
|
}
|
|
}
|
|
}
|
|
case ExprType::UNARY: {
|
|
std::shared_ptr<_Unary> unary = std::get<std::shared_ptr<_Unary>>(expr.value);
|
|
assert(unary != nullptr);
|
|
return parenthesize(unary->op.lexeme, {&unary->right});
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string AstPrinter::parenthesize(const std::string &name, std::vector<const Expr *> exprs) {
|
|
std::stringstream ss{};
|
|
ss << '(' << name;
|
|
for (const Expr *expr : exprs) {
|
|
ss << ' ' << print(*expr);
|
|
}
|
|
ss << ')';
|
|
|
|
return ss.str();
|
|
}
|