/***@authorCarol
* 计算表达式
* 利用一个操作数栈和一个操作栈来进行计算
* 出栈情况:当前字符串为操作并且优先级小于栈顶操作元素或者遇到“)”,将操作栈中栈顶元素出栈,操作数栈中出栈俩元素
* 入栈情况:“(”直接入栈,或者当前操作优先级大于栈顶元素则直接入栈,操作数直接入栈
*@paramexpression
*@return
*/
public static booleanparse2(String expression) {
Deque operands = new LinkedList<>();//操作数栈
Deque operate = new LinkedList<>();//操作栈
StringBuilder sb = newStringBuilder();try{byte[] bytes = expression.getBytes("GBK");for (int i = 0 ; i < bytes.length ; i ++) {//汉字
if (bytes[i] < 0) {if (i == bytes.length - 1) {//字符串异常截断//不要这个字
} else{
sb.append(new String(new byte[]{bytes[i], bytes[i + 1]}, "GBK"));
i++;
}continue;
}
String thisOp= new String(new byte[]{bytes[i]});//直接入栈
if ("(".equals(thisOp)) {
pushOperandIntoStack(operands, sb);
operate.addFirst(thisOp);continue;
}//到“(”之前的全部出栈
if (")".equals(thisOp)) {
pushOperandIntoStack(operands, sb);
String topOp=operate.pollFirst();while(!"(".equals(topOp)){
calculate(operands, topOp);if (operate.size() > 0) {
topOp=operate.pollFirst();
}else{//括号没匹配上,逻辑表达式出错
return false;
}
}continue;
}if (OperatorEnum.isOperator(thisOp)) {//当前是否为操作符//是,1.查看之前是否有字符未入栈,先入栈字符
pushOperandIntoStack(operands, sb);//2.查看下一个是否为操作,并且非括号,是合并当前一起入操作栈
String nextOp = new String(new byte[]{bytes[i + 1]});//下个与当前一起组成一个操作
if (!"(".equals(nextOp) && !")".equals(nextOp) &&OperatorEnum.isOperator(nextOp)) {
thisOp+=nextOp;
i++;
}//判断当前操作与栈顶操作优先级
if(operate.size() > 0){
String topOp=operate.getFirst();while(!"(".equals(topOp) && OperatorEnum.getEnumByName(topOp).getPriority()
topOp =operate.pollFirst();
calculate(operands, topOp);if (operate.size() > 0) {
topOp=operate.getFirst();
}else{break;
}
}
}
operate.addFirst(thisOp);
}else{
sb.append(thisOp);
}
}
}catch(Exception e){
e.printStackTrace();
}if(sb.length() > 0){
operands.addFirst(sb.toString());
}while(operate.size() > 0){
String topOp=operate.pollFirst();
calculate(operands, topOp);
}if (operands.size() > 0){
String str=operands.pollFirst();return StringUtils.isNotBlank(str) ? Boolean.parseBoolean(str) : false;
}return false;
}private static voidpushOperandIntoStack(Deque operands, StringBuilder sb){if(sb.length() > 0){
operands.addFirst(sb.toString());
sb.setLength(0);
}
}private static void calculate(Dequeoperands, String topOp){
String operand2=operands.pollFirst().trim();
String operand1=operands.pollFirst().trim();//判断两个操作数类型,不一致不可比较直接返回false
OperandTypeEnum type1 =judgeType(operand1);
OperandTypeEnum type2=judgeType(operand2);if (type1 ==type2) {switch(type1){caseNUM:
operands.addFirst(numCalculate(Long.parseLong(operand1), Long.parseLong(operand2),
OperatorEnum.getEnumByName(topOp))+ "");break;caseDATE:
operands.addFirst(dateCalculate(operand1, operand2, OperatorEnum.getEnumByName(topOp))+ "");break;caseSTR:
operands.addFirst(strCalculate(operand1, operand2, OperatorEnum.getEnumByName(topOp))+ "");break;
}
}else{
operands.addFirst("false");
}
}private staticOperandTypeEnum judgeType (String operands) {
operands=operands.trim();if (Pattern.matches("^[-\\+]?[\\d]*$", operands)) {returnOperandTypeEnum.NUM;
}if(DateUtil.verifyDateLegal(operands)) {returnOperandTypeEnum.DATE;
}returnOperandTypeEnum.STR;
}private static boolean numCalculate(long operand1, longoperand2, OperatorEnum operate){switch(operate){caseLT:return operand1 operand2;caseEGT:return operand1 >=operand2;caseEQ:return operand1 ==operand2;caseNEQ:return operand1 !=operand2;default:return true;
}
}private static booleanstrCalculate(String operand1, String operand2, OperatorEnum operate){switch(operate){caseEQ:returnoperand1.equals(operand2);caseNEQ:return !operand1.equals(operand2);caseAND:return "true".equals(operand1) && "true".equals(operand2);caseOR:return "true".equals(operand1) || "true".equals(operand2);default:return true;
}
}private static booleandateCalculate(String operand1, String operand2, OperatorEnum operate){switch(operate){caseLT:return DateUtil.compareDate(operand1, operand2) == -1 ? true : false;caseELT:return DateUtil.compareDate(operand1, operand2) <= 0 ? true : false;caseGT:return DateUtil.compareDate(operand1, operand2) == 1 ? true : false;caseEGT:return DateUtil.compareDate(operand1, operand2) >= 0 ? true : false;caseEQ:return DateUtil.compareDate(operand1, operand2) == 0 ? true : false;caseNEQ:return DateUtil.compareDate(operand1, operand2) != 0 ? true : false;default:return true;
}
}