From 93dbf3989dfd3016e2613c747ce71f5c849f6c45 Mon Sep 17 00:00:00 2001 From: Amanuel Bogale Date: Tue, 9 Jul 2024 11:03:46 -0700 Subject: [PATCH] refactor pt.2... at stmt/block --- include/ast/decl.hh | 52 ++++++------ include/ast/expr.hh | 96 ++++++++++++++-------- include/ast/grmr.hh | 34 -------- include/ast/parser.hh | 51 ++++++------ include/ast/printer.hh | 37 ++++++--- include/ast/resolver.hh | 47 +++++------ include/ast/stmt.hh | 99 +++++++++++----------- lib/ast/parser.cc | 176 +++++++++++++++++++++------------------- lib/ast/printer.cc | 103 +++++++++++++++++++---- lib/ast/resolver.cc | 38 +++++---- 10 files changed, 418 insertions(+), 315 deletions(-) diff --git a/include/ast/decl.hh b/include/ast/decl.hh index 409d0b2..cc73a06 100644 --- a/include/ast/decl.hh +++ b/include/ast/decl.hh @@ -22,48 +22,55 @@ namespace rift { namespace ast { - class Decl: public Accept + __DEFAULT_FORWARD_VA( + DeclStmt, + DeclVar, + DeclFunc + ); + + /// @class Visitor + /// @brief Visitor pattern for expressions + template + class DeclVisitor + { + virtual T visit_decl_stmt(const DeclStmt& decl) const; + virtual T visit_decl_var(const DeclVar& decl) const; + virtual T visit_decl_func(const DeclFunc& decl) const; + }; + + /// @class Decl + /// @brief Declarations acceptor + template + class Decl: public Accept { public: - virtual Tokens accept(const Visitor &visitor) const = 0; + virtual T accept(const Visitor &visitor) const = 0; virtual ~Decl() = default; - friend class Visitor; - friend class DeclStmt; - friend class DeclVar; }; + template class DeclStmt: public Decl { public: DeclStmt(std::unique_ptr stmt) : stmt(std::move(stmt)) {}; - Tokens accept(const Visitor &visitor) const override { return visitor.visit_decl_stmt(*this); } - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_decl_stmt(*this); } std::unique_ptr stmt; }; + template class DeclVar: public Decl { public: DeclVar(const Token &identifier): identifier(identifier), expr(nullptr) {}; DeclVar(const Token &identifier, std::unique_ptr expr): identifier(identifier), expr(std::move(expr)) {}; - Tokens accept(const Visitor &visitor) const override { return visitor.visit_decl_var(*this); } - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_decl_var(*this); } const Token& identifier; std::unique_ptr expr; }; + template class DeclFunc : public Decl { public: @@ -80,12 +87,7 @@ namespace rift std::unique_ptr func; - Tokens accept(const Visitor &visitor) const override { return visitor.visit_decl_func(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_decl_func(*this); }; }; } } \ No newline at end of file diff --git a/include/ast/expr.hh b/include/ast/expr.hh index b2731fa..32c2077 100644 --- a/include/ast/expr.hh +++ b/include/ast/expr.hh @@ -29,16 +29,50 @@ namespace rift { namespace ast { - /// @note forward declrations - __DEFAULT_FORWARD_NONE_VA( + + __DEFAULT_FORWARD_VA( + Assign, Binary, Grouping, Literal, Unary ); + __DEFAULT_FORWARD_VA( + Call, + Ternary, + VarExpr + ) + + /// @class Visitor + /// @brief Visitor pattern for expressions + template + class ExprVisitor + { + public: + /// @example x = 1 + 2; + virtual T visit_assign(const Assign& expr) const; + /// @example 1 + 2 + virtual T visit_binary(const Binary& expr) const; + /// @example (1 + 2) + virtual T visit_grouping(const Grouping& expr) const; + /// @example 1 + virtual T visit_literal(const Literal& expr) const; + /// @example x + virtual T visit_var_expr(const VarExpr& expr) const; + /// @example -1 + virtual T visit_unary(const Unary& expr) const; + /// @example (true) ? 1 : 2 + virtual T visit_ternary(const Ternary& expr) const; + /// @example x = foo(1, 2) + virtual T visit_call(const Call& expr) const; + }; + /// @class Expr + /// @tparam T: /// @brief Base class for all expressions + /// Acceptor in the visitor pattern usefull for accepting Expr/Stmt/Decl + /// to be evaluated via the visitor /// @details Types of expression include /// - Binary: An expression with two operands and an operator /// - Example: 1 + 2 @@ -48,59 +82,51 @@ namespace rift /// - Example: 1 /// - Unary: An expression with a single operator and a single operand /// - Example: -1 - class Expr : public Accept + template + class Expr { public: - virtual Token accept(const Visitor& visitor) const override = 0; - virtual string accept_printer(const Visitor& visitor) const override = 0; + virtual T accept(const ExprVisitor& visitor) const = 0; virtual ~Expr() = default; }; + #pragma mark - Concrete Expressions - using Exprs = std::unordered_map>; + template class Call : public Expr { public: + using Exprs = std::unordered_map>>; Call(Token name, Exprs&& args): name(name), args(std::move(args)) {}; Token name; // expr -> Literal::Identifier Exprs args; - inline Token accept(const Visitor& visitor) const override { return visitor.visit_call(*this); } - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - inline string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + inline T accept(const ExprVisitor& visitor) const override { return visitor.visit_call(*this); } }; + template class Ternary : public Expr { public: - Ternary(std::unique_ptr condition, std::unique_ptr left, std::unique_ptr right): condition(std::move(condition)), left(std::move(left)), right(std::move(right)) {}; + Ternary(std::unique_ptr> condition, std::unique_ptr> left, std::unique_ptr> right): condition(std::move(condition)), left(std::move(left)), right(std::move(right)) {}; std::unique_ptr condition; std::unique_ptr left; std::unique_ptr right; - inline Token accept(const Visitor& visitor) const override { return visitor.visit_ternary(*this); } - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - inline string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + inline T accept(const ExprVisitor& visitor) const override { return visitor.visit_ternary(*this); } }; + template class Assign : public Expr { public: - Assign(Token name, std::unique_ptr value): name(name), value(std::move(value)) {}; + Assign(Token name, std::unique_ptr> value): name(name), value(std::move(value)) {}; Token name; std::unique_ptr value; - inline Token accept(const Visitor& visitor) const override { return visitor.visit_assign(*this); } - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - inline string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + inline T accept(const ExprVisitor& visitor) const override { return visitor.visit_assign(*this); } }; /// @class Binary @@ -108,66 +134,66 @@ namespace rift /// @param op The operator /// @param right The right operand // template + template class Binary : public Expr { public: - Binary(std::unique_ptr left, Token op, std::unique_ptr right): op(op), left(std::move(left)), right(std::move(right)) {}; + Binary(std::unique_ptr> left, Token op, std::unique_ptr> right): op(op), left(std::move(left)), right(std::move(right)) {}; Token op; std::unique_ptr left; std::unique_ptr right; - inline Token accept(const Visitor& visitor) const override { return visitor.visit_binary(*this); } - inline string accept_printer(const Visitor& visitor) const override { return visitor.print_binary(*this); } + inline T accept(const ExprVisitor& visitor) const override { return visitor.visit_binary(*this); } }; /// @class Grouping /// @param expr The subexpression + template class Grouping : public Expr { public: Grouping(std::unique_ptr expr): expr(std::move(expr)) {}; std::unique_ptr expr; - inline Token accept(const Visitor& visitor) const override {return visitor.visit_grouping(*this);} - inline string accept_printer(const Visitor& visitor) const override {return visitor.print_grouping(*this);} + inline T accept(const ExprVisitor& visitor) const override {return visitor.visit_grouping(*this);} }; /// @class Unary /// @param op The operator /// @param expr The operand + template class Unary : public Expr { public: - Unary(Token op, std::unique_ptr expr): op(op), expr(std::move(expr)) {}; + Unary(Token op, std::unique_ptr> expr): op(op), expr(std::move(expr)) {}; Token op; std::unique_ptr expr; - inline Token accept(const Visitor& visitor) const override {return visitor.visit_unary(*this);} - inline string accept_printer(const Visitor& visitor) const override {return visitor.print_unary(*this);} + inline T accept(const ExprVisitor& visitor) const override {return visitor.visit_unary(*this);} }; /// @class VarExpr /// @param value The value of the variable + template class VarExpr: public Expr { public: VarExpr(Token value): value(value) {}; Token value; - inline Token accept(const Visitor &visitor) const override {return visitor.visit_var_expr(*this);} - inline string accept_printer(const Visitor& visitor) const override {return visitor.print_var_expr(*this);} + inline T accept(const ExprVisitor &visitor) const override {return visitor.visit_var_expr(*this);} }; /// @class Literal /// @param value The value of the literal + template class Literal: public Expr { public: Literal(Token value): value(value) {}; Token value; - inline Token accept(const Visitor &visitor) const override {return visitor.visit_literal(*this);} - inline string accept_printer(const Visitor& visitor) const override {return visitor.print_literal(*this);} + inline T accept(const ExprVisitor &visitor) const override {return visitor.visit_literal(*this);} }; } }; \ No newline at end of file diff --git a/include/ast/grmr.hh b/include/ast/grmr.hh index 81eb181..e9b383c 100644 --- a/include/ast/grmr.hh +++ b/include/ast/grmr.hh @@ -126,49 +126,15 @@ namespace rift { public: /* Evaluator */ - /* expr */ - virtual Token visit_assign(const Assign& expr) const; - virtual Token visit_binary(const Binary& expr) const; - virtual Token visit_grouping(const Grouping& expr) const; - virtual Token visit_literal(const Literal& expr) const; - virtual Token visit_var_expr(const VarExpr& expr) const; - virtual Token visit_unary(const Unary& expr) const; - virtual Token visit_ternary(const Ternary& expr) const; - virtual Token visit_call(const Call& expr) const; /* stmt */ /// @note TokenType::IGNORE is used to ignore statements returning void - virtual Token visit_expr_stmt(const StmtExpr& stmt) const; - virtual Token visit_print_stmt(const StmtPrint& stmt) const; - virtual Token visit_if_stmt(const StmtIf& stmt) const; - virtual Token visit_return_stmt(const StmtReturn& stmt) const; - virtual Token visit_block_stmt(const Block& block) const; - virtual Token visit_for_stmt(const For& decl) const; /* decl */ - virtual Tokens visit_decl_stmt(const DeclStmt& decl) const; - virtual Tokens visit_decl_var(const DeclVar& decl) const; - virtual Tokens visit_decl_func(const DeclFunc& decl) const; /* prgm */ virtual Tokens visit_program(const Program& prgm) const; - - /* Printer */ - /* expr */ - virtual string print_binary(const Binary& expr) const; - virtual string print_grouping(const Grouping& expr) const; - virtual string print_unary(const Unary& expr) const; - virtual string print_literal(const Literal& expr) const; - virtual string print_var_expr(const VarExpr& expr) const; - - /* stmt */ - // virtual void print_expr_stmt(const StmtExpr& expr) const; - // virtual void print_print_stmt(const StmtPrint& expr) const; - // virtual void print_var_stmt(const StmtVar& expr) const; - - /* virtual void print_program(const Program& prgm) const; */ - /* Resolver */ /* expr */ virtual Token resolve_assign(const ResolverAssign& expr) const; diff --git a/include/ast/parser.hh b/include/ast/parser.hh index 492e323..7496bf4 100644 --- a/include/ast/parser.hh +++ b/include/ast/parser.hh @@ -54,40 +54,44 @@ namespace rift /// @note rules in order of precedence /// @example 1 + 2 * 3 - std::unique_ptr expression(); + std::unique_ptr> expression(); /// @example 1==1 ? print("hi") : print("else") - std::unique_ptr ternary(); + std::unique_ptr> ternary(); /// @example identifier = 1 + 3 - std::unique_ptr assignment(); + std::unique_ptr> assignment(); /// @example 1 == 1, 1 != 2 - std::unique_ptr equality(); + std::unique_ptr> equality(); /// @example 1 > 2, 1 <= 2 - std::unique_ptr comparison(); + std::unique_ptr> comparison(); /// @example 1 + 2, 1 - 2 - std::unique_ptr term(); + std::unique_ptr> term(); /// @example 1 * 2, 1 / 2 - std::unique_ptr factor(); + std::unique_ptr> factor(); /// @example -1, !1 - std::unique_ptr unary(); + std::unique_ptr> unary(); /// @example method(); - std::unique_ptr call(); + std::unique_ptr> call(); /// @example var test; - std::unique_ptr var_expr(); + std::unique_ptr> var_expr(); /// @example 1, "string", true, false, nil - std::unique_ptr primary(); + std::unique_ptr> primary(); /// @note rules in order of precedence /// @example function(); - std::unique_ptr statement_expression(); + std::unique_ptr> statement_expression(); /// @example print(1 + 2); - std::unique_ptr statement_print(); + std::unique_ptr> statement_print(); /// @example if (1+2) print(3); - std::unique_ptr statement_if(); + std::unique_ptr> statement_if(); /// @example return 1; - std::unique_ptr statement_return(); - + std::unique_ptr> statement_return(); + /// @example { var x = 1; } + std::unique_ptr> statement_block(); + /// @example while(true) print("hi"); + std::unique_ptr> statement_for(); + /// @note rules in order of precedence /// @example var x = 1; std::unique_ptr declaration_statement(); @@ -96,26 +100,23 @@ namespace rift /// @example func test() {} std::unique_ptr declaration_func(); - /// @example while(true) print("hi"); - std::unique_ptr for_(); + /// @brief returns any statements that might be executed + std::unique_ptr> ret_stmt(); + /// @brief returns any declarations that might be executed + vec_prog ret_decl(); + - /// @example { var x = 1; } - std::unique_ptr block(); /// @example func test() {} or member.method() std::unique_ptr function(); /// @example 1, 2, 3 Tokens params(); /// @example 1+1, "str", a - Exprs args(Tokens params); + Call::Exprs args(Tokens params); /// @note program std::unique_ptr program(); /// @brief Syncronizes the parser to avoid error-cascading void synchronize(); - /// @brief returns any statements that might be executed - std::unique_ptr ret_stmt(); - /// @brief returns any declarations that might be executed - vec_prog ret_decl(); }; class ParserException : public ReaderException diff --git a/include/ast/printer.hh b/include/ast/printer.hh index a1b43a0..9b6227d 100644 --- a/include/ast/printer.hh +++ b/include/ast/printer.hh @@ -16,8 +16,9 @@ #include #include -// #include #include +#include +#include /// not in use now /// need futher re-evaluation @@ -28,27 +29,46 @@ namespace rift { namespace ast { - using vec = std::vector; using string = std::string; // using ExprStr = rift::ast::Expr; // using VisitStr = rift::ast::Visitor; /// @class Printer /// @brief This class is used to print the expression. - class Printer + class Printer: public ExprVisitor, public StmtVisitor, public DeclVisitor { public: + using vec = std::vector*>; Printer(); ~Printer() = default; - friend class Visitor; /// Prints the given expression string. /// @param expr The expression to print. /// @return string representation of the expression. - string print(Expr *expr) const; + string print(Expr *expr) const; - std::unique_ptr visitor; - + // expressions + string visit_assign(const Assign& expr) const override; + string visit_binary(const Binary& expr) const override; + string visit_grouping(const Grouping& expr) const override; + string visit_literal(const Literal& expr) const override; + string visit_var_expr(const VarExpr& expr) const override; + string visit_unary(const Unary& expr) const override; + string visit_ternary(const Ternary& expr) const override; + string visit_call(const Call& expr) const override; + + // statements + string visit_expr_stmt(const StmtExpr& stmt) const override; + string visit_print_stmt(const StmtPrint& stmt) const override; + string visit_if_stmt(const StmtIf& stmt) const override; + string visit_return_stmt(const StmtReturn& stmt) const override; + string visit_block_stmt(const Block& block) const override; + string visit_for_stmt(const For& decl) const override; + + // declarations + string visit_decl_stmt(const DeclStmt& decl) const override; + string visit_decl_var(const DeclVar& decl) const override; + string visit_decl_func(const DeclFunc& decl) const override; protected: /// @brief Wraps the given expression in parentheses. @@ -62,8 +82,5 @@ namespace rift /// @return The wrapped expression. string group(vec expr) const; }; - - /// only one printer available (alleivate dependencies) - static Printer* printer = new Printer(); } } \ No newline at end of file diff --git a/include/ast/resolver.hh b/include/ast/resolver.hh index cc964d7..2fd8962 100644 --- a/include/ast/resolver.hh +++ b/include/ast/resolver.hh @@ -64,41 +64,53 @@ namespace rift class ResolverBinary: public Resolver { public: - ResolverBinary(Binary &expr) : expr(expr) {}; + ResolverBinary(std::unique_ptr left, std::unique_ptr right) : left(std::move(left)), right(std::move(right)) {}; + ~ResolverBinary() = default; - Binary &expr; + std::unique_ptr left; + std::unique_ptr right; Token accept(const Visitor &visitor) const override { return visitor.resolve_binary(*this); } - ~ResolverBinary() = default; }; class ResolverGrouping: public Resolver { public: - ResolverGrouping(Grouping &expr) : expr(expr) {}; + ResolverGrouping(std::unique_ptr expr) : expr(std::move(expr)) {}; + ~ResolverGrouping() = default; - Grouping &expr; + std::unique_ptr expr; Token accept(const Visitor &visitor) const override { return visitor.resolve_grouping(*this); } - ~ResolverGrouping() = default; + }; + + class ResolverLiteral: public Resolver + { + public: + ResolverLiteral() = default; + ~ResolverLiteral() = default; + + Token accept(const Visitor &visitor) const override { return visitor.resolve_literal(*this); } }; class ResolverUnary: public Resolver { public: - ResolverUnary(Unary &expr) : expr(expr) {}; + ResolverUnary(std::unique_ptr expr) : expr(std::move(expr)) {}; + ~ResolverUnary() = default; - Unary &expr; + std::unique_ptr expr; Token accept(const Visitor &visitor) const override { return visitor.resolve_unary(*this); } - ~ResolverUnary() = default; }; class ResolverTernary: public Resolver { public: - ResolverTernary(Ternary &expr) : expr(expr) {}; + ResolverTernary(std::unique_ptr condition, std::unique_ptr left, std::unique_ptr right) : condition(std::move(condition)), left(std::move(left)), right(std::move(right)) {}; + ~ResolverTernary() = default; - Ternary &expr; + std::unique_ptr condition; + std::unique_ptr left; + std::unique_ptr right; Token accept(const Visitor &visitor) const override { return visitor.resolve_ternary(*this); } - ~ResolverTernary() = default; }; class ResolverCall: public Resolver @@ -121,16 +133,6 @@ namespace rift ~ResolverVarExpr() = default; }; - class ResolverLiteral: public Resolver - { - public: - ResolverLiteral(Literal &expr) : expr(expr) {}; - - Literal &expr; - Token accept(const Visitor &visitor) const override { return visitor.resolve_literal(*this); } - ~ResolverLiteral() = default; - }; - // STATEMENTS class ResolverStmtExpr: public Resolver @@ -247,6 +249,5 @@ namespace rift string message; }; - } } \ No newline at end of file diff --git a/include/ast/stmt.hh b/include/ast/stmt.hh index db99656..b8abd3a 100644 --- a/include/ast/stmt.hh +++ b/include/ast/stmt.hh @@ -28,18 +28,42 @@ namespace rift // template // class StmtVisitor; - __DEFAULT_FORWARD_NONE_VA( + __DEFAULT_FORWARD_VA( StmtExpr, StmtPrint, - StmtVar + StmtIf, + StmtReturn, + Block, + For ); - + /// @class Visitor + /// @brief Visitor pattern for expressions + template + class StmtVisitor + { + public: + /// @example [start, end] = [end, start]; + virtual T visit_expr_stmt(const StmtExpr& stmt) const; + /// @example print(x); + virtual T visit_print_stmt(const StmtPrint& stmt) const; + /// @example if (cond) {stmt} + virtual T visit_if_stmt(const StmtIf& stmt) const; + /// @example return x; + virtual T visit_return_stmt(const StmtReturn& stmt) const; + /// @example { x = 3; } + virtual T visit_block_stmt(const Block& block) const; + /// @example for i in arr {} + virtual T visit_for_stmt(const For& decl) const; + }; + + /// @class Stmt + /// @tparam T + template class Stmt: public rift::ast::Accept { public: - virtual Token accept(const Visitor &visitor) const = 0; - virtual string accept_printer(const Visitor& visitor) const = 0; + virtual T accept(const Visitor &visitor) const = 0; virtual ~Stmt() = default; }; @@ -58,49 +82,41 @@ namespace rift /// function range2(start, end) { /// start > end && ([start, end] = [end, start]); /// } + template class StmtExpr: public Stmt { public: - StmtExpr(std::unique_ptr expr) : expr(std::move(expr)) {}; + StmtExpr(std::unique_ptr> expr) : expr(std::move(expr)) {}; ~StmtExpr() = default; - std::unique_ptr expr; + std::unique_ptr> expr; - Token accept(const Visitor &visitor) const override { return visitor.visit_expr_stmt(*this); }; - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_expr_stmt(*this); }; }; + template class StmtPrint : public Stmt { public: - StmtPrint(std::unique_ptr& expr) : expr(std::move(expr)) {}; + StmtPrint(std::unique_ptr>& expr) : expr(std::move(expr)) {}; ~StmtPrint() = default; - std::unique_ptr expr; + std::unique_ptr> expr; - Token accept(const Visitor &visitor) const override { return visitor.visit_print_stmt(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_print_stmt(*this); }; }; + template class StmtIf : public Stmt { public: struct Stmt { public: Stmt() : expr(nullptr), stmt(nullptr), blk(nullptr) {}; - Stmt(std::unique_ptr expr): expr(std::move(expr)), stmt(nullptr), blk(nullptr) {} - Stmt(std::unique_ptr expr, std::unique_ptr stmt): expr(std::move(expr)), stmt(std::move(stmt)) {} - Stmt(std::unique_ptr expr, std::unique_ptr blk): expr(std::move(expr)), blk(std::move(blk)) {} + Stmt(std::unique_ptr> expr): expr(std::move(expr)), stmt(nullptr), blk(nullptr) {} + Stmt(std::unique_ptr> expr, std::unique_ptr stmt): expr(std::move(expr)), stmt(std::move(stmt)) {} + Stmt(std::unique_ptr> expr, std::unique_ptr blk): expr(std::move(expr)), blk(std::move(blk)) {} - std::unique_ptr expr; + std::unique_ptr> expr; std::unique_ptr stmt; std::unique_ptr blk; }; @@ -115,14 +131,10 @@ namespace rift Stmt* else_stmt; std::vector elif_stmts; - Token accept(const Visitor &visitor) const override { return visitor.visit_if_stmt(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_if_stmt(*this); }; }; + template class StmtReturn : public Stmt { public: @@ -130,14 +142,10 @@ namespace rift ~StmtReturn() = default; std::unique_ptr expr; - Token accept(const Visitor &visitor) const override { return visitor.visit_return_stmt(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_return_stmt(*this); }; }; + template class Block : public Stmt { public: @@ -145,14 +153,10 @@ namespace rift ~Block() = default; vec_prog decls = nullptr; - Token accept(const Visitor &visitor) const override { return visitor.visit_block_stmt(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_block_stmt(*this); }; }; + template class For : public Stmt { public: @@ -167,12 +171,7 @@ namespace rift std::unique_ptr blk; std::unique_ptr stmt_o; - Token accept(const Visitor &visitor) const override { return visitor.visit_for_stmt(*this); }; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunused-parameter" - // must uncomment visit_printer in printer.hh - string accept_printer(const Visitor& visitor) const override { return "unimplemented"; } - #pragma clang diagnostic pop + T accept(const Visitor &visitor) const override { return visitor.visit_for_stmt(*this); }; }; } } \ No newline at end of file diff --git a/lib/ast/parser.cc b/lib/ast/parser.cc index e8f17bf..4fc5f76 100644 --- a/lib/ast/parser.cc +++ b/lib/ast/parser.cc @@ -40,35 +40,54 @@ namespace rift } } + //////////////////////////////////////////////////////////////////////// #pragma mark - Expressions Parsing + //////////////////////////////////////////////////////////////////////// - std::unique_ptr Parser::primary() + std::unique_ptr> Parser::primary() { if (match({Token(TokenType::FALSE, "false", "", line)})) - return std::unique_ptr(new Literal(Token(TokenType::FALSE, "false", "", line))); + return std::unique_ptr>(new Literal(Token(TokenType::FALSE, "false", "", line))); if (match({Token(TokenType::TRUE, "true", "", line)})) - return std::unique_ptr(new Literal(Token(TokenType::TRUE, "true", "", line))); + return std::unique_ptr>(new Literal(Token(TokenType::TRUE, "true", "", line))); if (match({Token(TokenType::NIL, "nil", "", line)})) - return std::unique_ptr(new Literal(Token(TokenType::NIL, "nil", "", line))); + return std::unique_ptr>(new Literal(Token(TokenType::NIL, "nil", "", line))); if (match({Token(TokenType::NUMERICLITERAL, "", "", line)})) - return std::unique_ptr(new Literal(peekPrev(1))); + return std::unique_ptr>(new Literal(peekPrev(1))); if (match({Token(TokenType::STRINGLITERAL, "", "", line)})) - return std::unique_ptr(new Literal(Token(peekPrev(1)))); + return std::unique_ptr>(new Literal(Token(peekPrev(1)))); return nullptr; } - std::unique_ptr Parser::var_expr() + std::unique_ptr> Parser::var_expr() { if (match({Token(TokenType::IDENTIFIER, "", "", line)})) - return std::unique_ptr(new VarExpr(Token(peekPrev(1)))); + return std::unique_ptr>(new VarExpr(Token(peekPrev(1)))); if (match({Token(TokenType::C_IDENTIFIER, "", "", line)})) - return std::unique_ptr(new VarExpr(Token(peekPrev(1)))); + return std::unique_ptr>(new VarExpr(Token(peekPrev(1)))); else return primary(); } - std::unique_ptr Parser::call() + Call::Exprs Parser::args(Tokens params) + { + Call::Exprs exprs = {}; + int idx = 0; + while(peek().type != TokenType::RIGHT_PAREN) { + auto exp = expression(); + if (idx >= params.size()) + rift::error::report(line, "args", "Too many arguments", peek(), ParserException("Too many arguments")); + if (exp == nullptr) + rift::error::report(line, "args", "Expected expression", peek(), ParserException("Expected expression")); + + exprs.insert({params[idx].lexeme, std::move(exp)}); + idx++; + } + return exprs; + } + + std::unique_ptr> Parser::call() { auto expr = primary(); @@ -89,32 +108,32 @@ namespace rift // another dillema, how do i handle return 3; // do I handle it here or in the return stmt, I choose later // consume(Token(TokenType::SEMICOLON)); - return std::unique_ptr(new Call(idt, std::move(arg))); + return std::unique_ptr>(new Call(idt, std::move(arg))); } return expr; } - std::unique_ptr Parser::unary() + std::unique_ptr> Parser::unary() { if (match({Token(TokenType::BANG, "!", "", line)})) { auto op = peekPrev(); auto right = unary(); if (right == nullptr) rift::error::report(line, "unary", "Expected expression after unary operator", op, ParserException("Expected expression after unary operator")); - return std::unique_ptr(new Unary(op, std::move(right))); + return std::unique_ptr>(new Unary(op, std::move(right))); } if (match({Token(TokenType::MINUS, "-", "", line)})) { auto op = peekPrev(); auto right = unary(); if (right == nullptr) rift::error::report(line, "unary", "Expected expression after unary operator", op, ParserException("Expected expression after unary operator")); - return std::unique_ptr(new Unary(op, std::move(right))); + return std::unique_ptr>(new Unary(op, std::move(right))); } return call(); } - std::unique_ptr Parser::factor() + std::unique_ptr> Parser::factor() { auto expr = unary(); @@ -123,13 +142,13 @@ namespace rift auto right = unary(); if (expr == nullptr) rift::error::report(line, "factor", "Expected number before factor operator", op, ParserException("Expected number before factor operator")); if (right == nullptr) rift::error::report(line, "factor", "Expected number after factor operator", op, ParserException("Expected number after factor operator")); - expr = std::unique_ptr(new Binary(std::move(expr), op, std::move(right))); + expr = std::unique_ptr>(new Binary(std::move(expr), op, std::move(right))); } return expr; } - std::unique_ptr Parser::term() + std::unique_ptr> Parser::term() { auto expr = factor(); @@ -138,13 +157,13 @@ namespace rift auto right = factor(); if (expr == nullptr) rift::error::report(line, "term", "Expected number before term operator", op, ParserException("Expected number before term operator")); if (right == nullptr) rift::error::report(line, "term", "Expected number after term operator", op, ParserException("Expected number after term operator")); - expr = std::unique_ptr(new Binary(std::move(expr), op, std::move(right))); + expr = std::unique_ptr>(new Binary(std::move(expr), op, std::move(right))); } return expr; } - std::unique_ptr Parser::comparison() + std::unique_ptr> Parser::comparison() { auto expr = term(); @@ -153,13 +172,13 @@ namespace rift auto right = term(); if (expr == nullptr) rift::error::report(line, "comparison", "Expected expression before comparison operator", op, ParserException("Expected expression before comparison operator")); if (right == nullptr) rift::error::report(line, "comparison", "Expected expression after comparison operator", op, ParserException("Expected expression after comparison operator")); - expr = std::unique_ptr(new Binary(std::move(expr), op, std::move(right))); + expr = std::unique_ptr>(new Binary(std::move(expr), op, std::move(right))); } return expr; } - std::unique_ptr Parser::equality() + std::unique_ptr> Parser::equality() { auto expr = comparison(); @@ -169,13 +188,13 @@ namespace rift auto right = comparison(); if (expr == nullptr) rift::error::report(line, "equality", "Expected expression before equality operator", op, ParserException("Expected expression before equality operator")); if (right == nullptr) rift::error::report(line, "equality", "Expected expression after equality operator", op, ParserException("Expected expression after equality operator")); - expr = std::unique_ptr(new Binary(std::move(expr), op, std::move(right))); + expr = std::unique_ptr>(new Binary(std::move(expr), op, std::move(right))); } return expr; }; - std::unique_ptr Parser::ternary() + std::unique_ptr> Parser::ternary() { auto expr = equality(); @@ -183,13 +202,13 @@ namespace rift auto left = equality(); consume(Token(TokenType::COLON, ":", "", line), std::unique_ptr(new ParserException("Expected a colon while expecting a ternary operator"))); auto right = equality(); - return std::unique_ptr(new Ternary(std::move(expr),std::move(left),std::move(right))); + return std::unique_ptr>(new Ternary(std::move(expr),std::move(left),std::move(right))); } return expr; } - std::unique_ptr Parser::assignment() + std::unique_ptr> Parser::assignment() { if(match({Token(TokenType::EQUAL)})) { auto idt = peekPrev(2); @@ -197,23 +216,25 @@ namespace rift if (expr == nullptr) rift::error::report(line, "assignment", "Expected expression after assignment operator", peekPrev(), ParserException("Expected expression after assignment operator")); - return std::unique_ptr(new Assign(idt, std::move(expr))); + return std::unique_ptr>(new Assign(idt, std::move(expr))); } return ternary(); } - std::unique_ptr Parser::expression() + std::unique_ptr> Parser::expression() { auto ret = assignment(); return ret; } + //////////////////////////////////////////////////////////////////////// #pragma mark - Statements Parsing + //////////////////////////////////////////////////////////////////////// - std::unique_ptr Parser::ret_stmt() + std::unique_ptr> Parser::ret_stmt() { - std::unique_ptr stmt; + std::unique_ptr> stmt; if (consume (Token(TokenType::PRINT, "", "", line))) { stmt = statement_print(); } else if (consume(Token(TokenType::IF, "if", "if", line))) { @@ -221,45 +242,46 @@ namespace rift } else if (consume(Token(TokenType::RETURN))) { stmt = statement_return(); } else if (consume (Token(TokenType::FOR, "", "", line))) { - stmt = for_(); + stmt = statement_for(); } else if(match({Token(TokenType::LEFT_BRACE, "{", "", line)})) { - stmt = block(); + stmt = statement_block(); } else { stmt = statement_expression(); } return stmt; } - std::unique_ptr Parser::statement_expression() + std::unique_ptr> Parser::statement_expression() { auto expr = expression(); - return std::unique_ptr(new StmtExpr(std::move(expr))); + return std::unique_ptr>(new StmtExpr(std::move(expr))); } - std::unique_ptr Parser::statement_print() + std::unique_ptr> Parser::statement_print() { consume(Token(TokenType::LEFT_PAREN, "(", "", line), std::unique_ptr(new ParserException("Expected '(' after print"))); auto expr = expression(); consume(Token(TokenType::RIGHT_PAREN, ")", "", line), std::unique_ptr(new ParserException("Expected ')' after print"))); consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr(new ParserException("Expected ';' after print statement"))); - return std::unique_ptr(new StmtPrint(expr)); + return std::unique_ptr>(new StmtPrint(expr)); } - std::unique_ptr Parser::statement_if() + std::unique_ptr> Parser::statement_if() { - std::unique_ptr ret = std::make_unique(); + std::unique_ptr> ret = std::make_unique>(); consume(Token(TokenType::LEFT_PAREN, "(", "", line), std::unique_ptr(new ParserException("Expected '(' after if"))); auto expr = expression(); consume(Token(TokenType::RIGHT_PAREN, ")", "", line), std::unique_ptr(new ParserException("Expected ')' after if"))); /// if stmt - StmtIf::Stmt* if_stmt= new StmtIf::Stmt(std::move(expr)); + StmtIf::Stmt* if_stmt= new StmtIf::Stmt(std::move(expr)); // block vs stmt if (peek() == Token(TokenType::LEFT_BRACE, "{", "", line)) { consume(Token(TokenType::LEFT_BRACE, "{", "", line), std::unique_ptr(new ParserException("Expected '{' after if block"))); - auto blk = block(); - if_stmt->blk = std::move(blk); + auto blk = statement_block(); + // if_stmt->blk = std::move(blk); + if_stmt->blk = static_cast>>(std::move(blk)); } else { auto stmt = ret_stmt(); if_stmt->stmt = std::move(stmt); @@ -268,15 +290,15 @@ namespace rift /// elif stmts if (peek() == Token(TokenType::ELIF, "elif", "elif", line)) { - std::vector elif_stmts = {}; + std::vector::Stmt*> elif_stmts = {}; while (consume(Token(TokenType::ELIF, "elif", "elif", line))) { auto expr = expression(); - StmtIf::Stmt* curr = new StmtIf::Stmt(std::move(expr)); + StmtIf::Stmt* curr = new StmtIf::Stmt(std::move(expr)); // block vs stmt if (peek() == Token(TokenType::LEFT_BRACE, "{", "", line)) { consume(Token(TokenType::LEFT_BRACE, "{", "", line), std::unique_ptr(new ParserException("Expected '{' after elif block"))); - auto blk = block(); + auto blk = statement_block(); curr->blk = std::move(blk); } else { std::unique_ptr stmt = ret_stmt(); @@ -290,14 +312,14 @@ namespace rift /// else stmt if (consume(Token(TokenType::ELSE, "else", "else", line))) { - StmtIf::Stmt* else_stmt = new StmtIf::Stmt(); + StmtIf::Stmt* else_stmt = new StmtIf::Stmt(); // block vs stmt if (peek() == Token(TokenType::LEFT_BRACE, "{", "", line)) { consume(Token(TokenType::LEFT_BRACE, "{", "", line), std::unique_ptr(new ParserException("Expected '{' after else block"))); auto blk = block(); else_stmt->blk = std::move(blk); } else { - std::unique_ptr stmt = ret_stmt(); + std::unique_ptr> stmt = ret_stmt(); else_stmt->stmt = std::move(stmt); } ret->else_stmt = else_stmt; @@ -306,7 +328,7 @@ namespace rift return ret; } - std::unique_ptr Parser::block() + std::unique_ptr Parser::statement_block() { vec_prog decls = std::make_unique>>(); @@ -330,7 +352,9 @@ namespace rift return std::unique_ptr(new StmtReturn(std::move(expr))); } + //////////////////////////////////////////////////////////////////////// #pragma mark - Declarations Parsing + //////////////////////////////////////////////////////////////////////// std::unique_ptr Parser::declaration_statement() { @@ -386,7 +410,7 @@ namespace rift return std::unique_ptr(new DeclVar(Token(tok_t, idt.lexeme, idt.literal, idt.line))); } - std::unique_ptr Parser::for_() + std::unique_ptr Parser::statement_for() { std::unique_ptr _for = std::make_unique(); consume(Token(TokenType::LEFT_PAREN, "(", "", line), std::unique_ptr(new ParserException("Expected '(' after for"))); @@ -431,7 +455,9 @@ namespace rift return _func; } + //////////////////////////////////////////////////////////////////////// #pragma mark - Program / Block Parsing + //////////////////////////////////////////////////////////////////////// vec_prog Parser::ret_decl() { @@ -454,7 +480,26 @@ namespace rift return decls; } - #pragma mark - Functions / Methods + //////////////////////////////////////////////////////////////////////// + #pragma mark - Application + //////////////////////////////////////////////////////////////////////// + + std::unique_ptr Parser::program() + { + vec_prog decls = std::make_unique>>(); + + while (!atEnd()) { + auto inner = ret_decl(); + decls->insert(decls->end(), std::make_move_iterator(inner->begin()), std::make_move_iterator(inner->end())); + } + + // Environment::getInstance(true).clear(true); + return std::unique_ptr(new Program(std::move(decls))); + } + + //////////////////////////////////////////////////////////////////////// + # pragma mark - Utilities + //////////////////////////////////////////////////////////////////////// std::unique_ptr Parser::function() { @@ -492,41 +537,6 @@ namespace rift return toks; } - Exprs Parser::args(Tokens params) - { - Exprs exprs = {}; - int idx = 0; - while(peek().type != TokenType::RIGHT_PAREN) { - auto exp = expression(); - if (idx >= params.size()) - rift::error::report(line, "args", "Too many arguments", peek(), ParserException("Too many arguments")); - if (exp == nullptr) - rift::error::report(line, "args", "Expected expression", peek(), ParserException("Expected expression")); - - exprs.insert({params[idx].lexeme, std::move(exp)}); - idx++; - } - return exprs; - } - - - #pragma mark - Application - - std::unique_ptr Parser::program() - { - vec_prog decls = std::make_unique>>(); - - while (!atEnd()) { - auto inner = ret_decl(); - decls->insert(decls->end(), std::make_move_iterator(inner->begin()), std::make_move_iterator(inner->end())); - } - - // Environment::getInstance(true).clear(true); - return std::unique_ptr(new Program(std::move(decls))); - } - - # pragma mark - Utilities - void Parser::synchronize() { advance(); diff --git a/lib/ast/printer.cc b/lib/ast/printer.cc index 36fe866..1c1634b 100644 --- a/lib/ast/printer.cc +++ b/lib/ast/printer.cc @@ -21,24 +21,26 @@ namespace rift { namespace ast { + + /// only one printer available (alleivate dependencies) + static Printer* printer = new Printer(); + #pragma mark - Printer Printer::Printer() { - // this->visitor = std::unique_ptr(new Visitor()); - this->visitor = std::make_unique(); } - string Printer::print(Expr *expr) const + string Printer::print(Expr *expr) const { - return expr->accept_printer(*this->visitor); + return expr->accept(*this); } string Printer::parenthesize(string name, vec expr) const { string result = "(" + name; for (auto &e : expr) - result += " " + e->accept_printer(*this->visitor); + result += " " + e->accept(*this); result += ")"; return result; } @@ -47,43 +49,45 @@ namespace rift { string result = "["; for (auto &e : expr) - result += " " + e->accept_printer(*this->visitor); + result += " " + e->accept(*this); result += "]"; return result; } - #pragma mark - Visitor + //////////////////////////////////////////////////////////////////////// + #pragma mark - Expressions + //////////////////////////////////////////////////////////////////////// - string Visitor::print_binary(const Binary& expr) const + string Printer::visit_binary(const Binary& expr) const { - vec v; + Printer::vec v; v.push_back(expr.left.get()); v.push_back(expr.right.get()); - return printer->parenthesize(expr.op.lexeme, v); + return parenthesize(expr.op.lexeme, v); } - string Visitor::print_unary(const Unary& expr) const + string Printer::visit_unary(const Unary& expr) const { - vec v; + Printer::vec v; v.push_back(expr.expr.get()); return printer->parenthesize(expr.op.lexeme, v); } - string Visitor::print_grouping(const Grouping& expr) const + string Printer::visit_grouping(const Grouping& expr) const { - vec v; + Printer::vec v; v.push_back(expr.expr.get()); return printer->group(v); } - string Visitor::print_var_expr(const VarExpr& expr) const + string Printer::visit_var_expr(const VarExpr& expr) const { Token val = expr.value; std::any literal = val.getLiteral(); return ""; } - string Visitor::print_literal(const Literal& expr) const + string Printer::visit_literal(const Literal& expr) const { Token val = expr.value; std::any literal = val.getLiteral(); @@ -104,6 +108,73 @@ namespace rift return ""; } + + string Printer::visit_ternary(const Ternary& expr) const + { + Printer::vec v; + v.push_back(expr.condition.get()); + v.push_back(expr.left.get()); + v.push_back(expr.right.get()); + return parenthesize("?:", v); + } + + string Printer::visit_call(const Call& expr) const + { + return ""; + } + + //////////////////////////////////////////////////////////////////////// + #pragma mark - Statements + //////////////////////////////////////////////////////////////////////// + + string Printer::visit_expr_stmt(const StmtExpr& stmt) const + { + return parenthesize("expr_stmt", {stmt.expr.get()}); + } + + string Printer::visit_print_stmt(const StmtPrint& stmt) const + { + return parenthesize("print", {stmt.expr.get()}); + } + + string Printer::visit_if_stmt(const StmtIf& stmt) const + { + return ""; + } + + string Printer::visit_return_stmt(const StmtReturn& stmt) const + { + return ""; + } + + string Printer::visit_block_stmt(const Block& block) const + { + return ""; + } + + string Printer::visit_for_stmt(const For& decl) const + { + return ""; + } + + //////////////////////////////////////////////////////////////////////// + #pragma mark - Declarations + //////////////////////////////////////////////////////////////////////// + + string Printer::visit_decl_stmt(const DeclStmt& decl) const + { + return ""; + } + + string Printer::visit_decl_var(const DeclVar& decl) const + { + return ""; + } + + string Printer::visit_decl_func(const DeclFunc& decl) const + { + return ""; + } } } diff --git a/lib/ast/resolver.cc b/lib/ast/resolver.cc index c281a69..c2386f5 100644 --- a/lib/ast/resolver.cc +++ b/lib/ast/resolver.cc @@ -67,40 +67,50 @@ namespace rift #pragma mark - EXPRESSIONS - Token Visitor::resolve_assign(const ResolverAssign& expr) const + Token Visitor::resolve_literal(const ResolverLiteral& expr) const { - visit_assign(expr.expr); - Resolve::resolveLocal(&expr.expr, expr.expr.name); + return Token(); } - Token Visitor::resolve_binary(const ResolverBinary& expr) const + Token Visitor::resolve_unary(const ResolverUnary& expr) const { - visit_binary(expr.expr); + expr.expr->accept(*this); + return Token(); } - Token Visitor::resolve_call(const ResolverCall& expr) const + Token Visitor::resolve_binary(const ResolverBinary& expr) const { - visit_call(expr.expr); + expr.left->accept(*this); + expr.right->accept(*this); + return Token(); } Token Visitor::resolve_grouping(const ResolverGrouping& expr) const { - visit_grouping(expr.expr); + expr.expr->accept(*this); + return Token(); } - Token Visitor::resolve_unary(const ResolverUnary& expr) const + Token Visitor::resolve_ternary(const ResolverTernary& expr) const { - visit_unary(expr.expr); + if(truthy(expr.condition->accept(*this))) { + expr.left->accept(*this); + } else { + expr.right->accept(*this); + } + + return Token(); } - Token Visitor::resolve_ternary(const ResolverTernary& expr) const + Token Visitor::resolve_assign(const ResolverAssign& expr) const { - visit_ternary(expr.expr); + // visit_assign(expr.expr.); + Resolve::resolveLocal(&expr.expr, expr.expr.name); } - Token Visitor::resolve_literal(const ResolverLiteral& expr) const + Token Visitor::resolve_call(const ResolverCall& expr) const { - visit_literal(expr.expr); + visit_call(expr.expr); } Token Visitor::resolve_var_expr(const ResolverVarExpr& expr) const