diff --git a/src/antlr4/SysY.g4 b/src/antlr4/SysY.g4 index 82a624f..c29754d 100644 --- a/src/antlr4/SysY.g4 +++ b/src/antlr4/SysY.g4 @@ -10,16 +10,24 @@ compUnit ; funcDef - : Int Main L_PAREN R_PAREN block + : Int Ident L_PAREN R_PAREN block ; block - : L_BRACE stmt* R_BRACE + : L_BRACE blockItem* R_BRACE ; -stmt +blockItem + : decl + | stmt + ; + +decl : varDecl - | returnStmt + ; + +stmt + : returnStmt ; varDecl @@ -46,7 +54,6 @@ primary Int : 'int'; Return : 'return'; -Main : 'main'; AddOp : '+'; Assign : '='; diff --git a/src/frontend/AntlrDriver.cpp b/src/frontend/AntlrDriver.cpp index 296197c..6a93e90 100644 --- a/src/frontend/AntlrDriver.cpp +++ b/src/frontend/AntlrDriver.cpp @@ -12,6 +12,10 @@ namespace { +bool HasParsePrefix(const std::string& msg) { + return msg.rfind("[parse]", 0) == 0; +} + class ParseErrorListener : public antlr4::BaseErrorListener { public: void syntaxError(antlr4::Recognizer* /*recognizer*/, antlr4::Token* /*offendingSymbol*/, @@ -49,6 +53,9 @@ AntlrResult ParseFileWithAntlr(const std::string& path) { } catch (const std::exception& ex) { const std::string msg = ex.what(); if (!msg.empty()) { + if (HasParsePrefix(msg)) { + throw; + } throw std::runtime_error("[parse] 暂不支持的语法/词法 - " + msg); } if (auto* tok = parser->getCurrentToken()) { diff --git a/src/ir/IR.h b/src/ir/IR.h index 8641e00..0e60eb8 100644 --- a/src/ir/IR.h +++ b/src/ir/IR.h @@ -23,7 +23,7 @@ class Context { const std::shared_ptr& PtrInt32(); // 去重创建 i32 常量。 ConstantInt* GetConstInt(int v); - // 生成临时名称,如 %t0、%t1 ... + std::string NextTemp(); private: diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 1d4c6d2..a38652f 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -6,6 +6,13 @@ #include namespace ir { +namespace { + +bool IsArithmeticType(const std::shared_ptr& ty) { + return ty && ty->kind() == Type::Kind::Int32; +} + +} // namespace ConstantInt* IRBuilder::CreateConstInt(int v) { // 常量不需要挂在基本块里,由 Context 负责去重与生命周期。 @@ -17,7 +24,23 @@ BinaryInst* IRBuilder::CreateBinary(Opcode op, Value* lhs, Value* rhs, if (!insertBlock_) { throw std::runtime_error("IRBuilder 未设置插入点"); } - return insertBlock_->Append(op, Type::Int32(), lhs, rhs, name); + if (!lhs) { + throw std::runtime_error("IRBuilder::CreateBinary 缺少 lhs"); + } + if (!rhs) { + throw std::runtime_error("IRBuilder::CreateBinary 缺少 rhs"); + } + if (op != Opcode::Add) { + throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 Add"); + } + if (!lhs->type() || !rhs->type() || + lhs->type()->kind() != rhs->type()->kind()) { + throw std::runtime_error("IRBuilder::CreateBinary 操作数类型不匹配"); + } + if (!IsArithmeticType(lhs->type())) { + throw std::runtime_error("IRBuilder::CreateBinary 当前只支持 i32 二元运算"); + } + return insertBlock_->Append(op, lhs->type(), lhs, rhs, name); } AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) { diff --git a/src/irgen/IRGen.h b/src/irgen/IRGen.h index 8da583f..62ed290 100644 --- a/src/irgen/IRGen.h +++ b/src/irgen/IRGen.h @@ -32,6 +32,8 @@ class IRGenImpl { private: void GenFuncDef(SysYParser::FuncDefContext& func); void GenBlock(SysYParser::BlockContext& block); + bool GenBlockItem(SysYParser::BlockItemContext& item); + void GenDecl(SysYParser::DeclContext& decl); bool GenStmt(SysYParser::StmtContext& stmt); void GenVarDecl(SysYParser::VarDeclContext& decl); void GenReturnStmt(SysYParser::ReturnStmtContext& ret); diff --git a/src/irgen/IRGenDecl.cpp b/src/irgen/IRGenDecl.cpp index 4572767..7995743 100644 --- a/src/irgen/IRGenDecl.cpp +++ b/src/irgen/IRGenDecl.cpp @@ -6,15 +6,34 @@ #include "ir/IR.h" void IRGenImpl::GenBlock(SysYParser::BlockContext& block) { - for (auto* stmt : block.stmt()) { - if (stmt) { - if (GenStmt(*stmt)) { + for (auto* item : block.blockItem()) { + if (item) { + if (GenBlockItem(*item)) { break; } } } } +bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) { + if (item.decl()) { + GenDecl(*item.decl()); + return false; + } + if (item.stmt()) { + return GenStmt(*item.stmt()); + } + throw std::runtime_error("[irgen] 暂不支持的 blockItem 类型"); +} + +void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) { + if (decl.varDecl()) { + GenVarDecl(*decl.varDecl()); + return; + } + throw std::runtime_error("[irgen] 暂不支持的声明类型"); +} + void IRGenImpl::GenVarDecl(SysYParser::VarDeclContext& decl) { const std::string name = decl.Ident()->getText(); if (locals_.find(name) != locals_.end()) { diff --git a/src/irgen/IRGenFunc.cpp b/src/irgen/IRGenFunc.cpp index dfbe25f..36bd16c 100644 --- a/src/irgen/IRGenFunc.cpp +++ b/src/irgen/IRGenFunc.cpp @@ -19,8 +19,11 @@ void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) { if (!func.block()) { throw std::runtime_error("[irgen] 函数体为空"); } + if (!func.Ident()) { + throw std::runtime_error("[irgen] 缺少函数名"); + } - func_ = module_.CreateFunction("main", ir::Type::Int32()); + func_ = module_.CreateFunction(func.Ident()->getText(), ir::Type::Int32()); builder_.SetInsertPoint(func_->entry()); locals_.clear(); diff --git a/src/sem/Sema.cpp b/src/sem/Sema.cpp index 2d7ae22..d64d9f0 100644 --- a/src/sem/Sema.cpp +++ b/src/sem/Sema.cpp @@ -48,14 +48,27 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) { if (!func || !func->block()) { throw std::runtime_error("[sema] 缺少 main 函数定义"); } + if (!func->Ident() || func->Ident()->getText() != "main") { + throw std::runtime_error("[sema] 入口函数必须命名为 main"); + } SymbolTable table; + bool seen_return = false; + + const auto& items = func->block()->blockItem(); + if (items.empty()) { + throw std::runtime_error("[sema] main 函数不能为空,且必须以 return 结束"); + } - for (auto* stmt : func->block()->stmt()) { - if (!stmt) { + for (size_t i = 0; i < items.size(); ++i) { + auto* item = items[i]; + if (!item) { continue; } - if (auto* decl = stmt->varDecl()) { + if (seen_return) { + throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句"); + } + if (auto* decl = item->decl() ? item->decl()->varDecl() : nullptr) { const std::string name = decl->Ident()->getText(); if (table.Contains(name)) { throw std::runtime_error("[sema] 重复定义变量: " + name); @@ -66,10 +79,19 @@ void RunSema(SysYParser::CompUnitContext& comp_unit) { table.Add(name); continue; } - if (auto* ret = stmt->returnStmt()) { + if (auto* stmt = item->stmt(); stmt && stmt->returnStmt()) { + auto* ret = stmt->returnStmt(); CheckExpr(*ret->exp(), table); - break; + seen_return = true; + if (i + 1 != items.size()) { + throw std::runtime_error("[sema] return 必须是 main 函数中的最后一条语句"); + } + continue; } - throw std::runtime_error("[sema] 暂不支持的语句类型"); + throw std::runtime_error("[sema] 暂不支持的 blockItem 类型"); + } + + if (!seen_return) { + throw std::runtime_error("[sema] main 函数必须包含 return 语句"); } }