forked from NUDT-compiler/nudt-compiler-cpp
parent
477720eb5e
commit
04a29b2bf9
@ -1,30 +1,213 @@
|
||||
// 基于语法树的语义检查与名称绑定。
|
||||
#pragma once
|
||||
#ifndef SEMANTIC_ANALYSIS_H
|
||||
#define SEMANTIC_ANALYSIS_H
|
||||
|
||||
#include "SymbolTable.h"
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <any>
|
||||
#include <memory>
|
||||
|
||||
#include "SysYParser.h"
|
||||
// 错误信息结构体
|
||||
struct ErrorMsg {
|
||||
std::string msg;
|
||||
int line;
|
||||
int column;
|
||||
ErrorMsg(std::string m, int l, int c) : msg(std::move(m)), line(l), column(c) {}
|
||||
};
|
||||
|
||||
// 前向声明
|
||||
namespace antlr4 {
|
||||
class ParserRuleContext;
|
||||
namespace tree {
|
||||
class ParseTree;
|
||||
}
|
||||
}
|
||||
|
||||
// 语义/IR生成上下文核心类
|
||||
class IRGenContext {
|
||||
public:
|
||||
// 错误管理
|
||||
void RecordError(const ErrorMsg& err) { errors_.push_back(err); }
|
||||
const std::vector<ErrorMsg>& GetErrors() const { return errors_; }
|
||||
bool HasError() const { return !errors_.empty(); }
|
||||
void ClearErrors() { errors_.clear(); }
|
||||
|
||||
// 类型绑定/查询 - 使用 void* 以兼容测试代码
|
||||
void SetType(void* ctx, SymbolType type) {
|
||||
node_type_map_[ctx] = type;
|
||||
}
|
||||
|
||||
SymbolType GetType(void* ctx) const {
|
||||
auto it = node_type_map_.find(ctx);
|
||||
return it == node_type_map_.end() ? SymbolType::TYPE_UNKNOWN : it->second;
|
||||
}
|
||||
|
||||
// 常量值绑定/查询 - 使用 void* 以兼容测试代码
|
||||
void SetConstVal(void* ctx, const std::any& val) {
|
||||
const_val_map_[ctx] = val;
|
||||
}
|
||||
|
||||
std::any GetConstVal(void* ctx) const {
|
||||
auto it = const_val_map_.find(ctx);
|
||||
return it == const_val_map_.end() ? std::any() : it->second;
|
||||
}
|
||||
|
||||
// 循环状态管理
|
||||
void EnterLoop() { sym_table_.EnterLoop(); }
|
||||
void ExitLoop() { sym_table_.ExitLoop(); }
|
||||
bool InLoop() const { return sym_table_.InLoop(); }
|
||||
|
||||
// 类型判断工具函数
|
||||
bool IsIntType(const std::any& val) const {
|
||||
return val.type() == typeid(long) || val.type() == typeid(int);
|
||||
}
|
||||
|
||||
bool IsFloatType(const std::any& val) const {
|
||||
return val.type() == typeid(double) || val.type() == typeid(float);
|
||||
}
|
||||
|
||||
// 当前函数返回类型
|
||||
SymbolType GetCurrentFuncReturnType() const {
|
||||
return current_func_ret_type_;
|
||||
}
|
||||
|
||||
void SetCurrentFuncReturnType(SymbolType type) {
|
||||
current_func_ret_type_ = type;
|
||||
}
|
||||
|
||||
// 符号表访问
|
||||
SymbolTable& GetSymbolTable() { return sym_table_; }
|
||||
const SymbolTable& GetSymbolTable() const { return sym_table_; }
|
||||
|
||||
// 作用域管理
|
||||
void EnterScope() { sym_table_.EnterScope(); }
|
||||
void LeaveScope() { sym_table_.LeaveScope(); }
|
||||
size_t GetScopeDepth() const { return sym_table_.GetScopeDepth(); }
|
||||
|
||||
private:
|
||||
SymbolTable sym_table_;
|
||||
std::unordered_map<void*, SymbolType> node_type_map_;
|
||||
std::unordered_map<void*, std::any> const_val_map_;
|
||||
std::vector<ErrorMsg> errors_;
|
||||
SymbolType current_func_ret_type_ = SymbolType::TYPE_UNKNOWN;
|
||||
};
|
||||
|
||||
// 与现有 IRGen/主流程保持兼容的语义上下文占位。
|
||||
class SemanticContext {
|
||||
public:
|
||||
void BindVarUse(SysYParser::VarContext* use,
|
||||
SysYParser::VarDefContext* decl) {
|
||||
var_uses_[use] = decl;
|
||||
}
|
||||
void BindVarUse(const SysYParser::LValueContext* use,
|
||||
SysYParser::VarDefContext* decl) {
|
||||
var_uses_[use] = decl;
|
||||
}
|
||||
|
||||
SysYParser::VarDefContext* ResolveVarUse(
|
||||
const SysYParser::VarContext* use) const {
|
||||
auto it = var_uses_.find(use);
|
||||
return it == var_uses_.end() ? nullptr : it->second;
|
||||
}
|
||||
SysYParser::VarDefContext* ResolveVarUse(
|
||||
const SysYParser::LValueContext* use) const {
|
||||
auto it = var_uses_.find(use);
|
||||
return it == var_uses_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<const SysYParser::VarContext*,
|
||||
SysYParser::VarDefContext*>
|
||||
var_uses_;
|
||||
std::unordered_map<const SysYParser::LValueContext*,
|
||||
SysYParser::VarDefContext*>
|
||||
var_uses_;
|
||||
};
|
||||
|
||||
// 目前仅检查:
|
||||
// - 变量先声明后使用
|
||||
// - 局部变量不允许重复定义
|
||||
// 错误信息格式化工具函数
|
||||
inline std::string FormatErrMsg(const std::string& msg, int line, int col) {
|
||||
std::ostringstream oss;
|
||||
oss << "[行:" << line << ",列:" << col << "] " << msg;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// 语义分析访问器 - 继承自生成的基类
|
||||
class SemaVisitor : public SysYBaseVisitor {
|
||||
public:
|
||||
explicit SemaVisitor(IRGenContext& ctx) : ir_ctx_(ctx) {}
|
||||
|
||||
// 必须实现的 ANTLR4 接口
|
||||
std::any visit(antlr4::tree::ParseTree* tree) override {
|
||||
if (tree) {
|
||||
return tree->accept(this);
|
||||
}
|
||||
return std::any();
|
||||
}
|
||||
|
||||
std::any visitTerminal(antlr4::tree::TerminalNode* node) override {
|
||||
return std::any();
|
||||
}
|
||||
|
||||
std::any visitErrorNode(antlr4::tree::ErrorNode* node) override {
|
||||
if (node) {
|
||||
int line = node->getSymbol()->getLine();
|
||||
int col = node->getSymbol()->getCharPositionInLine() + 1;
|
||||
ir_ctx_.RecordError(ErrorMsg("语法错误节点", line, col));
|
||||
}
|
||||
return std::any();
|
||||
}
|
||||
|
||||
// 核心访问方法
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
|
||||
std::any visitDecl(SysYParser::DeclContext* ctx) override;
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
|
||||
std::any visitBtype(SysYParser::BtypeContext* ctx) override;
|
||||
std::any visitConstDef(SysYParser::ConstDefContext* ctx) override;
|
||||
std::any visitConstInitValue(SysYParser::ConstInitValueContext* ctx) override;
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
|
||||
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
|
||||
std::any visitInitValue(SysYParser::InitValueContext* ctx) override;
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
|
||||
std::any visitFuncType(SysYParser::FuncTypeContext* ctx) override;
|
||||
std::any visitFuncFParams(SysYParser::FuncFParamsContext* ctx) override;
|
||||
std::any visitFuncFParam(SysYParser::FuncFParamContext* ctx) override;
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
|
||||
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
|
||||
std::any visitStmt(SysYParser::StmtContext* ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
|
||||
std::any visitExp(SysYParser::ExpContext* ctx) override;
|
||||
std::any visitCond(SysYParser::CondContext* ctx) override;
|
||||
std::any visitLValue(SysYParser::LValueContext* ctx) override;
|
||||
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx) override;
|
||||
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
|
||||
std::any visitUnaryOp(SysYParser::UnaryOpContext* ctx) override;
|
||||
std::any visitFuncRParams(SysYParser::FuncRParamsContext* ctx) override;
|
||||
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
|
||||
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
|
||||
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
|
||||
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
|
||||
std::any visitConstExp(SysYParser::ConstExpContext* ctx) override;
|
||||
|
||||
// 通用子节点访问
|
||||
std::any visitChildren(antlr4::tree::ParseTree* node) override {
|
||||
std::any result;
|
||||
if (node) {
|
||||
for (auto* child : node->children) {
|
||||
if (child) {
|
||||
result = child->accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 获取上下文引用
|
||||
IRGenContext& GetContext() { return ir_ctx_; }
|
||||
const IRGenContext& GetContext() const { return ir_ctx_; }
|
||||
|
||||
private:
|
||||
IRGenContext& ir_ctx_;
|
||||
};
|
||||
|
||||
// 语义分析入口函数
|
||||
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx);
|
||||
|
||||
// 兼容旧流程入口。
|
||||
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
|
||||
|
||||
#endif // SEMANTIC_ANALYSIS_H
|
||||
@ -1,17 +1,201 @@
|
||||
// 极简符号表:记录局部变量定义点。
|
||||
#pragma once
|
||||
#ifndef SYMBOL_TABLE_H
|
||||
#define SYMBOL_TABLE_H
|
||||
|
||||
#include <any>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
|
||||
#include "SysYParser.h"
|
||||
// 核心类型枚举
|
||||
enum class SymbolType {
|
||||
TYPE_UNKNOWN, // 未知类型
|
||||
TYPE_INT, // 整型
|
||||
TYPE_FLOAT, // 浮点型
|
||||
TYPE_VOID, // 空类型
|
||||
TYPE_ARRAY, // 数组类型
|
||||
TYPE_FUNCTION // 函数类型
|
||||
};
|
||||
|
||||
// 获取类型名称字符串
|
||||
inline const char* SymbolTypeToString(SymbolType type) {
|
||||
switch (type) {
|
||||
case SymbolType::TYPE_INT: return "int";
|
||||
case SymbolType::TYPE_FLOAT: return "float";
|
||||
case SymbolType::TYPE_VOID: return "void";
|
||||
case SymbolType::TYPE_ARRAY: return "array";
|
||||
case SymbolType::TYPE_FUNCTION: return "function";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// 变量信息结构体
|
||||
struct VarInfo {
|
||||
SymbolType type = SymbolType::TYPE_UNKNOWN;
|
||||
bool is_const = false;
|
||||
std::any const_val;
|
||||
std::vector<int> array_dims; // 数组维度,空表示非数组
|
||||
void* decl_ctx = nullptr; // 关联的语法节点
|
||||
|
||||
// 检查是否为数组类型
|
||||
bool IsArray() const { return !array_dims.empty(); }
|
||||
|
||||
// 获取数组元素总数
|
||||
int GetArrayElementCount() const {
|
||||
int count = 1;
|
||||
for (int dim : array_dims) {
|
||||
count *= dim;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
// 函数信息结构体
|
||||
struct FuncInfo {
|
||||
SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
|
||||
std::string name;
|
||||
std::vector<SymbolType> param_types; // 参数类型列表
|
||||
void* decl_ctx = nullptr; // 关联的语法节点
|
||||
|
||||
// 检查参数匹配
|
||||
bool CheckParams(const std::vector<SymbolType>& actual_params) const {
|
||||
if (actual_params.size() != param_types.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < param_types.size(); ++i) {
|
||||
if (param_types[i] != actual_params[i] &&
|
||||
param_types[i] != SymbolType::TYPE_UNKNOWN &&
|
||||
actual_params[i] != SymbolType::TYPE_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// 作用域条目结构体
|
||||
struct ScopeEntry {
|
||||
// 变量符号表:符号名 -> (符号信息, 声明节点)
|
||||
std::unordered_map<std::string, std::pair<VarInfo, void*>> var_symbols;
|
||||
|
||||
// 函数符号表:符号名 -> (函数信息, 声明节点)
|
||||
std::unordered_map<std::string, std::pair<FuncInfo, void*>> func_symbols;
|
||||
|
||||
// 清空作用域
|
||||
void Clear() {
|
||||
var_symbols.clear();
|
||||
func_symbols.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// 符号表核心类
|
||||
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:
|
||||
// ========== 作用域管理 ==========
|
||||
|
||||
// 进入新作用域
|
||||
void EnterScope();
|
||||
|
||||
// 离开当前作用域
|
||||
void LeaveScope();
|
||||
|
||||
// 获取当前作用域深度
|
||||
size_t GetScopeDepth() const { return scopes_.size(); }
|
||||
|
||||
// 检查作用域栈是否为空
|
||||
bool IsEmpty() const { return scopes_.empty(); }
|
||||
|
||||
// ========== 变量符号管理 ==========
|
||||
|
||||
// 检查当前作用域是否包含指定变量
|
||||
bool CurrentScopeHasVar(const std::string& name) const;
|
||||
|
||||
// 绑定变量到当前作用域
|
||||
void BindVar(const std::string& name, const VarInfo& info, void* decl_ctx);
|
||||
|
||||
// 查找变量(从当前作用域向上遍历)
|
||||
bool LookupVar(const std::string& name, VarInfo& out_info, void*& out_decl_ctx) const;
|
||||
|
||||
// 快速查找变量(不获取详细信息)
|
||||
bool HasVar(const std::string& name) const {
|
||||
VarInfo info;
|
||||
void* ctx;
|
||||
return LookupVar(name, info, ctx);
|
||||
}
|
||||
|
||||
// ========== 函数符号管理 ==========
|
||||
|
||||
// 检查当前作用域是否包含指定函数
|
||||
bool CurrentScopeHasFunc(const std::string& name) const;
|
||||
|
||||
// 绑定函数到当前作用域
|
||||
void BindFunc(const std::string& name, const FuncInfo& info, void* decl_ctx);
|
||||
|
||||
// 查找函数(从当前作用域向上遍历)
|
||||
bool LookupFunc(const std::string& name, FuncInfo& out_info, void*& out_decl_ctx) const;
|
||||
|
||||
// 快速查找函数(不获取详细信息)
|
||||
bool HasFunc(const std::string& name) const {
|
||||
FuncInfo info;
|
||||
void* ctx;
|
||||
return LookupFunc(name, info, ctx);
|
||||
}
|
||||
|
||||
// ========== 循环状态管理 ==========
|
||||
|
||||
// 进入循环
|
||||
void EnterLoop();
|
||||
|
||||
// 离开循环
|
||||
void ExitLoop();
|
||||
|
||||
// 检查是否在循环内
|
||||
bool InLoop() const;
|
||||
|
||||
// 获取循环嵌套深度
|
||||
int GetLoopDepth() const { return loop_depth_; }
|
||||
|
||||
// ========== 辅助功能 ==========
|
||||
|
||||
// 清空所有作用域和状态
|
||||
void Clear();
|
||||
|
||||
// 获取当前作用域中所有变量名
|
||||
std::vector<std::string> GetCurrentScopeVarNames() const;
|
||||
|
||||
// 获取当前作用域中所有函数名
|
||||
std::vector<std::string> GetCurrentScopeFuncNames() const;
|
||||
|
||||
// 调试:打印符号表内容
|
||||
void Dump() const;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
|
||||
private:
|
||||
// 作用域栈
|
||||
std::stack<ScopeEntry> scopes_;
|
||||
|
||||
// 循环嵌套深度
|
||||
int loop_depth_ = 0;
|
||||
};
|
||||
|
||||
// 类型兼容性检查函数
|
||||
inline bool IsTypeCompatible(SymbolType expected, SymbolType actual) {
|
||||
if (expected == SymbolType::TYPE_UNKNOWN || actual == SymbolType::TYPE_UNKNOWN) {
|
||||
return true; // 未知类型视为兼容
|
||||
}
|
||||
|
||||
// 基本类型兼容规则
|
||||
if (expected == actual) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// int 可以隐式转换为 float
|
||||
if (expected == SymbolType::TYPE_FLOAT && actual == SymbolType::TYPE_INT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // SYMBOL_TABLE_H
|
||||
@ -1,200 +1,224 @@
|
||||
#include "sem/Sema.h"
|
||||
|
||||
#include <any>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "sem/SymbolTable.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
namespace {
|
||||
|
||||
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
|
||||
if (!lvalue.ID()) {
|
||||
throw std::runtime_error(FormatError("sema", "非法左值"));
|
||||
SymbolType ParseType(const std::string& text) {
|
||||
if (text == "int") {
|
||||
return SymbolType::TYPE_INT;
|
||||
}
|
||||
return lvalue.ID()->getText();
|
||||
}
|
||||
|
||||
class SemaVisitor final : public SysYBaseVisitor {
|
||||
public:
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("sema", "缺少编译单元"));
|
||||
}
|
||||
auto* func = ctx->funcDef();
|
||||
if (!func || !func->blockStmt()) {
|
||||
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
|
||||
}
|
||||
if (!func->ID() || func->ID()->getText() != "main") {
|
||||
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
|
||||
}
|
||||
func->accept(this);
|
||||
if (!seen_return_) {
|
||||
throw std::runtime_error(
|
||||
FormatError("sema", "main 函数必须包含 return 语句"));
|
||||
}
|
||||
return {};
|
||||
if (text == "float") {
|
||||
return SymbolType::TYPE_FLOAT;
|
||||
}
|
||||
if (text == "void") {
|
||||
return SymbolType::TYPE_VOID;
|
||||
}
|
||||
return SymbolType::TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override {
|
||||
if (!ctx || !ctx->blockStmt()) {
|
||||
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
|
||||
}
|
||||
if (!ctx->funcType() || !ctx->funcType()->INT()) {
|
||||
throw std::runtime_error(FormatError("sema", "当前仅支持 int main"));
|
||||
}
|
||||
const auto& items = ctx->blockStmt()->blockItem();
|
||||
if (items.empty()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("sema", "main 函数不能为空,且必须以 return 结束"));
|
||||
}
|
||||
ctx->blockStmt()->accept(this);
|
||||
return {};
|
||||
} // namespace
|
||||
|
||||
std::any SemaVisitor::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitDecl(SysYParser::DeclContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitConstDef(SysYParser::ConstDefContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitConstInitValue(SysYParser::ConstInitValueContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitVarDecl(SysYParser::VarDeclContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitVarDef(SysYParser::VarDefContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitInitValue(SysYParser::InitValueContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitFuncDef(SysYParser::FuncDefContext* ctx) {
|
||||
SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
|
||||
if (ctx && ctx->funcType()) {
|
||||
ret_type = ParseType(ctx->funcType()->getText());
|
||||
}
|
||||
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("sema", "缺少语句块"));
|
||||
}
|
||||
const auto& items = ctx->blockItem();
|
||||
for (size_t i = 0; i < items.size(); ++i) {
|
||||
auto* item = items[i];
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
if (seen_return_) {
|
||||
throw std::runtime_error(
|
||||
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
|
||||
}
|
||||
current_item_index_ = i;
|
||||
total_items_ = items.size();
|
||||
item->accept(this);
|
||||
}
|
||||
ir_ctx_.SetCurrentFuncReturnType(ret_type);
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitFuncType(SysYParser::FuncTypeContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitFuncFParams(SysYParser::FuncFParamsContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitFuncFParam(SysYParser::FuncFParamContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
||||
ir_ctx_.EnterScope();
|
||||
std::any result = visitChildren(ctx);
|
||||
ir_ctx_.LeaveScope();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitStmt(SysYParser::StmtContext* ctx) {
|
||||
if (!ctx) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
|
||||
}
|
||||
if (ctx->decl()) {
|
||||
ctx->decl()->accept(this);
|
||||
return {};
|
||||
}
|
||||
if (ctx->stmt()) {
|
||||
ctx->stmt()->accept(this);
|
||||
return {};
|
||||
}
|
||||
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
|
||||
if (ctx->WHILE()) {
|
||||
ir_ctx_.EnterLoop();
|
||||
std::any result = visitChildren(ctx);
|
||||
ir_ctx_.ExitLoop();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::any visitDecl(SysYParser::DeclContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("sema", "非法变量声明"));
|
||||
}
|
||||
if (!ctx->btype() || !ctx->btype()->INT()) {
|
||||
throw std::runtime_error(FormatError("sema", "当前仅支持局部 int 变量声明"));
|
||||
}
|
||||
auto* var_def = ctx->varDef();
|
||||
if (!var_def || !var_def->lValue()) {
|
||||
throw std::runtime_error(FormatError("sema", "非法变量声明"));
|
||||
}
|
||||
const std::string name = GetLValueName(*var_def->lValue());
|
||||
if (table_.Contains(name)) {
|
||||
throw std::runtime_error(FormatError("sema", "重复定义变量: " + name));
|
||||
}
|
||||
if (auto* init = var_def->initValue()) {
|
||||
if (!init->exp()) {
|
||||
throw std::runtime_error(FormatError("sema", "当前不支持聚合初始化"));
|
||||
}
|
||||
init->exp()->accept(this);
|
||||
}
|
||||
table_.Add(name, var_def);
|
||||
return {};
|
||||
if (ctx->BREAK() && !ir_ctx_.InLoop()) {
|
||||
ir_ctx_.RecordError(
|
||||
ErrorMsg("break 只能出现在循环语句中", ctx->getStart()->getLine(),
|
||||
ctx->getStart()->getCharPositionInLine() + 1));
|
||||
}
|
||||
|
||||
std::any visitStmt(SysYParser::StmtContext* ctx) override {
|
||||
if (!ctx || !ctx->returnStmt()) {
|
||||
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
|
||||
}
|
||||
ctx->returnStmt()->accept(this);
|
||||
return {};
|
||||
if (ctx->CONTINUE() && !ir_ctx_.InLoop()) {
|
||||
ir_ctx_.RecordError(
|
||||
ErrorMsg("continue 只能出现在循环语句中", ctx->getStart()->getLine(),
|
||||
ctx->getStart()->getCharPositionInLine() + 1));
|
||||
}
|
||||
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override {
|
||||
if (!ctx || !ctx->exp()) {
|
||||
throw std::runtime_error(FormatError("sema", "return 缺少表达式"));
|
||||
}
|
||||
ctx->exp()->accept(this);
|
||||
seen_return_ = true;
|
||||
if (current_item_index_ + 1 != total_items_) {
|
||||
throw std::runtime_error(
|
||||
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override {
|
||||
if (!ctx || !ctx->exp()) {
|
||||
throw std::runtime_error(FormatError("sema", "非法括号表达式"));
|
||||
}
|
||||
ctx->exp()->accept(this);
|
||||
std::any SemaVisitor::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
|
||||
if (!ctx) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::any visitVarExp(SysYParser::VarExpContext* ctx) override {
|
||||
if (!ctx || !ctx->var()) {
|
||||
throw std::runtime_error(FormatError("sema", "非法变量表达式"));
|
||||
}
|
||||
ctx->var()->accept(this);
|
||||
return {};
|
||||
if (ctx->exp() && ir_ctx_.GetCurrentFuncReturnType() == SymbolType::TYPE_VOID) {
|
||||
ir_ctx_.RecordError(
|
||||
ErrorMsg("void 函数不应返回表达式", ctx->getStart()->getLine(),
|
||||
ctx->getStart()->getCharPositionInLine() + 1));
|
||||
}
|
||||
|
||||
std::any visitNumberExp(SysYParser::NumberExpContext* ctx) override {
|
||||
if (!ctx || !ctx->number() || !ctx->number()->ILITERAL()) {
|
||||
throw std::runtime_error(FormatError("sema", "当前仅支持整数字面量"));
|
||||
}
|
||||
return {};
|
||||
if (!ctx->exp() &&
|
||||
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_VOID &&
|
||||
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_UNKNOWN) {
|
||||
ir_ctx_.RecordError(
|
||||
ErrorMsg("非 void 函数 return 必须带表达式", ctx->getStart()->getLine(),
|
||||
ctx->getStart()->getCharPositionInLine() + 1));
|
||||
}
|
||||
|
||||
std::any visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) override {
|
||||
if (!ctx || !ctx->exp(0) || !ctx->exp(1)) {
|
||||
throw std::runtime_error(FormatError("sema", "暂不支持的表达式形式"));
|
||||
}
|
||||
ctx->exp(0)->accept(this);
|
||||
ctx->exp(1)->accept(this);
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitExp(SysYParser::ExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitCond(SysYParser::CondContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitLValue(SysYParser::LValueContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) {
|
||||
if (!ctx) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::any visitVar(SysYParser::VarContext* ctx) override {
|
||||
if (!ctx || !ctx->ID()) {
|
||||
throw std::runtime_error(FormatError("sema", "非法变量引用"));
|
||||
}
|
||||
const std::string name = ctx->ID()->getText();
|
||||
auto* decl = table_.Lookup(name);
|
||||
if (!decl) {
|
||||
throw std::runtime_error(FormatError("sema", "使用了未定义的变量: " + name));
|
||||
}
|
||||
sema_.BindVarUse(ctx, decl);
|
||||
return {};
|
||||
if (ctx->ILITERAL()) {
|
||||
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
|
||||
ir_ctx_.SetConstVal(ctx, std::any(0L));
|
||||
} else if (ctx->FLITERAL()) {
|
||||
ir_ctx_.SetType(ctx, SymbolType::TYPE_FLOAT);
|
||||
ir_ctx_.SetConstVal(ctx, std::any(0.0));
|
||||
}
|
||||
|
||||
SemanticContext TakeSemanticContext() { return std::move(sema_); }
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
SymbolTable table_;
|
||||
SemanticContext sema_;
|
||||
bool seen_return_ = false;
|
||||
size_t current_item_index_ = 0;
|
||||
size_t total_items_ = 0;
|
||||
};
|
||||
std::any SemaVisitor::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
std::any SemaVisitor::visitUnaryOp(SysYParser::UnaryOpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitMulExp(SysYParser::MulExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitAddExp(SysYParser::AddExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitRelExp(SysYParser::RelExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitEqExp(SysYParser::EqExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitLAndExp(SysYParser::LAndExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitLOrExp(SysYParser::LOrExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
std::any SemaVisitor::visitConstExp(SysYParser::ConstExpContext* ctx) {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx) {
|
||||
if (!ctx) {
|
||||
throw std::invalid_argument("CompUnitContext is null");
|
||||
}
|
||||
SemaVisitor visitor(ir_ctx);
|
||||
visitor.visit(ctx);
|
||||
}
|
||||
|
||||
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
|
||||
SemaVisitor visitor;
|
||||
comp_unit.accept(&visitor);
|
||||
return visitor.TakeSemanticContext();
|
||||
IRGenContext ctx;
|
||||
RunSemanticAnalysis(&comp_unit, ctx);
|
||||
return SemanticContext();
|
||||
}
|
||||
|
||||
@ -1,17 +1,164 @@
|
||||
// 维护局部变量声明的注册与查找。
|
||||
#include "../../include/sem/SymbolTable.h"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "sem/SymbolTable.h"
|
||||
// 进入新作用域
|
||||
void SymbolTable::EnterScope() {
|
||||
scopes_.push(ScopeEntry());
|
||||
}
|
||||
|
||||
// 离开当前作用域
|
||||
void SymbolTable::LeaveScope() {
|
||||
if (scopes_.empty()) {
|
||||
throw std::runtime_error("SymbolTable Error: 作用域栈为空,无法退出");
|
||||
}
|
||||
scopes_.pop();
|
||||
}
|
||||
|
||||
// 绑定变量到当前作用域
|
||||
void SymbolTable::BindVar(const std::string& name, const VarInfo& info, void* decl_ctx) {
|
||||
if (CurrentScopeHasVar(name)) {
|
||||
throw std::runtime_error("变量'" + name + "'在当前作用域重复定义");
|
||||
}
|
||||
scopes_.top().var_symbols[name] = {info, decl_ctx};
|
||||
}
|
||||
|
||||
// 绑定函数到当前作用域
|
||||
void SymbolTable::BindFunc(const std::string& name, const FuncInfo& info, void* decl_ctx) {
|
||||
if (CurrentScopeHasFunc(name)) {
|
||||
throw std::runtime_error("函数'" + name + "'在当前作用域重复定义");
|
||||
}
|
||||
scopes_.top().func_symbols[name] = {info, decl_ctx};
|
||||
}
|
||||
|
||||
// 查找变量(从当前作用域向上遍历)
|
||||
bool SymbolTable::LookupVar(const std::string& name, VarInfo& out_info, void*& out_decl_ctx) const {
|
||||
if (scopes_.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto temp_stack = scopes_;
|
||||
while (!temp_stack.empty()) {
|
||||
auto& scope = temp_stack.top();
|
||||
auto it = scope.var_symbols.find(name);
|
||||
if (it != scope.var_symbols.end()) {
|
||||
out_info = it->second.first;
|
||||
out_decl_ctx = it->second.second;
|
||||
return true;
|
||||
}
|
||||
temp_stack.pop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找函数(从当前作用域向上遍历,通常函数在全局作用域)
|
||||
bool SymbolTable::LookupFunc(const std::string& name, FuncInfo& out_info, void*& out_decl_ctx) const {
|
||||
if (scopes_.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto temp_stack = scopes_;
|
||||
while (!temp_stack.empty()) {
|
||||
auto& scope = temp_stack.top();
|
||||
auto it = scope.func_symbols.find(name);
|
||||
if (it != scope.func_symbols.end()) {
|
||||
out_info = it->second.first;
|
||||
out_decl_ctx = it->second.second;
|
||||
return true;
|
||||
}
|
||||
temp_stack.pop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SymbolTable::Add(const std::string& name,
|
||||
SysYParser::VarDefContext* decl) {
|
||||
table_[name] = decl;
|
||||
// 检查当前作用域是否包含指定变量
|
||||
bool SymbolTable::CurrentScopeHasVar(const std::string& name) const {
|
||||
if (scopes_.empty()) {
|
||||
return false;
|
||||
}
|
||||
return scopes_.top().var_symbols.count(name) > 0;
|
||||
}
|
||||
|
||||
bool SymbolTable::Contains(const std::string& name) const {
|
||||
return table_.find(name) != table_.end();
|
||||
// 检查当前作用域是否包含指定函数
|
||||
bool SymbolTable::CurrentScopeHasFunc(const std::string& name) const {
|
||||
if (scopes_.empty()) {
|
||||
return false;
|
||||
}
|
||||
return scopes_.top().func_symbols.count(name) > 0;
|
||||
}
|
||||
|
||||
SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const {
|
||||
auto it = table_.find(name);
|
||||
return it == table_.end() ? nullptr : it->second;
|
||||
// 进入循环
|
||||
void SymbolTable::EnterLoop() {
|
||||
loop_depth_++;
|
||||
}
|
||||
|
||||
// 离开循环
|
||||
void SymbolTable::ExitLoop() {
|
||||
if (loop_depth_ > 0) loop_depth_--;
|
||||
}
|
||||
|
||||
// 检查是否在循环内
|
||||
bool SymbolTable::InLoop() const {
|
||||
return loop_depth_ > 0;
|
||||
}
|
||||
|
||||
// 清空所有作用域和状态
|
||||
void SymbolTable::Clear() {
|
||||
while (!scopes_.empty()) {
|
||||
scopes_.pop();
|
||||
}
|
||||
loop_depth_ = 0;
|
||||
}
|
||||
|
||||
// 获取当前作用域中所有变量名
|
||||
std::vector<std::string> SymbolTable::GetCurrentScopeVarNames() const {
|
||||
std::vector<std::string> names;
|
||||
if (!scopes_.empty()) {
|
||||
for (const auto& pair : scopes_.top().var_symbols) {
|
||||
names.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// 获取当前作用域中所有函数名
|
||||
std::vector<std::string> SymbolTable::GetCurrentScopeFuncNames() const {
|
||||
std::vector<std::string> names;
|
||||
if (!scopes_.empty()) {
|
||||
for (const auto& pair : scopes_.top().func_symbols) {
|
||||
names.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// 调试:打印符号表内容
|
||||
void SymbolTable::Dump() const {
|
||||
std::cout << "符号表内容 (作用域深度: " << scopes_.size() << "):\n";
|
||||
int scope_idx = 0;
|
||||
auto temp_stack = scopes_;
|
||||
|
||||
while (!temp_stack.empty()) {
|
||||
std::cout << "\n作用域 " << scope_idx++ << ":\n";
|
||||
auto& scope = temp_stack.top();
|
||||
|
||||
std::cout << " 变量:\n";
|
||||
for (const auto& var_pair : scope.var_symbols) {
|
||||
const VarInfo& info = var_pair.second.first;
|
||||
std::cout << " " << var_pair.first << ": "
|
||||
<< SymbolTypeToString(info.type)
|
||||
<< (info.is_const ? " (const)" : "")
|
||||
<< (info.IsArray() ? " [数组]" : "")
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
std::cout << " 函数:\n";
|
||||
for (const auto& func_pair : scope.func_symbols) {
|
||||
const FuncInfo& info = func_pair.second.first;
|
||||
std::cout << " " << func_pair.first << ": "
|
||||
<< SymbolTypeToString(info.ret_type) << " ("
|
||||
<< info.param_types.size() << " 个参数)\n";
|
||||
}
|
||||
|
||||
temp_stack.pop();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue