#include "expr.hh" #include "../tokenizer.hh" #include #include #include #include #include #include Expr::Expr(const Expr &other) : type{other.type} { switch(type) { case ExprType::BINARY: { std::shared_ptr ptr = std::get>(other.value); value = std::make_shared(*ptr); break; } case ExprType::GROUPING: { std::shared_ptr ptr = std::get>(other.value); value = std::make_shared(*ptr); break; } case ExprType::LITERAL: { std::shared_ptr ptr = std::get>(other.value); value = std::make_shared(*ptr); break; } case ExprType::UNARY: { std::shared_ptr ptr = std::get>(other.value); value = std::make_shared(*ptr); break; } } } // Move constructor Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} {} // Binary expressoin Expr::Expr(Expr left, Token op, Expr right) : type{ExprType::BINARY}, value{std::make_shared(left, op, right)} {} // Literal expression Expr::Expr(Object value) : type{ExprType::LITERAL}, value{std::make_shared(value)} {} // Unary expressoin Expr::Expr(Token op, Expr right) : type{ExprType::UNARY}, value{std::make_shared(op, right)} {} // Group expression // Has to take an extra parameter to avoid conflicting with copy constructor Expr::Expr(Expr expr, void *ptr) : type{ExprType::GROUPING}, value{std::make_shared(expr)} { (void)ptr; } std::string AstPrinter::print(const Expr &expr) { switch (expr.type) { case ExprType::BINARY: { std::shared_ptr binary = std::get>(expr.value); assert(binary != nullptr); return parenthesize(binary->op.lexeme, {binary->left, binary->right}); } case ExprType::GROUPING: { std::shared_ptr group = std::get>(expr.value); assert(group != nullptr); return parenthesize("group", {group->expr}); } case ExprType::LITERAL: { std::shared_ptr literal = std::get>(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(literal->value.value); return value; } case ObjectType::NUMBER: { double value = std::get(literal->value.value); return std::to_string(value); } } } case ExprType::UNARY: { std::shared_ptr unary = std::get>(expr.value); assert(unary != nullptr); return parenthesize(unary->op.lexeme, {unary->right}); } } } std::string AstPrinter::parenthesize(const std::string &name, std::vector exprs) { std::stringstream ss{}; ss << '(' << name; for (auto &expr : exprs) { ss << ' ' << print(expr); } ss << ')'; return ss.str(); }