将表达式(如 @a - @b + @c)中各部分 解析为token并存放在List中,算法如下:
ExpressUtils.java
public static List<Token> parse(String expr) {
List<Token> tokenList = new ArrayList<Token>();
TokenType type = TokenType.Text;
StringBuffer buf = new StringBuffer();
char[] charArray = expr.toCharArray();
for (int i = 0; i < charArray.length; ++i) {
char ch = charArray[i];
if (ch == '@') {
if (buf.length() > 0) {
tokenList.add(new Token(type, buf.toString()));
}
type = TokenType.Variant;
buf = new StringBuffer();
continue;
}
if (ch == '/' && i < charArray.length - 1 && charArray[i + 1] == '*') {
if (buf.length() > 0) {
tokenList.add(new Token(type, buf.toString()));
}
buf.append("/*");
++i;
type = TokenType.MultiLineComment;
continue;
}
if (ch == '/' && i < charArray.length - 1 && charArray[i + 1] == '/') {
if (buf.length() > 0) {
tokenList.add(new Token(type, buf.toString()));
}
buf.append("//");
++i;
type = TokenType.LineComment;
continue;
}
if (type == TokenType.Variant) {
if (Character.isLetter(ch) || Character.isDigit(ch)) {
buf.append(ch);
} else if (ch == '_') {
buf.append(ch);
} else {
tokenList.add(new Token(type, buf.toString()));
type = TokenType.Text;
buf = new StringBuffer();
--i;
}
continue;
}
if (type == TokenType.Text) {
buf.append(ch);
continue;
}
if (type == TokenType.MultiLineComment) {
if (ch == '*' && i < charArray.length - 1 && charArray[i + 1] == '/') {
buf.append("*/");
++i;
tokenList.add(new Token(type, buf.toString()));
type = TokenType.Text;
buf = new StringBuffer();
continue;
} else {
buf.append(ch);
}
}
if (type == TokenType.LineComment) {
if (ch == '\n') {
buf.append(ch);
tokenList.add(new Token(type, buf.toString()));
type = TokenType.Text;
buf = new StringBuffer();
} else if (ch == '\r') {
buf.append(ch);
if (i < charArray.length - 1 && charArray[i + 1] == '\n') {
buf.append(charArray[i + 1]);
++i;
}
tokenList.add(new Token(type, buf.toString()));
type = TokenType.Text;
buf = new StringBuffer();
} else {
buf.append(ch);
}
continue;
}
}
if (buf.length() > 0) {
tokenList.add(new Token(type, buf.toString()));
}
return tokenList;
}
将java源文件编译成类的Class型实例:JdkCompiler.java/JdkCompileTask.java
public synchronized Class<? extends Expr> compile(JavaSource javaSource) {
compileCount.incrementAndGet();
long startTimeMillis = System.nanoTime();
try {
final DiagnosticCollector<JavaFileObject> errs = new DiagnosticCollector<JavaFileObject>();
JdkCompileTask<Expr> compileTask = new JdkCompileTask<Expr>(classLoader, options);
String fullName = javaSource.getPackageName() + "." + javaSource.getClassName();
return (Class<? extends Expr>) compileTask.compile(fullName, javaSource.getSource(), errs);
} catch (JdkCompileException ex) {
DiagnosticCollector<JavaFileObject> diagnostics = ex.getDiagnostics();
throw new CompileExprException("compile error, source : \n" + javaSource + ", " + diagnostics.getDiagnostics(), ex);
} catch (Exception ex) {
throw new CompileExprException("compile error, source : \n" + javaSource, ex);
} finally {
// 编译时间统计
compileTimeNano.addAndGet(System.nanoTime() - startTimeMillis);
}
}
待研究:
javax.tools.JavaCompiler.JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler().