#ifndef EXPR_HH #define EXPR_HH #include "../tokenizer.hh" #include #include struct Expr; struct _Binary; struct _Grouping; struct _Literal; struct _Unary; struct _Variable; struct _Assign; enum class ExprType { BINARY, GROUPING, LITERAL, UNARY, VARIABLE, ASSIGN, }; using ExprVariant = std::variant< std::shared_ptr<_Binary>, std::shared_ptr<_Grouping>, std::shared_ptr<_Literal>, std::shared_ptr<_Unary>, std::shared_ptr<_Variable>, std::shared_ptr<_Assign> >; #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)}) #define Variable(NAME) (Expr{ExprType::VARIABLE, std::make_shared<_Variable>(NAME)}) #define Assign(NAME, VALUE) (Expr{ExprType::ASSIGN, std::make_shared<_Assign>(NAME, VALUE)}) struct Expr { Expr(ExprType type, ExprVariant value); // Copy constructor Expr(const Expr &other); // Move constructor Expr(Expr &&other) noexcept; // Copy assignment Expr &operator=(const Expr &other); // Move assignment Expr &operator=(Expr &&other) noexcept; ~Expr() = default; ExprType type; ExprVariant value; }; 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} {} Expr expr; }; struct _Literal { _Literal(Object value) : value{value} {} Object value; }; struct _Unary { _Unary(Token op, const Expr &right) : op{op}, right{right} {} Token op; Expr right; }; struct _Variable { _Variable(Token name) : name{name} {} Token name; }; struct _Assign { _Assign(Token name, const Expr &value) : name{name}, value{value} {} Token name; Expr value; }; #endif