Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(express): 支持一元正负号运算符 #355

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -18,6 +19,28 @@ public boolean createInstruction(ExpressRunner expressRunner, InstructionSet res
Stack<ForRelBreakContinue> forStack, ExpressNode node, boolean isRoot) throws Exception {
boolean returnVal = false;
ExpressNode[] children = node.getChildrenArray();
//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释代码删除

//// 检查是否是一元减号
//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];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
@@ -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");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

抛 QLException

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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|%",
Expand Down Expand Up @@ -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)^*",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里为什么要从左边改成右边?如果使用原来的就能能通过大多数测试(和 addOperatorWithLevelOfReference 相关的依旧过不了,因为还有其他代码需要修改)

"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)^*",
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Object> 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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

单元测试建议将所有的数字类型都进行一遍测试

}
}