From 1ba056f0aca96584593da7aa8d4e9a57d346a4bd Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Tue, 13 Aug 2024 14:03:23 +0000 Subject: [PATCH] set up semantic visitor --- include/ast/astnode.h | 17 +-- include/ast/astnode_visitor.h | 108 ++++++++++++++- include/ast/expr_astnode.h | 223 +++++++++++++++++++++++++++---- include/ast/scope.hpp | 7 +- include/ast/statement_astnode.h | 40 ++++++ include/ast/structural_astnode.h | 9 ++ src/ast/expr_astnode.cpp | 40 +++++- src/ast/semanticvisitor.cpp | 178 ++++++++++++++++++++++++ src/ast/statement_astnode.cpp | 22 ++- src/ast/structural_astnode.cpp | 17 ++- src/semantic/semantic.cpp | 3 + src/semantic/visitor.cpp | 59 +++++--- 12 files changed, 661 insertions(+), 62 deletions(-) create mode 100644 src/ast/semanticvisitor.cpp diff --git a/include/ast/astnode.h b/include/ast/astnode.h index 8d40368..546f106 100644 --- a/include/ast/astnode.h +++ b/include/ast/astnode.h @@ -6,13 +6,6 @@ #include "../semantic/visitor.h" #include "scope.hpp" #include "tools.h" -class ASTNodeVisitorBase { - friend Visitor; - - public: - virtual ~ASTNodeVisitorBase() = default; - virtual void visit(class ASTNodeBase *context) = 0; -}; class ASTNodeBase { friend Visitor; @@ -26,6 +19,14 @@ class ASTNodeBase { public: virtual ~ASTNodeBase() = default; - // virtual void accept(class ASTNodeVisitorBase *visitor) = 0; + virtual void accept(class ASTNodeVisitorBase *visitor) = 0; +}; + +class ASTNodeVisitorBase { + friend Visitor; + + public: + virtual ~ASTNodeVisitorBase() = default; + void visit(ASTNodeBase *context) { context->accept(this); } }; #endif \ No newline at end of file diff --git a/include/ast/astnode_visitor.h b/include/ast/astnode_visitor.h index 14145fa..4a8d225 100644 --- a/include/ast/astnode_visitor.h +++ b/include/ast/astnode_visitor.h @@ -1,6 +1,106 @@ -#ifndef ASTNODE_VISITOR_H -#define ASTNODE_VISITOR_H +#ifndef ASTNODE_ActuralVisitOR_H +#define ASTNODE_ActuralVisitOR_H + #include "astnode.h" #include "expr_astnode.h" -class ASTNodeVisitor : public ASTNodeVisitorBase {}; -#endif \ No newline at end of file +#include "statement_astnode.h" +#include "structural_astnode.h" + +class ASTNodeVirturalVisitor : public ASTNodeVisitorBase { + public: + // Structural AST Nodes + virtual void ActuralVisit(FuncDef_ASTNode *node) = 0; + virtual void ActuralVisit(ClassDef_ASTNode *node) = 0; + virtual void ActuralVisit(Program_ASTNode *node) = 0; + + // Statement AST Nodes + virtual void ActuralVisit(EmptyStatement_ASTNode *node) = 0; + virtual void ActuralVisit(DefinitionStatement_ASTNode *node) = 0; + virtual void ActuralVisit(ExprStatement_ASTNode *node) = 0; + virtual void ActuralVisit(IfStatement_ASTNode *node) = 0; + virtual void ActuralVisit(WhileStatement_ASTNode *node) = 0; + virtual void ActuralVisit(ForStatement_ASTNode *node) = 0; + virtual void ActuralVisit(JmpStatement_ASTNode *node) = 0; + virtual void ActuralVisit(SuiteStatement_ASTNode *node) = 0; + + // Expression AST Nodes + virtual void ActuralVisit(NewArrayExpr_ASTNode *node) = 0; + virtual void ActuralVisit(NewConstructExpr_ASTNode *node) = 0; + virtual void ActuralVisit(NewExpr_ASTNode *node) = 0; + virtual void ActuralVisit(AccessExpr_ASTNode *node) = 0; + virtual void ActuralVisit(IndexExpr_ASTNode *node) = 0; + virtual void ActuralVisit(SuffixExpr_ASTNode *node) = 0; + virtual void ActuralVisit(PrefixExpr_ASTNode *node) = 0; + virtual void ActuralVisit(OppositeExpr_ASTNode *node) = 0; + virtual void ActuralVisit(LNotExpr_ASTNode *node) = 0; + virtual void ActuralVisit(BNotExpr_ASTNode *node) = 0; + virtual void ActuralVisit(MDMExpr_ASTNode *node) = 0; + virtual void ActuralVisit(PMExpr_ASTNode *node) = 0; + virtual void ActuralVisit(RLExpr_ASTNode *node) = 0; + virtual void ActuralVisit(GGLLExpr_ASTNode *node) = 0; + virtual void ActuralVisit(NEExpr_ASTNode *node) = 0; + virtual void ActuralVisit(BAndExpr_ASTNode *node) = 0; + virtual void ActuralVisit(BXorExpr_ASTNode *node) = 0; + virtual void ActuralVisit(BOrExpr_ASTNode *node) = 0; + virtual void ActuralVisit(LAndExpr_ASTNode *node) = 0; + virtual void ActuralVisit(LOrExpr_ASTNode *node) = 0; + virtual void ActuralVisit(TernaryExpr_ASTNode *node) = 0; + virtual void ActuralVisit(AssignExpr_ASTNode *node) = 0; + virtual void ActuralVisit(ThisExpr_ASTNode *node) = 0; + virtual void ActuralVisit(ParenExpr_ASTNode *node) = 0; + virtual void ActuralVisit(IDExpr_ASTNode *node) = 0; + virtual void ActuralVisit(FunctionCallExpr_ASTNode *node) = 0; + virtual void ActuralVisit(FormattedStringExpr_ASTNode *node) = 0; + virtual void ActuralVisit(ConstantExpr_ASTNode *node) = 0; +}; + +class ASTSemanticCheckVisitor : public ASTNodeVirturalVisitor { + public: + ASTSemanticCheckVisitor() = default; + // Structural AST Nodes + void ActuralVisit(FuncDef_ASTNode *node) override; + void ActuralVisit(ClassDef_ASTNode *node) override; + void ActuralVisit(Program_ASTNode *node) override; + + // Statement AST Nodes + void ActuralVisit(EmptyStatement_ASTNode *node) override; + void ActuralVisit(DefinitionStatement_ASTNode *node) override; + void ActuralVisit(ExprStatement_ASTNode *node) override; + void ActuralVisit(IfStatement_ASTNode *node) override; + void ActuralVisit(WhileStatement_ASTNode *node) override; + void ActuralVisit(ForStatement_ASTNode *node) override; + void ActuralVisit(JmpStatement_ASTNode *node) override; + void ActuralVisit(SuiteStatement_ASTNode *node) override; + + // Expression AST Nodes + void ActuralVisit(NewArrayExpr_ASTNode *node) override; + void ActuralVisit(NewConstructExpr_ASTNode *node) override; + void ActuralVisit(NewExpr_ASTNode *node) override; + void ActuralVisit(AccessExpr_ASTNode *node) override; + void ActuralVisit(IndexExpr_ASTNode *node) override; + void ActuralVisit(SuffixExpr_ASTNode *node) override; + void ActuralVisit(PrefixExpr_ASTNode *node) override; + void ActuralVisit(OppositeExpr_ASTNode *node) override; + void ActuralVisit(LNotExpr_ASTNode *node) override; + void ActuralVisit(BNotExpr_ASTNode *node) override; + void ActuralVisit(MDMExpr_ASTNode *node) override; + void ActuralVisit(PMExpr_ASTNode *node) override; + void ActuralVisit(RLExpr_ASTNode *node) override; + void ActuralVisit(GGLLExpr_ASTNode *node) override; + void ActuralVisit(NEExpr_ASTNode *node) override; + void ActuralVisit(BAndExpr_ASTNode *node) override; + void ActuralVisit(BXorExpr_ASTNode *node) override; + void ActuralVisit(BOrExpr_ASTNode *node) override; + void ActuralVisit(LAndExpr_ASTNode *node) override; + void ActuralVisit(LOrExpr_ASTNode *node) override; + void ActuralVisit(TernaryExpr_ASTNode *node) override; + void ActuralVisit(AssignExpr_ASTNode *node) override; + void ActuralVisit(ThisExpr_ASTNode *node) override; + void ActuralVisit(ParenExpr_ASTNode *node) override; + void ActuralVisit(IDExpr_ASTNode *node) override; + void ActuralVisit(FunctionCallExpr_ASTNode *node) override; + void ActuralVisit(FormattedStringExpr_ASTNode *node) override; + void ActuralVisit(ConstantExpr_ASTNode *node) override; +}; + +#endif // ASTNODE_ActuralVisitOR_H \ No newline at end of file diff --git a/include/ast/expr_astnode.h b/include/ast/expr_astnode.h index 649b342..8f68110 100644 --- a/include/ast/expr_astnode.h +++ b/include/ast/expr_astnode.h @@ -7,159 +7,330 @@ class Expr_ASTNode : public ASTNodeBase { friend Visitor; + friend class ASTSemanticCheckVisitor; ExprTypeInfo expr_type_info; public: + Expr_ASTNode() = default; virtual ~Expr_ASTNode() = default; }; class BasicExpr_ASTNode : public Expr_ASTNode {}; // This is a virtual class + class NewArrayExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; bool has_initial_value; std::vector> dim_size; std::shared_ptr initial_value; + + public: + NewArrayExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class NewConstructExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; + + public: + NewConstructExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class NewExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; + + public: + NewExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class AccessExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr base; IdentifierType member; bool is_function; std::vector> arguments; + + public: + AccessExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class IndexExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr base; std::vector> indices; + + public: + IndexExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class SuffixExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr base; + + public: + SuffixExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class PrefixExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr base; + + public: + PrefixExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class OppositeExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr base; + + public: + OppositeExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class LNotExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr base; + + public: + LNotExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class BNotExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr base; + + public: + BNotExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class MDMExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + MDMExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class PMExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + PMExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class RLExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + RLExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class GGLLExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + GGLLExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class NEExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + NEExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class BAndExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + BAndExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class BXorExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + BXorExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class BOrExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + BOrExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class LAndExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + LAndExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class LOrExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr left; std::shared_ptr right; + + public: + LOrExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class TernaryExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr condition; std::shared_ptr src1; std::shared_ptr src2; + + public: + TernaryExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; + class AssignExpr_ASTNode : public Expr_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::string op; std::shared_ptr dest; std::shared_ptr src; + + public: + AssignExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class ThisExpr_ASTNode : public BasicExpr_ASTNode { friend Visitor; -}; -class ParenExpr_ASTNode : public BasicExpr_ASTNode { - friend Visitor; - std::shared_ptr expr; -}; -class IDExpr_ASTNode : public BasicExpr_ASTNode { - friend Visitor; - IdentifierType id; -}; -class FunctionCallExpr_ASTNode : public BasicExpr_ASTNode { - friend Visitor; - IdentifierType func_name; - std::vector> arguments; -}; -class FormattedStringExpr_ASTNode : public BasicExpr_ASTNode { - friend Visitor; - std::vector literals; - std::vector> exprs; -}; -struct NullType {}; -using AtomicConstantType = std::variant; -class ConstantExpr_ASTNode : public BasicExpr_ASTNode { - friend Visitor; - size_t level; - std::variant>> value; + friend class ASTSemanticCheckVisitor; + + public: + ThisExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; -#endif // EXPR_ASTNODE_H \ No newline at end of file +class ParenExpr_ASTNode : public BasicExpr_ASTNode { + friend Visitor; + friend class ASTSemanticCheckVisitor; + std::shared_ptr expr; + + public: + ParenExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; +}; + +class IDExpr_ASTNode : public BasicExpr_ASTNode { + friend Visitor; + friend class ASTSemanticCheckVisitor; + IdentifierType id; + + public: + IDExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; +}; + +class FunctionCallExpr_ASTNode : public BasicExpr_ASTNode { + friend Visitor; + friend class ASTSemanticCheckVisitor; + IdentifierType func_name; + std::vector> arguments; + + public: + FunctionCallExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; +}; + +class FormattedStringExpr_ASTNode : public BasicExpr_ASTNode { + friend Visitor; + friend class ASTSemanticCheckVisitor; + std::vector literals; + std::vector> exprs; + + public: + FormattedStringExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; +}; + +struct NullType {}; + +using AtomicConstantType = std::variant; + +class ConstantExpr_ASTNode : public BasicExpr_ASTNode { + friend Visitor; + friend class ASTSemanticCheckVisitor; + size_t level; + std::variant>> value; + + public: + ConstantExpr_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; +}; + +#endif // EXPR_ASTNODE_H diff --git a/include/ast/scope.hpp b/include/ast/scope.hpp index 0777291..ff56895 100644 --- a/include/ast/scope.hpp +++ b/include/ast/scope.hpp @@ -13,6 +13,7 @@ class ScopeBase { friend class FunctionScope; friend class ClassDefScope; friend class GlobalScope; + friend class ASTSemanticCheckVisitor; protected: ScopeBase *parent; // cannot use std::shared_ptr because of circular dependency @@ -118,8 +119,10 @@ class ClassDefScope : public ScopeBase { return false; } } - if (member_functions.find(name) != member_functions.end()) { - return false; + if (ttl == 0) { + if (member_functions.find(name) != member_functions.end()) { + return false; + } } return parent->VariableNameAvailable(name, ttl + 1); } diff --git a/include/ast/statement_astnode.h b/include/ast/statement_astnode.h index 13e66e6..74325d8 100644 --- a/include/ast/statement_astnode.h +++ b/include/ast/statement_astnode.h @@ -10,43 +10,83 @@ class Statement_ASTNode : public ASTNodeBase { class EmptyStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; + + public: + EmptyStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class DefinitionStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; ExprTypeInfo var_type; std::vector>> vars; + + public: + DefinitionStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class ExprStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr expr; + + public: + ExprStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class IfStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; bool has_else_clause; std::shared_ptr condition; std::shared_ptr if_clause; std::shared_ptr else_clause; + + public: + IfStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class WhileStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr condition; std::shared_ptr loop_body; + + public: + WhileStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class ForStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::shared_ptr initial; std::shared_ptr condition; std::shared_ptr update; std::shared_ptr loop_body; + + public: + ForStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class JmpStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; uint8_t jmp_type; // 0: return, 1: break, 2: continue std::shared_ptr return_value; + + public: + JmpStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class SuiteStatement_ASTNode : public Statement_ASTNode { friend Visitor; + friend class ASTSemanticCheckVisitor; std::vector> statements; + + public: + SuiteStatement_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; #endif // STATEMENT_ASTNODE_H \ No newline at end of file diff --git a/include/ast/structural_astnode.h b/include/ast/structural_astnode.h index 5c2d3bf..51a7908 100644 --- a/include/ast/structural_astnode.h +++ b/include/ast/structural_astnode.h @@ -4,10 +4,12 @@ #include #include #include "astnode.h" + #include "expr_astnode.h" #include "statement_astnode.h" class FuncDef_ASTNode : public ASTNodeBase { friend Visitor; + friend class ASTSemanticCheckVisitor; bool is_constructor; IdentifierType func_name; ExprTypeInfo return_type; @@ -16,26 +18,33 @@ class FuncDef_ASTNode : public ASTNodeBase { public: FuncDef_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class ClassDef_ASTNode : public ASTNodeBase { friend Visitor; + friend class ASTSemanticCheckVisitor; private: std::string class_name; std::vector> member_variables; std::vector> member_functions; std::shared_ptr constructor; + std::vector> sorted_children; public: ClassDef_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; class Program_ASTNode : public ASTNodeBase { friend Visitor; + friend class ASTSemanticCheckVisitor; std::vector> global_variables; std::vector> classes; std::vector> functions; + std::vector> sorted_children; public: Program_ASTNode() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) override; }; #endif \ No newline at end of file diff --git a/src/ast/expr_astnode.cpp b/src/ast/expr_astnode.cpp index 71824f6..4e9fdd6 100644 --- a/src/ast/expr_astnode.cpp +++ b/src/ast/expr_astnode.cpp @@ -1 +1,39 @@ -#include "expr_astnode.h" \ No newline at end of file +#include "expr_astnode.h" +#include +#include "astnode_visitor.h" +#define SetAutoAccept(name) \ + void name::accept(class ASTNodeVisitorBase *visitor) { \ + if (auto v = dynamic_cast(visitor)) { \ + v->ActuralVisit(this); \ + } else \ + throw std::runtime_error("Cannot automatically dispatch visitor"); \ + } +SetAutoAccept(NewArrayExpr_ASTNode); +SetAutoAccept(NewConstructExpr_ASTNode); +SetAutoAccept(NewExpr_ASTNode); +SetAutoAccept(AccessExpr_ASTNode); +SetAutoAccept(IndexExpr_ASTNode); +SetAutoAccept(SuffixExpr_ASTNode); +SetAutoAccept(PrefixExpr_ASTNode); +SetAutoAccept(OppositeExpr_ASTNode); +SetAutoAccept(LNotExpr_ASTNode); +SetAutoAccept(BNotExpr_ASTNode); +SetAutoAccept(MDMExpr_ASTNode); +SetAutoAccept(PMExpr_ASTNode); +SetAutoAccept(RLExpr_ASTNode); +SetAutoAccept(GGLLExpr_ASTNode); +SetAutoAccept(NEExpr_ASTNode); +SetAutoAccept(BAndExpr_ASTNode); +SetAutoAccept(BXorExpr_ASTNode); +SetAutoAccept(BOrExpr_ASTNode); +SetAutoAccept(LAndExpr_ASTNode); +SetAutoAccept(LOrExpr_ASTNode); +SetAutoAccept(TernaryExpr_ASTNode); +SetAutoAccept(AssignExpr_ASTNode); +SetAutoAccept(ThisExpr_ASTNode); +SetAutoAccept(ParenExpr_ASTNode); +SetAutoAccept(IDExpr_ASTNode); +SetAutoAccept(FunctionCallExpr_ASTNode); +SetAutoAccept(FormattedStringExpr_ASTNode); +SetAutoAccept(ConstantExpr_ASTNode); +#undef SetAutoAccept \ No newline at end of file diff --git a/src/ast/semanticvisitor.cpp b/src/ast/semanticvisitor.cpp new file mode 100644 index 0000000..cda8d13 --- /dev/null +++ b/src/ast/semanticvisitor.cpp @@ -0,0 +1,178 @@ +#include "astnode_visitor.h" +#include "tools.h" + +// Structural AST Nodes +void ASTSemanticCheckVisitor::ActuralVisit(FuncDef_ASTNode *node) { node->func_body->accept(this); } + +void ASTSemanticCheckVisitor::ActuralVisit(ClassDef_ASTNode *node) { + for (auto ch : node->sorted_children) { + ch->accept(this); + } +} + +void ASTSemanticCheckVisitor::ActuralVisit(Program_ASTNode *node) { + for (auto ch : node->sorted_children) { + ch->accept(this); + } +} + +// Statement AST Nodes +void ASTSemanticCheckVisitor::ActuralVisit(EmptyStatement_ASTNode *node) {} + +void ASTSemanticCheckVisitor::ActuralVisit(DefinitionStatement_ASTNode *node) { + auto cur_scope = node->current_scope; + for (const auto &var : node->vars) { + if (!cur_scope->add_variable(var.first, node->var_type)) { + throw SemanticError("Variable redefinition for " + var.first, 1); + } + } +} + +void ASTSemanticCheckVisitor::ActuralVisit(ExprStatement_ASTNode *node) { node->expr->accept(this); } + +void ASTSemanticCheckVisitor::ActuralVisit(IfStatement_ASTNode *node) { + node->condition->accept(this); + node->if_clause->accept(this); + if (node->has_else_clause) { + node->else_clause->accept(this); + } +} + +void ASTSemanticCheckVisitor::ActuralVisit(WhileStatement_ASTNode *node) { + node->condition->accept(this); + node->loop_body->accept(this); +} + +void ASTSemanticCheckVisitor::ActuralVisit(ForStatement_ASTNode *node) { + if (node->initial) { + node->initial->accept(this); + } + if (node->condition) { + node->condition->accept(this); + } + if (node->update) { + node->update->accept(this); + } + node->loop_body->accept(this); +} + +void ASTSemanticCheckVisitor::ActuralVisit(JmpStatement_ASTNode *node) {} + +void ASTSemanticCheckVisitor::ActuralVisit(SuiteStatement_ASTNode *node) { + for (auto ch : node->statements) { + ch->accept(this); + } +} + +// Expression AST Nodes +void ASTSemanticCheckVisitor::ActuralVisit(NewArrayExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(NewConstructExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(NewExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(AccessExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(IndexExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(SuffixExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(PrefixExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(OppositeExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(LNotExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(BNotExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(MDMExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(PMExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(RLExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(GGLLExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(NEExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(BAndExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(BXorExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(BOrExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(LAndExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(LOrExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(TernaryExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(AssignExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(ThisExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(ParenExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(IDExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(FunctionCallExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(FormattedStringExpr_ASTNode *node) { + // TODO: Implement this method +} + +void ASTSemanticCheckVisitor::ActuralVisit(ConstantExpr_ASTNode *node) { + // TODO: Implement this method +} diff --git a/src/ast/statement_astnode.cpp b/src/ast/statement_astnode.cpp index 7d84b2b..3606247 100644 --- a/src/ast/statement_astnode.cpp +++ b/src/ast/statement_astnode.cpp @@ -1 +1,21 @@ -#include "statement_astnode.h" \ No newline at end of file +#include "statement_astnode.h" +#include +#include "astnode_visitor.h" +#define SetAutoAccept(name) \ + void name::accept(class ASTNodeVisitorBase *visitor) { \ + if (auto v = dynamic_cast(visitor)) { \ + v->ActuralVisit(this); \ + } else \ + throw std::runtime_error("Cannot automatically dispatch visitor"); \ + } + +SetAutoAccept(EmptyStatement_ASTNode); +SetAutoAccept(DefinitionStatement_ASTNode); +SetAutoAccept(ExprStatement_ASTNode); +SetAutoAccept(IfStatement_ASTNode); +SetAutoAccept(WhileStatement_ASTNode); +SetAutoAccept(ForStatement_ASTNode); +SetAutoAccept(JmpStatement_ASTNode); +SetAutoAccept(SuiteStatement_ASTNode); + +#undef SetAutoAccept \ No newline at end of file diff --git a/src/ast/structural_astnode.cpp b/src/ast/structural_astnode.cpp index 9864b72..8046a5f 100644 --- a/src/ast/structural_astnode.cpp +++ b/src/ast/structural_astnode.cpp @@ -1 +1,16 @@ -#include "structural_astnode.h" \ No newline at end of file +#include "structural_astnode.h" +#include +#include "astnode_visitor.h" + +#define SetAutoAccept(name) \ + void name::accept(class ASTNodeVisitorBase *visitor) { \ + if (auto v = dynamic_cast(visitor)) { \ + v->ActuralVisit(this); \ + } else \ + throw std::runtime_error("Cannot automatically dispatch visitor"); \ + } + +SetAutoAccept(FuncDef_ASTNode); +SetAutoAccept(ClassDef_ASTNode); +SetAutoAccept(Program_ASTNode); +#undef SetAutoAccpet \ No newline at end of file diff --git a/src/semantic/semantic.cpp b/src/semantic/semantic.cpp index 21ab397..87f40dd 100644 --- a/src/semantic/semantic.cpp +++ b/src/semantic/semantic.cpp @@ -4,6 +4,7 @@ #include "MXParser.h" #include "antlr4-runtime.h" #include "ast/ast.h" +#include "ast/astnode_visitor.h" #include "visitor.h" class MXErrorListener : public antlr4::BaseErrorListener { @@ -33,6 +34,8 @@ std::shared_ptr CheckAndDecorate(std::shared_ptr(def)) { auto classNode = std::any_cast>(visit(classDefContext)); program->classes.push_back(classNode); + program->sorted_children.push_back(classNode); } else if (auto defineStmtContext = dynamic_cast(def)) { auto defineNode = std::dynamic_pointer_cast( std::any_cast>(visit(defineStmtContext))); program->global_variables.push_back(defineNode); + program->sorted_children.push_back(defineNode); } else if (auto funcDefContext = dynamic_cast(def)) { auto funcNode = std::any_cast>(visit(funcDefContext)); program->functions.push_back(funcNode); + program->sorted_children.push_back(funcNode); } else if (auto EOFToken = dynamic_cast(def)) { if (EOFToken == context->EOF()) break; throw std::runtime_error("unknown subnode occurred in visitMxprog"); @@ -160,20 +163,38 @@ std::any Visitor::visitClass_def(MXParser::Class_defContext *context) { class_def->class_name = context->ID()->getText(); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "building a class named " << class_def->class_name << std::endl; - std::vector constructors = context->class_constructor(); - if (constructors.size() > 1) throw SemanticError("Multiple constructor found for class " + class_def->class_name, 2); - if (constructors.size() > 0) - class_def->constructor = std::any_cast>(visit(constructors[0])); - std::vector functions = context->function_def(); - for (auto func : functions) { - auto func_node = std::any_cast>(visit(func)); - class_def->member_functions.push_back(func_node); - } - std::vector vars = context->class_var_def(); - for (auto var : vars) { - auto var_node = std::dynamic_pointer_cast( - std::any_cast>(visit(var))); - class_def->member_variables.push_back(var_node); + // std::vector constructors = context->class_constructor(); + if (context->class_constructor().size() > 1) + throw SemanticError("Multiple constructor found for class " + class_def->class_name, 2); + // if (constructors.size() > 0) + // class_def->constructor = std::any_cast>(visit(constructors[0])); + // std::vector functions = context->function_def(); + // for (auto func : functions) { + // auto func_node = std::any_cast>(visit(func)); + // class_def->member_functions.push_back(func_node); + // } + // std::vector vars = context->class_var_def(); + // for (auto var : vars) { + // auto var_node = std::dynamic_pointer_cast( + // std::any_cast>(visit(var))); + // class_def->member_variables.push_back(var_node); + // } + for (size_t i = 3; i < context->children.size(); i++) { + if (auto var_def_ctx = dynamic_cast(context->children[i])) { + auto var_node = std::dynamic_pointer_cast( + std::any_cast>(visit(context->children[i]))); + class_def->member_variables.push_back(var_node); + class_def->sorted_children.push_back(var_node); + } else if (auto constructor_ctx = dynamic_cast(context->children[i])) { + auto constructor_node = std::any_cast>(visit(context->children[i])); + class_def->constructor = constructor_node; + class_def->sorted_children.push_back(constructor_node); + } else if (auto func_def_ctx = dynamic_cast(context->children[i])) { + auto func_node = std::any_cast>(visit(context->children[i])); + class_def->member_functions.push_back(func_node); + class_def->sorted_children.push_back(func_node); + } else + break; } nodetype_stk.pop_back(); @@ -217,9 +238,9 @@ std::any Visitor::visitClass_var_def(MXParser::Class_var_defContext *context) { member_var_def->vars.push_back(std::make_pair(id->getText(), nullptr)); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded member variable name is " << id->getText() << std::endl; - if (!member_var_def->current_scope->add_variable(id->getText(), member_var_def->var_type)) { - throw SemanticError("Variable name " + id->getText() + " is not available", 1); - } + // if (!member_var_def->current_scope->add_variable(id->getText(), member_var_def->var_type)) { + // throw SemanticError("Variable name " + id->getText() + " is not available", 1); + // } } nodetype_stk.pop_back(); @@ -494,8 +515,8 @@ std::any Visitor::visitDefine_statement(MXParser::Define_statementContext *conte if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ID) { def_stmt->vars.push_back(std::make_pair(context->children[i]->getText(), nullptr)); - if (!def_stmt->current_scope->add_variable(context->children[i]->getText(), def_stmt->var_type)) - throw SemanticError("Variable " + context->children[i]->getText() + " already defined", 1); + // if (!def_stmt->current_scope->add_variable(context->children[i]->getText(), def_stmt->var_type)) + // throw SemanticError("Variable " + context->children[i]->getText() + " already defined", 1); } else throw std::runtime_error("unknown subnode occurred in visitDefine_statement"); i++;