style(ir): 纠正代码位置

This commit is contained in:
jing
2026-03-11 22:08:27 +08:00
parent 62dde8d7ab
commit fab6983d40
17 changed files with 193 additions and 88 deletions

View File

@@ -3,3 +3,22 @@
// - 维护或可计算前驱/后继关系,用于 CFG 分析与优化 // - 维护或可计算前驱/后继关系,用于 CFG 分析与优化
#include "ir/IR.h" #include "ir/IR.h"
#include <utility>
namespace ir {
BasicBlock::BasicBlock(std::string name) : name_(std::move(name)) {}
const std::string& BasicBlock::name() const { return name_; }
bool BasicBlock::HasTerminator() const {
return !instructions_.empty() && instructions_.back()->IsTerminator();
}
const std::vector<std::unique_ptr<Instruction>>& BasicBlock::instructions()
const {
return instructions_;
}
} // namespace ir

View File

@@ -20,4 +20,12 @@ BasicBlock* Function::CreateBlock(const std::string& name) {
return ptr; return ptr;
} }
BasicBlock* Function::entry() { return entry_; }
const BasicBlock* Function::entry() const { return entry_; }
const std::vector<std::unique_ptr<BasicBlock>>& Function::blocks() const {
return blocks_;
}
} // namespace ir } // namespace ir

View File

@@ -41,8 +41,8 @@ Context& DefaultContext();
class Type { class Type {
public: public:
enum class Kind { Void, Int32, PtrInt32 }; enum class Kind { Void, Int32, PtrInt32 };
explicit Type(Kind k) : kind_(k) {} explicit Type(Kind k);
Kind kind() const { return kind_; } Kind kind() const;
static std::shared_ptr<Type> Void(); static std::shared_ptr<Type> Void();
static std::shared_ptr<Type> Int32(); static std::shared_ptr<Type> Int32();
static std::shared_ptr<Type> PtrInt32(); static std::shared_ptr<Type> PtrInt32();
@@ -53,14 +53,13 @@ class Type {
class Value { class Value {
public: public:
Value(std::shared_ptr<Type> ty, std::string name) Value(std::shared_ptr<Type> ty, std::string name);
: type_(std::move(ty)), name_(std::move(name)) {}
virtual ~Value() = default; virtual ~Value() = default;
const std::shared_ptr<Type>& type() const { return type_; } const std::shared_ptr<Type>& type() const;
const std::string& name() const { return name_; } const std::string& name() const;
void set_name(std::string n) { name_ = std::move(n); } void set_name(std::string n);
void AddUser(Instruction* user) { users_.push_back(user); } void AddUser(Instruction* user);
const std::vector<Instruction*>& users() const { return users_; } const std::vector<Instruction*>& users() const;
protected: protected:
std::shared_ptr<Type> type_; std::shared_ptr<Type> type_;
@@ -77,16 +76,16 @@ class ConstantInt : public Value {
int value_{}; int value_{};
}; };
// 后续还需要扩展更多指令类型。
enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret }; enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret };
class Instruction : public Value { class Instruction : public Value {
public: public:
Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "") Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name = "");
: Value(std::move(ty), std::move(name)), opcode_(op) {} Opcode opcode() const;
Opcode opcode() const { return opcode_; } bool IsTerminator() const;
bool IsTerminator() const { return opcode_ == Opcode::Ret; } BasicBlock* parent() const;
BasicBlock* parent() const { return parent_; } void set_parent(BasicBlock* parent);
void set_parent(BasicBlock* parent) { parent_ = parent; }
private: private:
Opcode opcode_; Opcode opcode_;
@@ -97,8 +96,8 @@ class BinaryInst : public Instruction {
public: public:
BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs, BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
std::string name); std::string name);
Value* lhs() const { return lhs_; } Value* lhs() const;
Value* rhs() const { return rhs_; } Value* rhs() const;
private: private:
Value* lhs_; Value* lhs_;
@@ -108,7 +107,7 @@ class BinaryInst : public Instruction {
class ReturnInst : public Instruction { class ReturnInst : public Instruction {
public: public:
explicit ReturnInst(Value* val); explicit ReturnInst(Value* val);
Value* value() const { return value_; } Value* value() const;
private: private:
Value* value_; Value* value_;
@@ -122,7 +121,7 @@ class AllocaInst : public Instruction {
class LoadInst : public Instruction { class LoadInst : public Instruction {
public: public:
LoadInst(Value* ptr, std::string name); LoadInst(Value* ptr, std::string name);
Value* ptr() const { return ptr_; } Value* ptr() const;
private: private:
Value* ptr_; Value* ptr_;
@@ -131,8 +130,8 @@ class LoadInst : public Instruction {
class StoreInst : public Instruction { class StoreInst : public Instruction {
public: public:
StoreInst(Value* val, Value* ptr); StoreInst(Value* val, Value* ptr);
Value* value() const { return value_; } Value* value() const;
Value* ptr() const { return ptr_; } Value* ptr() const;
private: private:
Value* value_; Value* value_;
@@ -141,14 +140,10 @@ class StoreInst : public Instruction {
class BasicBlock { class BasicBlock {
public: public:
explicit BasicBlock(std::string name) : name_(std::move(name)) {} explicit BasicBlock(std::string name);
const std::string& name() const { return name_; } const std::string& name() const;
bool HasTerminator() const { bool HasTerminator() const;
return !instructions_.empty() && instructions_.back()->IsTerminator(); const std::vector<std::unique_ptr<Instruction>>& instructions() const;
}
const std::vector<std::unique_ptr<Instruction>>& instructions() const {
return instructions_;
}
template <typename T, typename... Args> template <typename T, typename... Args>
T* Append(Args&&... args) { T* Append(Args&&... args) {
if (HasTerminator()) { if (HasTerminator()) {
@@ -172,11 +167,9 @@ class Function : public Value {
// 允许显式指定返回类型,便于后续扩展多种函数签名。 // 允许显式指定返回类型,便于后续扩展多种函数签名。
Function(std::string name, std::shared_ptr<Type> ret_type); Function(std::string name, std::shared_ptr<Type> ret_type);
BasicBlock* CreateBlock(const std::string& name); BasicBlock* CreateBlock(const std::string& name);
BasicBlock* entry() { return entry_; } BasicBlock* entry();
const BasicBlock* entry() const { return entry_; } const BasicBlock* entry() const;
const std::vector<std::unique_ptr<BasicBlock>>& blocks() const { const std::vector<std::unique_ptr<BasicBlock>>& blocks() const;
return blocks_;
}
private: private:
BasicBlock* entry_ = nullptr; BasicBlock* entry_ = nullptr;
@@ -188,9 +181,7 @@ class Module {
// 创建函数时显式传入返回类型,便于在 IRGen 中根据语法树信息选择类型。 // 创建函数时显式传入返回类型,便于在 IRGen 中根据语法树信息选择类型。
Function* CreateFunction(const std::string& name, Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type); std::shared_ptr<Type> ret_type);
const std::vector<std::unique_ptr<Function>>& functions() const { const std::vector<std::unique_ptr<Function>>& functions() const;
return functions_;
}
private: private:
std::vector<std::unique_ptr<Function>> functions_; std::vector<std::unique_ptr<Function>> functions_;
@@ -198,17 +189,15 @@ class Module {
class IRBuilder { class IRBuilder {
public: public:
explicit IRBuilder(BasicBlock* bb) : insertBlock_(bb) {} explicit IRBuilder(BasicBlock* bb);
void SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; } void SetInsertPoint(BasicBlock* bb);
BasicBlock* GetInsertBlock() const { return insertBlock_; } BasicBlock* GetInsertBlock() const;
// 构造常量、二元运算、返回指令的最小集合。 // 构造常量、二元运算、返回指令的最小集合。
ConstantInt* CreateConstInt(int v); ConstantInt* CreateConstInt(int v);
BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs, BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name); const std::string& name);
BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name) { BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name);
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
AllocaInst* CreateAllocaI32(const std::string& name); AllocaInst* CreateAllocaI32(const std::string& name);
LoadInst* CreateLoad(Value* ptr, const std::string& name); LoadInst* CreateLoad(Value* ptr, const std::string& name);
StoreInst* CreateStore(Value* val, Value* ptr); StoreInst* CreateStore(Value* val, Value* ptr);

View File

@@ -18,6 +18,12 @@ bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
} // namespace } // namespace
IRBuilder::IRBuilder(BasicBlock* bb) : insertBlock_(bb) {}
void IRBuilder::SetInsertPoint(BasicBlock* bb) { insertBlock_ = bb; }
BasicBlock* IRBuilder::GetInsertBlock() const { return insertBlock_; }
ConstantInt* IRBuilder::CreateConstInt(int v) { ConstantInt* IRBuilder::CreateConstInt(int v) {
// 常量不需要挂在基本块里,由 Context 负责去重与生命周期。 // 常量不需要挂在基本块里,由 Context 负责去重与生命周期。
return DefaultContext().GetConstInt(v); return DefaultContext().GetConstInt(v);
@@ -47,6 +53,11 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs,
return insertBlock_->Append<BinaryInst>(op, lhs->type(), lhs, rhs, name); return insertBlock_->Append<BinaryInst>(op, lhs->type(), lhs, rhs, name);
} }
BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) { AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
if (!insertBlock_) { if (!insertBlock_) {
throw std::runtime_error("IRBuilder 未设置插入点"); throw std::runtime_error("IRBuilder 未设置插入点");

View File

@@ -18,6 +18,17 @@ bool IsPtrInt32Type(const std::shared_ptr<Type>& ty) {
} // namespace } // namespace
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
: Value(std::move(ty), std::move(name)), opcode_(op) {}
Opcode Instruction::opcode() const { return opcode_; }
bool Instruction::IsTerminator() const { return opcode_ == Opcode::Ret; }
BasicBlock* Instruction::parent() const { return parent_; }
void Instruction::set_parent(BasicBlock* parent) { parent_ = parent; }
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs, BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
Value* rhs, std::string name) Value* rhs, std::string name)
: Instruction(op, std::move(ty), std::move(name)), lhs_(lhs), rhs_(rhs) { : Instruction(op, std::move(ty), std::move(name)), lhs_(lhs), rhs_(rhs) {
@@ -45,6 +56,10 @@ BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
} }
} }
Value* BinaryInst::lhs() const { return lhs_; }
Value* BinaryInst::rhs() const { return rhs_; }
ReturnInst::ReturnInst(Value* val) ReturnInst::ReturnInst(Value* val)
: Instruction(Opcode::Ret, Type::Void(), ""), value_(val) { : Instruction(Opcode::Ret, Type::Void(), ""), value_(val) {
if (!value_) { if (!value_) {
@@ -53,6 +68,8 @@ ReturnInst::ReturnInst(Value* val)
value_->AddUser(this); value_->AddUser(this);
} }
Value* ReturnInst::value() const { return value_; }
AllocaInst::AllocaInst(std::string name) AllocaInst::AllocaInst(std::string name)
: Instruction(Opcode::Alloca, Type::PtrInt32(), std::move(name)) {} : Instruction(Opcode::Alloca, Type::PtrInt32(), std::move(name)) {}
@@ -67,6 +84,8 @@ LoadInst::LoadInst(Value* ptr, std::string name)
ptr_->AddUser(this); ptr_->AddUser(this);
} }
Value* LoadInst::ptr() const { return ptr_; }
StoreInst::StoreInst(Value* val, Value* ptr) StoreInst::StoreInst(Value* val, Value* ptr)
: Instruction(Opcode::Store, Type::Void(), ""), value_(val), ptr_(ptr) { : Instruction(Opcode::Store, Type::Void(), ""), value_(val), ptr_(ptr) {
if (!value_) { if (!value_) {
@@ -85,4 +104,8 @@ StoreInst::StoreInst(Value* val, Value* ptr)
ptr_->AddUser(this); ptr_->AddUser(this);
} }
Value* StoreInst::value() const { return value_; }
Value* StoreInst::ptr() const { return ptr_; }
} // namespace ir } // namespace ir

View File

@@ -12,4 +12,8 @@ Function* Module::CreateFunction(const std::string& name,
return functions_.back().get(); return functions_.back().get();
} }
const std::vector<std::unique_ptr<Function>>& Module::functions() const {
return functions_;
}
} // namespace ir } // namespace ir

View File

@@ -6,6 +6,10 @@
namespace ir { namespace ir {
Type::Type(Kind k) : kind_(k) {}
Type::Kind Type::kind() const { return kind_; }
std::shared_ptr<Type> Type::Void() { return DefaultContext().Void(); } std::shared_ptr<Type> Type::Void() { return DefaultContext().Void(); }
std::shared_ptr<Type> Type::Int32() { return DefaultContext().Int32(); } std::shared_ptr<Type> Type::Int32() { return DefaultContext().Int32(); }

View File

@@ -5,6 +5,19 @@
namespace ir { namespace ir {
Value::Value(std::shared_ptr<Type> ty, std::string name)
: type_(std::move(ty)), name_(std::move(name)) {}
const std::shared_ptr<Type>& Value::type() const { return type_; }
const std::string& Value::name() const { return name_; }
void Value::set_name(std::string n) { name_ = std::move(n); }
void Value::AddUser(Instruction* user) { users_.push_back(user); }
const std::vector<Instruction*>& Value::users() const { return users_; }
ConstantInt::ConstantInt(int v) : Value(Type::Int32(), ""), value_(v) {} ConstantInt::ConstantInt(int v) : Value(Type::Int32(), ""), value_(v) {}
} // namespace ir } // namespace ir

View File

@@ -9,6 +9,7 @@
#include "SysYParser.h" #include "SysYParser.h"
#include "ir/IR.h" #include "ir/IR.h"
#include "sem/Sema.h"
namespace antlr4 { namespace antlr4 {
namespace tree { namespace tree {
@@ -25,7 +26,7 @@ class Value;
class IRGenImpl { class IRGenImpl {
public: public:
explicit IRGenImpl(ir::Module& module); IRGenImpl(ir::Module& module, const SemanticContext& sema);
void Gen(SysYParser::CompUnitContext& cu); void Gen(SysYParser::CompUnitContext& cu);
@@ -43,10 +44,12 @@ class IRGenImpl {
ir::Value* GenPrimary(SysYParser::PrimaryContext& primary); ir::Value* GenPrimary(SysYParser::PrimaryContext& primary);
ir::Module& module_; ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_; ir::Function* func_;
ir::IRBuilder builder_; ir::IRBuilder builder_;
// 当前只维护函数级局部变量表;若后续引入嵌套块作用域,需要改成作用域栈 // 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态
std::unordered_map<std::string, ir::Value*> locals_; std::unordered_map<SysYParser::VarDeclContext*, ir::Value*> storage_map_;
}; };
std::unique_ptr<ir::Module> GenerateIR(antlr4::tree::ParseTree* tree); std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema);

View File

@@ -36,12 +36,11 @@ void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
} }
void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) { void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) {
const std::string name = decl.Ident()->getText(); if (storage_map_.find(&decl) != storage_map_.end()) {
if (locals_.find(name) != locals_.end()) { throw std::runtime_error("[irgen] 声明重复生成存储槽位");
throw std::runtime_error("[irgen] 重复定义变量: " + name);
} }
auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp()); auto* slot = builder_.CreateAllocaI32(ir::DefaultContext().NextTemp());
locals_[name] = slot; storage_map_[&decl] = slot;
ir::Value* init = nullptr; ir::Value* init = nullptr;
if (decl.exp()) { if (decl.exp()) {

View File

@@ -4,21 +4,12 @@
#include <stdexcept> #include <stdexcept>
#include "SysYParser.h" #include "SysYParser.h"
#include "antlr4-runtime.h"
#include "ir/IR.h" #include "ir/IR.h"
std::unique_ptr<ir::Module> GenerateIR(antlr4::tree::ParseTree* tree) { std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
if (!tree) { const SemanticContext& sema) {
throw std::runtime_error("[irgen] 语法树为空");
}
auto* cu = dynamic_cast<SysYParser::CompUnitContext*>(tree);
if (!cu) {
throw std::runtime_error("[irgen] 语法树根节点不是 compUnit");
}
auto module = std::make_unique<ir::Module>(); auto module = std::make_unique<ir::Module>();
IRGenImpl gen(*module); IRGenImpl gen(*module, sema);
gen.Gen(*cu); gen.Gen(tree);
return module; return module;
} }

View File

@@ -33,10 +33,15 @@ ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
return ir::DefaultContext().GetConstInt(std::stoi(primary.Number()->getText())); return ir::DefaultContext().GetConstInt(std::stoi(primary.Number()->getText()));
} }
if (primary.Ident()) { if (primary.Ident()) {
const std::string name = primary.Ident()->getText(); auto* decl = sema_.ResolveVarUse(&primary);
auto it = locals_.find(name); if (!decl) {
if (it == locals_.end()) { throw std::runtime_error("[irgen] 变量使用缺少语义绑定: " +
throw std::runtime_error("[irgen] 变量未找到: " + name); primary.Ident()->getText());
}
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error("[irgen] 变量声明缺少存储槽位: " +
primary.Ident()->getText());
} }
return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp()); return builder_.CreateLoad(it->second, ir::DefaultContext().NextTemp());
} }

View File

@@ -19,8 +19,8 @@ void VerifyFunctionStructure(const ir::Function& func) {
} // namespace } // namespace
IRGenImpl::IRGenImpl(ir::Module& module) IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module), func_(nullptr), builder_(nullptr) {} : module_(module), sema_(sema), func_(nullptr), builder_(nullptr) {}
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) { void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
if (!cu.funcDef()) { if (!cu.funcDef()) {
@@ -39,7 +39,7 @@ void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32()); func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32());
builder_.SetInsertPoint(func_->entry()); builder_.SetInsertPoint(func_->entry());
locals_.clear(); storage_map_.clear();
GenBlock(*func.block()); GenBlock(*func.block());
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。 // 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。

View File

@@ -30,9 +30,9 @@ int main(int argc, char** argv) {
if (!comp_unit) { if (!comp_unit) {
throw std::runtime_error("[main] 语法树根节点不是 compUnit"); throw std::runtime_error("[main] 语法树根节点不是 compUnit");
} }
RunSema(*comp_unit); auto sema = RunSema(*comp_unit);
auto module = GenerateIR(antlr.tree); auto module = GenerateIR(*comp_unit, sema);
if (opts.emit_ir) { if (opts.emit_ir) {
ir::IRPrinter printer; ir::IRPrinter printer;
if (need_blank_line) { if (need_blank_line) {

View File

@@ -7,43 +7,47 @@
namespace { namespace {
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table); void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table,
SemanticContext& sema);
void CheckPrimary(SysYParser::PrimaryContext& primary, void CheckPrimary(SysYParser::PrimaryContext& primary,
const SymbolTable& table) { const SymbolTable& table, SemanticContext& sema) {
if (primary.Number()) { if (primary.Number()) {
return; return;
} }
if (primary.Ident()) { if (primary.Ident()) {
const std::string name = primary.Ident()->getText(); const std::string name = primary.Ident()->getText();
if (!table.Contains(name)) { auto* decl = table.Lookup(name);
if (!decl) {
throw std::runtime_error("[sema] 使用了未定义的变量: " + name); throw std::runtime_error("[sema] 使用了未定义的变量: " + name);
} }
sema.BindVarUse(&primary, decl);
return; return;
} }
if (primary.exp()) { if (primary.exp()) {
CheckExpr(*primary.exp(), table); CheckExpr(*primary.exp(), table, sema);
return; return;
} }
throw std::runtime_error("[sema] 暂不支持的 primary 形式"); throw std::runtime_error("[sema] 暂不支持的 primary 形式");
} }
void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table) { void CheckExpr(SysYParser::ExpContext& exp, const SymbolTable& table,
SemanticContext& sema) {
if (!exp.addExp()) { if (!exp.addExp()) {
throw std::runtime_error("[sema] 非法表达式"); throw std::runtime_error("[sema] 非法表达式");
} }
const auto& terms = exp.addExp()->primary(); const auto& terms = exp.addExp()->primary();
for (auto* term : terms) { for (auto* term : terms) {
CheckPrimary(*term, table); CheckPrimary(*term, table, sema);
} }
} }
} // namespace } // namespace
void RunSema(SysYParser::CompUnitContext& comp_unit) { SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
auto* func = comp_unit.funcDef(); auto* func = comp_unit.funcDef();
if (!func || !func->block()) { if (!func || !func->block()) {
throw std::runtime_error("[sema] 缺少 main 函数定义"); throw std::runtime_error("[sema] 缺少 main 函数定义");
@@ -53,6 +57,7 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
} }
SymbolTable table; SymbolTable table;
SemanticContext sema;
bool seen_return = false; bool seen_return = false;
const auto& items = func->block()->blockItem(); const auto& items = func->block()->blockItem();
@@ -74,14 +79,14 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
throw std::runtime_error("[sema] 重复定义变量: " + name); throw std::runtime_error("[sema] 重复定义变量: " + name);
} }
if (decl->exp()) { if (decl->exp()) {
CheckExpr(*decl->exp(), table); CheckExpr(*decl->exp(), table, sema);
} }
table.Add(name); table.Add(name, decl);
continue; continue;
} }
if (auto* stmt = item->stmt(); stmt && stmt->returnStmt()) { if (auto* stmt = item->stmt(); stmt && stmt->returnStmt()) {
auto* ret = stmt->returnStmt(); auto* ret = stmt->returnStmt();
CheckExpr(*ret->exp(), table); CheckExpr(*ret->exp(), table, sema);
seen_return = true; seen_return = true;
if (i + 1 != items.size()) { if (i + 1 != items.size()) {
throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句"); throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句");
@@ -94,4 +99,6 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) {
if (!seen_return) { if (!seen_return) {
throw std::runtime_error("[sema] main 函数必须包含 return 语句"); throw std::runtime_error("[sema] main 函数必须包含 return 语句");
} }
return sema;
} }

View File

@@ -1,9 +1,30 @@
// 基于语法树的极简语义检查。 // 基于语法树的极简语义检查与名称绑定
#pragma once #pragma once
#include <unordered_map>
#include "SysYParser.h" #include "SysYParser.h"
class SemanticContext {
public:
void BindVarUse(SysYParser::PrimaryContext* use,
SysYParser::VarDeclContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDeclContext* ResolveVarUse(
const SysYParser::PrimaryContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
private:
std::unordered_map<const SysYParser::PrimaryContext*,
SysYParser::VarDeclContext*>
var_uses_;
};
// 目前仅检查: // 目前仅检查:
// - 变量先声明后使用 // - 变量先声明后使用
// - 局部变量不允许重复定义 // - 局部变量不允许重复定义
void RunSema(SysYParser::CompUnitContext& comp_unit); SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);

View File

@@ -1,16 +1,24 @@
// 极简符号表:记录局部变量是否定义。 // 极简符号表:记录局部变量定义
#pragma once #pragma once
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "SysYParser.h"
class SymbolTable { class SymbolTable {
public: public:
void Add(const std::string& name) { table_[name] = true; } void Add(const std::string& name, SysYParser::VarDeclContext* decl) {
table_[name] = decl;
}
bool Contains(const std::string& name) const { bool Contains(const std::string& name) const {
return table_.find(name) != table_.end(); return table_.find(name) != table_.end();
} }
SysYParser::VarDeclContext* Lookup(const std::string& name) const {
auto it = table_.find(name);
return it == table_.end() ? nullptr : it->second;
}
private: private:
std::unordered_map<std::string, bool> table_; std::unordered_map<std::string, SysYParser::VarDeclContext*> table_;
}; };