自研表達式引擎,支援類似 new(Class).method(param).chain() 的鏈式調用語法,核心為 AstParser 將字串解析為抽象語法樹(AST)。
package com.attilax.lang;
public class AstParser {
private Object obj; // 上下文物件,傳遞給各表達式
private Object rzt; // 最後一個表達式的結果
public List<Object> getExprsLiAst(String code) {
List<String> tokens = new JavaExpFsm(code).getTokens(); // 詞法分析
List<Object> astList = new ArrayList<>();
List<String> slice = new ArrayList<>();
for (int i = 0; i < tokens.size(); i++) {
String tk = tokens.get(i).trim();
if (".".equals(tk)) { // 點號為表達式分隔符
astList.add(buildExprs(slice));
slice.clear();
continue;
}
slice.add(tk);
if (i == tokens.size() - 1) { // 最後一段
astList.add(buildExprs(slice));
}
}
return astList;
}
private Exprs buildExprs(List<String> slice) {
Exprs e = new Exprs();
e.method = slice.get(0); // new(...) 或 methodName
if (slice.size() == 3) { // 無參數:method()
e.params = new ArrayList<>();
} else { // 有參數:method(p1, p2)
e.params = slice.subList(2, slice.size() - 1); // 去掉 method ( )
}
return e;
}
public Object parse(List<Object> ast) {
for (Object node : ast) {
parseSingle(node);
}
return rzt;
}
private void parseSingle(Object node) {
Exprs e = (Exprs) node;
e.obj = this.obj; // 注入上下文
this.rzt = e.calc(); // 執行表達式
this.obj = e.obj; // 更新上下文(支援鏈式)
}
}
JavaExpFsm 處理括號、引號、逗號、點號等,產出 Token 列表。new(A).b().c(d) → 三個 Exprs 節點。Exprs 執行後更新 obj,實現 a.b().c() 鏈式調用。String s = "new(com.attilax.orm.AtiOrmV2).queryAsRzt(\"select sum(rmb) from recharge where accountId in (select id from account where promoter=888)\")"; List<Object> ast = new AstParser().getExprsLiAst(s); Object result = new AstParser().parse(ast); // 執行並得到結果
ExpressionParser(Spring EL)或 MVEL 替代自研。Attilax (艾龍) — 博客 | Email: 1466519819@qq.com