diff --git a/cclox_src/main.cc b/cclox_src/main.cc index cd6aa5e..c993924 100644 --- a/cclox_src/main.cc +++ b/cclox_src/main.cc @@ -18,15 +18,13 @@ int main(int argc, char *argv[]) { // run_interpreter(argc, argv); Token unary_op{TokenType::MINUS, "-", Object{}, 1}; - Expr left_literal = Literal(123); - Expr left = Unary(unary_op, left_literal.to_expr_ptr()); + Expr left{unary_op, Expr{123}}; Token op{TokenType::STAR, "*", Object{}, 1}; - Expr right_literal = Literal(45.67); - Expr right = Grouping(right_literal.to_expr_ptr()); + Expr right{Expr{45.67}, nullptr}; - Expr expr = Binary(left.to_expr_ptr(), op, right.to_expr_ptr()); + Expr expr{left, op, right}; AstPrinter printer{}; std::cout << printer.print(expr) << '\n'; diff --git a/cclox_src/parser/expr.cc b/cclox_src/parser/expr.cc index 35c5348..79c0e88 100644 --- a/cclox_src/parser/expr.cc +++ b/cclox_src/parser/expr.cc @@ -1,42 +1,90 @@ #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: { - _Binary node = std::get<_Binary>(expr.value); - assert(node.left != NULL && node.right != NULL); - return parenthesize(node.op.lexeme, {*node.left, *node.right}); + std::shared_ptr binary = std::get>(expr.value); + assert(binary != nullptr); + return parenthesize(binary->op.lexeme, {binary->left, binary->right}); } case ExprType::GROUPING: { - _Grouping node = std::get<_Grouping>(expr.value); - assert(node.expression != NULL); - return parenthesize("group", {*node.expression}); + std::shared_ptr group = std::get>(expr.value); + assert(group != nullptr); + return parenthesize("group", {group->expr}); } case ExprType::LITERAL: { - _Literal node = std::get<_Literal>(expr.value); - switch (node.value.type) { + 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(node.value.value); + std::string value = std::get(literal->value.value); return value; } case ObjectType::NUMBER: { - double value = std::get(node.value.value); + double value = std::get(literal->value.value); return std::to_string(value); } } } case ExprType::UNARY: { - _Unary node = std::get<_Unary>(expr.value); - assert(node.right != NULL); - return parenthesize(node.op.lexeme, {*node.right}); + std::shared_ptr unary = std::get>(expr.value); + assert(unary != nullptr); + return parenthesize(unary->op.lexeme, {unary->right}); } } } diff --git a/cclox_src/parser/expr.hh b/cclox_src/parser/expr.hh index 144bfb7..cc6ac9d 100644 --- a/cclox_src/parser/expr.hh +++ b/cclox_src/parser/expr.hh @@ -7,27 +7,10 @@ #include struct Expr; - -using ExprPtr = std::shared_ptr; - -struct _Binary { - ExprPtr left; - Token op; - ExprPtr right; -}; - -struct _Grouping { - ExprPtr expression; -}; - -struct _Literal { - Object value; -}; - -struct _Unary { - Token op; - ExprPtr right; -}; +struct Binary; +struct Grouping; +struct Literal; +struct Unary; enum class ExprType { BINARY, @@ -36,30 +19,59 @@ enum class ExprType { UNARY, }; -using ExprVariant = std::variant<_Binary, _Grouping, _Literal, _Unary>; +using ExprVariant = std::variant< + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr +>; struct Expr { + // Copy constructor + Expr(const Expr &other); + + // Move constructor + Expr(const Expr &&other); + + // Binary expressoin + Expr(Expr left, Token op, Expr right); + + // Literal expression + Expr(Object value); + + // Unary expressoin + Expr(Token op, Expr right); + + // Group expression + // Has to take an extra parameter to avoid conflicting with copy constructor + Expr(Expr expr, void *ptr); + ExprType type; ExprVariant value; - - ExprPtr to_expr_ptr() { return std::make_shared(*this); } }; -inline Expr Binary(ExprPtr left, Token op, ExprPtr right) { - return Expr{ExprType::BINARY, _Binary{left, op, right}}; -} +struct Binary { + Binary(Expr left, Token op, Expr right) : left{left}, op{op}, right{right} {} + Expr left; + Token op; + Expr right; +}; -inline Expr Grouping(ExprPtr expr) { - return Expr{ExprType::GROUPING, _Grouping{expr}}; -} +struct Grouping { + Grouping(Expr expr) : expr{expr} {} + Expr expr; +}; -inline Expr Literal(Object value) { - return Expr{ExprType::LITERAL, _Literal{value}}; -} +struct Literal { + Literal(Object value) : value{value} {} + Object value; +}; -inline Expr Unary(Token op, ExprPtr right) { - return Expr{ExprType::UNARY, _Unary{op, right}}; -} +struct Unary { + Unary(Token op, Expr right) : op{op}, right{right} {} + Token op; + Expr right; +}; class AstPrinter { public: