From 5d4bb511d1983ffb2a484bc3c8f2e42e1261376d Mon Sep 17 00:00:00 2001 From: mxr <> Date: Tue, 24 Mar 2026 15:38:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(sem)=E8=A1=A5=E5=85=85=E7=AC=A6=E5=8F=B7?= =?UTF-8?q?=E8=A1=A8=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/sem/SymbolTable.h | 64 +++++++++++++++-- src/sem/SymbolTable.cpp | 146 +++++++++++++++++++++++++++++++++++--- 2 files changed, 196 insertions(+), 14 deletions(-) diff --git a/include/sem/SymbolTable.h b/include/sem/SymbolTable.h index c9396dd..d52fc9b 100644 --- a/include/sem/SymbolTable.h +++ b/include/sem/SymbolTable.h @@ -3,15 +3,67 @@ #include #include +#include +#include #include "SysYParser.h" +#include "../ir/IR.h" + +// 符号种类 +enum class SymbolKind { + Variable, + Function, + Parameter, + Constant +}; + +// 符号条目 +struct Symbol { + std::string name; + SymbolKind kind; + std::shared_ptr type; // 指向 Type 对象的智能指针 + int scope_level = 0; // 定义时的作用域深度 + int stack_offset = -1; // 局部变量/参数栈偏移(全局变量为 -1) + bool is_initialized = false; // 是否已初始化 + + // 对于函数,额外存储参数列表(类型已包含在函数类型中,这里仅用于快速访问) + std::vector> param_types; + + // 对于常量,存储常量值(此处仅支持 int32) + int const_value = 0; + + // 关联的语法树节点(用于报错位置或进一步分析) + SysYParser::VarDefContext* var_def_ctx = nullptr; + SysYParser::FuncDefContext* func_def_ctx = nullptr; +}; class SymbolTable { - public: - void Add(const std::string& name, SysYParser::VarDefContext* decl); - bool Contains(const std::string& name) const; - SysYParser::VarDefContext* Lookup(const std::string& name) const; + public: + SymbolTable(); + ~SymbolTable() = default; + + // ----- 作用域管理 ----- + void enterScope(); // 进入新作用域 + void exitScope(); // 退出当前作用域 + int currentScopeLevel() const { return static_cast(scopes_.size()) - 1; } + + // ----- 符号操作(推荐使用)----- + bool addSymbol(const Symbol& sym); // 添加符号到当前作用域 + Symbol* lookup(const std::string& name); // 从当前作用域向外查找 + Symbol* lookupCurrent(const std::string& name); // 仅在当前作用域查找 + + // ----- 与原接口兼容(保留原有功能)----- + void Add(const std::string& name, SysYParser::VarDefContext* decl); + bool Contains(const std::string& name) const; + SysYParser::VarDefContext* Lookup(const std::string& name) const; + + // ----- 辅助函数:从语法树节点构造 Type ----- + static std::shared_ptr getTypeFromVarDef(SysYParser::VarDefContext* ctx); + static std::shared_ptr getTypeFromFuncDef(SysYParser::FuncDefContext* ctx); + + private: + // 作用域栈:每个元素是一个从名字到符号的映射 + std::vector> scopes_; - private: - std::unordered_map table_; + static constexpr int GLOBAL_SCOPE = 0; // 全局作用域索引 }; diff --git a/src/sem/SymbolTable.cpp b/src/sem/SymbolTable.cpp index ffeea89..69fc91f 100644 --- a/src/sem/SymbolTable.cpp +++ b/src/sem/SymbolTable.cpp @@ -1,17 +1,147 @@ -// 维护局部变量声明的注册与查找。 - #include "sem/SymbolTable.h" -void SymbolTable::Add(const std::string& name, - SysYParser::VarDefContext* decl) { - table_[name] = decl; +// ---------- 构造函数 ---------- +SymbolTable::SymbolTable() { + // 初始化全局作用域 + scopes_.emplace_back(); +} + +// ---------- 作用域管理 ---------- +void SymbolTable::enterScope() { + scopes_.emplace_back(); +} + +void SymbolTable::exitScope() { + if (scopes_.size() > 1) { + scopes_.pop_back(); + } + // 不能退出全局作用域 +} + +// ---------- 符号添加与查找 ---------- +bool SymbolTable::addSymbol(const Symbol& sym) { + auto& current_scope = scopes_.back(); + if (current_scope.find(sym.name) != current_scope.end()) { + return false; // 重复定义 + } + current_scope[sym.name] = sym; + return true; +} + +Symbol* SymbolTable::lookup(const std::string& name) { + // 从当前作用域向外层查找 + for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) { + auto& scope = *it; + auto found = scope.find(name); + if (found != scope.end()) { + return &found->second; + } + } + return nullptr; +} + +Symbol* SymbolTable::lookupCurrent(const std::string& name) { + auto& current_scope = scopes_.back(); + auto it = current_scope.find(name); + if (it != current_scope.end()) { + return &it->second; + } + return nullptr; +} + +// ---------- 兼容原接口 ---------- +void SymbolTable::Add(const std::string& name, SysYParser::VarDefContext* decl) { + Symbol sym; + sym.name = name; + sym.kind = SymbolKind::Variable; + sym.type = getTypeFromVarDef(decl); + sym.var_def_ctx = decl; + sym.scope_level = currentScopeLevel(); + addSymbol(sym); } bool SymbolTable::Contains(const std::string& name) const { - return table_.find(name) != table_.end(); + // const 方法不能修改 scopes_,我们模拟查找 + for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) { + if (it->find(name) != it->end()) { + return true; + } + } + return false; } SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const { - auto it = table_.find(name); - return it == table_.end() ? nullptr : it->second; + for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) { + auto found = it->find(name); + if (found != it->end()) { + // 只返回变量定义的上下文(函数等其他符号返回 nullptr) + if (found->second.kind == SymbolKind::Variable) { + return found->second.var_def_ctx; + } + return nullptr; + } + } + return nullptr; +} + +// ---------- 辅助函数:从语法树节点构造 Type ---------- +std::shared_ptr SymbolTable::getTypeFromVarDef(SysYParser::VarDefContext* ctx) { + // 这里需要根据实际的语法树结构来提取类型。 + // 假设 ctx 中包含类型节点和数组维度信息。 + // 以下代码为示意,具体实现需根据你的 SysY 语法定义调整。 + + // 1. 判断基本类型(int / float / void 等) + std::shared_ptr base_type; + if (ctx->type() && ctx->type()->INT()) { + base_type = Type::GetInt32Type(); + } else if (ctx->type() && ctx->type()->FLOAT()) { + // 若你扩展了 float 类型,可类似处理 + // base_type = Type::GetFloatType(); + } else { + // 默认为 int + base_type = Type::GetInt32Type(); + } + + // 2. 处理数组维度 + // 假设 ctx 中有 arraySpecifier() 返回维度列表,每个维度是一个表达式节点 + // 这里简单假设维度值在语法树中已经计算好,并存储在某个 vector 中 + std::vector dims; + // 示意:遍历数组维度节点,将常量值推入 dims + // for (auto dimNode : ctx->arraySpecifier()) { + // dims.push_back(parseConstExpr(dimNode)); + // } + + if (dims.empty()) { + // 非数组,直接返回基本类型 + return base_type; + } else { + // 数组类型:递归构建数组类型 + // 注意:Type::GetArrayType 需要元素类型和维度列表 + return Type::GetArrayType(base_type, dims); + } +} + +std::shared_ptr SymbolTable::getTypeFromFuncDef(SysYParser::FuncDefContext* ctx) { + // 提取返回类型 + std::shared_ptr ret_type; + if (ctx->type() && ctx->type()->VOID()) { + ret_type = Type::GetVoidType(); + } else if (ctx->type() && ctx->type()->INT()) { + ret_type = Type::GetInt32Type(); + } else { + ret_type = Type::GetInt32Type(); // 默认 + } + + // 提取参数类型列表 + std::vector> param_types; + if (ctx->paramList()) { + for (auto param : ctx->paramList()->param()) { + // 假设 param 包含类型信息 + // 这里简单构建 int 类型,实际需根据参数声明解析 + param_types.push_back(Type::GetInt32Type()); + } + } + + // 创建函数类型 + return Type::GetFunctionType(ret_type, param_types); }