feat: 优化声明语句语义分析

- 重构代码,优化分析流程,增加对常量声明的处理
-改进错误处理和日志输出,提高可读性和调试友好性
- 修复了一些潜在的语义分析问题,如常量未初始化的检查
This commit is contained in:
Luke 2025-08-26 01:16:40 +08:00
parent 1872221666
commit d0c34ce1c2

View File

@ -6,7 +6,9 @@ import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer;
import org.jcnc.snow.compiler.semantic.core.Context; import org.jcnc.snow.compiler.semantic.core.Context;
import org.jcnc.snow.compiler.semantic.core.ModuleInfo; import org.jcnc.snow.compiler.semantic.core.ModuleInfo;
import org.jcnc.snow.compiler.semantic.error.SemanticError; import org.jcnc.snow.compiler.semantic.error.SemanticError;
import org.jcnc.snow.compiler.semantic.symbol.*; import org.jcnc.snow.compiler.semantic.symbol.Symbol;
import org.jcnc.snow.compiler.semantic.symbol.SymbolKind;
import org.jcnc.snow.compiler.semantic.symbol.SymbolTable;
import org.jcnc.snow.compiler.semantic.type.BuiltinType; import org.jcnc.snow.compiler.semantic.type.BuiltinType;
import org.jcnc.snow.compiler.semantic.type.Type; import org.jcnc.snow.compiler.semantic.type.Type;
@ -25,7 +27,7 @@ import org.jcnc.snow.compiler.semantic.type.Type;
public class DeclarationAnalyzer implements StatementAnalyzer<DeclarationNode> { public class DeclarationAnalyzer implements StatementAnalyzer<DeclarationNode> {
/** /**
* 变量声明语句执行语义分析 * 单条声明语句执行语义分析
* *
* @param ctx 当前语义分析上下文对象提供类型解析错误记录日志输出等功能 * @param ctx 当前语义分析上下文对象提供类型解析错误记录日志输出等功能
* @param mi 当前模块信息支持跨模块引用检查本分析器未直接使用 * @param mi 当前模块信息支持跨模块引用检查本分析器未直接使用
@ -40,45 +42,53 @@ public class DeclarationAnalyzer implements StatementAnalyzer<DeclarationNode> {
SymbolTable locals, SymbolTable locals,
DeclarationNode decl) { DeclarationNode decl) {
// 1. 解析声明类型 /* ---------- 1. 解析类型 ---------- */
Type varType = ctx.parseType(decl.getType()); Type varType = ctx.parseType(decl.getType());
if (varType == null) { if (varType == null) {
// 未知类型记录错误并使用 int 兜底避免后续空指针
ctx.getErrors().add(new SemanticError(decl, ctx.getErrors().add(new SemanticError(decl,
"未知类型: " + decl.getType())); "未知类型: " + decl.getType()));
ctx.log("错误: 未知类型 " + decl.getType() ctx.log("错误: 未知类型 " + decl.getType()
+ " 声明 " + decl.getName()); + " (声明 " + decl.getName() + ")");
varType = BuiltinType.INT; // 容错处理: 默认降级为 int varType = BuiltinType.INT;
} }
ctx.log("声明变量: " + decl.getName() ctx.log("声明" + (decl.isConst() ? "常量" : "变量")
+ " 类型: " + varType); + ": " + decl.getName() + " 类型: " + varType);
// 2. 将变量注册到当前作用域符号表中检查重复定义 /* ---------- 2. 常量必须初始化 ---------- */
if (!locals.define(new Symbol( if (decl.isConst() && decl.getInitializer().isEmpty()) {
decl.getName(), varType, SymbolKind.VARIABLE
))) {
ctx.getErrors().add(new SemanticError(decl, ctx.getErrors().add(new SemanticError(decl,
"变量重复声明: " + decl.getName())); "常量必须在声明时初始化: " + decl.getName()));
ctx.log("错误: 变量重复声明 " + decl.getName()); // 继续分析以捕获更多错误
} }
// 3. 检查初始化表达式如果存在 /* ---------- 3. 注册符号并检测重名 ---------- */
Type finalVarType = varType; // 用于 lambda 捕获 SymbolKind kind = decl.isConst() ? SymbolKind.CONSTANT
decl.getInitializer().ifPresent(init -> { : SymbolKind.VARIABLE;
Type initType = ctx.getRegistry().getExpressionAnalyzer(init) if (!locals.define(new Symbol(decl.getName(), varType, kind))) {
.analyze(ctx, mi, fn, locals, init); ctx.getErrors().add(new SemanticError(decl,
"重复声明: " + decl.getName()));
ctx.log("错误: 重复声明 " + decl.getName());
}
// 检查类型是否兼容或是否允许数值宽化转换 /* ---------- 4. 校验初始化表达式(若存在) ---------- */
if (!finalVarType.isCompatible(initType)) { Type finalVarType = varType;
boolean canWiden = finalVarType.isNumeric() decl.getInitializer().ifPresent(initExpr -> {
&& initType.isNumeric() // 4.1 获取初始化表达式类型
&& Type.widen(initType, finalVarType) == finalVarType; Type initType = ctx.getRegistry()
if (!canWiden) { .getExpressionAnalyzer(initExpr)
ctx.getErrors().add(new SemanticError(decl, .analyze(ctx, mi, fn, locals, initExpr);
"初始化类型不匹配: 期望 " + finalVarType
+ ", 实际 " + initType)); // 4.2 类型兼容性检查 + 数值宽化
ctx.log("错误: 初始化类型不匹配 " boolean compatible = finalVarType.isCompatible(initType);
+ decl.getName()); boolean widenOK = finalVarType.isNumeric()
} && initType.isNumeric()
&& Type.widen(initType, finalVarType) == finalVarType;
if (!compatible && !widenOK) {
ctx.getErrors().add(new SemanticError(decl,
"初始化类型不匹配: 期望 " + finalVarType + ", 实际 " + initType));
ctx.log("错误: 初始化类型不匹配 " + decl.getName());
} }
}); });
} }