#ifndef EXPR_HH #define EXPR_HH #include "../tokenizer.hh" #include #include #include #define BinaryExpr(LEFT, OP, RIGHT) ( \ Expr{ \ .type = ExprType::BINARY, \ .value = Binary{.left = LEFT, .op = OP, .right = RIGHT} \ } \ ) #define GroupingExpr(EXPR) ( \ Expr{ \ .type = ExprType::GROUPING, \ .value = Grouping{.expression = EXPR} \ } \ ) #define LiteralExpr(VALUE) ( \ Expr{ \ .type = ExprType::LITERAL, \ .value = Literal{.value = VALUE} \ } \ ) #define UnaryExpr(OP, RIGHT) ( \ Expr{ \ .type = ExprType::UNARY, \ .value = Unary{.op = OP, .right = RIGHT} \ } \ ) #define BinaryExprPtr(LEFT, OP, RIGHT) (std::make_shared(BinaryExpr(LEFT, OP, RIGHT))) #define GroupingExprPtr(EXPR) (std::make_shared(GroupingExpr(EXPR))) #define LiteralExprPtr(VALUE) (std::make_shared(LiteralExpr(VALUE))) #define UnaryExprPtr(OP, RIGHT) (std::make_shared(UnaryExpr(OP, RIGHT))) 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; }; enum class ExprType { BINARY, GROUPING, LITERAL, UNARY, }; using Expression = std::variant; struct Expr { ExprType type; Expression value; }; class AstPrinter { public: std::string print(const Expr &expr); private: std::string parenthesize(const std::string &name, std::vector exprs); }; #endif