103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
#include "expr.hh"
|
|
#include "../tokenizer.hh"
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include <sstream>
|
|
|
|
// Copy constructor
|
|
Expr::Expr(const Expr &other) : type{other.type} {
|
|
switch(type) {
|
|
case ExprType::BINARY: {
|
|
std::shared_ptr<Binary> ptr = std::get<std::shared_ptr<Binary>>(other.value);
|
|
value = std::make_shared<Binary>(*ptr);
|
|
break;
|
|
}
|
|
case ExprType::GROUPING: {
|
|
std::shared_ptr<Grouping> ptr = std::get<std::shared_ptr<Grouping>>(other.value);
|
|
value = std::make_shared<Grouping>(*ptr);
|
|
break;
|
|
}
|
|
case ExprType::LITERAL: {
|
|
std::shared_ptr<Literal> ptr = std::get<std::shared_ptr<Literal>>(other.value);
|
|
value = std::make_shared<Literal>(*ptr);
|
|
break;
|
|
}
|
|
case ExprType::UNARY: {
|
|
std::shared_ptr<Unary> ptr = std::get<std::shared_ptr<Unary>>(other.value);
|
|
value = std::make_shared<Unary>(*ptr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Move constructor
|
|
Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} {}
|
|
|
|
// Binary expressoin
|
|
Expr::Expr(const Expr &left, Token op, const Expr &right)
|
|
: type{ExprType::BINARY}, value{std::make_shared<Binary>(left, op, right)} {}
|
|
|
|
// Literal expression
|
|
Expr::Expr(Object value)
|
|
: type{ExprType::LITERAL}, value{std::make_shared<Literal>(value)} {}
|
|
|
|
// Unary expressoin
|
|
Expr::Expr(Token op, const Expr &right)
|
|
: type{ExprType::UNARY}, value{std::make_shared<Unary>(op, right)} {}
|
|
|
|
// Group expression
|
|
// Has to take an extra parameter to avoid conflicting with copy constructor
|
|
Expr::Expr(const Expr &expr, void *ptr)
|
|
: type{ExprType::GROUPING}, value{std::make_shared<Grouping>(expr)} { (void)ptr; }
|
|
|
|
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::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();
|
|
}
|