diff --git a/cclox_src/main.cc b/cclox_src/main.cc index c993924..58fd9ce 100644 --- a/cclox_src/main.cc +++ b/cclox_src/main.cc @@ -18,13 +18,13 @@ int main(int argc, char *argv[]) { // run_interpreter(argc, argv); Token unary_op{TokenType::MINUS, "-", Object{}, 1}; - Expr left{unary_op, Expr{123}}; + Expr left{Unary(unary_op, Literal(123))}; Token op{TokenType::STAR, "*", Object{}, 1}; - Expr right{Expr{45.67}, nullptr}; + Expr right{Grouping(Literal(45.67))}; - Expr expr{left, op, right}; + Expr expr{Binary(left, op, right)}; AstPrinter printer{}; std::cout << printer.print(expr) << '\n'; diff --git a/cclox_src/parser.cc b/cclox_src/parser.cc index 51b13f6..17db8d5 100644 --- a/cclox_src/parser.cc +++ b/cclox_src/parser.cc @@ -2,5 +2,6 @@ #define PARSER_CC #include "parser/expr.cc" +#include "parser/printer.cc" #endif diff --git a/cclox_src/parser.hh b/cclox_src/parser.hh index bba6ee1..167b802 100644 --- a/cclox_src/parser.hh +++ b/cclox_src/parser.hh @@ -2,5 +2,6 @@ #define PARSER_HH #include "parser/expr.hh" +#include "parser/printer.hh" #endif diff --git a/cclox_src/parser/expr.cc b/cclox_src/parser/expr.cc index b961da3..f7a6482 100644 --- a/cclox_src/parser/expr.cc +++ b/cclox_src/parser/expr.cc @@ -2,101 +2,176 @@ #include "../tokenizer.hh" #include #include -#include #include -#include -#include + +Expr::Expr(ExprType type, ExprVariant value) : type{type}, value{value} {} // Copy constructor 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); + std::shared_ptr<_Binary> ptr = std::get>(other.value); + value = std::make_shared<_Binary>(*ptr); break; } case ExprType::GROUPING: { - std::shared_ptr ptr = std::get>(other.value); - value = std::make_shared(*ptr); + std::shared_ptr<_Grouping> ptr = std::get>(other.value); + value = std::make_shared<_Grouping>(*ptr); break; } case ExprType::LITERAL: { - std::shared_ptr ptr = std::get>(other.value); - value = std::make_shared(*ptr); + std::shared_ptr<_Literal> ptr = std::get>(other.value); + value = std::make_shared<_Literal>(*ptr); break; } case ExprType::UNARY: { - std::shared_ptr ptr = std::get>(other.value); - value = std::make_shared(*ptr); + std::shared_ptr<_Unary> ptr = std::get>(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(left, op, right)} {} - -// Literal expression -Expr::Expr(Object value) - : type{ExprType::LITERAL}, value{std::make_shared(value)} {} - -// Unary expressoin -Expr::Expr(Token op, const 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(const Expr &expr, void *ptr) - : type{ExprType::GROUPING}, value{std::make_shared(expr)} { (void)ptr; } - -std::string AstPrinter::print(const Expr &expr) { - switch (expr.type) { +Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} { + switch(type) { case ExprType::BINARY: { - std::shared_ptr binary = std::get>(expr.value); - assert(binary != nullptr); - return parenthesize(binary->op.lexeme, {&binary->left, &binary->right}); + std::shared_ptr<_Binary> ptr = std::get>(other.value); + ptr.reset(); + break; } case ExprType::GROUPING: { - std::shared_ptr group = std::get>(expr.value); - assert(group != nullptr); - return parenthesize("group", {&group->expr}); + std::shared_ptr<_Grouping> ptr = std::get>(other.value); + ptr.reset(); + break; } 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); - } - } + std::shared_ptr<_Literal> ptr = std::get>(other.value); + ptr.reset(); + break; } case ExprType::UNARY: { - std::shared_ptr unary = std::get>(expr.value); - assert(unary != nullptr); - return parenthesize(unary->op.lexeme, {&unary->right}); + std::shared_ptr<_Unary> ptr = std::get>(other.value); + ptr.reset(); + break; } } } -std::string AstPrinter::parenthesize(const std::string &name, std::vector exprs) { - std::stringstream ss{}; - ss << '(' << name; - for (const Expr *expr : exprs) { - ss << ' ' << print(*expr); +// Copy assignment +Expr &Expr::operator=(const Expr &other) { + if (this == &other) { + return *this; } - ss << ')'; - return ss.str(); + switch(type) { + case ExprType::BINARY: { + std::shared_ptr<_Binary> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::GROUPING: { + std::shared_ptr<_Grouping> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::LITERAL: { + std::shared_ptr<_Literal> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::UNARY: { + std::shared_ptr<_Unary> ptr = std::get>(value); + ptr.reset(); + break; + } + } + + type = other.type; + + switch(type) { + case ExprType::BINARY: { + std::shared_ptr<_Binary> ptr = std::get>(other.value); + value = std::make_shared<_Binary>(*ptr); + break; + } + case ExprType::GROUPING: { + std::shared_ptr<_Grouping> ptr = std::get>(other.value); + value = std::make_shared<_Grouping>(*ptr); + break; + } + case ExprType::LITERAL: { + std::shared_ptr<_Literal> ptr = std::get>(other.value); + value = std::make_shared<_Literal>(*ptr); + break; + } + case ExprType::UNARY: { + std::shared_ptr<_Unary> ptr = std::get>(other.value); + value = std::make_shared<_Unary>(*ptr); + break; + } + } + + return *this; +} + +// Move assignment +Expr &Expr::operator=(const Expr &&other) { + if (this == &other) { + return *this; + } + + switch(type) { + case ExprType::BINARY: { + std::shared_ptr<_Binary> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::GROUPING: { + std::shared_ptr<_Grouping> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::LITERAL: { + std::shared_ptr<_Literal> ptr = std::get>(value); + ptr.reset(); + break; + } + case ExprType::UNARY: { + std::shared_ptr<_Unary> ptr = std::get>(value); + ptr.reset(); + break; + } + } + + type = other.type; + + switch(type) { + case ExprType::BINARY: { + std::shared_ptr<_Binary> optr = std::get>(other.value); + value = std::move(other.value); + optr.reset(); + break; + } + case ExprType::GROUPING: { + std::shared_ptr<_Grouping> optr = std::get>(other.value); + value = std::move(other.value); + optr.reset(); + break; + } + case ExprType::LITERAL: { + std::shared_ptr<_Literal> optr = std::get>(other.value); + value = std::move(other.value); + optr.reset(); + break; + } + case ExprType::UNARY: { + std::shared_ptr<_Unary> optr = std::get>(other.value); + value = std::move(other.value); + optr.reset(); + break; + } + } + + return *this; } diff --git a/cclox_src/parser/expr.hh b/cclox_src/parser/expr.hh index 869eaac..4c393ce 100644 --- a/cclox_src/parser/expr.hh +++ b/cclox_src/parser/expr.hh @@ -3,14 +3,13 @@ #include "../tokenizer.hh" #include -#include #include struct Expr; -struct Binary; -struct Grouping; -struct Literal; -struct Unary; +struct _Binary; +struct _Grouping; +struct _Literal; +struct _Unary; enum class ExprType { BINARY, @@ -20,64 +19,57 @@ enum class ExprType { }; using ExprVariant = std::variant< - std::shared_ptr, - std::shared_ptr, - std::shared_ptr, - std::shared_ptr + std::shared_ptr<_Binary>, + std::shared_ptr<_Grouping>, + std::shared_ptr<_Literal>, + std::shared_ptr<_Unary> >; +#define Binary(LEFT, OP, RIGHT) (Expr{ExprType::BINARY, std::make_shared<_Binary>(LEFT, OP, RIGHT)}) +#define Grouping(EXPR) (Expr{ExprType::GROUPING, std::make_shared<_Grouping>(EXPR)}) +#define Literal(VALUE) (Expr{ExprType::LITERAL, std::make_shared<_Literal>(VALUE)}) +#define Unary(OP, RIGHT) (Expr{ExprType::UNARY, std::make_shared<_Unary>(OP, RIGHT)}) + struct Expr { + Expr(ExprType type, ExprVariant value); + // Copy constructor Expr(const Expr &other); // Move constructor Expr(const Expr &&other); - // Binary expressoin - Expr(const Expr &left, Token op, const Expr &right); + // Copy assignment + Expr &operator=(const Expr &other); - // Literal expression - Expr(Object value); - - // Unary expressoin - Expr(Token op, const Expr &right); - - // Group expression - // Has to take an extra parameter to avoid conflicting with copy constructor - Expr(const Expr &expr, void *ptr); + // Move assignment + Expr &operator=(const Expr &&other); ExprType type; ExprVariant value; }; -struct Binary { - Binary(const Expr &left, Token op, const Expr &right) : left{left}, op{op}, right{right} {} +struct _Binary { + _Binary(const Expr &left, Token op, const Expr &right) : left{left}, op{op}, right{right} {} Expr left; Token op; Expr right; }; -struct Grouping { - Grouping(const Expr &expr) : expr{expr} {} +struct _Grouping { + _Grouping(const Expr &expr) : expr{expr} {} Expr expr; }; -struct Literal { - Literal(Object value) : value{value} {} +struct _Literal { + _Literal(Object value) : value{value} {} Object value; }; -struct Unary { - Unary(Token op, const Expr &right) : op{op}, right{right} {} +struct _Unary { + _Unary(Token op, const Expr &right) : op{op}, right{right} {} Token op; Expr right; }; -class AstPrinter { -public: - std::string print(const Expr &expr); -private: - std::string parenthesize(const std::string &name, std::vector exprs); -}; - #endif diff --git a/cclox_src/parser/printer.cc b/cclox_src/parser/printer.cc new file mode 100644 index 0000000..a885e93 --- /dev/null +++ b/cclox_src/parser/printer.cc @@ -0,0 +1,53 @@ +#include "printer.hh" +#include "expr.hh" +#include +#include +#include + +std::string AstPrinter::print(const Expr &expr) { + switch (expr.type) { + case ExprType::BINARY: { + std::shared_ptr<_Binary> binary = std::get>(expr.value); + assert(binary != nullptr); + return parenthesize(binary->op.lexeme, {&binary->left, &binary->right}); + } + case ExprType::GROUPING: { + std::shared_ptr<_Grouping> group = std::get>(expr.value); + assert(group != nullptr); + return parenthesize("group", {&group->expr}); + } + case ExprType::LITERAL: { + std::shared_ptr<_Literal> 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> 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 (const Expr *expr : exprs) { + ss << ' ' << print(*expr); + } + ss << ')'; + + return ss.str(); +} diff --git a/cclox_src/parser/printer.hh b/cclox_src/parser/printer.hh new file mode 100644 index 0000000..fecd3e2 --- /dev/null +++ b/cclox_src/parser/printer.hh @@ -0,0 +1,14 @@ +#ifndef PRINTER_HH +#define PRINTER_HH + +#include "expr.hh" +#include + +class AstPrinter { +public: + std::string print(const Expr &expr); +private: + std::string parenthesize(const std::string &name, std::vector exprs); +}; + +#endif