将表达式(如 @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().