#pragma once #include #include typedef std::vector dot; enum class binop { plus, minus, times, divide, land, lor, eq, neq, lt, lte, gt, gte }; enum class unop { lnot }; struct expr { virtual ~expr() = default; virtual void print_dot(dot& into, std::string prefix) = 0; }; typedef expr* expr_ptr; struct expr_id : expr { std::string id; expr_id(std::string i) : id(std::move(i)) {} virtual void print_dot(dot& into, std::string prefix); }; struct expr_int : expr { int val; expr_int(int i) : val(i) {} virtual void print_dot(dot& into, std::string prefix); }; struct expr_float : expr { double val; expr_float(double f) : val(f) {} virtual void print_dot(dot& into, std::string prefix); }; struct expr_binop : expr { binop op; expr_ptr left; expr_ptr right; expr_binop(binop nop, expr_ptr l, expr_ptr r) : op(nop), left(std::move(l)), right(std::move(r)) {} virtual void print_dot(dot& into, std::string prefix); }; struct expr_unop : expr { unop op; expr_ptr child; expr_unop(unop nop, expr_ptr c) : op(nop), child(std::move(c)) {} virtual void print_dot(dot& into, std::string prefix); }; struct expr_assign : expr { std::string var; expr_ptr child; expr_assign(std::string v, expr_ptr c) : var(std::move(v)), child(std::move(c)) {} virtual void print_dot(dot& into, std::string prefix); }; template expr_ptr make_expr(Ts&& ... ts) { return expr_ptr(new T(std::move(ts)...)); } struct stmt { virtual ~stmt() = default; virtual void print_dot(dot& into, std::string prefix) = 0; }; typedef stmt* stmt_ptr; struct stmt_block : stmt { std::vector children; virtual void print_dot(dot& into, std::string prefix); }; struct stmt_if : stmt { expr_ptr cond; stmt_ptr then; stmt_ptr els; stmt_if(expr_ptr c, stmt_ptr t, stmt_ptr e = nullptr) : cond(std::move(c)), then(std::move(t)), els(std::move(e)) {} virtual void print_dot(dot& into, std::string prefix); }; struct stmt_while : stmt { expr_ptr cond; stmt_ptr body; stmt_while(expr_ptr c, stmt_ptr b) : cond(std::move(c)), body(std::move(b)) {} virtual void print_dot(dot& into, std::string prefix); }; struct stmt_break : stmt { virtual void print_dot(dot& into, std::string prefix); }; struct stmt_expr : stmt { expr_ptr child; stmt_expr(expr_ptr c) : child(std::move(c)) {} virtual void print_dot(dot& into, std::string prefix); }; template stmt_ptr make_stmt(Ts&& ... ts) { return stmt_ptr(new T(std::move(ts)...)); }