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.core.IROpCode;
|
||||||
import org.jcnc.snow.compiler.ir.instruction.CallInstruction;
|
import org.jcnc.snow.compiler.ir.instruction.CallInstruction;
|
||||||
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
|
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.IRConstant;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
import org.jcnc.snow.compiler.ir.utils.ExpressionUtils;
|
import org.jcnc.snow.compiler.ir.utils.ExpressionUtils;
|
||||||
@ -59,11 +60,32 @@ public record ExpressionBuilder(IRContext ctx) {
|
|||||||
case BinaryExpressionNode bin -> buildBinary(bin);
|
case BinaryExpressionNode bin -> buildBinary(bin);
|
||||||
// 函数调用
|
// 函数调用
|
||||||
case CallExpressionNode call -> buildCall(call);
|
case CallExpressionNode call -> buildCall(call);
|
||||||
|
case UnaryExpressionNode u -> buildUnary(u);
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"不支持的表达式类型: " + expr.getClass().getSimpleName());
|
"不支持的表达式类型: " + 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)。
|
* 直接将表达式计算结果写入指定的目标寄存器(dest)。
|
||||||
|
|||||||
@ -19,9 +19,6 @@ import java.util.Set;
|
|||||||
* <li>对不合法的词素自动标记为 UNKNOWN 类型。</li>
|
* <li>对不合法的词素自动标记为 UNKNOWN 类型。</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @author 你的名字
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
*/
|
||||||
public class TokenFactory {
|
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.STRING_LITERAL.name(), new StringLiteralParselet());
|
||||||
prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet());
|
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));
|
||||||
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(CallExpressionNode.class, new CallExpressionAnalyzer());
|
||||||
registry.registerExpressionAnalyzer(BinaryExpressionNode.class, new BinaryExpressionAnalyzer());
|
registry.registerExpressionAnalyzer(BinaryExpressionNode.class, new BinaryExpressionAnalyzer());
|
||||||
|
|
||||||
// 对尚未实现的表达式类型使用兜底处理器(如 MemberExpression)
|
// ---------- 注册一元表达式分析器 ----------
|
||||||
|
registry.registerExpressionAnalyzer(UnaryExpressionNode.class,new UnaryExpressionAnalyzer());
|
||||||
|
|
||||||
|
// 对尚未实现的表达式类型使用兜底处理器
|
||||||
registry.registerExpressionAnalyzer(MemberExpressionNode.class,
|
registry.registerExpressionAnalyzer(MemberExpressionNode.class,
|
||||||
new UnsupportedExpressionAnalyzer<>());
|
new UnsupportedExpressionAnalyzer<>());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user