feat:语义分析支持布尔值比较
This commit is contained in:
parent
dff64e7dbb
commit
a64209c211
@ -11,79 +11,75 @@ import org.jcnc.snow.compiler.semantic.type.BuiltinType;
|
|||||||
import org.jcnc.snow.compiler.semantic.type.Type;
|
import org.jcnc.snow.compiler.semantic.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code BinaryExpressionAnalyzer} 是一个用于分析二元表达式的语义分析器。
|
* {@code BinaryExpressionAnalyzer} 负责对二元表达式做语义分析并返回其类型。
|
||||||
* <p>
|
* <p>
|
||||||
* 支持的特性包括:
|
* 支持特性:
|
||||||
* <ul>
|
* 1. 字符串拼接「+」
|
||||||
* <li>字符串拼接(当运算符为加号 "+" 且任一操作数为字符串类型时)</li>
|
* 2. 数值运算与自动宽化
|
||||||
* <li>数值类型的自动宽化转换(如 int 与 float 运算将转换为 float)</li>
|
* 3. 比较 / 关系运算
|
||||||
* <li>基本的数值运算符(如 +, -, *, /, %)</li>
|
* 4. 布尔值比较(== / !=)
|
||||||
* <li>关系运算符和比较运算符(如 <, <=, >, >=, ==, !=)</li>
|
|
||||||
* </ul>
|
|
||||||
* 对于不支持的运算符或不兼容的类型组合,将记录语义错误,并默认返回 {@code BuiltinType.INT} 以保持分析过程的连续性。
|
|
||||||
* <p>
|
* <p>
|
||||||
* 实现类遵循 {@code ExpressionAnalyzer<BinaryExpressionNode>} 接口规范。
|
* 如遇不支持的运算符或不兼容的类型组合,将记录语义错误,
|
||||||
|
* 并以 {@code int} 作为回退类型,保持后续分析不中断。
|
||||||
*/
|
*/
|
||||||
public class BinaryExpressionAnalyzer implements ExpressionAnalyzer<BinaryExpressionNode> {
|
public class BinaryExpressionAnalyzer implements ExpressionAnalyzer<BinaryExpressionNode> {
|
||||||
|
|
||||||
/**
|
|
||||||
* 分析给定的二元表达式节点,返回其表达式类型。
|
|
||||||
*
|
|
||||||
* @param ctx 当前语义分析上下文,用于访问日志记录、错误收集、注册表等服务。
|
|
||||||
* @param mi 当前模块信息,包含模块级别的符号与类型定义。
|
|
||||||
* @param fn 当前正在分析的函数节点。
|
|
||||||
* @param locals 当前函数作用域内的符号表,用于变量查找。
|
|
||||||
* @param bin 要分析的二元表达式节点。
|
|
||||||
* @return 分析后推断出的表达式类型。
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Type analyze(Context ctx,
|
public Type analyze(Context ctx,
|
||||||
ModuleInfo mi,
|
ModuleInfo mi,
|
||||||
FunctionNode fn,
|
FunctionNode fn,
|
||||||
SymbolTable locals,
|
SymbolTable locals,
|
||||||
BinaryExpressionNode bin) {
|
BinaryExpressionNode bin) {
|
||||||
|
|
||||||
ctx.log("检查二元表达式: " + bin.operator());
|
ctx.log("检查二元表达式: " + bin.operator());
|
||||||
|
|
||||||
// 获取左侧表达式类型
|
/* ----------- 先递归分析左右子表达式类型 ----------- */
|
||||||
Type left = ctx.getRegistry().getExpressionAnalyzer(bin.left())
|
Type left = ctx.getRegistry()
|
||||||
|
.getExpressionAnalyzer(bin.left())
|
||||||
.analyze(ctx, mi, fn, locals, bin.left());
|
.analyze(ctx, mi, fn, locals, bin.left());
|
||||||
|
|
||||||
// 获取右侧表达式类型
|
Type right = ctx.getRegistry()
|
||||||
Type right = ctx.getRegistry().getExpressionAnalyzer(bin.right())
|
.getExpressionAnalyzer(bin.right())
|
||||||
.analyze(ctx, mi, fn, locals, bin.right());
|
.analyze(ctx, mi, fn, locals, bin.right());
|
||||||
|
|
||||||
String op = bin.operator();
|
String op = bin.operator();
|
||||||
|
|
||||||
// 情况 1:字符串拼接(+ 操作符且任一操作数为字符串类型)
|
/* ----------- 情况 1:字符串拼接 ----------- */
|
||||||
if (op.equals("+") &&
|
if (op.equals("+") &&
|
||||||
(left == BuiltinType.STRING || right == BuiltinType.STRING)) {
|
(left == BuiltinType.STRING || right == BuiltinType.STRING)) {
|
||||||
return BuiltinType.STRING;
|
return BuiltinType.STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况 2:数值类型运算或比较
|
/* ----------- 情况 1.5:布尔值比较 ----------- */
|
||||||
|
if (("==".equals(op) || "!=".equals(op)) &&
|
||||||
|
left == BuiltinType.BOOLEAN &&
|
||||||
|
right == BuiltinType.BOOLEAN) {
|
||||||
|
return BuiltinType.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------- 情况 2:数值运算 / 比较 ----------- */
|
||||||
if ("+-*/%".contains(op) || ("<<=>>===!=").contains(op)) {
|
if ("+-*/%".contains(op) || ("<<=>>===!=").contains(op)) {
|
||||||
if (left.isNumeric() && right.isNumeric()) {
|
if (left.isNumeric() && right.isNumeric()) {
|
||||||
// 自动宽化到更宽的数值类型(如 int + float => float)
|
// 自动数值宽化(如 int + float → float)
|
||||||
Type wide = Type.widen(left, right);
|
Type wide = Type.widen(left, right);
|
||||||
if (wide == null) wide = BuiltinType.INT; // 容错降级为 int
|
if (wide == null) wide = BuiltinType.INT; // 容错降级
|
||||||
|
|
||||||
// 若为比较运算符,统一返回 boolean 类型作为布尔值表示
|
// 比较运算统一返回 boolean
|
||||||
if ("< <= > >= == !=".contains(op)) {
|
if ("< <= > >= == !=".contains(op)) {
|
||||||
return BuiltinType.BOOLEAN;
|
return BuiltinType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wide;
|
return wide;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况 3:不支持的类型组合,记录语义错误
|
/* ----------- 情况 3:不支持的类型组合 ----------- */
|
||||||
ctx.getErrors().add(new SemanticError(
|
ctx.getErrors().add(new SemanticError(
|
||||||
bin,
|
bin,
|
||||||
String.format("运算符 '%s' 不支持类型: %s 和 %s", op, left, right)
|
String.format("运算符 '%s' 不支持类型: %s 和 %s", op, left, right)
|
||||||
));
|
));
|
||||||
ctx.log("错误: 运算符 '" + op + "' 不支持类型: " + left + ", " + right);
|
ctx.log("错误: 运算符 '" + op + "' 不支持类型: " + left + ", " + right);
|
||||||
|
|
||||||
// 错误情况下默认返回 int 类型,以保证语义分析不中断
|
// 回退类型
|
||||||
return BuiltinType.INT;
|
return BuiltinType.INT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user