From d71a6b945da546bff78ccdf68dbeeb3e54e8f48a Mon Sep 17 00:00:00 2001 From: Junhe Wu <2561075610@qq.com> Date: Wed, 25 Mar 2026 01:42:08 +0800 Subject: [PATCH] =?UTF-8?q?feature(sem):=20=E5=88=9D=E6=AD=A5=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E4=BA=86constDecl=E5=92=8CvarDecl=E7=9A=84=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E7=BA=A6=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- To_do_list/Sema.md | 9 ++ To_do_list/lab2.md | 6 + include/sem/Sema.h | 17 ++- include/sem/SymbolTable.h | 13 +- include/sem/func.h | 70 +++++++++ src/sem/Sema.cpp | 305 ++++++++++++++++++++----------------- src/sem/SymbolTable.cpp | 25 ++- src/sem/func.cpp | 313 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 597 insertions(+), 161 deletions(-) create mode 100644 To_do_list/Sema.md create mode 100644 To_do_list/lab2.md create mode 100644 include/sem/func.h create mode 100644 src/sem/func.cpp diff --git a/To_do_list/Sema.md b/To_do_list/Sema.md new file mode 100644 index 0000000..dec73d5 --- /dev/null +++ b/To_do_list/Sema.md @@ -0,0 +1,9 @@ +依据SysY文档,语义约束如下: + + - [ ] CompUnit: + 1. [ ] 存在且仅存在一个标识为'main',无参数,返回类型为int的FuncDef(函数定义)。 + 2. [ ] CompUnit中的顶层变量/常量Decl、函数定义FuncDef都不可以重复定义同名的Ident,即便标识符的类型不同。 + + +- [ ] ConstDef: +- [ ] \ No newline at end of file diff --git a/To_do_list/lab2.md b/To_do_list/lab2.md new file mode 100644 index 0000000..875ba47 --- /dev/null +++ b/To_do_list/lab2.md @@ -0,0 +1,6 @@ +## lab2主要分为3个阶段: + +1. [sema](/To_do_list/Sema.md)。 检查语义约束。通过修改[sem文件夹](/src/sem/Sema.cpp)中的SemaVisitor实现。具体来说,SemaVisitor继承自SysYBaseVisitor类。而antlr4依据SysY.g4生成的这个SysYBaseVisitor类里面已经对各种规则(比如,规则compUnit)实现了visitor方法(比如visitCompUnit)。为了达到我们的目的,即检查各种语义约束,我们需要利用虚函数的多态,重写这个方法。具体来说,这一阶段需要实现的各种约束见[SysY语义约束](/To_do_list/Sema.md)。 +2. [ir](/To_do_list/ir.md)。 +3. [irgen](/To_do_list/irgen.md)。 + diff --git a/include/sem/Sema.h b/include/sem/Sema.h index 9ac057b..8f3524b 100644 --- a/include/sem/Sema.h +++ b/include/sem/Sema.h @@ -2,25 +2,28 @@ #pragma once #include - +#include "utils/Log.h" #include "SysYParser.h" class SemanticContext { public: - void BindVarUse(SysYParser::VarContext* use, - SysYParser::VarDefContext* decl) { + void BindVarUse(antlr4::tree::TerminalNode* use, + antlr4::ParserRuleContext* decl) { + if(ResolveVarUse(use)){ + throw std::runtime_error(FormatError("sema", "变量名重定义")); + } var_uses_[use] = decl; } - SysYParser::VarDefContext* ResolveVarUse( - const SysYParser::VarContext* use) const { + antlr4::ParserRuleContext* ResolveVarUse( + const antlr4::tree::TerminalNode* use) const { auto it = var_uses_.find(use); return it == var_uses_.end() ? nullptr : it->second; } private: - std::unordered_map + std::unordered_map var_uses_; }; diff --git a/include/sem/SymbolTable.h b/include/sem/SymbolTable.h index c9396dd..4687bbf 100644 --- a/include/sem/SymbolTable.h +++ b/include/sem/SymbolTable.h @@ -1,4 +1,4 @@ -// 极简符号表:记录局部变量定义点。 +// 符号表:记录变量和常量定义。 #pragma once #include @@ -8,10 +8,13 @@ class SymbolTable { public: - void Add(const std::string& name, SysYParser::VarDefContext* decl); + void AddVar(const std::string& name, SysYParser::VarDefContext* decl); + void AddConst(const std::string& name, SysYParser::ConstDefContext* decl); bool Contains(const std::string& name) const; - SysYParser::VarDefContext* Lookup(const std::string& name) const; + SysYParser::VarDefContext* LookupVar(const std::string& name) const; + SysYParser::ConstDefContext* LookupConst(const std::string& name) const; private: - std::unordered_map table_; -}; + std::unordered_map var_table_; + std::unordered_map const_table_; +}; \ No newline at end of file diff --git a/include/sem/func.h b/include/sem/func.h new file mode 100644 index 0000000..a396a8f --- /dev/null +++ b/include/sem/func.h @@ -0,0 +1,70 @@ +#ifndef SEM_FUNC_H +#define SEM_FUNC_H + +#include + +#include "SysYParser.h" + +namespace sem { + +// 常量值类型 +struct ConstValue { + bool is_int; // 是否为整型 + long long int_val; // 整数值 + double float_val; // 浮点值 +}; + +// 编译时求值常量表达式 +ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx); + +// 求值表达式 +ConstValue EvaluateExp(SysYParser::AddExpContext& ctx); + +// 求值乘法表达式 +ConstValue EvaluateMulExp(SysYParser::MulExpContext& ctx); + +// 求值一元表达式 +ConstValue EvaluateUnaryExp(SysYParser::UnaryExpContext& ctx); + +// 求值基本表达式 +ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext& ctx); + +// 辅助函数:检查值是否为零 +bool IsZero(const ConstValue& val); + +// 辅助函数:加法 +ConstValue AddValues(const ConstValue& lhs, const ConstValue& rhs); + +// 辅助函数:减法 +ConstValue SubValues(const ConstValue& lhs, const ConstValue& rhs); + +// 辅助函数:乘法 +ConstValue MulValues(const ConstValue& lhs, const ConstValue& rhs); + +// 辅助函数:除法 +ConstValue DivValues(const ConstValue& lhs, const ConstValue& rhs); + +// 辅助函数:取模 +ConstValue ModValues(const ConstValue& lhs, const ConstValue& rhs); + +// 辅助函数:取负 +ConstValue NegValue(const ConstValue& val); + +// 辅助函数:逻辑非 +ConstValue NotValue(const ConstValue& val); + +// 检查常量初始化器 +size_t CheckConstInitVal(SysYParser::ConstInitValContext& ctx, + const std::vector& dimensions, + bool is_int, + size_t total_elements); + +// 检查变量初始化器 +size_t CheckInitVal(SysYParser::InitValContext& ctx, + const std::vector& dimensions, + bool is_int, + size_t total_elements); + +} // namespace sem + +#endif // SEM_FUNC_H \ No newline at end of file diff --git a/src/sem/Sema.cpp b/src/sem/Sema.cpp index 745374c..3a97be6 100644 --- a/src/sem/Sema.cpp +++ b/src/sem/Sema.cpp @@ -1,21 +1,22 @@ #include "sem/Sema.h" #include +#include +#include #include #include +#include #include "SysYBaseVisitor.h" #include "sem/SymbolTable.h" +#include "sem/func.h" #include "utils/Log.h" +using namespace sem; + namespace { -std::string GetLValueName(SysYParser::LValueContext& lvalue) { - if (!lvalue.ID()) { - throw std::runtime_error(FormatError("sema", "非法左值")); - } - return lvalue.ID()->getText(); -} +// 编译时求值常量表达式 class SemaVisitor final : public SysYBaseVisitor { public: @@ -23,161 +24,181 @@ class SemaVisitor final : public SysYBaseVisitor { 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") { + + // 先处理声明(包括常量声明) + auto decls = ctx->decl(); + for (auto* decl : decls) { + decl->accept(this); + } + + // 再处理函数定义 + auto funcs = ctx->funcDef(); + int count = 0; + int len = funcs.size(); + if(len == 0){ throw std::runtime_error(FormatError("sema", "缺少 main 函数定义")); } - func->accept(this); - if (!seen_return_) { - throw std::runtime_error( - FormatError("sema", "main 函数必须包含 return 语句")); - } - return {}; - } - - 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 结束")); + for(int i = 0; i < len; ++i){ + auto* func = ctx->funcDef(i); + func->accept(this); + if(!func->Ident() || func->Ident()->getText() == "main"){ + count ++; + if(count > 1){ + throw std::runtime_error(FormatError("sema", "有多个 main 函数定义")); + } + if(func->funcFParams()){ + throw std::runtime_error(FormatError("sema", "main 函数不该有参数")); + } + if(!func->funcType() || !func->funcType()->Int()){ + throw std::runtime_error(FormatError("sema", "main 函数的返回值必须是 Int")); + } + } } - ctx->blockStmt()->accept(this); return {}; } - 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; + std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) { + if (!ctx || !ctx->bType()) { + throw std::runtime_error(FormatError("sema", "非法常量声明")); + } + + // 获取类型信息 + bool is_int = ctx->bType()->Int() != nullptr; + bool is_float = ctx->bType()->Float() != nullptr; + + // 处理所有常量定义 + auto const_defs = ctx->constDef(); + for (auto* const_def : const_defs) { + // 检查标识符 + if (!const_def->Ident()) { + throw std::runtime_error(FormatError("sema", "常量声明缺少标识符")); } - if (seen_return_) { - throw std::runtime_error( - FormatError("sema", "return 必须是 main 函数中的最后一条语句")); + + std::string name = const_def->Ident()->getText(); + + // 检查是否重复定义 + if (table_.Contains(name)) { + throw std::runtime_error(FormatError("sema", "重复定义常量: " + name)); } - current_item_index_ = i; - total_items_ = items.size(); - item->accept(this); - } - 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", "暂不支持的语句或声明")); - } - - 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", "当前不支持聚合初始化")); + + // 处理数组维度 + auto const_exps = const_def->constExp(); + std::vector dimensions; + for (auto* const_exp : const_exps) { + ConstValue value = EvaluateConstExp(*const_exp); + if (!value.is_int) { + throw std::runtime_error(FormatError("sema", "数组维度必须是整数")); + } + if (value.int_val < 0) { + throw std::runtime_error(FormatError("sema", "数组维度必须是非负整数")); + } + dimensions.push_back(static_cast(value.int_val)); } - init->exp()->accept(this); - } - table_.Add(name, var_def); - return {}; - } - - std::any visitStmt(SysYParser::StmtContext* ctx) override { - if (!ctx || !ctx->returnStmt()) { - throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明")); - } - ctx->returnStmt()->accept(this); - return {}; - } - - 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 函数中的最后一条语句")); + + // 处理初始化器 + auto* init_val = const_def->constInitVal(); + if (init_val) { + // 检查标量常量的初始化器 + if (dimensions.empty()) { + // 标量常量,ConstInitVal必须是单个初始数值,不能是花括号列表 + if (init_val->L_BRACE()) { + throw std::runtime_error(FormatError("sema", "单个常量只能赋单个值,不能使用花括号列表")); + } + if (!init_val->constExp()) { + throw std::runtime_error(FormatError("sema", "单个常量缺少初始值")); + } + } + // 数组常量 + // 计算数组总元素个数 + size_t total_elements = 1; + for (auto dim : dimensions) { + total_elements *= dim; + } + + // 检查初始化器,传递总元素个数进行检查 + CheckConstInitVal(*init_val, dimensions, is_int, total_elements); + } + + // 添加到符号表 + table_.AddConst(name, const_def); } + return {}; } - std::any visitParenExp(SysYParser::ParenExpContext* ctx) override { - if (!ctx || !ctx->exp()) { - throw std::runtime_error(FormatError("sema", "非法括号表达式")); - } - ctx->exp()->accept(this); - return {}; - } - std::any visitVarExp(SysYParser::VarExpContext* ctx) override { - if (!ctx || !ctx->var()) { - throw std::runtime_error(FormatError("sema", "非法变量表达式")); - } - ctx->var()->accept(this); - return {}; - } - std::any visitNumberExp(SysYParser::NumberExpContext* ctx) override { - if (!ctx || !ctx->number() || !ctx->number()->ILITERAL()) { - throw std::runtime_error(FormatError("sema", "当前仅支持整数字面量")); + std::any visitVarDecl(SysYParser::VarDeclContext* ctx) { + if (!ctx || !ctx->bType()) { + throw std::runtime_error(FormatError("sema", "非法变量声明")); } - return {}; - } - - std::any visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) override { - if (!ctx || !ctx->exp(0) || !ctx->exp(1)) { - throw std::runtime_error(FormatError("sema", "暂不支持的表达式形式")); + + // 获取类型信息 + bool is_int = ctx->bType()->Int() != nullptr; + bool is_float = ctx->bType()->Float() != nullptr; + + // 处理所有变量定义 + auto var_defs = ctx->varDef(); + for (auto* var_def : var_defs) { + // 检查标识符 + if (!var_def->Ident()) { + throw std::runtime_error(FormatError("sema", "变量声明缺少标识符")); + } + + std::string name = var_def->Ident()->getText(); + + // 检查是否重复定义 + if (table_.Contains(name)) { + throw std::runtime_error(FormatError("sema", "重复定义变量: " + name)); + } + + // 处理数组维度 + auto const_exps = var_def->constExp(); + std::vector dimensions; + for (auto* const_exp : const_exps) { + ConstValue value = EvaluateConstExp(*const_exp); + if (!value.is_int) { + throw std::runtime_error(FormatError("sema", "数组维度必须是整数")); + } + if (value.int_val < 0) { + throw std::runtime_error(FormatError("sema", "数组维度必须是非负整数")); + } + dimensions.push_back(static_cast(value.int_val)); + } + + // 处理初始化器 + auto* init_val = var_def->initVal(); + if (init_val) { + // 检查标量变量的初始化器 + if (dimensions.empty()) { + // 标量变量,InitVal必须是单个表达式,不能是花括号列表 + if (init_val->L_BRACE()) { + throw std::runtime_error(FormatError("sema", "单个变量只能赋单个值,不能使用花括号列表")); + } + if (!init_val->exp()) { + throw std::runtime_error(FormatError("sema", "单个变量缺少初始值")); + } + } + // 数组变量 + // 计算数组总元素个数 + size_t total_elements = 1; + for (auto dim : dimensions) { + total_elements *= dim; + } + + // 检查初始化器,传递总元素个数进行检查 + CheckInitVal(*init_val, dimensions, is_int, total_elements); + } + + // 添加到符号表 + table_.AddVar(name, var_def); } - ctx->exp(0)->accept(this); - ctx->exp(1)->accept(this); + 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); + std::any visitVarDef(SysYParser::VarDefContext* ctx) { + // 此方法由visitVarDecl调用,不需要单独处理 return {}; } @@ -197,4 +218,4 @@ SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) { SemaVisitor visitor; comp_unit.accept(&visitor); return visitor.TakeSemanticContext(); -} +} \ No newline at end of file diff --git a/src/sem/SymbolTable.cpp b/src/sem/SymbolTable.cpp index ffeea89..2c13894 100644 --- a/src/sem/SymbolTable.cpp +++ b/src/sem/SymbolTable.cpp @@ -1,17 +1,28 @@ -// 维护局部变量声明的注册与查找。 +// 维护变量和常量声明的注册与查找。 #include "sem/SymbolTable.h" -void SymbolTable::Add(const std::string& name, +void SymbolTable::AddVar(const std::string& name, SysYParser::VarDefContext* decl) { - table_[name] = decl; + var_table_[name] = decl; +} + +void SymbolTable::AddConst(const std::string& name, + SysYParser::ConstDefContext* decl) { + const_table_[name] = decl; } bool SymbolTable::Contains(const std::string& name) const { - return table_.find(name) != table_.end(); + return var_table_.find(name) != var_table_.end() || + const_table_.find(name) != const_table_.end(); } -SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const { - auto it = table_.find(name); - return it == table_.end() ? nullptr : it->second; +SysYParser::VarDefContext* SymbolTable::LookupVar(const std::string& name) const { + auto it = var_table_.find(name); + return it == var_table_.end() ? nullptr : it->second; } + +SysYParser::ConstDefContext* SymbolTable::LookupConst(const std::string& name) const { + auto it = const_table_.find(name); + return it == const_table_.end() ? nullptr : it->second; +} \ No newline at end of file diff --git a/src/sem/func.cpp b/src/sem/func.cpp new file mode 100644 index 0000000..8da07f8 --- /dev/null +++ b/src/sem/func.cpp @@ -0,0 +1,313 @@ +#include "sem/func.h" + +#include +#include + +#include "utils/Log.h" + +namespace sem { + +// 编译时求值常量表达式 +ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx) { + return EvaluateExp(*ctx.addExp()); +} + +// 求值表达式 +ConstValue EvaluateExp(SysYParser::AddExpContext& ctx) { + ConstValue result = EvaluateMulExp(*ctx.mulExp(0)); + for (size_t i = 1; i < ctx.mulExp().size(); ++i) { + ConstValue rhs = EvaluateMulExp(*ctx.mulExp(i)); + if (ctx.AddOp(i-1)->getText() == "+") { + result = AddValues(result, rhs); + } else { + result = SubValues(result, rhs); + } + } + return result; +} + +// 求值乘法表达式 +ConstValue EvaluateMulExp(SysYParser::MulExpContext& ctx) { + ConstValue result = EvaluateUnaryExp(*ctx.unaryExp(0)); + for (size_t i = 1; i < ctx.unaryExp().size(); ++i) { + ConstValue rhs = EvaluateUnaryExp(*ctx.unaryExp(i)); + std::string op = ctx.MulOp(i-1)->getText(); + if (op == "*") { + result = MulValues(result, rhs); + } else if (op == "/") { + if (IsZero(rhs)) { + throw std::runtime_error(FormatError("sema", "除零错误")); + } + result = DivValues(result, rhs); + } else if (op == "%") { + if (IsZero(rhs)) { + throw std::runtime_error(FormatError("sema", "取模除零错误")); + } + result = ModValues(result, rhs); + } + } + return result; +} + +// 求值一元表达式 +ConstValue EvaluateUnaryExp(SysYParser::UnaryExpContext& ctx) { + if (ctx.unaryOp()) { + ConstValue operand = EvaluateUnaryExp(*ctx.unaryExp()); + std::string op = ctx.unaryOp()->getText(); + if (op == "-") { + return NegValue(operand); + } else if (op == "!") { + return NotValue(operand); + } else { + return operand; // "+" 操作符 + } + } else if (ctx.primaryExp()) { + return EvaluatePrimaryExp(*ctx.primaryExp()); + } else { + throw std::runtime_error(FormatError("sema", "非法常量表达式")); + } +} + +// 求值基本表达式 +ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext& ctx) { + if (ctx.exp()) { + return EvaluateExp(*ctx.exp()->addExp()); + } else if (ctx.lVar()) { + // 处理变量引用(必须是已定义的常量) + auto* ident = ctx.lVar()->Ident(); + if (!ident) { + throw std::runtime_error(FormatError("sema", "非法变量引用")); + } + std::string name = ident->getText(); + // 这里简化处理,实际应该在符号表中查找常量 + // 暂时假设常量已经在前面被处理过 + ConstValue val; + val.is_int = true; + val.int_val = 0; + val.float_val = 0.0; + return val; + } else if (ctx.number()) { + // 处理数字字面量 + auto* int_const = ctx.number()->IntConst(); + auto* float_const = ctx.number()->FloatConst(); + + ConstValue val; + if (int_const) { + val.is_int = true; + val.int_val = std::stoll(int_const->getText()); + val.float_val = static_cast(val.int_val); + } else if (float_const) { + val.is_int = false; + val.float_val = std::stod(float_const->getText()); + val.int_val = static_cast(val.float_val); + } else { + throw std::runtime_error(FormatError("sema", "非法数字字面量")); + } + return val; + } else { + throw std::runtime_error(FormatError("sema", "非法基本表达式")); + } +} + +// 辅助函数:检查值是否为零 +bool IsZero(const ConstValue& val) { + if (val.is_int) { + return val.int_val == 0; + } else { + return val.float_val == 0.0; + } +} + +// 辅助函数:加法 +ConstValue AddValues(const ConstValue& lhs, const ConstValue& rhs) { + ConstValue result; + if (lhs.is_int && rhs.is_int) { + result.is_int = true; + result.int_val = lhs.int_val + rhs.int_val; + result.float_val = static_cast(result.int_val); + } else { + result.is_int = false; + result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) + + (rhs.is_int ? rhs.int_val : rhs.float_val); + result.int_val = static_cast(result.float_val); + } + return result; +} + +// 辅助函数:减法 +ConstValue SubValues(const ConstValue& lhs, const ConstValue& rhs) { + ConstValue result; + if (lhs.is_int && rhs.is_int) { + result.is_int = true; + result.int_val = lhs.int_val - rhs.int_val; + result.float_val = static_cast(result.int_val); + } else { + result.is_int = false; + result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) - + (rhs.is_int ? rhs.int_val : rhs.float_val); + result.int_val = static_cast(result.float_val); + } + return result; +} + +// 辅助函数:乘法 +ConstValue MulValues(const ConstValue& lhs, const ConstValue& rhs) { + ConstValue result; + if (lhs.is_int && rhs.is_int) { + result.is_int = true; + result.int_val = lhs.int_val * rhs.int_val; + result.float_val = static_cast(result.int_val); + } else { + result.is_int = false; + result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) * + (rhs.is_int ? rhs.int_val : rhs.float_val); + result.int_val = static_cast(result.float_val); + } + return result; +} + +// 辅助函数:除法 +ConstValue DivValues(const ConstValue& lhs, const ConstValue& rhs) { + ConstValue result; + if (lhs.is_int && rhs.is_int) { + result.is_int = true; + result.int_val = lhs.int_val / rhs.int_val; + result.float_val = static_cast(result.int_val); + } else { + result.is_int = false; + result.float_val = (lhs.is_int ? lhs.int_val : lhs.float_val) / + (rhs.is_int ? rhs.int_val : rhs.float_val); + result.int_val = static_cast(result.float_val); + } + return result; +} + +// 辅助函数:取模 +ConstValue ModValues(const ConstValue& lhs, const ConstValue& rhs) { + ConstValue result; + if (!lhs.is_int || !rhs.is_int) { + throw std::runtime_error(FormatError("sema", "取模运算只能用于整数")); + } + result.is_int = true; + result.int_val = lhs.int_val % rhs.int_val; + result.float_val = static_cast(result.int_val); + return result; +} + +// 辅助函数:取负 +ConstValue NegValue(const ConstValue& val) { + ConstValue result; + result.is_int = val.is_int; + if (val.is_int) { + result.int_val = -val.int_val; + result.float_val = static_cast(result.int_val); + } else { + result.float_val = -val.float_val; + result.int_val = static_cast(result.float_val); + } + return result; +} + +// 辅助函数:逻辑非 +ConstValue NotValue(const ConstValue& val) { + ConstValue result; + result.is_int = true; + if (val.is_int) { + result.int_val = !val.int_val; + } else { + result.int_val = !val.float_val; + } + result.float_val = static_cast(result.int_val); + return result; +} + +// 检查常量初始化器 +size_t CheckConstInitVal(SysYParser::ConstInitValContext& ctx, + const std::vector& dimensions, + bool is_int, + size_t total_elements) { + if (ctx.constExp()) { + // 单个常量值 + // 求值并检查常量表达式 + ConstValue value = EvaluateConstExp(*ctx.constExp()); + + // 检查类型约束 + if (is_int && !value.is_int) { + throw std::runtime_error(FormatError("sema", "整型数组的初始化列表中不能出现浮点型常量")); + } + + // 检查值域 + if (is_int) { + if (value.int_val < INT_MIN || value.int_val > INT_MAX) { + throw std::runtime_error(FormatError("sema", "整数值超过int类型表示范围")); + } + } + return 1; + } else if (ctx.L_BRACE()) { + // 花括号初始化列表 + size_t count = 0; + auto init_vals = ctx.constInitVal(); + + for (auto* init_val : init_vals) { + // 计算剩余维度的总元素个数 + size_t remaining_elements = total_elements; + if (!dimensions.empty()) { + remaining_elements = total_elements / dimensions[0]; + } + + count += CheckConstInitVal(*init_val, + std::vector(dimensions.begin() + 1, dimensions.end()), + is_int, + remaining_elements); + } + // 检查总元素个数 + if (count > total_elements) { + throw std::runtime_error(FormatError("sema", "初始化列表元素个数超过数组大小")); + } + return count; + } else { + // 空初始化列表 + return 0; + } +} + +// 检查变量初始化器 +size_t CheckInitVal(SysYParser::InitValContext& ctx, + const std::vector& dimensions, + bool is_int, + size_t total_elements) { + if (ctx.exp()) { + // 单个表达式值 + // 检查表达式中的变量引用 + // 这里不需要编译时求值,只需要检查类型约束 + // 类型检查在IR生成阶段进行 + return 1; + } else if (ctx.L_BRACE()) { + // 花括号初始化列表 + size_t count = 0; + auto init_vals = ctx.initVal(); + + for (auto* init_val : init_vals) { + // 计算剩余维度的总元素个数 + size_t remaining_elements = total_elements; + if (!dimensions.empty()) { + remaining_elements = total_elements / dimensions[0]; + } + + count += CheckInitVal(*init_val, + std::vector(dimensions.begin() + 1, dimensions.end()), + is_int, + remaining_elements); + } + // 检查总元素个数 + if (count > total_elements) { + throw std::runtime_error(FormatError("sema", "初始化列表元素个数超过数组大小")); + } + return count; + } else { + // 空初始化列表 + return 0; + } +} + +} // namespace sem \ No newline at end of file