diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
index a658d9d..b725ff1 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java
@@ -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)。
diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java
index 98155f6..e6463f4 100644
--- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java
+++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java
@@ -19,9 +19,6 @@ import java.util.Set;
*
对不合法的词素自动标记为 UNKNOWN 类型。
*
*
- *
- * @author 你的名字
- * @version 1.0
*/
public class TokenFactory {
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java
new file mode 100644
index 0000000..be60c24
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/UnaryExpressionNode.java
@@ -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;
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
index 1a1d124..4f79274 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
@@ -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));
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java
new file mode 100644
index 0000000..9d7a323
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/UnaryOperatorParselet.java
@@ -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);
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java
new file mode 100644
index 0000000..37f2ec0
--- /dev/null
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/UnaryExpressionAnalyzer.java
@@ -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 {
+
+ @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;
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java
index 865bb5e..c8de9e0 100644
--- a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java
@@ -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<>());
}