#ifndef EXPR_HH #define EXPR_HH #include "../tokenizer.hh" #include #include struct Expr; struct _Binary; struct _Grouping; struct _Literal; struct _Unary; enum class ExprType { BINARY, GROUPING, LITERAL, UNARY, }; using ExprVariant = std::variant< 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); // Copy assignment Expr &operator=(const Expr &other); // 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} {} 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; }; #endif