#pragma once #include #include enum class ASTNodeType { // Expression nodes NewArrayExpr, NewConstructExpr, NewExpr, MemberVariableAccessExpr, MemberFunctionAccessExpr, IndexExpr, SuffixExpr, PrefixExpr, OppositeExpr, LNotExpr, BNotExpr, MDMExpr, PMExpr, RLExpr, GGLLExpr, NEExpr, BAndExpr, BXorExpr, BOrExpr, LAndExpr, LOrExpr, TernaryExpr, AssignExpr, ThisExpr, ParenExpr, IDExpr, FunctionCallExpr, FormattedStringExpr, ConstantExpr, // Statement nodes EmptyStatement, DefinitionStatement, ExprStatement, IfStatement, WhileStatement, ForStatement, JmpStatement, SuiteStatement, // Structural nodes FuncDef, Constructor, ClassVariable, ClassDef, Program }; class SemanticError : public std::exception { std::string msg; int error_code; public: SemanticError(const std::string &msg, int error_code) : msg(msg), error_code(error_code) {} const char *what() const noexcept override { return msg.c_str(); } int GetErrorCode() const { return error_code; } }; using IdentifierType = std::string; struct ArrayType { bool has_base_type; IdentifierType basetype; size_t level; }; inline bool operator==(const ArrayType &l, const ArrayType &r) { return l.has_base_type == r.has_base_type && l.basetype == r.basetype && l.level == r.level; } using ExprTypeInfo = std::variant; inline bool operator==(const ExprTypeInfo &l, const ExprTypeInfo &r) { if (std::holds_alternative(r) && std::get(r) == "null") { if (std::holds_alternative(l)) { std::string l_type = std::get(l); if (l_type == "int" || l_type == "bool" || l_type == "string") { return false; } return true; } return true; } if (std::holds_alternative(l)) { return std::holds_alternative(r) && std::get(l) == std::get(r); } if (std::holds_alternative(l)) { return std::holds_alternative(r) && std::get(l) == std::get(r); } throw std::runtime_error("something strange happened"); } inline bool operator!=(const ExprTypeInfo &l, const ExprTypeInfo &r) { return !(l == r); }