feat: 实现一元运算符取反'-'
This commit is contained in:
parent
bca073cb28
commit
7679da2657
@ -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)。
|
||||
|
||||
@ -19,9 +19,6 @@ import java.util.Set;
|
||||
* <li>对不合法的词素自动标记为 UNKNOWN 类型。</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @author 你的名字
|
||||
* @version 1.0
|
||||
*/
|
||||
public class TokenFactory {
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<>());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user