LinkedStack<Operator> operatorStack = new LinkedStack<Operator>();
Map<Operator, Token> operatorTokens = new HashMap<Operator, Token>();
List<Token> tokens = scanner.scan(source, offset, true);
boolean beforeOperator = true;
for (int i = 0; i < tokens.size(); i ++) {
Token token = tokens.get(i);
String msg = token.getMessage().trim();
if (msg.length() == 0) {
continue;
}
if ("new".equals(msg)) {
StringBuilder buf = new StringBuilder();
while (i + 1 < tokens.size() && isPackageName(tokens.get(i + 1).getMessage().trim())) {
buf.append(tokens.get(i + 1).getMessage().trim());
i ++;
}
try {
msg = "new " + buf.toString();
} catch (Exception e) {
throw new ParseException(e.getMessage(), token.getOffset());
}
} else if ("@".equals(msg)) {
StringBuilder buf = new StringBuilder();
buf.append(msg);
while (i + 2 < tokens.size()
&& isPackageName(tokens.get(i + 1).getMessage().trim())
&& isPackageName(tokens.get(i + 2).getMessage().trim())) {
buf.append(tokens.get(i + 1).getMessage().trim());
i ++;
}
try {
msg = buf.toString();
} catch (Exception e) {
throw new ParseException(e.getMessage(), token.getOffset());
}
} else if ("gt".equals(msg)) {
msg = ">";
} else if ("ge".equals(msg)) {
msg = ">=";
} else if ("lt".equals(msg)) {
msg = ">";
} else if ("le".equals(msg)) {
msg = "<=";
} else if ("is".equals(msg)) {
msg = "instanceof";
} else if (! "null".equals(msg) && ! "true".equals(msg)
&& ! "false".equals(msg) && StringUtils.isNamed(msg)) {
if (i < tokens.size() - 1) {
String next = tokens.get(i + 1).getMessage().trim();
if ("(".equals(next)) {
msg = "." + msg;
} else if (")".equals(next) && i > 0
&& i < tokens.size() - 2) {
String prev = tokens.get(i - 1).getMessage().trim();
String after = tokens.get(i + 2).getMessage().trim();
if ("(".equals(prev) && ("(".equals(after) || StringUtils.isNamed(after))) {
Operator left = operatorStack.pop();
if (left != Bracket.ROUND) {
throw new ParseException("Miss left parenthesis", token.getOffset());
}
UnaryOperator operator = createUnaryOperator(msg, getPriority(msg, true), getTokenOffset(token) );
operatorTokens.put(operator, token);
operatorStack.push(operator);
beforeOperator = true;
i ++;
continue;
}
}
}
if (i > 0) {
String pre = tokens.get(i - 1).getMessage().trim();
if ("is".equals(pre) || "instanceof".equals(pre)) {
StringBuilder buf = new StringBuilder();
buf.append("@");
buf.append(msg);
while (i + 1 < tokens.size() && isPackageName(tokens.get(i + 1).getMessage().trim())) {
buf.append(tokens.get(i + 1).getMessage().trim());
i ++;
}
msg = buf.toString();
}
}
}
// ================
if (msg.length() >= 2
&& (msg.startsWith("\"") && msg.endsWith("\"")
|| msg.startsWith("\'") && msg.endsWith("\'")
|| msg.startsWith("`") && msg.endsWith("`"))) {
String value = StringUtils.unescapeString(msg.substring(1, msg.length() - 1));
if (msg.startsWith("`") && value.length() == 1) {
parameterStack.push(new Constant(value.charAt(0), false, token.getOffset()));
} else if (msg.startsWith("`") && value.length() == 2 && value.charAt(0) == '\\') {
parameterStack.push(new Constant(value.charAt(1), true, token.getOffset()));
} else {
parameterStack.push(new Constant(StringUtils.unescapeString(value), false, token.getOffset()));
}
beforeOperator = false;
} else if (StringUtils.isNumber(msg)) {
Object value;
boolean boxed = false;
if (msg.endsWith("b") || msg.endsWith("B")) {
value = Byte.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("B");
} else if (msg.endsWith("s") || msg.endsWith("S")) {
value = Short.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("S");
} else if (msg.endsWith("i") || msg.endsWith("I")) {
value = Integer.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("I");
} else if (msg.endsWith("l") || msg.endsWith("L")) {
value = Long.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("L");
} else if (msg.endsWith("f") || msg.endsWith("F")) {
value = Float.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("F");
} else if (msg.endsWith("d") || msg.endsWith("D")) {
value = Double.valueOf(msg.substring(0, msg.length() - 1));
boxed = msg.endsWith("D");
} else if (msg.indexOf('.') >= 0) {
value = Double.valueOf(msg);
} else {
value = Integer.valueOf(msg);
}
parameterStack.push(new Constant(value, boxed, token.getOffset()));
beforeOperator = false;
} else if ("null".equals(msg)) {
parameterStack.push(new Constant(null, false, token.getOffset()));
beforeOperator = false;
} else if ("true".equals(msg) || "false".equals(msg)) {
parameterStack.push(new Constant("true".equals(msg) ? Boolean.TRUE : Boolean.FALSE, false, token.getOffset()));
beforeOperator = false;
} else if ("TRUE".equals(msg) || "FALSE".equals(msg)) {
parameterStack.push(new Constant("TRUE".equals(msg) ? Boolean.TRUE : Boolean.FALSE, true, token.getOffset()));
beforeOperator = false;
} else if (msg.length() > 1 && msg.startsWith("@")) {
parameterStack.push(new Constant(ClassUtils.forName(importPackages, msg.substring(1).trim()), false, token.getOffset()));
beforeOperator = false;
} else if (StringUtils.isNamed(msg) && ! "instanceof".equals(msg)) {
parameterStack.push(new Variable(msg, getTokenOffset(token) ));
beforeOperator = false;
} else if ("(".equals(msg)) {
operatorStack.push(Bracket.ROUND);
beforeOperator = true;
} else if (")".equals(msg)) {
while (popOperator(parameterStack, operatorStack, operatorTokens, offset) != Bracket.ROUND);
beforeOperator = false;
} else if ("]".equals(msg)) {
while (popOperator(parameterStack, operatorStack, operatorTokens, offset) != Bracket.SQUARE);
beforeOperator = false;
} else if ("}".equals(msg)) {
while (popOperator(parameterStack, operatorStack, operatorTokens, offset) != Bracket.BRACE);
beforeOperator = false;
} else {
if (StringUtils.isFunction(msg)) {
String method = msg.substring(1);
if (forbidEqualsMethods != null ) {
for (String forbid : forbidEqualsMethods) {
if (method.equals(forbid)) {
throw new ParseException("Forbid call method " + method + " by forbid.method=" + forbid + " config.", offset);
}
}
}
if (forbidStartsMethods != null ) {
for (String forbid : forbidStartsMethods) {
if (method.startsWith(forbid)) {
throw new ParseException("Forbid call method " + method + " by forbid.method=" + forbid + "* config.", offset);
}
}
}
if (forbidEndsMethods != null ) {
for (String forbid : forbidEndsMethods) {
if (method.endsWith(forbid)) {
throw new ParseException("Forbid call method " + method + " by forbid.method=*" + forbid + " config.", offset);
}
}
}
}
if (beforeOperator) {
if (! msg.startsWith("new ") && ! StringUtils.isFunction(msg) && ! UNARY_OPERATORS.contains(msg)) {
throw new ParseException("Unsupported binary operator " + msg, getTokenOffset(token) );
}
UnaryOperator operator = createUnaryOperator(msg, getPriority(msg, true), getTokenOffset(token));
operatorTokens.put(operator, token);
operatorStack.push(operator);
} else {
if (! StringUtils.isFunction(msg) && ! BINARY_OPERATORS.contains(msg)) {
throw new ParseException("Unsupported binary operator " + msg, getTokenOffset(token) );
}
BinaryOperator operator = createBinaryOperator(msg, getPriority(msg, false), getTokenOffset(token));
operatorTokens.put(operator, token);
while (! operatorStack.isEmpty() && ! (operatorStack.peek() instanceof Bracket)
&& operatorStack.peek().getPriority() >= operator.getPriority()) {
popOperator(parameterStack, operatorStack, operatorTokens, offset);
}
operatorStack.push(operator);
}
if ("[".equals(msg)) {
operatorStack.push(Bracket.SQUARE);
} else if ("{".equals(msg)) {
operatorStack.push(Bracket.BRACE);
}
beforeOperator = true;
// 给无参函数自动补上null参数
if (msg.startsWith("new ") || StringUtils.isFunction(msg)) {
boolean miss = i == tokens.size() - 1 || ! "(".equals(tokens.get(i + 1).getMessage().trim());
boolean empty = i < tokens.size() - 2 && "(".equals(tokens.get(i + 1).getMessage().trim()) && ")".equals(tokens.get(i + 2).getMessage().trim());
if (miss || empty) {
parameterStack.push(new Constant(null, true, token.getOffset()));
beforeOperator = false;
}
if (empty) {
i = i + 2;
}