自定义逻辑表达式,关键字:= 等于,& 与,| 或, !非, ( , ) ,<> 包含,>< 不包含, # 不等于。
表达式支持括号标识作用域。
自动机分析如下:
JAVA 实现:
public class ConditionAnalysis2 { // 终止符号 Set<Character> signSet; ConditionAnalysis2() { this.signSet = new HashSet<Character>(); signSet.add(' '); signSet.add('='); signSet.add('('); signSet.add(')'); signSet.add('#'); signSet.add('<'); signSet.add('>'); signSet.add('&'); signSet.add('|'); }public boolean analysis(String expression) { if (null == expression || expression.length() == 0) return false; if (expression.charAt(0) != '(') expression = "(" + expression + ")"; Res res = this.getRes(expression, 0, new Context(ContextStatus.START), false); return res.res; } private Res getRes(String expression, int left, Context context, boolean isOppo) { int len = expression.length(), right = left; while (right < len) { char c = expression.charAt(right); if (c == ' ') { right++; continue; } // 回归 if (')' == c) { if (isOppo) context.currentRes = !context.currentRes; Res res = new Res(context.currentRes, left, right + 1); System.out.println(expression.substring(isOppo ? left - 2 : left - 1, right + 1) + " : " + res.res); return res; } // 递归 if (c == '(' || (c == '!' && right + 1 < len && expression.charAt(right + 1) == '(')) { Res partRes = null; if (c == '(') partRes = this.getRes(expression, right + 1, new Context(ContextStatus.WAIT_RES), false); else partRes = this.getRes(expression, right + 2, new Context(ContextStatus.WAIT_RES), true); if (null == partRes) throw new RuntimeException("error at " + right); if (null == context.currentRes) context.currentRes = partRes.res; else { if (context.contextStatus == ContextStatus.AND) { context.currentRes = context.currentRes & partRes.res; } else if (context.contextStatus == ContextStatus.OR) { context.currentRes = context.currentRes | partRes.res; } } context.contextStatus = ContextStatus.RES; right = partRes.right; continue; } // 顺序 if (c == '&') { context.contextStatus = ContextStatus.AND; right++; continue; } if (c == '|') { context.contextStatus = ContextStatus.OR; right++; continue; } Res partRes = this.getPartRes(expression, right); if (context.contextStatus == ContextStatus.WAIT_RES) { context.currentRes = partRes.res; } else if (context.contextStatus == ContextStatus.AND) { context.currentRes = context.currentRes & partRes.res; } else if (context.contextStatus == ContextStatus.OR) { context.currentRes = context.currentRes | partRes.res; } context.contextStatus = ContextStatus.RES; right = partRes.right; } if (isOppo) context.currentRes = !context.currentRes; return new Res(context.currentRes, left, right); } private Res getPartRes(String expression, int left) { int len = expression.length(), right = left; Context currentContext = new Context(ContextStatus.WAIT_TOKEN); Token leftToken = null; boolean isOppo = false; Res res = null; while (right < len) { char c = expression.charAt(right); if (c == ' ') { right++; continue; } if (c == '!') { if (currentContext.contextStatus == ContextStatus.WAIT_TOKEN || currentContext.contextStatus == ContextStatus.WAIT_OPPO2) { currentContext.contextStatus = ContextStatus.WAIT_OPPO2; isOppo = !isOppo; right++; continue; } throw new RuntimeException("error ! at " + right); } if (c == '=' || c == '#' || c == '<' || c == '>') { if (c == '=') currentContext.contextStatus = ContextStatus.EQ; else if (c == '#') currentContext.contextStatus = ContextStatus.NOT_EQ; else if (c == '<' && currentContext.contextStatus == ContextStatus.TOKEN) currentContext.contextStatus = ContextStatus.XYW; else if (c == '<' && currentContext.contextStatus == ContextStatus.DYW) currentContext.contextStatus = ContextStatus.NOT_CON; else if (c == '>' && currentContext.contextStatus == ContextStatus.TOKEN) currentContext.contextStatus = ContextStatus.DYW; else if (c == '>' && currentContext.contextStatus == ContextStatus.XYW) currentContext.contextStatus = ContextStatus.CON; right++; continue; } Token token = this.getToken(expression, right); if (currentContext.contextStatus == ContextStatus.WAIT_TOKEN || currentContext.contextStatus == ContextStatus.WAIT_OPPO2) { leftToken = token; currentContext.contextStatus = ContextStatus.TOKEN; right = token.right; continue; } else { Boolean currentRes = null; if (currentContext.contextStatus == ContextStatus.EQ) { currentRes = token.token.equals(leftToken.token); } else if (currentContext.contextStatus == ContextStatus.NOT_EQ) { currentRes = !token.token.equals(leftToken.token); } else if (currentContext.contextStatus == ContextStatus.CON) { currentRes = leftToken.token.contains(token.token); } else if (currentContext.contextStatus == ContextStatus.NOT_CON) { currentRes = !leftToken.token.contains(token.token); } else if (currentContext.contextStatus == ContextStatus.XYW) { currentRes = Long.valueOf(leftToken.token) < Long.valueOf(token.token); } else if (currentContext.contextStatus == ContextStatus.DYW) { currentRes = Long.valueOf(leftToken.token) > Long.valueOf(token.token); } if (null == currentRes) throw new RuntimeException("res is null! error at " + right); right = token.right; if (isOppo) currentRes = !currentRes; res = new Res(currentRes, left, right); break; } } System.out.println(" " + expression.substring(left, right) + " : " + res.res); return res; } private Token getToken(String expression, int left) { int len = expression.length(), right = left; char c = expression.charAt(right); StringBuilder stringBuilder = new StringBuilder(); while (right < len && !this.signSet.contains(c)) { stringBuilder.append(expression.charAt(right)); right++; if (right < len) c = expression.charAt(right); } return new Token(stringBuilder.toString(), left, right); } class Res { Boolean res; int left, right; public Res(Boolean res, int left, int right) { this.res = res; this.left = left; this.right = right; } } class Token { String token; int left; int right; Token(String token, int left, int right) { this.token = token; this.left = left; this.right = right; } } class Context { ContextStatus contextStatus; Boolean currentRes; Context(ContextStatus contextStatus) { this.contextStatus = contextStatus; } } public enum ContextStatus { // 外层状态 START, WAIT_OPPO, WAIT_OPPO2, WAIT_RES, WAIT_RES2, RES, AND, OR, DONE, // 内层状态 WAIT_TOKEN, TOKEN, EQ, NOT_EQ, XYW, DYW, CON, NOT_CON } }
标签:right,自定义,ContextStatus,token,context,currentRes,解析,contextStatus,表达式 From: https://www.cnblogs.com/niuyourou/p/17162305.html