feat: 实现一元运算符取反'-'

This commit is contained in:
Luke 2025-06-12 16:39:15 +08:00
parent bca073cb28
commit 7679da2657
7 changed files with 115 additions and 4 deletions

View File

@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IROpCode;
import org.jcnc.snow.compiler.ir.instruction.CallInstruction;
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
import org.jcnc.snow.compiler.ir.instruction.UnaryOperationInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import org.jcnc.snow.compiler.ir.utils.ExpressionUtils;
@ -59,11 +60,32 @@ public record ExpressionBuilder(IRContext ctx) {
case BinaryExpressionNode bin -> buildBinary(bin);
// 函数调用
case CallExpressionNode call -> buildCall(call);
case UnaryExpressionNode u -> buildUnary(u);
default -> throw new IllegalStateException(
"不支持的表达式类型: " + expr.getClass().getSimpleName());
};
}
private IRVirtualRegister buildUnary(UnaryExpressionNode un) {
String op = un.operator();
IRVirtualRegister val = build(un.operand());
// -x NEG_I32
if (op.equals("-")) {
IRVirtualRegister dest = ctx.newRegister();
ctx.addInstruction(new UnaryOperationInstruction(
IROpCode.NEG_I32, dest, val));
return dest;
}
// !x (x == 0)
if (op.equals("!")) {
IRVirtualRegister zero = InstructionFactory.loadConst(ctx, 0);
return InstructionFactory.binOp(ctx, IROpCode.CMP_EQ, val, zero);
}
throw new IllegalStateException("未知一元运算符: " + op);
}
/**
* 直接将表达式计算结果写入指定的目标寄存器dest

View File

@ -19,9 +19,6 @@ import java.util.Set;
* <li>对不合法的词素自动标记为 UNKNOWN 类型</li>
* </ul>
* </p>
*
* @author 你的名字
* @version 1.0
*/
public class TokenFactory {

View File

@ -0,0 +1,17 @@
package org.jcnc.snow.compiler.parser.ast;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
/**
* 一元表达式节点例如 -x !x
*
* @param operator 运算符字符串 ("-" / "!")
* @param operand 操作数表达式
*/
public record UnaryExpressionNode(String operator,
ExpressionNode operand) implements ExpressionNode {
@Override public String toString() {
return operator + operand;
}
}

View File

@ -45,6 +45,10 @@ public class PrattExpressionParser implements ExpressionParser {
prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet());
prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet());
// 注册一元前缀运算
prefixes.put(TokenType.MINUS.name(), new UnaryOperatorParselet());
prefixes.put(TokenType.NOT.name(), new UnaryOperatorParselet());
// 注册中缀解析器
infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put("-", new BinaryOperatorParselet(Precedence.SUM, true));

View File

@ -0,0 +1,19 @@
package org.jcnc.snow.compiler.parser.expression;
import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
/** 前缀一元运算解析器(支持 - 和 ! */
public class UnaryOperatorParselet implements PrefixParselet {
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
// 递归解析右侧使用自身优先级
ExpressionNode right =
new PrattExpressionParser().parseExpression(ctx, Precedence.UNARY);
return new UnaryExpressionNode(token.getLexeme(), right);
}
}

View File

@ -0,0 +1,49 @@
package org.jcnc.snow.compiler.semantic.analyzers.expression;
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode;
import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer;
import org.jcnc.snow.compiler.semantic.core.Context;
import org.jcnc.snow.compiler.semantic.core.ModuleInfo;
import org.jcnc.snow.compiler.semantic.error.SemanticError;
import org.jcnc.snow.compiler.semantic.symbol.SymbolTable;
import org.jcnc.snow.compiler.semantic.type.BuiltinType;
import org.jcnc.snow.compiler.semantic.type.Type;
/** 一元表达式语义分析 */
public class UnaryExpressionAnalyzer implements ExpressionAnalyzer<UnaryExpressionNode> {
@Override
public Type analyze(Context ctx, ModuleInfo mi, FunctionNode fn,
SymbolTable locals, UnaryExpressionNode expr) {
// 先分析操作数
Type operandType = ctx.getRegistry()
.getExpressionAnalyzer(expr.operand())
.analyze(ctx, mi, fn, locals, expr.operand());
switch (expr.operator()) {
case "-" -> {
if (!operandType.isNumeric()) {
ctx.getErrors().add(new SemanticError(expr,
"'-' 只能应用于数值类型,当前为 " + operandType));
return BuiltinType.INT;
}
return operandType;
}
case "!" -> {
if (operandType != BuiltinType.BOOLEAN) {
ctx.getErrors().add(new SemanticError(expr,
"'!' 只能应用于 boolean 类型,当前为 " + operandType));
return BuiltinType.BOOLEAN;
}
return BuiltinType.BOOLEAN;
}
default -> {
ctx.getErrors().add(new SemanticError(expr,
"未知一元运算符: " + expr.operator()));
return BuiltinType.INT;
}
}
}
}

View File

@ -55,7 +55,10 @@ public final class AnalyzerRegistrar {
registry.registerExpressionAnalyzer(CallExpressionNode.class, new CallExpressionAnalyzer());
registry.registerExpressionAnalyzer(BinaryExpressionNode.class, new BinaryExpressionAnalyzer());
// 对尚未实现的表达式类型使用兜底处理器 MemberExpression
// ---------- 注册一元表达式分析器 ----------
registry.registerExpressionAnalyzer(UnaryExpressionNode.class,new UnaryExpressionAnalyzer());
// 对尚未实现的表达式类型使用兜底处理器
registry.registerExpressionAnalyzer(MemberExpressionNode.class,
new UnsupportedExpressionAnalyzer<>());
}