#include "sem/Sema.h" #include #include #include #include #include #include "SysYBaseVisitor.h" #include "sem/func.h" #include "utils/Log.h" using namespace sem; namespace { // ─── 作用域栈 ───────────────────────────────────────────────────────────────── class ScopeStack { public: void PushScope() { scopes_.emplace_back(); } void PopScope() { if (!scopes_.empty()) scopes_.pop_back(); } // 在当前作用域定义符号 void Define(const std::string& name, antlr4::ParserRuleContext* decl) { if (scopes_.empty()) return; scopes_.back()[name] = decl; } // 检查当前作用域是否已定义(用于重复定义检查) bool ContainsInCurrent(const std::string& name) const { return !scopes_.empty() && scopes_.back().count(name) > 0; } // 向上查找 antlr4::ParserRuleContext* Lookup(const std::string& name) const { for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) { auto found = it->find(name); if (found != it->end()) return found->second; } return nullptr; } private: std::vector> scopes_; }; // ─── 语义分析访问者 ──────────────────────────────────────────────────────────── class SemaVisitor final : public SysYBaseVisitor { public: // 顶层:global scope → decl (global var/const) → funcDef std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override { if (!ctx) { throw std::runtime_error(FormatError("sema", "缺少编译单元")); } scope_.PushScope(); // global scope // 先处理全局声明 for (auto* decl : ctx->decl()) { if (decl) decl->accept(this); } // 再处理函数定义 bool has_main = false; for (auto* func : ctx->funcDef()) { if (!func) continue; if (func->Ident() && func->Ident()->getText() == "main") { has_main = true; } func->accept(this); } if (!has_main) { throw std::runtime_error(FormatError("sema", "缺少main函数定义")); } scope_.PopScope(); return {}; } // 函数定义:参数入作用域 → 函数体 std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override { if (!ctx) return {}; scope_.PushScope(); if (auto* params = ctx->funcFParams()) { for (auto* param : params->funcFParam()) { if (!param || !param->Ident()) continue; std::string name = param->Ident()->getText(); if (scope_.ContainsInCurrent(name)) { throw std::runtime_error( FormatError("sema", "参数重复定义: " + name)); } scope_.Define(name, param); } } if (ctx->block()) ctx->block()->accept(this); scope_.PopScope(); return {}; } // 块:新作用域 std::any visitBlock(SysYParser::BlockContext* ctx) override { if (!ctx) return {}; scope_.PushScope(); for (auto* item : ctx->blockItem()) { if (item) item->accept(this); } scope_.PopScope(); return {}; } // 块内项:分发 std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override { if (!ctx) return {}; if (ctx->decl()) ctx->decl()->accept(this); if (ctx->stmt()) ctx->stmt()->accept(this); return {}; } // 声明:分发到 varDecl / constDecl std::any visitDecl(SysYParser::DeclContext* ctx) override { if (!ctx) return {}; if (ctx->varDecl()) ctx->varDecl()->accept(this); if (ctx->constDecl()) ctx->constDecl()->accept(this); return {}; } // 变量声明 std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override { if (!ctx) return {}; for (auto* varDef : ctx->varDef()) { if (!varDef || !varDef->Ident()) continue; std::string name = varDef->Ident()->getText(); if (scope_.ContainsInCurrent(name)) { throw std::runtime_error( FormatError("sema", "变量重复定义: " + name)); } scope_.Define(name, varDef); // 访问初始化表达式中的变量引用 if (varDef->initVal()) varDef->initVal()->accept(this); } return {}; } // 常量声明 std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override { if (!ctx) return {}; for (auto* constDef : ctx->constDef()) { if (!constDef || !constDef->Ident()) continue; std::string name = constDef->Ident()->getText(); if (scope_.ContainsInCurrent(name)) { throw std::runtime_error( FormatError("sema", "常量重复定义: " + name)); } scope_.Define(name, constDef); // 初始化表达式中的引用 if (constDef->constInitVal()) constDef->constInitVal()->accept(this); } return {}; } // 语句:分发各种形式 std::any visitStmt(SysYParser::StmtContext* ctx) override { if (!ctx) return {}; // 赋值语句:lVar = exp; if (ctx->lVar() && ctx->Assign()) { ctx->lVar()->accept(this); if (ctx->exp()) ctx->exp()->accept(this); return {}; } // 表达式语句:(exp)?; if (ctx->exp() && !ctx->Return() && !ctx->If() && !ctx->While()) { ctx->exp()->accept(this); return {}; } // 块语句 if (ctx->block()) { ctx->block()->accept(this); return {}; } // if 语句 if (ctx->If()) { if (ctx->cond()) ctx->cond()->accept(this); auto stmts = ctx->stmt(); for (auto* s : stmts) { if (s) s->accept(this); } return {}; } // while 语句 if (ctx->While()) { if (ctx->cond()) ctx->cond()->accept(this); auto stmts = ctx->stmt(); for (auto* s : stmts) { if (s) s->accept(this); } return {}; } // return 语句 if (ctx->Return()) { if (ctx->exp()) ctx->exp()->accept(this); return {}; } // break / continue:无变量引用 return {}; } // lVar:绑定变量使用 std::any visitLVar(SysYParser::LVarContext* ctx) override { if (!ctx || !ctx->Ident()) return {}; std::string name = ctx->Ident()->getText(); auto* decl = scope_.Lookup(name); if (!decl) { // 可能是外部函数或未声明变量,不强制报错(IRGen 会处理外部调用) // 但对变量使用报错 throw std::runtime_error( FormatError("sema", "未声明变量: " + name)); } sema_.BindVarUse(ctx->Ident(), decl); // 下标表达式也需要访问 for (auto* e : ctx->exp()) { if (e) e->accept(this); } return {}; } // 表达式:通过 visitChildren 自动递归 std::any visitExp(SysYParser::ExpContext* ctx) override { return visitChildren(ctx); } std::any visitAddExp(SysYParser::AddExpContext* ctx) override { return visitChildren(ctx); } std::any visitMulExp(SysYParser::MulExpContext* ctx) override { return visitChildren(ctx); } std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override { // 函数调用:Ident L_PAREN ... if (ctx->Ident() && ctx->L_PAREN()) { if (ctx->funcRParams()) ctx->funcRParams()->accept(this); return {}; } return visitChildren(ctx); } std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override { return visitChildren(ctx); } std::any visitCond(SysYParser::CondContext* ctx) override { return visitChildren(ctx); } std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override { return visitChildren(ctx); } std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override { return visitChildren(ctx); } std::any visitRelExp(SysYParser::RelExpContext* ctx) override { return visitChildren(ctx); } std::any visitEqExp(SysYParser::EqExpContext* ctx) override { return visitChildren(ctx); } std::any visitFuncRParams(SysYParser::FuncRParamsContext* ctx) override { return visitChildren(ctx); } std::any visitInitVal(SysYParser::InitValContext* ctx) override { return visitChildren(ctx); } std::any visitConstInitVal(SysYParser::ConstInitValContext* ctx) override { // 常量初始化器中通常没有变量引用(只有字面量), // 但如果有 constExp 引用其他常量则需要访问 return visitChildren(ctx); } std::any visitConstExp(SysYParser::ConstExpContext* ctx) override { return visitChildren(ctx); } SemanticContext TakeSemanticContext() { return std::move(sema_); } private: ScopeStack scope_; SemanticContext sema_; }; } // namespace SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) { SemaVisitor visitor; comp_unit.accept(&visitor); return visitor.TakeSemanticContext(); }