package com.mossle.bpm.expr;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Expr {
private List<String> opers = new ArrayList<String>();
public Expr() {
// 优先级,&&高于||
opers.add("&&");
opers.add("||");
opers.add("(");
opers.add(")");
}
public List<String> evaluate(String text, ExprProcessor exprProcessor) {
List<Token> tokens = parse(text);
Stack<List<String>> stack = new Stack<List<String>>();
for (Token token : tokens) {
if (token.isOper()) {
List<String> right = stack.pop();
List<String> left = stack.pop();
List<String> value = exprProcessor.process(left, right,
token.getValue());
stack.push(value);
} else {
stack.push(exprProcessor.process(token.getValue()));
}
}
return stack.pop();
}
public List<Token> parse(String text) {
List<Token> tokens = lex(text);
Stack<Token> tokenStack = new Stack<Token>();
List<Token> output = new ArrayList<Token>();
for (Token token : tokens) {
processToken(token, tokenStack, output);
}
popTokenStack(tokenStack, output, false);
return output;
}
/**
* 依次对token进行处理,这个过程是把token按照反序排列.
* <p>
* 原表达式为:“OA组 || 平台组”,处理后就变成:“OA组 平台组 ||”
* </p>
*/
public void processToken(Token token, Stack<Token> tokenStack,
List<Token> output) {
if (token.isOper()) {
processOper(token, tokenStack, output);
} else {
processSymb(token, output);
}
}
/**
* 处理操作符.
*/
public void processOper(Token token, Stack<Token> tokenStack,
List<Token> output) {
if ("(".equals(token.getValue())) {
tokenStack.push(token);
return;
}
if (")".equals(token.getValue())) {
popTokenStack(tokenStack, output, true);
return;
}
if (tokenStack.empty()) {
tokenStack.push(token);
return;
}
Token innerToken = tokenStack.peek();
// 越靠前,索引越小,优先级越高
if (opers.indexOf(innerToken.getValue()) <= opers.indexOf(token
.getValue())) {
// 如果当前token的优先级低于栈顶的操作符优先级,就弹出栈顶的操作符
output.add(tokenStack.pop());
}
tokenStack.push(token);
}
/**
* 处理操作值.
*/
public void processSymb(Token token, List<Token> output) {
output.add(token);
}
/**
* 把堆栈中保存的操作符都弹出来,忽略().
*/
public void popTokenStack(Stack<Token> tokenStack, List<Token> output,
boolean breakWhenLeftBracket) {
while (!tokenStack.empty()) {
Token token = tokenStack.pop();
if ("(".equals(token.getValue())) {
if (breakWhenLeftBracket) {
return;
} else {
continue;
}
}
output.add(token);
}
}
public List<Token> lex(String text) {
List<Token> tokens = new ArrayList<Token>();
StringBuilder buff = new StringBuilder();
Oper bracket = null;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case ' ':
if (buff.length() > 0) {
String value = buff.toString();
buff = new StringBuilder();
if (opers.contains(value)) {
Oper oper = new Oper();
oper.setValue(value);
tokens.add(oper);
} else {
Symb symb = new Symb();
symb.setValue(value);
tokens.add(symb);
}
}
break;
case '(':
if (buff.length() > 0) {
String value = buff.toString();
buff = new StringBuilder();
if (opers.contains(value)) {
Oper oper = new Oper();
oper.setValue(value);
tokens.add(oper);
} else {
Symb symb = new Symb();
symb.setValue(value);
tokens.add(symb);
}
}
bracket = new Oper();
bracket.setValue("(");
tokens.add(bracket);
break;
case ')':
if (buff.length() > 0) {
String value = buff.toString();
buff = new StringBuilder();
if (opers.contains(value)) {
Oper oper = new Oper();
oper.setValue(value);
tokens.add(oper);
} else {
Symb symb = new Symb();
symb.setValue(value);
tokens.add(symb);
}
}
bracket = new Oper();
bracket.setValue(")");
tokens.add(bracket);
break;
default:
buff.append(c);
break;
}
}
if (buff.length() > 0) {
String value = buff.toString();
if (opers.contains(value)) {
Oper oper = new Oper();
oper.setValue(value);
tokens.add(oper);
} else {
Symb symb = new Symb();
symb.setValue(value);
tokens.add(symb);
}
}
return tokens;
}
}