feature(sem): 初步完成了constDecl和varDecl的语义约束

pull/3/head
Junhe Wu 6 days ago
parent 91134d1350
commit d71a6b945d

@ -0,0 +1,9 @@
依据SysY文档语义约束如下
- [ ] CompUnit:
1. [ ] 存在且仅存在一个标识为'main'无参数返回类型为int的FuncDef(函数定义)。
2. [ ] CompUnit中的顶层变量/常量Decl、函数定义FuncDef都不可以重复定义同名的Ident即便标识符的类型不同。
- [ ] ConstDef:
- [ ]

@ -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)。

@ -2,25 +2,28 @@
#pragma once
#include <unordered_map>
#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<const SysYParser::VarContext*,
SysYParser::VarDefContext*>
std::unordered_map<const antlr4::tree::TerminalNode*,
antlr4::ParserRuleContext*>
var_uses_;
};

@ -1,4 +1,4 @@
// 极简符号表:记录局部变量定义
// 符号表:记录变量和常量定义。
#pragma once
#include <string>
@ -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<std::string, SysYParser::VarDefContext*> table_;
};
std::unordered_map<std::string, SysYParser::VarDefContext*> var_table_;
std::unordered_map<std::string, SysYParser::ConstDefContext*> const_table_;
};

@ -0,0 +1,70 @@
#ifndef SEM_FUNC_H
#define SEM_FUNC_H
#include <vector>
#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<size_t>& dimensions,
bool is_int,
size_t total_elements);
// 检查变量初始化器
size_t CheckInitVal(SysYParser::InitValContext& ctx,
const std::vector<size_t>& dimensions,
bool is_int,
size_t total_elements);
} // namespace sem
#endif // SEM_FUNC_H

@ -1,21 +1,22 @@
#include "sem/Sema.h"
#include <any>
#include <climits>
#include <cfloat>
#include <stdexcept>
#include <string>
#include <vector>
#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<size_t> 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<size_t>(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<size_t> 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<size_t>(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();
}
}

@ -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;
}

@ -0,0 +1,313 @@
#include "sem/func.h"
#include <stdexcept>
#include <string>
#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<double>(val.int_val);
} else if (float_const) {
val.is_int = false;
val.float_val = std::stod(float_const->getText());
val.int_val = static_cast<long long>(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<double>(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<long long>(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<double>(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<long long>(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<double>(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<long long>(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<double>(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<long long>(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<double>(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<double>(result.int_val);
} else {
result.float_val = -val.float_val;
result.int_val = static_cast<long long>(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<double>(result.int_val);
return result;
}
// 检查常量初始化器
size_t CheckConstInitVal(SysYParser::ConstInitValContext& ctx,
const std::vector<size_t>& 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<size_t>(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<size_t>& 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<size_t>(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
Loading…
Cancel
Save