From 09f2f168ae4b6fff69df8e73946e8a6301321917 Mon Sep 17 00:00:00 2001 From: hy Date: Fri, 11 Oct 2024 14:44:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(express):=20=E6=94=AF=E6=8C=81=E4=B8=80?= =?UTF-8?q?=E5=85=83=E6=AD=A3=E8=B4=9F=E5=8F=B7=E8=BF=90=E7=AE=97=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 `OperatorFactory` 和 `OperatorInstructionFactory` 中增加了对一元正负号运算符的支持,并添加了相应的单元测试。同时更新了 `KeyWordDefine4Java` 以识别新的运算符。 - 新增 `OperatorUnaryPlus` 和 `OperatorUnaryMinus` 类 - 更新 `KeyWordDefine4Java` 以支持一元正负号运算符 - 添加 `Issue345NegativeNumberTest` 单元测试 --- .../OperatorInstructionFactory.java | 23 ++++++++ .../instruction/op/OperatorFactory.java | 10 ++++ .../instruction/op/OperatorUnaryMinus.java | 53 +++++++++++++++++++ .../instruction/op/OperatorUnaryPlus.java | 23 ++++++++ .../express/parse/KeyWordDefine4Java.java | 4 +- .../issue/Issue345NegativeNumberTest.java | 25 +++++++++ 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/ql/util/express/instruction/op/OperatorUnaryMinus.java create mode 100644 src/main/java/com/ql/util/express/instruction/op/OperatorUnaryPlus.java create mode 100644 src/test/java/com/ql/util/express/issue/Issue345NegativeNumberTest.java diff --git a/src/main/java/com/ql/util/express/instruction/OperatorInstructionFactory.java b/src/main/java/com/ql/util/express/instruction/OperatorInstructionFactory.java index 1c270d583..219fc2f95 100644 --- a/src/main/java/com/ql/util/express/instruction/OperatorInstructionFactory.java +++ b/src/main/java/com/ql/util/express/instruction/OperatorInstructionFactory.java @@ -10,6 +10,7 @@ import com.ql.util.express.instruction.detail.InstructionOperator; import com.ql.util.express.instruction.detail.InstructionReturn; import com.ql.util.express.instruction.op.OperatorBase; +import com.ql.util.express.instruction.op.OperatorUnaryMinus; import com.ql.util.express.parse.ExpressNode; class OperatorInstructionFactory extends InstructionFactory { @@ -18,6 +19,28 @@ public boolean createInstruction(ExpressRunner expressRunner, InstructionSet res Stack forStack, ExpressNode node, boolean isRoot) throws Exception { boolean returnVal = false; ExpressNode[] children = node.getChildrenArray(); + // + //// 检查是否是一元减号 + //if ((node.isTypeEqualsOrChild("-") || node.isTypeEqualsOrChild("+")) && children.length == 1) { + // // 处理一元减号的子表达式 + // boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, children[0], false); + // returnVal = returnVal || tmpHas; + // + // if (node.isTypeEqualsOrChild("+")) { + // OperatorBase unaryPlusOp = new OperatorUnaryMinus("+"); + // result.addInstruction(new InstructionOperator(unaryPlusOp, 1).setLine(node.getLine())); + // } + // + // if (node.isTypeEqualsOrChild("-")) { + // // 创建一元减号操作符 + // OperatorBase unaryMinusOp = new OperatorUnaryMinus("-"); + // // 添加一元减号指令 + // result.addInstruction(new InstructionOperator(unaryMinusOp, 1).setLine(node.getLine())); + // } + // + // return returnVal; + //} + int[] finishPoint = new int[children.length]; for (int i = 0; i < children.length; i++) { ExpressNode tmpNode = children[i]; diff --git a/src/main/java/com/ql/util/express/instruction/op/OperatorFactory.java b/src/main/java/com/ql/util/express/instruction/op/OperatorFactory.java index 3219da0e5..7071745a5 100644 --- a/src/main/java/com/ql/util/express/instruction/op/OperatorFactory.java +++ b/src/main/java/com/ql/util/express/instruction/op/OperatorFactory.java @@ -127,6 +127,16 @@ public OperatorBase getOperator(String operatorName) { * 创建一个新的操作符实例 */ public OperatorBase newInstance(ExpressNode opItem) throws Exception { + ExpressNode[] children = opItem.getChildrenArray(); + // 如果是单目操作符号,而且只有一个参数 + if ((opItem.isTypeEqualsOrChild("-") || opItem.isTypeEqualsOrChild("+")) && children.length == 1) { + if (opItem.isTypeEqualsOrChild("+")) { + return new OperatorUnaryPlus("+"); + } + if (opItem.isTypeEqualsOrChild("-")) { + return new OperatorUnaryMinus("-"); + } + } OperatorBase op = operatorMap.get(opItem.getNodeType().getName()); if (op == null) { op = operatorMap.get(opItem.getTreeType().getName()); diff --git a/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryMinus.java b/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryMinus.java new file mode 100644 index 000000000..2ad445fa6 --- /dev/null +++ b/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryMinus.java @@ -0,0 +1,53 @@ +package com.ql.util.express.instruction.op; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.ql.util.express.Operator; + +public class OperatorUnaryMinus extends Operator { + public OperatorUnaryMinus(String name) { + this.name = name; + } + + public OperatorUnaryMinus(String aliasName, String name, String errorInfo) { + this.name = name; + this.aliasName = aliasName; + this.errorInfo = errorInfo; + } + + @Override + public Object executeInner(Object[] list) throws Exception { + if (list[0] instanceof Number) { + return negate((Number) list[0]); + } + throw new Exception("Cannot apply unary minus to non-number type"); + } + + public static Number negate(Number number) { + if (number == null) { + return null; + } + + if (number instanceof Integer) { + return -number.intValue(); + } else if (number instanceof Long) { + return -number.longValue(); + } else if (number instanceof Float) { + return -number.floatValue(); + } else if (number instanceof Double) { + return -number.doubleValue(); + } else if (number instanceof BigInteger) { + return ((BigInteger) number).negate(); + } else if (number instanceof BigDecimal) { + return ((BigDecimal) number).negate(); + } else if (number instanceof Short) { + return (short) -number.shortValue(); + } else if (number instanceof Byte) { + return (byte) -number.byteValue(); + } else { + // 对于其他类型的 Number + return -number.doubleValue(); + } + } +} diff --git a/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryPlus.java b/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryPlus.java new file mode 100644 index 000000000..d15f2f8fd --- /dev/null +++ b/src/main/java/com/ql/util/express/instruction/op/OperatorUnaryPlus.java @@ -0,0 +1,23 @@ +package com.ql.util.express.instruction.op; + +import com.ql.util.express.Operator; + +public class OperatorUnaryPlus extends Operator { + public OperatorUnaryPlus(String name) { + this.name = name; + } + + public OperatorUnaryPlus(String aliasName, String name, String errorInfo) { + this.name = name; + this.aliasName = aliasName; + this.errorInfo = errorInfo; + } + + @Override + public Object executeInner(Object[] list) throws Exception { + if (list[0] instanceof Number) { + return list[0]; + } + throw new Exception("Cannot apply unary plus to non-number type"); + } +} diff --git a/src/main/java/com/ql/util/express/parse/KeyWordDefine4Java.java b/src/main/java/com/ql/util/express/parse/KeyWordDefine4Java.java index dac22022e..e825e80bf 100644 --- a/src/main/java/com/ql/util/express/parse/KeyWordDefine4Java.java +++ b/src/main/java/com/ql/util/express/parse/KeyWordDefine4Java.java @@ -60,7 +60,7 @@ public class KeyWordDefine4Java { + "*$RIGHT_BRACKET~))", "[]:TYPE=EXPRESS,DEFINE=[~$EXPRESS*$]~#[]", - "OP_LEVEL1:TYPE=OPERATOR,DEFINE=~|!", + "OP_LEVEL1:TYPE=OPERATOR,DEFINE=~|!|-|+", "OP_LEVEL2:TYPE=OPERATOR,DEFINE=++|--", "OP_LEVEL3:TYPE=OPERATOR,DEFINE=&|MAYBE|XOR|<<|>>", "OP_LEVEL4:TYPE=OPERATOR,DEFINE=*|/|mod|%", @@ -97,7 +97,7 @@ public class KeyWordDefine4Java { "ARRAY_CALL_POST:TYPE=EXPRESS,DEFINE=(METHOD_CALL|FIELD_CALL)$([->ARRAY_CALL^$EXPRESS$]~)^*", "CAST_CALL:TYPE=EXPRESS,DEFINE=(LEFT_BRACKET~$CONST_CLASS$RIGHT_BRACKET~#cast)^*$((LAMBDA#LAMBDA)|ARRAY_CALL)", - "EXPRESS_OP_L1:TYPE=EXPRESS,DEFINE=OP_LEVEL1^*$CAST_CALL", + "EXPRESS_OP_L1:TYPE=EXPRESS,DEFINE=(OP_LEVEL1^$CAST_CALL)^*", "EXPRESS_OP_L2:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L1$OP_LEVEL2^*", "EXPRESS_OP_L3:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L2$(OP_LEVEL3^$EXPRESS_OP_L2)^*", "EXPRESS_OP_L4:TYPE=EXPRESS,DEFINE=EXPRESS_OP_L3$(OP_LEVEL4^$EXPRESS_OP_L3)^*", diff --git a/src/test/java/com/ql/util/express/issue/Issue345NegativeNumberTest.java b/src/test/java/com/ql/util/express/issue/Issue345NegativeNumberTest.java new file mode 100644 index 000000000..018d9ebf9 --- /dev/null +++ b/src/test/java/com/ql/util/express/issue/Issue345NegativeNumberTest.java @@ -0,0 +1,25 @@ +package com.ql.util.express.issue; + +import java.math.BigDecimal; + +import com.ql.util.express.DefaultContext; +import com.ql.util.express.ExpressRunner; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author zgxkbtl + */ +public class Issue345NegativeNumberTest { + @Test + public void test() throws Exception { + ExpressRunner runner = new ExpressRunner(false, true); + DefaultContext context = new DefaultContext<>(); + BigDecimal value = new BigDecimal("12.22"); + context.put("b", value); + String express = "-b"; + Object result = runner.execute(express, context, null, true, true); + //Assert.assertTrue((Boolean)result); + Assert.assertEquals(new BigDecimal("-12.22"), result); + } +} \ No newline at end of file