feat(sem)补充符号表实现

mxr 3 weeks ago
parent c450277c83
commit 5d4bb511d1

@ -3,15 +3,67 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <memory>
#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; // 指向 Type 对象的智能指针
int scope_level = 0; // 定义时的作用域深度
int stack_offset = -1; // 局部变量/参数栈偏移(全局变量为 -1
bool is_initialized = false; // 是否已初始化
// 对于函数,额外存储参数列表(类型已包含在函数类型中,这里仅用于快速访问)
std::vector<std::shared_ptr<Type>> 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<int>(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<Type> getTypeFromVarDef(SysYParser::VarDefContext* ctx);
static std::shared_ptr<Type> getTypeFromFuncDef(SysYParser::FuncDefContext* ctx);
private:
// 作用域栈:每个元素是一个从名字到符号的映射
std::vector<std::unordered_map<std::string, Symbol>> scopes_;
private:
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
static constexpr int GLOBAL_SCOPE = 0; // 全局作用域索引
};

@ -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<Type> SymbolTable::getTypeFromVarDef(SysYParser::VarDefContext* ctx) {
// 这里需要根据实际的语法树结构来提取类型。
// 假设 ctx 中包含类型节点和数组维度信息。
// 以下代码为示意,具体实现需根据你的 SysY 语法定义调整。
// 1. 判断基本类型int / float / void 等)
std::shared_ptr<Type> 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<int> 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<Type> SymbolTable::getTypeFromFuncDef(SysYParser::FuncDefContext* ctx) {
// 提取返回类型
std::shared_ptr<Type> 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<std::shared_ptr<Type>> 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);
}

Loading…
Cancel
Save