├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java └── com └── greenpineyu └── fel ├── Expression.java ├── Fel.java ├── FelEngine.java ├── FelEngineImpl.java ├── common ├── ArrayUtils.java ├── Callable.java ├── FelBuilder.java ├── Null.java ├── NumberUtil.java ├── ObjectUtils.java ├── ReflectUtil.java └── StringUtils.java ├── compile ├── AbstCompiler.java ├── CompileService.java ├── ConstExp.java ├── ConstExpSrc.java ├── FelCompiler.java ├── FelCompiler16.java ├── FelCompilerClassloader.java ├── FelJavaFileObject.java ├── FelMethod.java ├── FileClassLoader.java ├── InterpreterSourceBuilder.java ├── JavaSource.java ├── SourceBuilder.java ├── SourceGenerator.java ├── SourceGeneratorImpl.java ├── VarBuffer.java └── java.template ├── context ├── AbstractContext.java ├── ArrayCtx.java ├── ArrayCtxImpl.java ├── ContextChain.java ├── EmptyContext.java ├── FelContext.java ├── MapContext.java └── Var.java ├── exception ├── CompileException.java ├── EvalException.java ├── ParseException.java └── SecurityException.java ├── function ├── CommonFunction.java ├── Dollar.java ├── ErrorValue.java ├── FunMgr.java ├── Function.java ├── JavaMethod.java ├── StableFunction.java ├── TolerantFunction.java └── operator │ ├── Add.java │ ├── And.java │ ├── CollectionGet.java │ ├── Cond.java │ ├── Div.java │ ├── Dot.java │ ├── Equal.java │ ├── GreaterThan.java │ ├── GreaterThenEqual.java │ ├── LessThen.java │ ├── LessThenEqual.java │ ├── Mod.java │ ├── Mul.java │ ├── NotEqual.java │ ├── NotOper.java │ ├── Or.java │ └── Sub.java ├── interpreter ├── ConstInterpreter.java ├── Interpreter.java └── ProxyInterpreter.java ├── optimizer ├── ConstExpOpti.java ├── ConstOpti.java ├── Interpreters.java ├── Optimizer.java └── VarVisitOpti.java ├── parser ├── AbstFelNode.java ├── AbstFelParser.java ├── AntlrParser.java ├── ConstNode.java ├── FelLexer.java ├── FelNode.java ├── FelParser.java ├── FunNode.java ├── NodeAdaptor.java ├── Parser.java ├── Stable.java └── VarAstNode.java └── security ├── RegexSecurityMgr.java ├── SecurityMgr.java └── SecurityMgrImpl.java /.gitignore: -------------------------------------------------------------------------------- 1 | #* 2 | *$ 3 | *.BAK 4 | *.Z 5 | *.bak 6 | *.class 7 | *.elc 8 | *.ln 9 | *.log 10 | *.o 11 | *.obj 12 | *.olb 13 | *.old 14 | *.orig 15 | *.pyc 16 | *.pyo 17 | *.rej 18 | */.git/* 19 | *~ 20 | ,* 21 | .#* 22 | .DS_Store 23 | .del-* 24 | .deployables 25 | .make.state 26 | .nse_depinfo 27 | .svn 28 | CVS.adm 29 | RCS 30 | RCSLOG 31 | SCCS 32 | _$* 33 | _svn 34 | .classpath 35 | .project 36 | .settings/* 37 | target/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | fel 2 | === 3 | 4 | Fast Expression Language 5 | 6 | Fel是轻量级的高效的表达式计算引擎 7 | 详情请参阅:[http://code.google.com/p/fast-el/] 8 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.eweb4j 5 | fel 6 | 0.8 7 | 8 | fel 9 | http://code.google.com/p/fast-el/ 10 | Fast Expression Language 11 | 12 | 13 | greenpineyu 14 | 青松 15 | greenpineyu@gmail.com 16 | http://code.google.com/p/fast-el/ 17 | 8 18 | 19 | 20 | 21 | Github Issue 22 | https://github.com/laiweiwei/fel/issues 23 | 24 | 25 | 26 | The Apache Software License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0.txt 28 | 29 | 30 | 31 | git@github.com:laiweiwei/fel.git 32 | https://github.com/laiweiwei/fel.git 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-javadoc-plugin 39 | 2.7 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.antlr 47 | antlr-runtime 48 | 3.4 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/Expression.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | 5 | public interface Expression { 6 | /** 7 | * 求表达式的值 8 | * @param arguments 9 | * @return 10 | */ 11 | Object eval(FelContext context); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/Fel.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel; 2 | 3 | import java.util.Map; 4 | 5 | import com.greenpineyu.fel.context.ArrayCtxImpl; 6 | import com.greenpineyu.fel.context.FelContext; 7 | import com.greenpineyu.fel.context.MapContext; 8 | import com.greenpineyu.fel.context.Var; 9 | 10 | public class Fel { 11 | static FelEngineImpl engine = new FelEngineImpl(); 12 | 13 | public static Object eval(String exp, Var... vars) { 14 | return engine.eval(exp, vars); 15 | } 16 | 17 | public static Object eval(String exp, Map vars) { 18 | FelContext ctx = new MapContext(vars); 19 | return engine.eval(exp, ctx); 20 | } 21 | 22 | public static Expression compile(String exp, Var... vars) { 23 | return engine.compile(exp, vars); 24 | } 25 | 26 | public static Expression compile(String exp, Map vars) { 27 | return engine.compile(exp, new MapContext(vars)); 28 | } 29 | 30 | public static FelEngine newEngine() { 31 | return new FelEngineImpl(); 32 | } 33 | 34 | public static FelContext newContext(String name) { 35 | if ("Array".equalsIgnoreCase(name)) { 36 | return new ArrayCtxImpl(); 37 | } 38 | return new MapContext(); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Object eval = eval("0.1+0.19"); 43 | System.out.println(eval); 44 | System.out.println(0.1 + 0.19); 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/FelEngine.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel; 2 | 3 | import com.greenpineyu.fel.compile.CompileService; 4 | import com.greenpineyu.fel.context.FelContext; 5 | import com.greenpineyu.fel.function.FunMgr; 6 | import com.greenpineyu.fel.function.Function; 7 | import com.greenpineyu.fel.optimizer.Optimizer; 8 | import com.greenpineyu.fel.parser.FelNode; 9 | import com.greenpineyu.fel.parser.Parser; 10 | import com.greenpineyu.fel.security.SecurityMgr; 11 | 12 | /** 13 | * 表达式引擎 14 | * 15 | * @author yqs 16 | */ 17 | public interface FelEngine { 18 | 19 | /** 20 | * 默认实例 21 | */ 22 | FelEngine instance = new FelEngineImpl(); 23 | 24 | /** 25 | * 执行表达式,获取结果 26 | * 27 | * @param exp 28 | * @return 29 | */ 30 | Object eval(String exp); 31 | 32 | /** 33 | * 使用指定的引擎上下文执行表达式,获取结果 34 | * 35 | * @param exp 36 | * @param ctx 引擎上下文 37 | * @return 38 | */ 39 | Object eval(String exp, FelContext ctx); 40 | 41 | /** 42 | * 解析表达式为节点 43 | * 44 | * @param exp 45 | * @return 46 | */ 47 | FelNode parse(String exp); 48 | 49 | /** 50 | * 编译表达式 51 | * 52 | * @param exp 53 | * @param ctx 54 | * @param opts 编译优化选项 55 | * @return 56 | */ 57 | Expression compile(String exp, FelContext ctx, Optimizer... opts); 58 | 59 | /** 60 | * @return 引擎执行环境 61 | */ 62 | FelContext getContext(); 63 | 64 | /** 65 | * 添加函数到用户函数库中(执行表达式时,优先从用户函数库中获取函数) 66 | * 67 | * @param fun 68 | * @return 69 | */ 70 | void addFun(Function fun); 71 | 72 | /** 73 | * 获取编译器 74 | * @return 75 | */ 76 | CompileService getCompiler() ; 77 | 78 | /** 79 | * 设置编译器 80 | * @param compiler 81 | */ 82 | void setCompiler(CompileService compiler); 83 | 84 | /** 85 | * 获取解析器 86 | * @return 87 | */ 88 | Parser getParser(); 89 | 90 | /** 91 | * 设置解析器 92 | * @param parser 93 | */ 94 | void setParser(Parser parser); 95 | 96 | /** 97 | * 获取函数管理器 98 | * @return 99 | */ 100 | FunMgr getFunMgr(); 101 | 102 | /** 103 | * 设置函数管理器 104 | * @param funMgr 105 | */ 106 | void setFunMgr(FunMgr funMgr); 107 | 108 | /** 109 | * 设置Context 110 | * @param context 111 | */ 112 | void setContext(FelContext context); 113 | 114 | /** 115 | * 返回安全管理器 116 | * @return 117 | */ 118 | SecurityMgr getSecurityMgr(); 119 | 120 | /** 121 | * 设置安全管理器 122 | * @param mgr 123 | */ 124 | void setSecurityMgr(SecurityMgr mgr); 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/FelEngineImpl.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel; 2 | 3 | import com.greenpineyu.fel.common.FelBuilder; 4 | import com.greenpineyu.fel.compile.CompileService; 5 | import com.greenpineyu.fel.context.ArrayCtxImpl; 6 | import com.greenpineyu.fel.context.FelContext; 7 | import com.greenpineyu.fel.context.Var; 8 | import com.greenpineyu.fel.function.FunMgr; 9 | import com.greenpineyu.fel.function.Function; 10 | import com.greenpineyu.fel.optimizer.Optimizer; 11 | import com.greenpineyu.fel.optimizer.VarVisitOpti; 12 | import com.greenpineyu.fel.parser.AntlrParser; 13 | import com.greenpineyu.fel.parser.FelNode; 14 | import com.greenpineyu.fel.parser.Parser; 15 | import com.greenpineyu.fel.security.SecurityMgr; 16 | 17 | /** 18 | * 执行引擎 19 | * 20 | * @author yqs 21 | * 22 | */ 23 | public class FelEngineImpl implements FelEngine { 24 | 25 | private FelContext context; 26 | 27 | private CompileService compiler; 28 | 29 | private Parser parser; 30 | 31 | private FunMgr funMgr; 32 | 33 | private SecurityMgr securityMgr; 34 | 35 | 36 | public SecurityMgr getSecurityMgr() { 37 | return securityMgr; 38 | } 39 | 40 | public void setSecurityMgr(SecurityMgr securityMgr) { 41 | this.securityMgr = securityMgr; 42 | } 43 | 44 | public FelEngineImpl(FelContext context) { 45 | this.context = context; 46 | compiler = new CompileService(); 47 | parser = new AntlrParser(this); 48 | this.funMgr=new FunMgr(); 49 | } 50 | 51 | { 52 | this.securityMgr = FelBuilder.newSecurityMgr(); 53 | } 54 | 55 | public FelEngineImpl() { 56 | this(new ArrayCtxImpl()); 57 | // this(new MapContext()); 58 | } 59 | 60 | 61 | public FelNode parse(String exp) { 62 | return parser.parse(exp); 63 | } 64 | 65 | 66 | public Object eval(String exp) { 67 | return this.eval(exp, this.context); 68 | } 69 | 70 | public Object eval(String exp, Var... vars) { 71 | FelNode node = parse(exp); 72 | Optimizer opt = new VarVisitOpti(vars); 73 | node = opt.call(context, node); 74 | return node.eval(context); 75 | } 76 | 77 | public Object eval(String exp, FelContext ctx) { 78 | return parse(exp).eval(ctx); 79 | } 80 | 81 | public Expression compile(String exp, Var... vars) { 82 | return compile(exp, null, new VarVisitOpti(vars)); 83 | } 84 | 85 | public Expression compile(String exp, FelContext ctx, Optimizer... opts) { 86 | if (ctx == null) { 87 | ctx = this.context; 88 | } 89 | FelNode node = parse(exp); 90 | if (opts != null) { 91 | for (Optimizer opt : opts) { 92 | if (opt != null) { 93 | node = opt.call(ctx, node); 94 | } 95 | } 96 | } 97 | return compiler.compile(ctx, node, exp); 98 | } 99 | 100 | public String toString() { 101 | return "FelEngine"; 102 | } 103 | 104 | public void addFun(Function fun) { 105 | this.funMgr.add(fun); 106 | } 107 | 108 | public FelContext getContext() { 109 | return this.context; 110 | } 111 | 112 | public CompileService getCompiler() { 113 | return compiler; 114 | } 115 | 116 | public void setCompiler(CompileService compiler) { 117 | this.compiler = compiler; 118 | } 119 | 120 | public Parser getParser() { 121 | return parser; 122 | } 123 | 124 | public void setParser(Parser parser) { 125 | this.parser = parser; 126 | } 127 | 128 | public FunMgr getFunMgr() { 129 | return funMgr; 130 | } 131 | 132 | public void setFunMgr(FunMgr funMgr) { 133 | this.funMgr = funMgr; 134 | } 135 | 136 | public void setContext(FelContext context) { 137 | this.context = context; 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | 6 | public class ArrayUtils { 7 | /** 8 | *

Checks if an array of Objects is empty or {@code null}.

9 | * 10 | * @param array the array to test 11 | * @return {@code true} if the array is empty or {@code null} 12 | * @since 2.1 13 | */ 14 | public static boolean isEmpty(Object[] array) { 15 | return array == null || array.length == 0; 16 | } 17 | 18 | /** 19 | *

Outputs an array as a String, treating {@code null} as an empty array.

20 | * 21 | *

Multi-dimensional arrays are handled correctly, including 22 | * multi-dimensional primitive arrays.

23 | * 24 | *

The format is that of Java source code, for example {a,b}.

25 | * 26 | * @param array the array to get a toString for, may be {@code null} 27 | * @return a String representation of the array, '{}' if null array input 28 | */ 29 | // public static String toString(Object array) { 30 | // 31 | // return toString(array, "{}"); 32 | // } 33 | // 34 | // /** 35 | // *

Outputs an array as a String handling {@code null}s.

36 | // * 37 | // *

Multi-dimensional arrays are handled correctly, including 38 | // * multi-dimensional primitive arrays.

39 | // * 40 | // *

The format is that of Java source code, for example {a,b}.

41 | // * 42 | // * @param array the array to get a toString for, may be {@code null} 43 | // * @param stringIfNull the String to return if the array is {@code null} 44 | // * @return a String representation of the array 45 | // */ 46 | // public static String toString(Object array, String stringIfNull) { 47 | // if (array == null) { 48 | // return stringIfNull; 49 | // } 50 | // return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString(); 51 | // } 52 | 53 | /** 54 | *

Produces a new array containing the elements between 55 | * the start and end indices.

56 | * 57 | *

The start index is inclusive, the end index exclusive. 58 | * Null array input produces null output.

59 | * 60 | *

The component type of the subarray is always the same as 61 | * that of the input array. Thus, if the input is an array of type 62 | * {@code Date}, the following usage is envisaged:

63 | * 64 | *
 65 |      * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
 66 |      * 
67 | * 68 | * @param the component type of the array 69 | * @param array the array 70 | * @param startIndexInclusive the starting index. Undervalue (<0) 71 | * is promoted to 0, overvalue (>array.length) results 72 | * in an empty array. 73 | * @param endIndexExclusive elements up to endIndex-1 are present in the 74 | * returned subarray. Undervalue (< startIndex) produces 75 | * empty array, overvalue (>array.length) is demoted to 76 | * array length. 77 | * @return a new array containing the elements between 78 | * the start and end indices. 79 | * @since 2.1 80 | */ 81 | public static T[] subarray(T[] array, int startIndexInclusive, int endIndexExclusive) { 82 | if (array == null) { 83 | return null; 84 | } 85 | if (startIndexInclusive < 0) { 86 | startIndexInclusive = 0; 87 | } 88 | if (endIndexExclusive > array.length) { 89 | endIndexExclusive = array.length; 90 | } 91 | int newSize = endIndexExclusive - startIndexInclusive; 92 | Class type = array.getClass().getComponentType(); 93 | if (newSize <= 0) { 94 | @SuppressWarnings("unchecked") // OK, because array is of type T 95 | final T[] emptyArray = (T[]) Array.newInstance(type, 0); 96 | return emptyArray; 97 | } 98 | @SuppressWarnings("unchecked") // OK, because array is of type T 99 | T[] subarray = (T[]) Array.newInstance(type, newSize); 100 | System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); 101 | return subarray; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/Callable.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | /** 4 | * 5 | * 可调用接口 6 | * @author yuqingsong 7 | * 8 | * @param 参数返回值 9 | * @param

参数类型 10 | */ 11 | public interface Callable { 12 | 13 | R call(P... arg); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/FelBuilder.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | import java.io.File; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | import com.greenpineyu.fel.security.RegexSecurityMgr; 8 | import com.greenpineyu.fel.security.SecurityMgr; 9 | 10 | public class FelBuilder { 11 | 12 | /** 13 | * 构建安全管理器 14 | * @return 15 | */ 16 | public static SecurityMgr newSecurityMgr() { 17 | Set disables = new HashSet(); 18 | disables.add(System.class.getCanonicalName() + ".*"); 19 | disables.add(Runtime.class.getCanonicalName() + ".*"); 20 | disables.add(Process.class.getCanonicalName() + ".*"); 21 | disables.add(File.class.getCanonicalName() + ".*"); 22 | disables.add("java.net.*"); 23 | disables.add("com.greenpineyu.fel.compile.*"); 24 | disables.add("com.greenpineyu.fel.security.*"); 25 | return new RegexSecurityMgr(null, disables); 26 | } 27 | 28 | public static void main(String[] args) { 29 | System.out.println(System.class.getCanonicalName()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/Null.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | /** 4 | * 用于表示Null值 5 | * @author yuqingsong 6 | * 7 | */ 8 | public class Null { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/ObjectUtils.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | 4 | public class ObjectUtils { 5 | /** 6 | *

Compares two objects for equality, where either one or both 7 | * objects may be {@code null}.

8 | * 9 | *
10 |      * ObjectUtils.equals(null, null)                  = true
11 |      * ObjectUtils.equals(null, "")                    = false
12 |      * ObjectUtils.equals("", null)                    = false
13 |      * ObjectUtils.equals("", "")                      = true
14 |      * ObjectUtils.equals(Boolean.TRUE, null)          = false
15 |      * ObjectUtils.equals(Boolean.TRUE, "true")        = false
16 |      * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE)  = true
17 |      * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
18 |      * 
19 | * 20 | * @param object1 the first object, may be {@code null} 21 | * @param object2 the second object, may be {@code null} 22 | * @return {@code true} if the values of both objects are the same 23 | */ 24 | public static boolean equals(Object object1, Object object2) { 25 | if (object1 == object2) { 26 | return true; 27 | } 28 | if ((object1 == null) || (object2 == null)) { 29 | return false; 30 | } 31 | return object1.equals(object2); 32 | } 33 | 34 | /** 35 | *

Gets the {@code toString} of an {@code Object} returning 36 | * an empty string ("") if {@code null} input.

37 | * 38 | *
39 |      * ObjectUtils.toString(null)         = ""
40 |      * ObjectUtils.toString("")           = ""
41 |      * ObjectUtils.toString("bat")        = "bat"
42 |      * ObjectUtils.toString(Boolean.TRUE) = "true"
43 |      * 
44 | * 45 | * @see StringUtils#defaultString(String) 46 | * @see String#valueOf(Object) 47 | * @param obj the Object to {@code toString}, may be null 48 | * @return the passed in Object's toString, or nullStr if {@code null} input 49 | * @since 2.0 50 | */ 51 | public static String toString(Object obj) { 52 | return obj == null ? "" : obj.toString(); 53 | } 54 | 55 | /** 56 | *

Compares two objects for inequality, where either one or both 57 | * objects may be {@code null}.

58 | * 59 | *
60 |      * ObjectUtils.notEqual(null, null)                  = false
61 |      * ObjectUtils.notEqual(null, "")                    = true
62 |      * ObjectUtils.notEqual("", null)                    = true
63 |      * ObjectUtils.notEqual("", "")                      = false
64 |      * ObjectUtils.notEqual(Boolean.TRUE, null)          = true
65 |      * ObjectUtils.notEqual(Boolean.TRUE, "true")        = true
66 |      * ObjectUtils.notEqual(Boolean.TRUE, Boolean.TRUE)  = false
67 |      * ObjectUtils.notEqual(Boolean.TRUE, Boolean.FALSE) = true
68 |      * 
69 | * 70 | * @param object1 the first object, may be {@code null} 71 | * @param object2 the second object, may be {@code null} 72 | * @return {@code false} if the values of both objects are the same 73 | */ 74 | public static boolean notEqual(Object object1, Object object2) { 75 | return ObjectUtils.equals(object1, object2) == false; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/ReflectUtil.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class ReflectUtil { 8 | 9 | /** 10 | * key为基本类型及其包装类型,value为包装类型 11 | */ 12 | static final Map,Class> wrapperCls; 13 | /** 14 | * key为基本类型及其包装类型,value为基本类型 15 | */ 16 | static final Map,Class> primitiveCls; 17 | 18 | static final Map,Class> numberClassMap; 19 | static{ 20 | numberClassMap = wrapperNumberCls(); 21 | primitiveCls = new HashMap, Class>(primitiveNumberCls()); 22 | primitiveCls.put(boolean.class, boolean.class); 23 | primitiveCls.put(Boolean.class, boolean.class); 24 | 25 | wrapperCls = new HashMap, Class>(wrapperNumberCls()); 26 | wrapperCls.put(boolean.class, Boolean.class); 27 | wrapperCls.put(Boolean.class, Boolean.class); 28 | } 29 | 30 | private static Map,Class> primitiveNumberCls() { 31 | Map,Class> map = new HashMap, Class>(); 32 | map.put(byte.class, byte.class); 33 | map.put(Byte.class, byte.class); 34 | 35 | map.put(short.class, short.class); 36 | map.put(Short.class, short.class); 37 | 38 | map.put(int.class, int.class); 39 | map.put(Integer.class, int.class); 40 | 41 | map.put(long.class, long.class); 42 | map.put(Long.class, long.class); 43 | 44 | map.put(float.class, float.class); 45 | map.put(Float.class, float.class); 46 | 47 | map.put(double.class, double.class); 48 | map.put(Double.class, double.class); 49 | 50 | map.put(char.class, char.class); 51 | map.put(Character.class, char.class); 52 | return map; 53 | } 54 | 55 | private static Map,Class> wrapperNumberCls() { 56 | Map,Class> map = new HashMap, Class>(); 57 | map.put(byte.class, Byte.class); 58 | map.put(Byte.class, Byte.class); 59 | 60 | map.put(short.class, Short.class); 61 | map.put(Short.class, Short.class); 62 | 63 | map.put(int.class, Integer.class); 64 | map.put(Integer.class, Integer.class); 65 | 66 | map.put(long.class, Long.class); 67 | map.put(Long.class, Long.class); 68 | 69 | map.put(float.class, Float.class); 70 | map.put(Float.class, Float.class); 71 | 72 | map.put(double.class, Double.class); 73 | map.put(Double.class, Double.class); 74 | 75 | map.put(char.class, Character.class); 76 | map.put(Character.class, Character.class); 77 | return map; 78 | } 79 | 80 | /** 81 | * 是基本类型中的数值类型(包含包装类型) 82 | * @return 83 | */ 84 | public static boolean isPrimitiveOrWrapNumber(Class c){ 85 | return numberClassMap.containsKey(c); 86 | } 87 | public static boolean isPrimitiveNumber(Class c){ 88 | if(c == null){ 89 | return false; 90 | } 91 | return c.isPrimitive()&&(c!=boolean.class); 92 | // return numberClassMap.containsKey(c); 93 | } 94 | 95 | public static Class toWrapperClass(Class c){ 96 | return wrapperCls.get(c); 97 | } 98 | public static Class toPrimitiveClass(Class c){ 99 | return primitiveCls.get(c); 100 | } 101 | 102 | /* 103 | public static void main(String[] args) { 104 | System.out.println((1+"2"+3)); 105 | int[] a = new int[]{5,4,3,2,10,100,1}; 106 | sort(a); 107 | System.out.println(Arrays.toString(a)); 108 | }*/ 109 | 110 | public static void sort(int[] array){ 111 | for (int i = 1; i < array.length; i++) { 112 | int j = i-1; 113 | int current = array[i]; 114 | for(;j>-1&¤t cls,String attr,Class[] paramTypes){ 130 | if(attr == null || "".equals(attr)){ 131 | return null; 132 | } 133 | String firstUpper = String.valueOf(attr.charAt(0)).toUpperCase()+attr.substring(1); 134 | Method[] methods = cls.getMethods(); 135 | 136 | Method finalMethod = null; 137 | String[] methodNames = new String[]{attr,"get"+firstUpper,"is"+firstUpper}; 138 | for (String methodName : methodNames) { 139 | finalMethod = match(methodName, paramTypes, methods); 140 | if(finalMethod!=null){ 141 | break; 142 | } 143 | } 144 | return finalMethod; 145 | 146 | /* 147 | String get = "get"; 148 | finalMethod = match(get, paramTypes, methods, finalMethod); 149 | if(finalMethod!=null){ 150 | return finalMethod; 151 | }*/ 152 | } 153 | 154 | public static Method getMethod(Class cls,String methodName,Class[] paramTypes){ 155 | Method[] methods = cls.getMethods(); 156 | return match(methodName,paramTypes,methods); 157 | 158 | } 159 | private static Method match(String methodName, Class[] paramValueTypes, 160 | Method[] methods) { 161 | Method finalMethod = null; 162 | //方法名称和参数长度核匹配的方法,当不能精确匹配时,返回此方法 163 | Method nameParamLengthEqualsMethod = null; 164 | out:for (Method m : methods) { 165 | String name = m.getName(); 166 | if(name.equals(methodName) ){ 167 | Class[] methodParamTypes = m.getParameterTypes(); 168 | if(methodParamTypes!=null&& paramValueTypes != null){ 169 | if(methodParamTypes.length== paramValueTypes.length){ 170 | if(nameParamLengthEqualsMethod == null){ 171 | nameParamLengthEqualsMethod = m; 172 | } 173 | 174 | //比较参数是否匹配 175 | for (int i = 0; i < methodParamTypes.length; i++) { 176 | Class c1 = methodParamTypes[i]; 177 | Class c2 = paramValueTypes[i]; 178 | if(!isTypeMatch(c1, c2)){ 179 | //如果不匹配,找下一个方法 180 | continue out; 181 | } 182 | } 183 | finalMethod = m; 184 | break; 185 | } 186 | }else if(ArrayUtils.isEmpty(methodParamTypes)&&ArrayUtils.isEmpty(paramValueTypes)){ 187 | //如果参数都为null,认为是方法是匹配的 188 | finalMethod = m; 189 | break; 190 | } 191 | } 192 | } 193 | return finalMethod == null?nameParamLengthEqualsMethod:finalMethod; 194 | } 195 | 196 | public static boolean isTypeMatch(Class c1,Class c2){ 197 | if(c1 == c2||c2==Null.class){ 198 | //当c2为Null.class时,表示参数值是null,null值可以与任何类型匹配类型 199 | return true; 200 | } 201 | Class w1 = ReflectUtil.toWrapperClass(c1); 202 | Class w2 = ReflectUtil.toWrapperClass(c2); 203 | if(w1!=null){ 204 | //可能转换成包装类型 205 | if(w1==w2){ 206 | //查看包装类型是否相等 207 | return true; 208 | } 209 | } 210 | //判断c2是不是c1的子类,如果是,返回true 211 | return c1.isAssignableFrom(c2); 212 | } 213 | 214 | static public String getClassName(Class cls){ 215 | if(cls == null){ 216 | return "null"; 217 | } 218 | return cls.getCanonicalName(); 219 | } 220 | 221 | 222 | } 223 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/common/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.common; 2 | 3 | public class StringUtils { 4 | 5 | /** 6 | * Represents a failed index search. 7 | * @since 2.1 8 | */ 9 | public static final int INDEX_NOT_FOUND = -1; 10 | 11 | public static boolean isEmpty(CharSequence cs) { 12 | return cs == null || cs.length() == 0; 13 | } 14 | 15 | /** 16 | *

Checks if a CharSequence is not empty ("") and not null.

17 | * 18 | *
 19 |     * StringUtils.isNotEmpty(null)      = false
 20 |     * StringUtils.isNotEmpty("")        = false
 21 |     * StringUtils.isNotEmpty(" ")       = true
 22 |     * StringUtils.isNotEmpty("bob")     = true
 23 |     * StringUtils.isNotEmpty("  bob  ") = true
 24 |     * 
25 | * 26 | * @param cs the CharSequence to check, may be null 27 | * @return {@code true} if the CharSequence is not empty and not null 28 | * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 29 | */ 30 | public static boolean isNotEmpty(CharSequence cs) { 31 | return !StringUtils.isEmpty(cs); 32 | } 33 | 34 | 35 | /** 36 | *

Replaces all occurrences of a String within another String.

37 | * 38 | *

A {@code null} reference passed to this method is a no-op.

39 | * 40 | *
 41 |     * StringUtils.replace(null, *, *)        = null
 42 |     * StringUtils.replace("", *, *)          = ""
 43 |     * StringUtils.replace("any", null, *)    = "any"
 44 |     * StringUtils.replace("any", *, null)    = "any"
 45 |     * StringUtils.replace("any", "", *)      = "any"
 46 |     * StringUtils.replace("aba", "a", null)  = "aba"
 47 |     * StringUtils.replace("aba", "a", "")    = "b"
 48 |     * StringUtils.replace("aba", "a", "z")   = "zbz"
 49 |     * 
50 | * 51 | * @see #replace(String text, String searchString, String replacement, int max) 52 | * @param text text to search and replace in, may be null 53 | * @param searchString the String to search for, may be null 54 | * @param replacement the String to replace it with, may be null 55 | * @return the text with any replacements processed, 56 | * {@code null} if null String input 57 | */ 58 | public static String replace(String text, String searchString, String replacement) { 59 | return replace(text, searchString, replacement, -1); 60 | } 61 | 62 | 63 | /** 64 | *

Replaces a String with another String inside a larger String, 65 | * for the first {@code max} values of the search String.

66 | * 67 | *

A {@code null} reference passed to this method is a no-op.

68 | * 69 | *
 70 |     * StringUtils.replace(null, *, *, *)         = null
 71 |     * StringUtils.replace("", *, *, *)           = ""
 72 |     * StringUtils.replace("any", null, *, *)     = "any"
 73 |     * StringUtils.replace("any", *, null, *)     = "any"
 74 |     * StringUtils.replace("any", "", *, *)       = "any"
 75 |     * StringUtils.replace("any", *, *, 0)        = "any"
 76 |     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
 77 |     * StringUtils.replace("abaa", "a", "", -1)   = "b"
 78 |     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
 79 |     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
 80 |     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
 81 |     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
 82 |     * 
83 | * 84 | * @param text text to search and replace in, may be null 85 | * @param searchString the String to search for, may be null 86 | * @param replacement the String to replace it with, may be null 87 | * @param max maximum number of values to replace, or {@code -1} if no maximum 88 | * @return the text with any replacements processed, 89 | * {@code null} if null String input 90 | */ 91 | public static String replace(String text, String searchString, String replacement, int max) { 92 | if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 93 | return text; 94 | } 95 | int start = 0; 96 | int end = text.indexOf(searchString, start); 97 | if (end == INDEX_NOT_FOUND) { 98 | return text; 99 | } 100 | int replLength = searchString.length(); 101 | int increase = replacement.length() - replLength; 102 | increase = (increase < 0 ? 0 : increase); 103 | increase *= (max < 0 ? 16 : (max > 64 ? 64 : max)); 104 | StringBuilder buf = new StringBuilder(text.length() + increase); 105 | while (end != INDEX_NOT_FOUND) { 106 | buf.append(text.substring(start, end)).append(replacement); 107 | start = end + replLength; 108 | if (--max == 0) { 109 | break; 110 | } 111 | end = text.indexOf(searchString, start); 112 | } 113 | buf.append(text.substring(start)); 114 | return buf.toString(); 115 | } 116 | 117 | 118 | /** 119 | *

Removes all occurrences of a character from within the source string.

120 | * 121 | *

A {@code null} source string will return {@code null}. 122 | * An empty ("") source string will return the empty string.

123 | * 124 | *
125 |     * StringUtils.remove(null, *)       = null
126 |     * StringUtils.remove("", *)         = ""
127 |     * StringUtils.remove("queued", 'u') = "qeed"
128 |     * StringUtils.remove("queued", 'z') = "queued"
129 |     * 
130 | * 131 | * @param str the source String to search, may be null 132 | * @param remove the char to search for and remove, may be null 133 | * @return the substring with the char removed if found, 134 | * {@code null} if null String input 135 | * @since 2.1 136 | */ 137 | public static String remove(String str, char remove) { 138 | if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 139 | return str; 140 | } 141 | char[] chars = str.toCharArray(); 142 | int pos = 0; 143 | for (int i = 0; i < chars.length; i++) { 144 | if (chars[i] != remove) { 145 | chars[pos++] = chars[i]; 146 | } 147 | } 148 | return new String(chars, 0, pos); 149 | } 150 | 151 | //----------------------------------------------------------------------- 152 | /** 153 | *

Compares two CharSequences, returning {@code true} if they are equal.

154 | * 155 | *

{@code null}s are handled without exceptions. Two {@code null} 156 | * references are considered to be equal. The comparison is case sensitive.

157 | * 158 | *
159 |     * StringUtils.equals(null, null)   = true
160 |     * StringUtils.equals(null, "abc")  = false
161 |     * StringUtils.equals("abc", null)  = false
162 |     * StringUtils.equals("abc", "abc") = true
163 |     * StringUtils.equals("abc", "ABC") = false
164 |     * 
165 | * 166 | * @see java.lang.String#equals(Object) 167 | * @param cs1 the first CharSequence, may be null 168 | * @param cs2 the second CharSequence, may be null 169 | * @return {@code true} if the CharSequences are equal, case sensitive, or 170 | * both {@code null} 171 | * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 172 | */ 173 | public static boolean equals(CharSequence cs1, CharSequence cs2) { 174 | return cs1 == null ? cs2 == null : cs1.equals(cs2); 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/AbstCompiler.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.LinkedBlockingQueue; 8 | import java.util.concurrent.ThreadPoolExecutor; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | import com.greenpineyu.fel.Expression; 12 | import com.greenpineyu.fel.common.StringUtils; 13 | 14 | public abstract class AbstCompiler implements FelCompiler { 15 | 16 | /** 17 | * class文件夹 18 | */ 19 | static final String CLASS_DIR; 20 | 21 | private String classpath4compile; 22 | 23 | private static final String BASE_DIR; 24 | static ClassLoader loader; 25 | static { 26 | String userDir = System.getProperty("user.dir"); 27 | BASE_DIR = userDir + File.separator + "fel" + File.separator; 28 | CLASS_DIR = BASE_DIR + "classes" + File.separator; 29 | loader = new FileClassLoader(AbstCompiler.class.getClassLoader(), 30 | CLASS_DIR); 31 | createClassDir(); 32 | } 33 | 34 | { 35 | classpath4compile = classPathToString(); 36 | } 37 | 38 | /** 39 | * Class文件所在文件夹,包含包名 40 | */ 41 | static String getClassPackageDir(String pack) { 42 | return CLASS_DIR + packageToPath(pack) + File.separator; 43 | } 44 | 45 | // protected abstract List getClassPath(ClassLoader cl); 46 | 47 | protected String classPathToString() { 48 | List paths = CompileService.getClassPath(this.getClass().getClassLoader()); 49 | StringBuilder cpStr = new StringBuilder(); 50 | for (String c : paths) { 51 | cpStr.append(c + File.pathSeparator); 52 | } 53 | return cpStr.toString(); 54 | } 55 | 56 | static String getSrcPackageDir(String pack) { 57 | return BASE_DIR + "src" + File.separator + packageToPath(pack) 58 | + File.separator; 59 | } 60 | 61 | /*private static String getPath(Class cls) { 62 | String path = ""; 63 | try { 64 | URL location = cls.getProtectionDomain().getCodeSource() 65 | .getLocation(); 66 | path = URLDecoder.decode(location.getFile(), "UTF-8"); 67 | } catch (UnsupportedEncodingException e) { 68 | } 69 | return path; 70 | }*/ 71 | 72 | /*private static String getClassPath() { 73 | 74 | // 将三项添加到classpath 1:lib中的所有jar 2:class目录 3:系统属性:"java.class.path" 75 | 76 | Class cls = AbstCompiler.class; 77 | String path = getPath(cls); 78 | boolean isJar = path.endsWith(".jar"); 79 | Set cpSet = new HashSet(); 80 | if (isJar) { 81 | File jarFile = new File(path); 82 | File lib = jarFile.getParentFile(); 83 | if (lib != null) { 84 | cpSet.addAll(getLibJars(jarFile.getParent())); 85 | String web_inf = lib.getParent(); 86 | String classDir = web_inf + File.separator + "classes"; 87 | File classDirfile = new File(classDir); 88 | if (classDirfile != null && classDirfile.exists()) { 89 | cpSet.add(classDir); 90 | } 91 | } 92 | } else { 93 | // String classFullName = cls.getName().replaceAll("\\.", "/"); 94 | // int index = path.lastIndexOf(classFullName + ".class"); 95 | // if (index != -1) { 96 | // String classDir = path.substring(0, index); 97 | cpSet.add(path); 98 | File classDirFile = new File(path); 99 | File web_inf = classDirFile.getParentFile(); 100 | String libDir = web_inf + File.separator + "lib"; 101 | cpSet.addAll(getLibJars(libDir)); 102 | // } 103 | } 104 | String systemCp = System.getProperty("java.class.path"); 105 | if (systemCp != null) { 106 | String[] cps = systemCp.split(File.pathSeparator); 107 | if (cps != null) { 108 | cpSet.addAll(Arrays.asList(cps)); 109 | } 110 | } 111 | String cpStr = ""; 112 | for (String c : cpSet) { 113 | cpStr += c + File.pathSeparator; 114 | } 115 | return cpStr; 116 | }*/ 117 | 118 | /* private static Set getLibJars(String libDir) { 119 | Set jarPathSet = new HashSet(); 120 | File dir = new File(libDir); 121 | if (dir != null && dir.isDirectory()) { 122 | File[] files = dir.listFiles(new FilenameFilter() { 123 | public boolean accept(File dir, String name) { 124 | return name.endsWith(".jar"); 125 | } 126 | }); 127 | for (int i = 0; i < files.length; i++) { 128 | File file = files[i]; 129 | String absolutePath = file.getAbsolutePath(); 130 | jarPathSet.add(absolutePath); 131 | } 132 | } 133 | return jarPathSet; 134 | }*/ 135 | 136 | public Expression compile(JavaSource src) { 137 | Class compile; 138 | try { 139 | compile = this.compileToClass(src); 140 | return compile.newInstance(); 141 | } catch (ClassNotFoundException e1) { 142 | e1.printStackTrace(); 143 | } catch (InstantiationException e) { 144 | e.printStackTrace(); 145 | } catch (IllegalAccessException e) { 146 | e.printStackTrace(); 147 | }finally{ 148 | String className = src.getName(); 149 | String pack = src.getPackageName(); 150 | String srcPackageDir = getSrcPackageDir(pack); 151 | clean(srcPackageDir,getClassPackageDir(pack),className); 152 | } 153 | return null; 154 | } 155 | 156 | 157 | abstract Class compileToClass(JavaSource expr) 158 | throws ClassNotFoundException; 159 | 160 | static void createClassDir() { 161 | new File(CLASS_DIR).mkdirs(); 162 | } 163 | 164 | private static ExecutorService exeService = initThreadPool(); 165 | 166 | private static ExecutorService initThreadPool() { 167 | return new ThreadPoolExecutor(0, 10, 5L, TimeUnit.SECONDS, 168 | new LinkedBlockingQueue()); 169 | } 170 | 171 | void clean(final String srcPackageDir, 172 | final String classPackageDir, final String fileName) { 173 | if (exeService.isShutdown()) { 174 | exeService = initThreadPool(); 175 | } 176 | exeService.execute(new Runnable() { 177 | public void run() { 178 | // 优先级设置成最低 179 | Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 180 | delFile(srcPackageDir, classPackageDir, fileName); 181 | } 182 | }); 183 | // exeService.shutdown(); 184 | } 185 | 186 | void delFile(final String srcPackageDir, final String classPackageDir, 187 | final String fileName) { 188 | String src = srcPackageDir + fileName + ".java"; 189 | deleteFile(src); 190 | String cls = classPackageDir + fileName + ".class"; 191 | deleteFile(cls); 192 | } 193 | 194 | void deleteFile(String src) { 195 | File file = new File(src); 196 | // System.out.println("delete file:"+src); 197 | if (file.exists()) { 198 | file.delete(); 199 | } 200 | } 201 | 202 | 203 | List getCompileOption() { 204 | List options = new ArrayList(); 205 | options.add("-encoding"); 206 | options.add("UTF-8"); 207 | options.add("-d"); 208 | options.add(CLASS_DIR); 209 | 210 | if (StringUtils.isNotEmpty(classpath4compile)) { 211 | options.add("-classpath"); 212 | options.add(classpath4compile); 213 | } 214 | return options; 215 | } 216 | 217 | /** 218 | * 将包名转换成包路径 219 | * 220 | * @param packageName 221 | * @return 222 | */ 223 | private static String packageToPath(String packageName) { 224 | String sep = File.separator; 225 | // if (sep.equals("\\")) { 226 | // sep = "\\\\"; 227 | // } 228 | return StringUtils.replace(packageName, ".", sep); 229 | // return packageName.replaceAll("\\.", sep); 230 | } 231 | 232 | } 233 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/CompileService.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.util.ArrayList; 7 | import java.util.Enumeration; 8 | import java.util.List; 9 | 10 | import com.greenpineyu.fel.Expression; 11 | import com.greenpineyu.fel.context.FelContext; 12 | import com.greenpineyu.fel.parser.FelNode; 13 | 14 | public class CompileService { 15 | 16 | private SourceGenerator srcGen; 17 | private FelCompiler complier; 18 | 19 | public SourceGenerator getSrcGen() { 20 | return srcGen; 21 | } 22 | 23 | public void setSrcGen(SourceGenerator srcGen) { 24 | this.srcGen = srcGen; 25 | } 26 | 27 | public FelCompiler getComplier() { 28 | return complier; 29 | } 30 | 31 | public void setComplier(FelCompiler complier) { 32 | this.complier = complier; 33 | } 34 | 35 | { 36 | srcGen = new SourceGeneratorImpl(); 37 | String name = getCompilerClassName(); 38 | FelCompiler comp = newCompiler(name); 39 | complier = comp; 40 | } 41 | 42 | public static List getClassPath(ClassLoader cl) { 43 | List paths = new ArrayList(); 44 | while (cl != null) { 45 | boolean isUrlClassloader = cl instanceof URLClassLoader; 46 | if (isUrlClassloader) { 47 | URLClassLoader urlClassLoader = (URLClassLoader) cl; 48 | for (URL url : urlClassLoader.getURLs()) { 49 | paths.add(url.getFile()); 50 | } 51 | } else { 52 | Enumeration resources = null; 53 | try { 54 | resources = cl.getResources("/"); 55 | } catch (IOException e) { 56 | e.printStackTrace(); 57 | } 58 | if (resources != null) { 59 | while (resources.hasMoreElements()) { 60 | URL resource = resources.nextElement(); 61 | paths.add(resource.getFile()); 62 | } 63 | } 64 | } 65 | cl = cl.getParent(); 66 | } 67 | return paths; 68 | } 69 | 70 | private FelCompiler newCompiler(String name) { 71 | FelCompiler comp = null; 72 | try { 73 | @SuppressWarnings("unchecked") 74 | Class cls = (Class) Class.forName(name); 75 | comp = cls.newInstance(); 76 | } catch (ClassNotFoundException e) { 77 | e.printStackTrace(); 78 | } catch (InstantiationException e) { 79 | e.printStackTrace(); 80 | } catch (IllegalAccessException e) { 81 | e.printStackTrace(); 82 | } finally { 83 | } 84 | return comp; 85 | } 86 | 87 | private String getCompilerClassName() { 88 | String version = System.getProperty("java.version"); 89 | String compileClassName = FelCompiler.class.getName(); 90 | if (version != null && version.startsWith("1.5")) { 91 | compileClassName += "15"; 92 | } else { 93 | compileClassName += "16"; 94 | } 95 | return compileClassName; 96 | } 97 | 98 | public Expression compile(FelContext ctx, FelNode node, String originalExp) { 99 | try { 100 | JavaSource src = srcGen.getSource(ctx, node); 101 | if (src instanceof ConstExpSrc) { 102 | ConstExpSrc s = (ConstExpSrc) src; 103 | return s.getValue(); 104 | } 105 | src.setSource("// 表达式:" + originalExp + "\n" + src.getSource()); 106 | // System.out.println("****************\n" + src.getSource()); 107 | return complier.compile(src); 108 | } catch (Exception e) { 109 | e.printStackTrace(); 110 | } 111 | return null; 112 | } 113 | 114 | public static void main(String[] args) { 115 | System.getProperties().list(System.out); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/ConstExp.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.Expression; 4 | import com.greenpineyu.fel.context.FelContext; 5 | 6 | public final class ConstExp implements Expression { 7 | public ConstExp(Object o) { 8 | this.value = o; 9 | } 10 | 11 | private final Object value; 12 | 13 | public final Object eval(FelContext context) { 14 | return value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/ConstExpSrc.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | /** 4 | * @author yuqingsong 5 | * 6 | */ 7 | public class ConstExpSrc extends JavaSource { 8 | 9 | public ConstExpSrc(Object o) { 10 | this.value = new ConstExp(o); 11 | } 12 | 13 | private final ConstExp value; 14 | 15 | public ConstExp getValue() { 16 | return value; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FelCompiler.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.Expression; 4 | 5 | public interface FelCompiler { 6 | 7 | /** 8 | * 9 | * 编译代码,并创建Expression 10 | * @param expr 11 | * @return 12 | */ 13 | public Expression compile(JavaSource src); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FelCompiler16.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.URI; 6 | import java.net.URISyntaxException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import javax.tools.DiagnosticCollector; 11 | import javax.tools.FileObject; 12 | import javax.tools.ForwardingJavaFileManager; 13 | import javax.tools.JavaCompiler; 14 | import javax.tools.JavaCompiler.CompilationTask; 15 | import javax.tools.JavaFileManager; 16 | import javax.tools.JavaFileObject; 17 | import javax.tools.JavaFileObject.Kind; 18 | import javax.tools.StandardJavaFileManager; 19 | import javax.tools.StandardLocation; 20 | import javax.tools.ToolProvider; 21 | 22 | import com.greenpineyu.fel.Expression; 23 | import com.greenpineyu.fel.exception.CompileException; 24 | 25 | public class FelCompiler16 implements FelCompiler { 26 | private final FelCompilerClassloader classLoader; 27 | 28 | private final JavaCompiler compiler; 29 | 30 | private final List options; 31 | 32 | private DiagnosticCollector diagnostics; 33 | 34 | private final JavaFileManager javaFileManager; 35 | 36 | public FelCompiler16() { 37 | compiler = ToolProvider.getSystemJavaCompiler(); 38 | 39 | if (compiler == null) { 40 | throw new IllegalStateException( 41 | "Cannot find the system Java compiler. " 42 | + "Check that your class path includes tools.jar"); 43 | } 44 | 45 | this.classLoader = new FelCompilerClassloader(this.getClass() 46 | .getClassLoader()); 47 | diagnostics = new DiagnosticCollector(); 48 | final StandardJavaFileManager fileManager = compiler 49 | .getStandardFileManager(diagnostics, null, null); 50 | 51 | ClassLoader loader = this.classLoader.getParent(); 52 | List paths = CompileService.getClassPath(loader); 53 | List cpFiles = new ArrayList(); 54 | if (paths != null && (!paths.isEmpty())) { 55 | for (String file : paths) { 56 | cpFiles.add(new File(file)); 57 | } 58 | } 59 | try { 60 | fileManager.setLocation(StandardLocation.CLASS_PATH, cpFiles); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | 65 | /* 66 | 67 | 68 | if (loader instanceof URLClassLoader 69 | && (!loader.getClass().getName() 70 | .equals("sun.misc.Launcher$AppClassLoader"))) { 71 | System.out.println("..............................asdfasdf......................"); 72 | try { 73 | URLClassLoader urlClassLoader = (URLClassLoader) loader; 74 | List path = new ArrayList(); 75 | for (URL url : urlClassLoader.getURLs()) { 76 | File file = new File(url.getFile()); 77 | path.add(file); 78 | } 79 | fileManager.setLocation(StandardLocation.CLASS_PATH, path); 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | } 83 | } else { 84 | Enumeration resources = null; 85 | try { 86 | resources = loader.getResources("/"); 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | } 90 | if (resources != null) { 91 | List path = new ArrayList(); 92 | while (resources.hasMoreElements()) { 93 | URL resource = resources.nextElement(); 94 | File file = new File(resource.getFile()); 95 | path.add(file); 96 | } 97 | } 98 | 99 | }*/ 100 | 101 | javaFileManager = new ForwardingJavaFileManager( 102 | fileManager) { 103 | @Override 104 | public JavaFileObject getJavaFileForOutput(Location location, 105 | String qualifiedName, Kind kind, FileObject outputFile) 106 | throws IOException { 107 | // 由于编译成功后的bytecode需要放到file中,所以需要将file放到classloader中,以便读取bytecode生成Class对象. 108 | classLoader.add(qualifiedName, outputFile); 109 | return (JavaFileObject) outputFile; 110 | } 111 | }; 112 | this.options = new ArrayList(); 113 | // this.options.add("-O"); 114 | } 115 | 116 | public Expression compile(JavaSource src) { 117 | 118 | Class compile = compileToClass(src); 119 | try { 120 | return (Expression) compile.newInstance(); 121 | } catch (InstantiationException e) { 122 | e.printStackTrace(); 123 | } catch (IllegalAccessException e) { 124 | e.printStackTrace(); 125 | } 126 | return null; 127 | } 128 | 129 | 130 | public synchronized Class compileToClass(final JavaSource src) { 131 | List compileSrcs = new ArrayList(); 132 | String className = src.getSimpleName(); 133 | final FelJavaFileObject compileSrc = new FelJavaFileObject(className, 134 | src.getSource()); 135 | compileSrcs.add(compileSrc); 136 | final CompilationTask task = compiler.getTask(null, javaFileManager, 137 | diagnostics, options, null, compileSrcs); 138 | final Boolean result = task.call(); 139 | if (result == null || !result.booleanValue()) { 140 | // diagnostics. 141 | // 编译失败 142 | // diagnostics.getDiagnostics() 143 | throw new CompileException(src.getSource() + "\n" 144 | + diagnostics.getDiagnostics().toString()); 145 | } 146 | try { 147 | return loadClass(src.getName()); 148 | } catch (ClassNotFoundException e) { 149 | e.printStackTrace(); 150 | } 151 | return null; 152 | } 153 | 154 | @SuppressWarnings("unchecked") 155 | public Class loadClass(final String qualifiedClassName) 156 | throws ClassNotFoundException { 157 | return (Class) classLoader.loadClass(qualifiedClassName); 158 | } 159 | 160 | static URI toUri(String name) { 161 | try { 162 | return new URI(name); 163 | } catch (URISyntaxException e) { 164 | throw new RuntimeException(e); 165 | } 166 | } 167 | 168 | } 169 | 170 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FelCompilerClassloader.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.tools.FileObject; 7 | 8 | public final class FelCompilerClassloader extends ClassLoader { 9 | private final Map compileFileMap = new HashMap(); 10 | 11 | public FelCompilerClassloader(ClassLoader parentClassLoader) { 12 | super(parentClassLoader); 13 | } 14 | 15 | 16 | @Override 17 | protected synchronized Class findClass(String qualifiedClassName) throws ClassNotFoundException { 18 | FileObject file = compileFileMap.remove(qualifiedClassName); 19 | if (file != null) { 20 | byte[] bytes = ((FelJavaFileObject) file).getByteCode(); 21 | return defineClass(qualifiedClassName, bytes, 0, bytes.length); 22 | } 23 | return super.findClass(qualifiedClassName); 24 | } 25 | 26 | public void add(String qualifiedClassName, final FileObject javaFile) { 27 | compileFileMap.put(qualifiedClassName, javaFile); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FelJavaFileObject.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.net.URI; 8 | 9 | import javax.tools.SimpleJavaFileObject; 10 | 11 | /** 12 | * 编译时,用于提供类源码和保存类的字节码 13 | * 14 | * @author yuqingsong 15 | * 16 | */ 17 | public class FelJavaFileObject extends SimpleJavaFileObject { 18 | 19 | // If kind == CLASS, this stores byte code from openOutputStream 20 | private final ByteArrayOutputStream byteCodeOs = new ByteArrayOutputStream(); 21 | 22 | // if kind == SOURCE, this contains the source text 23 | private final CharSequence src; 24 | 25 | public FelJavaFileObject(final String baseName, final CharSequence source) { 26 | super(FelCompiler16.toUri(baseName + ".java"), 27 | Kind.SOURCE); 28 | this.src = source; 29 | } 30 | 31 | FelJavaFileObject(final String name, final Kind kind) { 32 | super(FelCompiler16.toUri(name), kind); 33 | src = null; 34 | } 35 | 36 | public FelJavaFileObject(URI uri, Kind kind) { 37 | super (uri, kind); 38 | src = null; 39 | } 40 | 41 | @Override 42 | public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws UnsupportedOperationException { 43 | if (src == null) { 44 | throw new UnsupportedOperationException(); 45 | } 46 | 47 | return src; 48 | } 49 | 50 | @Override 51 | public InputStream openInputStream() { 52 | return new ByteArrayInputStream(getByteCode()); 53 | } 54 | 55 | @Override 56 | public OutputStream openOutputStream() { 57 | return byteCodeOs; 58 | } 59 | 60 | byte[] getByteCode() { 61 | return byteCodeOs.toByteArray(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FelMethod.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | /** 7 | * 8 | */ 9 | public class FelMethod implements SourceBuilder { 10 | 11 | private Class returnType; 12 | 13 | private String code; 14 | 15 | 16 | public FelMethod(Class returnType,String code){ 17 | this.returnType = returnType; 18 | this.code = code; 19 | } 20 | 21 | 22 | public Class returnType(FelContext ctx, FelNode node) { 23 | return returnType; 24 | } 25 | 26 | 27 | public void setReturnType(Class returnType) { 28 | this.returnType = returnType; 29 | } 30 | 31 | 32 | public String source(FelContext ctx, FelNode node) { 33 | return code; 34 | } 35 | 36 | 37 | public void setCode(String code) { 38 | this.code = code; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/FileClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | 8 | public class FileClassLoader extends ClassLoader { 9 | private String dir; 10 | public static final String fileType = ".class"; 11 | 12 | public FileClassLoader(ClassLoader arg0, String dir) { 13 | super(arg0); 14 | this.dir = dir; 15 | } 16 | 17 | public Class findClass(String name) { 18 | byte[] data = loadClassData(name); 19 | return defineClass(name, data, 0, data.length); 20 | } 21 | 22 | public byte[] loadClassData(String name) { 23 | name = name.replaceAll("\\.", "/"); 24 | FileInputStream fis = null; 25 | byte[] data = null; 26 | try { 27 | fis = new FileInputStream(new File(dir + name + fileType)); 28 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 29 | int ch = 0; 30 | while ((ch = fis.read()) != -1) { 31 | baos.write(ch); 32 | } 33 | data = baos.toByteArray(); 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | }finally{ 37 | if(fis!= null){ 38 | try { 39 | fis.close(); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | } 45 | return data; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/InterpreterSourceBuilder.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.context.AbstractContext; 4 | import com.greenpineyu.fel.context.FelContext; 5 | import com.greenpineyu.fel.interpreter.Interpreter; 6 | import com.greenpineyu.fel.parser.FelNode; 7 | 8 | public class InterpreterSourceBuilder implements SourceBuilder { 9 | 10 | 11 | 12 | 13 | private static final SourceBuilder instance; 14 | 15 | public static SourceBuilder getInstance() { 16 | return instance; 17 | } 18 | 19 | static{ 20 | instance = new InterpreterSourceBuilder(); 21 | } 22 | 23 | 24 | 25 | public Class returnType(FelContext ctx, FelNode node) { 26 | return AbstractContext.getVarType(node.getInterpreter().interpret(ctx, node)); 27 | } 28 | 29 | /** 30 | * 用户自定义解析器生成的java代码 31 | * 32 | * @param ctx 33 | * @param node 34 | * @return 35 | */ 36 | public String source(FelContext ctx, FelNode node) { 37 | // 用户设置了解释器 38 | // Interpreter inte = new ProxyInterpreter(node.getInterpreter(), node); 39 | Interpreter inte = node.getInterpreter(); 40 | SourceBuilder nodeBuilder = node.toMethod(ctx); 41 | Class type =nodeBuilder.returnType(ctx, node); 42 | String code = "("+type.getName()+")"; 43 | String varName = VarBuffer.push(inte,Interpreter.class); 44 | String nodeVarName = VarBuffer.push(node, FelNode.class); 45 | code += varName + ".interpret(context," + nodeVarName + ")"; 46 | boolean isNumber = Number.class.isAssignableFrom(type); 47 | if(isNumber){ 48 | code="("+code+").doubleValue()"; 49 | } 50 | return code; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/JavaSource.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | public class JavaSource { 4 | 5 | /** 6 | * 类名,不包含包名 7 | */ 8 | private String simpleName; 9 | 10 | /** 11 | * java源码 12 | */ 13 | private String source; 14 | 15 | /** 16 | * 包名 17 | */ 18 | private String packageName; 19 | 20 | public String getPackageName() { 21 | return packageName; 22 | } 23 | 24 | public void setPackageName(String packageName) { 25 | this.packageName = packageName; 26 | } 27 | 28 | public String getSimpleName() { 29 | return simpleName; 30 | } 31 | 32 | public void setSimpleName(String name) { 33 | this.simpleName = name; 34 | } 35 | 36 | public String getName(){ 37 | return packageName + "." + simpleName; 38 | } 39 | 40 | public String getSource() { 41 | return source; 42 | } 43 | 44 | public void setSource(String source) { 45 | this.source = source; 46 | } 47 | 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/SourceBuilder.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | /** 7 | * 创建java源码接口,此接口和SourceGenerator的区别在于,后者负责创建整个java类的源码。前者只用了创建表达式的代码片断。 8 | * @author yuqingsong 9 | * 10 | */ 11 | public interface SourceBuilder { 12 | 13 | /** 14 | * 类型 15 | * @param ctx TODO 16 | * @param node TODO 17 | * @return 18 | */ 19 | Class returnType(FelContext ctx, FelNode node); 20 | /** 21 | * 构建源码 22 | * @param node TODO 23 | * @return 24 | */ 25 | String source(FelContext ctx, FelNode node); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/SourceGenerator.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.optimizer.Optimizer; 5 | import com.greenpineyu.fel.parser.FelNode; 6 | 7 | public interface SourceGenerator { 8 | 9 | /** 10 | * 获取表达式JAVA源代码 11 | * @param node TODO 12 | * @return 13 | */ 14 | JavaSource getSource(FelContext ctx, FelNode node); 15 | 16 | void addOpti(Optimizer opti); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/SourceGeneratorImpl.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | import com.greenpineyu.fel.Expression; 14 | import com.greenpineyu.fel.FelEngine; 15 | import com.greenpineyu.fel.FelEngineImpl; 16 | import com.greenpineyu.fel.common.Callable; 17 | import com.greenpineyu.fel.common.ReflectUtil; 18 | import com.greenpineyu.fel.common.StringUtils; 19 | import com.greenpineyu.fel.context.FelContext; 20 | import com.greenpineyu.fel.optimizer.ConstExpOpti; 21 | import com.greenpineyu.fel.optimizer.ConstOpti; 22 | import com.greenpineyu.fel.optimizer.Optimizer; 23 | import com.greenpineyu.fel.parser.AbstFelNode; 24 | import com.greenpineyu.fel.parser.ConstNode; 25 | import com.greenpineyu.fel.parser.FelNode; 26 | import com.greenpineyu.fel.parser.VarAstNode; 27 | 28 | public class SourceGeneratorImpl implements SourceGenerator { 29 | 30 | private List opt; 31 | 32 | private static String template; 33 | 34 | private static int count = 0; 35 | 36 | private Map localvars; 37 | 38 | /** 39 | * 包名 40 | */ 41 | static final String PACKAGE; 42 | 43 | { 44 | opt = new ArrayList(); 45 | localvars = new HashMap(); 46 | initOpti(); 47 | } 48 | 49 | static { 50 | String fullName = SourceGeneratorImpl.class.getName(); 51 | PACKAGE = fullName.substring(0, fullName.lastIndexOf(".")); 52 | 53 | StringBuilder sb = new StringBuilder(); 54 | InputStream in = SourceGeneratorImpl.class 55 | .getResourceAsStream("java.template"); 56 | BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 57 | String line = null; 58 | try { 59 | while ((line = reader.readLine()) != null) { 60 | sb.append(line).append("\r\n"); 61 | } 62 | } catch (IOException e) { 63 | e.printStackTrace(); 64 | } 65 | template = sb.toString(); 66 | } 67 | 68 | public JavaSource getSource(FelContext ctx, FelNode node) { 69 | 70 | String src = ""; 71 | String className = getClassName(); 72 | synchronized(this){ 73 | node = optimize(ctx, node); 74 | if (node instanceof ConstNode) { 75 | ConstNode n = (ConstNode) node; 76 | return new ConstExpSrc(n.interpret(null, null)); 77 | } 78 | SourceBuilder builder = node.toMethod(ctx); 79 | String exp = builder.source(ctx, node); 80 | src = buildsource(exp, className); 81 | this.localvars.clear(); 82 | } 83 | // System.out.println("****************\n" + src); 84 | JavaSource returnMe = new JavaSource(); 85 | returnMe.setSimpleName(className); 86 | returnMe.setSource(src); 87 | returnMe.setPackageName(PACKAGE); 88 | return returnMe; 89 | } 90 | 91 | private String buildsource(String expression, String className) { 92 | String src = StringUtils.replace(template,"${classname}", className); 93 | // src = src.replaceAll("\\$\\{extends\\}", "Object"); 94 | StringBuilder attrs = new StringBuilder(); 95 | String pop = VarBuffer.pop(); 96 | if (pop != null) { 97 | // 第一行不需要添加空格 98 | attrs.append(pop).append("\r\n"); 99 | pop = VarBuffer.pop(); 100 | } 101 | while(pop!=null){ 102 | attrs.append(" ").append(pop).append("\r\n"); 103 | pop = VarBuffer.pop(); 104 | } 105 | // removeLastEnter(attrs); 106 | src = StringUtils.replace(src, "${attrs}", attrs.toString()); 107 | src = StringUtils.replace(src, "${localVars}", getLocalVarsCode()); 108 | src = StringUtils.replace(src, "${expression}", expression); 109 | // src = src.replaceAll("\\$\\{attrs\\}", attrs.toString()); 110 | // src = src.replaceAll("\\$\\{localVars\\}", getLocalVarsCode()); 111 | // src = src.replaceAll("\\$\\{expression\\}", expression); 112 | return src; 113 | } 114 | 115 | private String getClassName() { 116 | String className = null; 117 | synchronized (SourceGeneratorImpl.class) { 118 | className = "Fel_" + count++; 119 | } 120 | return className; 121 | } 122 | 123 | private String getLocalVarsCode() { 124 | StringBuilder sb = new StringBuilder(); 125 | Collection values = localvars.values(); 126 | boolean isFirst = true; 127 | for (StringKeyValue code : values) { 128 | if (isFirst) { 129 | // 第一行不需要添加空格 130 | isFirst = false; 131 | } else { 132 | sb.append(" "); 133 | } 134 | sb.append(code.value).append("\r\n"); 135 | } 136 | removeLastEnter(sb); 137 | return sb.toString(); 138 | } 139 | 140 | private void removeLastEnter(StringBuilder sb) { 141 | if(sb.length()>0){ 142 | sb.delete(sb.length()-2, sb.length()); 143 | } 144 | } 145 | 146 | // private final int localVarCount = 0; 147 | 148 | /* 149 | * private String getLocalVarName() { String varName = null; synchronized 150 | * (SourceGeneratorImpl.class) { varName = "var_" + localVarCount++; } 151 | * return varName; } 152 | */ 153 | 154 | class StringKeyValue { 155 | String key; 156 | String value; 157 | 158 | public StringKeyValue(String key, String value) { 159 | this.key = key; 160 | this.value = value; 161 | } 162 | } 163 | 164 | /** 165 | * 对节点进行优化 166 | * 167 | * @param ctx 168 | * @param node 169 | * @return 170 | */ 171 | private FelNode optimize(FelContext ctx, FelNode node) { 172 | for (Optimizer o : opt) { 173 | node = o.call(ctx, node); 174 | } 175 | return node; 176 | } 177 | 178 | private void initOpti() { 179 | // 进行常量优化(计算表达式中的常量节点) 180 | Optimizer constOpti = new ConstOpti(); 181 | this.addOpti(constOpti); 182 | 183 | // 如果整个表达式是一个常量,再进行一次优化(可以减少装包拆包花费的时间) 184 | Optimizer constExpOpti = new ConstExpOpti(); 185 | 186 | this.addOpti(constExpOpti); 187 | 188 | 189 | // 进行变量优化 190 | Optimizer optimizVars = getVarOpti(); 191 | this.addOpti(optimizVars); 192 | } 193 | 194 | public static final Callable varsFilter = new Callable() { 195 | public Boolean call(FelNode... node) { 196 | FelNode n = node[0]; 197 | return VarAstNode.isVar(n); 198 | } 199 | }; 200 | 201 | /** 202 | * 获取变量优化方案 203 | * 204 | * @return 205 | */ 206 | private Optimizer getVarOpti() { 207 | Optimizer optimizVars = new Optimizer() { 208 | public FelNode call(FelContext ctx, FelNode node) { 209 | List nodes = AbstFelNode.getNodes(node,varsFilter); 210 | // 多次出现的变量 211 | // List repeatNodes = new ArrayList(); 212 | 213 | Map> repeatNodeMap = new HashMap>(); 214 | for (FelNode n : nodes) { 215 | String name = n.getText(); 216 | List repeatNodes = repeatNodeMap.get(name); 217 | if(repeatNodes == null){ 218 | repeatNodes = new ArrayList(); 219 | repeatNodeMap.put(name, repeatNodes); 220 | } 221 | repeatNodes.add(n); 222 | // if(count != null){ 223 | // repeatNodes.add(n); 224 | // count.increment(); 225 | // }else{ 226 | // count = new MutableInt(1); 227 | // varCount.put(name, count); 228 | // } 229 | } 230 | for (List repeatNodes : repeatNodeMap.values()) { 231 | if(repeatNodes.size()>1){ 232 | for (FelNode n : repeatNodes) { 233 | n.setSourcebuilder(getVarSrcBuilder(n.toMethod(ctx))); 234 | } 235 | } 236 | } 237 | 238 | return node; 239 | } 240 | 241 | /** 242 | * 修改变量的代码生成方式 243 | * 244 | * @param ctx 245 | * @param node 246 | */ 247 | @SuppressWarnings("unused") 248 | private void setVarSourceBuilder(FelContext ctx, FelNode node) { 249 | if (node instanceof VarAstNode) { 250 | node.setSourcebuilder(getVarSrcBuilder(node.toMethod(ctx))); 251 | } else { 252 | List children = node.getChildren(); 253 | if (children != null && !children.isEmpty()) { 254 | for (FelNode child : children) { 255 | setVarSourceBuilder(ctx, child); 256 | } 257 | } 258 | 259 | } 260 | } 261 | 262 | private SourceBuilder getVarSrcBuilder(final SourceBuilder old) { 263 | 264 | return new SourceBuilder() { 265 | 266 | public String source(FelContext ctx, FelNode node) { 267 | String text = node.getText(); 268 | if (localvars.containsKey(text)) { 269 | StringKeyValue kv = localvars.get(text); 270 | return kv.key; 271 | } 272 | // String varName = getLocalVarName(); 273 | String varName = text; 274 | Class type = this.returnType(ctx, node); 275 | String declare = ""; 276 | String typeDeclare = type.getCanonicalName(); 277 | if(ReflectUtil.isPrimitiveOrWrapNumber(type)){ 278 | Class primitiveClass = ReflectUtil.toPrimitiveClass(type); 279 | typeDeclare = primitiveClass.getSimpleName(); 280 | }else if (Number.class.isAssignableFrom(type)) { 281 | typeDeclare = "double"; 282 | } 283 | 284 | declare = typeDeclare + " " + varName + " = " 285 | + old.source(ctx, node) + "; //" + text; 286 | StringKeyValue kv = new StringKeyValue(varName, declare); 287 | localvars.put(text, kv); 288 | return varName; 289 | } 290 | 291 | public Class returnType(FelContext ctx, FelNode n) { 292 | // VarAstNode node = (VarAstNode) old; 293 | return old.returnType(ctx, n); 294 | } 295 | }; 296 | } 297 | }; 298 | return optimizVars; 299 | } 300 | 301 | public void addOpti(Optimizer opti) { 302 | this.opt.add(opti); 303 | } 304 | 305 | public static void main(String[] args) { 306 | FelEngine engine = new FelEngineImpl(); 307 | FelContext ctx = engine.getContext(); 308 | ctx.set("i", 100); 309 | ctx.set("pi", 3.14f); 310 | String exp = "pi*i*i*pi"; 311 | Expression expObj = engine.compile(exp, ctx); 312 | Object eval = expObj.eval(ctx); 313 | // cost(ctx, new Abcd()); 314 | cost(ctx, expObj); 315 | System.out.println(eval); 316 | } 317 | 318 | private static void cost(FelContext ctx, Expression expObj) { 319 | int count = 10*1000*1000; 320 | long start = System.currentTimeMillis(); 321 | for (int i = 0; i < count; i++) { 322 | expObj.eval(ctx); 323 | } 324 | long end = System.currentTimeMillis(); 325 | System.out.println(end-start); 326 | } 327 | } 328 | 329 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/VarBuffer.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Stack; 6 | import java.util.UUID; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | 10 | 11 | public class VarBuffer { 12 | static private ThreadLocal> varCodes; 13 | static private ThreadLocal> vars; 14 | static { 15 | varCodes = new ThreadLocal>(); 16 | vars = new ThreadLocal>(); 17 | } 18 | 19 | private static int count; 20 | 21 | /** 22 | * 获取当前线程中的变量代码(类的属性代码)stack 23 | * 24 | * @return 25 | */ 26 | private static Stack getVarCodes(){ 27 | Stack stack = varCodes.get(); 28 | if(stack == null){ 29 | stack = new Stack(); 30 | varCodes.set(stack); 31 | } 32 | return stack; 33 | } 34 | 35 | /** 36 | * 获取当前线程中的保存的对象Map。 37 | * 38 | * @return 39 | */ 40 | private static Map getVars(){ 41 | Map map = vars.get(); 42 | if(map == null){ 43 | map = new HashMap(); 44 | vars.set(map); 45 | } 46 | return map; 47 | } 48 | 49 | /** 50 | * 将变量存入线程 51 | * 52 | * @param attrCode 53 | */ 54 | static public String push(Object var){ 55 | return push(var,var.getClass()); 56 | 57 | } 58 | static public String push(Object var,Class cls){ 59 | String varName = getVarName(); 60 | 61 | String type = cls.getName(); 62 | String varId = UUID.randomUUID().toString(); 63 | 64 | getVars().put(varId, var); 65 | String code = "private static final " + type + " " + varName 66 | +" = ("+type+")"+VarBuffer.class.getSimpleName()+".pop(\""+varId+"\");"; 67 | getVarCodes().push(code); 68 | return varName; 69 | } 70 | 71 | 72 | 73 | synchronized static private String getVarName(){ 74 | return "attr_"+count++; 75 | } 76 | 77 | /** 78 | * 从线程取出变量 79 | * 80 | * @param attrCode 81 | * @return 82 | */ 83 | public static String pop(){ 84 | Stack stack = getVarCodes(); 85 | if(stack.empty()){ 86 | return null; 87 | } 88 | return stack.pop(); 89 | } 90 | 91 | public static Object pop(String name){ 92 | return getVars().remove(name); 93 | } 94 | 95 | private static ThreadLocal tl = new ThreadLocal(); 96 | public static void main(String[] args) { 97 | int i = 100; 98 | ExecutorService pool = Executors.newFixedThreadPool(i); 99 | for (int j = 0; j < i; j++) { 100 | pool.submit(new Runnable() { 101 | 102 | public void run() { 103 | String name = Thread.currentThread().getName(); 104 | System.out.println("*******************"+name+" start************************"); 105 | tl.set(name); 106 | get(name); 107 | System.out.println("*******************"+name+" end************************"); 108 | 109 | } 110 | 111 | private void get(String name) { 112 | String string = tl.get(); 113 | System.out.println(name+":"+(name == string)); 114 | } 115 | }); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/compile/java.template: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.compile; 2 | 3 | import com.greenpineyu.fel.common.*; 4 | import com.greenpineyu.fel.Expression; 5 | import com.greenpineyu.fel.context.*; 6 | //import org.apache.commons.lang3.ObjectUtils; 7 | //import org.apache.commons.lang3.StringUtils; 8 | 9 | public class ${classname} implements Expression{ 10 | ${attrs} 11 | public Object eval(FelContext context) { 12 | ${localVars} 13 | return ${expression}; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/AbstractContext.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | 4 | import com.greenpineyu.fel.common.ReflectUtil; 5 | 6 | public abstract class AbstractContext implements FelContext{ 7 | 8 | 9 | 10 | // @Override 11 | // public Object get(String name) { 12 | // Var var = this.getVar(name); 13 | // return var==null?null:var.getValue(); 14 | // } 15 | 16 | public void setVar(Var var) { 17 | // 设置变量值 18 | throw new UnsupportedOperationException(this.getClass().getSimpleName() + "不能存储变量"); 19 | } 20 | 21 | public void set(String name, Object value) { 22 | this.setVar(new Var(name,value)); 23 | } 24 | 25 | public Var getVar(String name) { 26 | Object value = get(name); 27 | return new Var(name, value, null); 28 | } 29 | 30 | 31 | public static Class getVarType(String varName, FelContext ctx) { 32 | Var var = ctx.getVar(varName); 33 | return var == null?null:var.getType(); 34 | } 35 | 36 | public static Class getVarType(Object varValue) { 37 | Class type = null; 38 | if (varValue != null) { 39 | type = varValue.getClass(); 40 | } 41 | return getVarType(type); 42 | } 43 | 44 | public static Class getVarType(Class type) { 45 | if(type == null){ 46 | return NULL.getClass(); 47 | } 48 | if(type.isPrimitive()){ 49 | // 基本类型转换成包装类型 50 | type = ReflectUtil.toWrapperClass(type); 51 | } 52 | if(ReflectUtil.isPrimitiveOrWrapNumber(type)){ 53 | return type; 54 | }else if (Number.class.isAssignableFrom(type)) { 55 | type = Number.class; 56 | } 57 | return type; 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/ArrayCtx.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | public interface ArrayCtx extends FelContext { 4 | 5 | /** 6 | * 根据索引获取变量值 7 | * @param i 8 | * @return 9 | */ 10 | Object get(int i); 11 | 12 | /** 13 | * 获取变量的索引 14 | * @param name 15 | * @return 16 | */ 17 | int getIndex(String name); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/ArrayCtxImpl.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class ArrayCtxImpl implements ArrayCtx{ 8 | 9 | 10 | /** 11 | * 保存对象类型的变量,包含数值类型的变量 12 | */ 13 | private Var[] vars = new Var[10]; 14 | 15 | private Map indexMap = new HashMap(); 16 | 17 | public ArrayCtxImpl(){ 18 | } 19 | public ArrayCtxImpl(Map vars){ 20 | if(vars!=null){ 21 | for (Map.Entry e : vars.entrySet()) { 22 | this.set(e.getKey(), e.getValue()); 23 | } 24 | } 25 | } 26 | 27 | public Object get(int i) { 28 | return vars[i].getValue(); 29 | } 30 | 31 | public int getIndex(String name) { 32 | Integer i = indexMap.get(name); 33 | return i!=null?i:-1; 34 | } 35 | 36 | 37 | public Object get(String name) { 38 | Var var = getVar(name); 39 | return var!=null?var.getValue():null; 40 | } 41 | 42 | public Var getVar(String name) { 43 | int index = getIndex(name); 44 | if(index == -1){ 45 | return null; 46 | } 47 | return vars[index]; 48 | } 49 | 50 | /** 51 | * 获取变量,如果变量不存在,就添加一个新的变量。 52 | * @param name 53 | * @return 54 | */ 55 | private Var getVarWithoutNull(String name){ 56 | Var var = getVar(name); 57 | if(var == null){ 58 | var = new Var(name,null); 59 | setVar(var); 60 | } 61 | return var; 62 | } 63 | 64 | 65 | 66 | /** 67 | * 确保vars.length>minCapacity 68 | * @param minCapacity 69 | */ 70 | public void ensureCapacity(int minCapacity) { 71 | int oldCapacity = vars.length; 72 | if (minCapacity > oldCapacity) { 73 | int newCapacity = (oldCapacity * 3)/2 + 1; 74 | if (newCapacity < minCapacity) 75 | newCapacity = minCapacity; 76 | // minCapacity is usually close to size, so this is a win: 77 | vars = Arrays.copyOf(vars, newCapacity); 78 | } 79 | } 80 | 81 | public void set(String name, Object value) { 82 | getVarWithoutNull(name).setValue(value); 83 | } 84 | 85 | public void setVar(Var var) { 86 | int i = addToIndexMap(var.getName()); 87 | if(i getVarType(String varName) { 36 | // return AbstractConetxt.getVarType(varName, this); 37 | // } 38 | 39 | public Var getVar(String name) { 40 | Var object = current.getVar(name); 41 | if(object != null){ 42 | return object; 43 | } 44 | return parent.getVar(name); 45 | } 46 | 47 | public void setVar(Var var) { 48 | current.setVar(var); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/EmptyContext.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | /** 4 | * 空执行上下文 5 | * 6 | * @author yuqingsong 7 | * 8 | */ 9 | /* 10 | public class EmptyContext implements FelContext{ 11 | 12 | private static final FelContext instance; 13 | 14 | public static FelContext getInstance() { 15 | return instance; 16 | } 17 | 18 | static{ 19 | instance= new EmptyContext(); 20 | } 21 | 22 | private EmptyContext(){}; 23 | 24 | 25 | @Override 26 | public Object get(String name) { 27 | return null; 28 | } 29 | 30 | @Override 31 | public void set(String name, Object value) { 32 | throw new UnsupportedOperationException("空Context"); 33 | } 34 | 35 | // @Override 36 | // public Class getVarType(String varName) { 37 | // throw new UnsupportedOperationException("空Context"); 38 | // } 39 | 40 | 41 | @Override 42 | public Var getVar(String name) { 43 | throw new UnsupportedOperationException("空Context"); 44 | } 45 | 46 | 47 | @Override 48 | public void setVar(Var var) { 49 | throw new UnsupportedOperationException("空Context"); 50 | 51 | } 52 | 53 | } 54 | */ 55 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/FelContext.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | import com.greenpineyu.fel.common.Null; 4 | 5 | 6 | 7 | public interface FelContext { 8 | 9 | 10 | Null NULL = new Null(); 11 | 12 | /** 13 | * 获取变量值 14 | * 15 | * @param name 16 | * 变量名称 17 | * @return 变量值,如果没有找到变量,返回FelContext.NOT_FOUND 18 | */ 19 | Object get(String name); 20 | 21 | /** 22 | * 设置变量 23 | * 24 | * @param name 25 | * 变量名称 26 | * @param value 27 | * 变量值 28 | */ 29 | void set(String name, Object value); 30 | 31 | Var getVar(String name); 32 | 33 | void setVar(Var var); 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/MapContext.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 8 | * @author yuqingsong 9 | * 10 | */ 11 | /* 12 | * 更合适的实现方式是使用组合,而不是继承,这里继承HashMap是为了提高get方法的效率。 13 | */ 14 | @SuppressWarnings("serial") 15 | public class MapContext extends HashMap implements FelContext { 16 | public MapContext() { 17 | } 18 | 19 | public MapContext(Map map){ 20 | // this.putAll(map); 21 | if(map != null){ 22 | for (Map.Entry e : map.entrySet()) { 23 | String name = e.getKey(); 24 | Object value = e.getValue(); 25 | this.set(name, value); 26 | } 27 | } 28 | } 29 | 30 | public Object get(String name) { 31 | Var object = super.get(name); 32 | if (object != null) { 33 | // 对象有值,或者包含此变量时,返回object 34 | return object.getValue(); 35 | } 36 | return null; 37 | // map中不包含此变量返回NOT_FOUND 38 | // return NOT_FOUND; 39 | } 40 | 41 | // @Override 42 | // public Class getVarType(String varName) { 43 | // return AbstractConetxt.getVarType(varName,this); 44 | // } 45 | 46 | 47 | public void set(String name, Object value) { 48 | // 如果变量已经存在,就不再重复创建变量。 49 | Var var = getVar(name); 50 | if (var != null) { 51 | var.setValue(value); 52 | } else { 53 | this.put(name, new Var(name, value)); 54 | } 55 | } 56 | 57 | public static String toString(Object var) { 58 | return var == null ? null : var.toString(); 59 | } 60 | 61 | public Var getVar(String name) { 62 | return super.get(name); 63 | } 64 | 65 | public void setVar(Var var) { 66 | super.put(var.getName(), var); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/context/Var.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.context; 2 | 3 | import com.greenpineyu.fel.common.Null; 4 | 5 | /** 6 | * 变量 7 | * @author yuqingsong 8 | * 9 | * @param 变量的类型 10 | */ 11 | public class Var { 12 | 13 | public Var(String name,Object value,Class type){ 14 | this.name = name; 15 | this.value = value; 16 | this.type = type; 17 | // if(type == null){ 18 | // // 如果没有指定type,将type设置成value.getClass。 19 | //// setTypeByValue(value); 20 | // } 21 | } 22 | private Class getTypeByValue() { 23 | return value!=null?value.getClass():Null.class; 24 | // this.type = getTypeByValue; 25 | } 26 | public Var(String name,Object value){ 27 | this(name,value,null); 28 | } 29 | 30 | /** 31 | * 变量名称 32 | */ 33 | private String name; 34 | 35 | /** 36 | * 变量值 37 | */ 38 | private Object value; 39 | 40 | /** 41 | * 变量值 42 | */ 43 | private Class type; 44 | 45 | 46 | public Class getType() { 47 | return type!=null?type:getTypeByValue(); 48 | } 49 | 50 | public void setType(Class type) { 51 | this.type = type; 52 | } 53 | 54 | public String getName() { 55 | return name; 56 | } 57 | 58 | public void setName(String name) { 59 | this.name = name; 60 | } 61 | 62 | public Object getValue() { 63 | return value; 64 | } 65 | 66 | public void setValue(Object value) { 67 | this.value = value; 68 | } 69 | 70 | public static void main(String[] args) { 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/exception/CompileException.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.exception; 2 | 3 | @SuppressWarnings("serial") 4 | public class CompileException extends RuntimeException { 5 | public CompileException(String msg) { 6 | super(msg); 7 | } 8 | 9 | public CompileException(String msg, Throwable cause) { 10 | super(msg, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/exception/EvalException.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.exception; 2 | 3 | @SuppressWarnings("serial") 4 | public class EvalException extends RuntimeException { 5 | public EvalException(String msg) { 6 | super(msg); 7 | } 8 | 9 | public EvalException(String msg, Throwable cause) { 10 | super(msg, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/exception/ParseException.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.exception; 2 | 3 | @SuppressWarnings("serial") 4 | public class ParseException extends RuntimeException { 5 | public ParseException(String msg) { 6 | super(msg); 7 | } 8 | 9 | public ParseException(String msg, Throwable cause) { 10 | super(msg, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/exception/SecurityException.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.exception; 2 | 3 | @SuppressWarnings("serial") 4 | public class SecurityException extends RuntimeException { 5 | public SecurityException(String msg) { 6 | super(msg); 7 | } 8 | 9 | public SecurityException(String msg, Throwable cause) { 10 | super(msg, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/CommonFunction.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.Expression; 6 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 7 | import com.greenpineyu.fel.compile.SourceBuilder; 8 | import com.greenpineyu.fel.context.FelContext; 9 | import com.greenpineyu.fel.parser.FelNode; 10 | 11 | /** 12 | * 普通函数 13 | * 14 | * @author yqs 15 | * 16 | */ 17 | public abstract class CommonFunction implements Function { 18 | 19 | /* 20 | * (non-Javadoc) 21 | * 22 | * @see .script.function.Function#call(.script.antlr.AstNode, 23 | * .script.context.ScriptContext) 24 | */ 25 | public Object call(FelNode node, FelContext context) { 26 | // 如果参数中包含表达式,执行表达式。将表达式替换成表达式执行结果。 27 | Object[] children = evalArgs(node, context); 28 | return call(children); 29 | } 30 | 31 | public SourceBuilder toMethod(FelNode node, FelContext ctx) { 32 | return InterpreterSourceBuilder.getInstance(); 33 | } 34 | 35 | 36 | public static Object[] evalArgs(FelNode node, FelContext context) { 37 | Object[] returnMe = null; 38 | List children = node.getChildren(); 39 | if(children!=null&& children.size()>0){ 40 | Object[] args = children.toArray(); 41 | int size = args.length; 42 | returnMe = new Object[size]; 43 | System.arraycopy(args, 0, returnMe, 0, size); 44 | for (int i = 0; i < size; i++) { 45 | Object child = args[i]; 46 | if (child instanceof Expression) { 47 | Expression childExp = ((Expression) child); 48 | returnMe[i] = childExp.eval(context); 49 | } 50 | } 51 | } 52 | return returnMe; 53 | } 54 | 55 | public static void main(String[] args) { 56 | /* 57 | * List list = new ArrayList(); String[] abc = new String[] { "1", "3", 58 | * "4" }; for (int i = 0; i < abc.length; i++) { String string = abc[i]; 59 | * list.add(string); } int time = 1000000; long s1 = 60 | * System.currentTimeMillis(); 61 | * 62 | * for (int i = 0; i < time; i++) { abc.clone(); } long s2 = 63 | * System.currentTimeMillis(); System.out.println("花费的时间:" + (s2 - s1)); 64 | * 65 | * for (int i = 0; i < time; i++) { list.toArray(new Object[0]); } long 66 | * s3 = System.currentTimeMillis(); System.out.println("花费的时间:" + (s3 - 67 | * s2)); 68 | */ 69 | // Object[] returnMe = null; 70 | // Object[] children = node.getChildrenArray(); 71 | // int size = children.length; 72 | // if (size > 0) { 73 | // returnMe = (Object[]) children.clone(); 74 | // for (int i = 0; i < size; i++) { 75 | // Object child = children[i]; 76 | // if (child instanceof Expression) { 77 | // Expression childExp = ((Expression) child); 78 | // returnMe[i] = childExp.eval(context); 79 | // } 80 | // } 81 | // } 82 | // return returnMe; 83 | } 84 | 85 | /** 86 | * 调用函数 87 | * 88 | * @param arguments 89 | * @return 90 | */ 91 | abstract public Object call(Object[] arguments); 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/Dollar.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import com.greenpineyu.fel.FelEngine; 4 | import com.greenpineyu.fel.common.StringUtils; 5 | import com.greenpineyu.fel.compile.FelMethod; 6 | import com.greenpineyu.fel.compile.SourceBuilder; 7 | import com.greenpineyu.fel.context.FelContext; 8 | import com.greenpineyu.fel.parser.FelNode; 9 | 10 | /** 11 | * $函数,通过$获取class或者创建对象 ${Math} 结果为 Math.class ${Dollar.new} 结果为 new Dollar() 12 | * 13 | * @author yuqingsong 14 | * 15 | */ 16 | public class Dollar implements Function { 17 | 18 | 19 | public String getName() { 20 | return "$"; 21 | } 22 | 23 | public Object call(FelNode node, FelContext context) { 24 | String txt = getChildText(node); 25 | 26 | boolean isNew = isNew(txt); 27 | Class cls = getClass(txt, isNew); 28 | if (isNew) { 29 | return newObject(cls); 30 | 31 | } else { 32 | return cls; 33 | } 34 | } 35 | 36 | private Object newObject(Class cls) { 37 | Object o = null; 38 | if (cls != null) { 39 | try { 40 | o = cls.newInstance(); 41 | } catch (InstantiationException e) { 42 | e.printStackTrace(); 43 | } catch (IllegalAccessException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | return o; 48 | } 49 | 50 | private static final String suffix = ".new"; 51 | 52 | @SuppressWarnings("unused") 53 | private Class getClass(FelNode node) { 54 | String txt = getChildText(node); 55 | boolean isNew = isNew(txt); 56 | return getClass(txt, isNew); 57 | } 58 | 59 | private Class getClass(String txt, boolean isNew) { 60 | String className = txt; 61 | if (isNew) { 62 | className = className.substring(0, txt.length() - suffix.length()); 63 | } 64 | if (className.indexOf(".") == -1) { 65 | className = "java.lang." + className; 66 | } 67 | try { 68 | Class clz = Class.forName(className); 69 | return clz; 70 | } catch (ClassNotFoundException e) { 71 | e.printStackTrace(); 72 | } 73 | return null; 74 | } 75 | 76 | private boolean isNew(String txt) { 77 | boolean isNew = txt.endsWith(suffix); 78 | return isNew; 79 | } 80 | 81 | private String getChildText(FelNode node) { 82 | String txt = node.getChildren().get(0).getText(); 83 | txt = StringUtils.remove(txt, '\''); 84 | txt = StringUtils.remove(txt, '"'); 85 | return txt; 86 | } 87 | 88 | public SourceBuilder toMethod(FelNode node, FelContext ctx) { 89 | String txt = getChildText(node); 90 | 91 | boolean isNew = isNew(txt); 92 | Class cls = getClass(txt, isNew); 93 | String code = cls.getName(); 94 | if (isNew) { 95 | code = "new " + code + "()"; 96 | } 97 | return new FelMethod(cls, code); 98 | } 99 | 100 | public static void main(String[] args) { 101 | // System.out.println("abc.new".endsWith(".new")); 102 | String exp = "$('Math').max($('Math').min(1,2),3).doubleValue()"; 103 | exp = "$('String.new').concat('abc')"; 104 | Object eval = FelEngine.instance 105 | .eval(exp); 106 | System.out.println(eval); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/ErrorValue.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import com.greenpineyu.fel.parser.FelNode; 4 | 5 | /** 6 | * 包名 .script.function 7 | * 类名 ERRORVALUE.java 8 | * 创建日期 Oct 27, 20108:56:26 AM 9 | * 作者 10 | * 版权 11 | */ 12 | public class ErrorValue { 13 | 14 | /** 15 | * 错误节点 16 | */ 17 | private FelNode node; 18 | 19 | /** 20 | * 错误信息 21 | */ 22 | private String errorMsg; 23 | 24 | public ErrorValue(FelNode node,String errorMsg){ 25 | this.node = node; 26 | this.errorMsg = errorMsg; 27 | } 28 | 29 | public FelNode getNode() { 30 | return node; 31 | } 32 | 33 | public void setNode(FelNode node) { 34 | this.node = node; 35 | } 36 | 37 | public String getErrorMsg() { 38 | return errorMsg; 39 | } 40 | 41 | public void setErrorMsg(String errorMsg) { 42 | this.errorMsg = errorMsg; 43 | } 44 | 45 | public String toString() { 46 | if (errorMsg != null) { 47 | return errorMsg; 48 | } 49 | return "执行脚本出错"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/FunMgr.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.greenpineyu.fel.function.operator.Add; 7 | import com.greenpineyu.fel.function.operator.CollectionGet; 8 | import com.greenpineyu.fel.function.operator.Cond; 9 | import com.greenpineyu.fel.function.operator.Div; 10 | import com.greenpineyu.fel.function.operator.Dot; 11 | import com.greenpineyu.fel.function.operator.Equal; 12 | import com.greenpineyu.fel.function.operator.GreaterThan; 13 | import com.greenpineyu.fel.function.operator.GreaterThenEqual; 14 | import com.greenpineyu.fel.function.operator.LessThen; 15 | import com.greenpineyu.fel.function.operator.LessThenEqual; 16 | import com.greenpineyu.fel.function.operator.And; 17 | import com.greenpineyu.fel.function.operator.Mod; 18 | import com.greenpineyu.fel.function.operator.Mul; 19 | import com.greenpineyu.fel.function.operator.NotEqual; 20 | import com.greenpineyu.fel.function.operator.NotOper; 21 | import com.greenpineyu.fel.function.operator.Or; 22 | import com.greenpineyu.fel.function.operator.Sub; 23 | 24 | public class FunMgr { 25 | 26 | // private static FunMgr instance = new FunMgr(); 27 | 28 | public FunMgr() { 29 | userFunMap = new HashMap(); 30 | } 31 | 32 | /** 33 | * 用户函数 34 | */ 35 | private Map userFunMap; 36 | 37 | /** 38 | * 共用函数 39 | */ 40 | private Map funcMap; 41 | 42 | { 43 | funcMap = new HashMap(); 44 | 45 | // // 操作符函数 46 | addFun(new Dot()); 47 | // funcMap.put(".", new Dot()); 48 | 49 | addFun(new CollectionGet()); 50 | // funcMap.put(new CollectionGet().instance.getName(), CollectionGet.instance); 51 | 52 | addFun(new Cond()); 53 | // funcMap.put(CondOperator.instance.getName(), CondOperator.instance); 54 | addFun(new Dollar()); 55 | // funcMap.put(Dollar.instance.getName(), Dollar.instance); 56 | addFun(new NotOper()); 57 | // funcMap.put(NotOper.instance.getName(), NotOper.instance); 58 | 59 | addFun(new Add());//+ 60 | addFun(new Sub());//- 61 | // funcMap.put(Add.getInstance().getName(), Add.getInstance());// + 62 | // funcMap.put(Sub.getInstance().getName(), Sub.getInstance());// - 63 | // funcMap.put(EqualsOperator.EQUAL_STR, EqualsOperator.EQUAL);// == 64 | addFun(new Equal());//== 65 | addFun(new NotEqual());//!= 66 | // funcMap.put(EqualsOperator.NOEQUAL_STR, EqualsOperator.NOEQUAL);// != 67 | addFun(new Mul());// * 68 | addFun(new Div());// / 69 | addFun(new Mod());// % 70 | // funcMap.put(MultiplicativeOperator.MUL_STR, MultiplicativeOperator.MUL);// * 71 | // funcMap.put(MultiplicativeOperator.DIV_STR, MultiplicativeOperator.DIV);// / 72 | // funcMap.put(MultiplicativeOperator.MOD_STR, MultiplicativeOperator.MOD);// % 73 | addFun(new LessThen());// < 74 | addFun(new LessThenEqual());// <= 75 | addFun(new GreaterThan());// > 76 | addFun(new GreaterThenEqual());// >= 77 | // funcMap.put(RelationalOperator.LESSTHEN_STR, 78 | // RelationalOperator.LESSTHEN);// < 79 | // funcMap.put(RelationalOperator.GREATERTHAN_STR, 80 | // RelationalOperator.GREATERTHAN);// > 81 | // funcMap.put(RelationalOperator.LESSTHENOREQUALS_STR, 82 | // RelationalOperator.LESSTHENOREQUALS);// <= 83 | // funcMap.put(RelationalOperator.GREATERTHANOREQUALS_STR, 84 | // RelationalOperator.GREATERTHANOREQUALS);// >= 85 | // funcMap.put(LogicalOperator.AND_STR.toLowerCase(), LogicalOperator.AND);// AND 86 | addFun(new And());// && 87 | addFun(new Or());// || 88 | // funcMap.put(LogicalOperator.AND2_STR, LogicalOperator.AND2);// && 89 | // funcMap.put(LogicalOperator.OR_STR.toLowerCase(), LogicalOperator.OR);// OR 90 | // funcMap.put(LogicalOperator.OR2_STR, LogicalOperator.OR2);// || 91 | // funcMap.put(Like.getInstance().getName(), Like.getInstance());// like 92 | // funcMap.put(In.getInstance().getName(), In.getInstance());// in 93 | 94 | 95 | 96 | 97 | } 98 | 99 | private void addFun(Function fun) { 100 | funcMap.put(fun.getName(), fun); 101 | } 102 | 103 | /** 104 | * 获取函数。先从用户函数中取,如没有获取到,再从共用函数中获取。 105 | * @param funName 106 | * @return 107 | */ 108 | public Function getFun(String funName) { 109 | if(funName!=null) { 110 | String newFunName = getLowerCaseName(funName); 111 | Function userFun = userFunMap.get(newFunName); 112 | if(userFun != null){ 113 | return userFun; 114 | } 115 | return funcMap.get(newFunName); 116 | } 117 | return null; 118 | } 119 | 120 | private String getLowerCaseName(String funName) { 121 | return funName.toLowerCase(); 122 | } 123 | 124 | /** 125 | * 添加函数到用户函数库中 126 | * @param fun 127 | */ 128 | public void add(Function fun) { 129 | if (fun != null) { 130 | String name = fun.getName(); 131 | if(name==null || "".equals(name)){ 132 | throw new IllegalArgumentException("函数名称不能为空"); 133 | }else{ 134 | userFunMap.put(getLowerCaseName(name), fun); 135 | } 136 | } 137 | } 138 | 139 | 140 | /** 141 | * 移除用户函数 142 | * @param name 143 | */ 144 | public void remove(String name){ 145 | if (name != null) { 146 | userFunMap.remove(getLowerCaseName(name)); 147 | } 148 | } 149 | 150 | // static public FunMgr getInstance() { 151 | // return instance; 152 | // } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/Function.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import com.greenpineyu.fel.compile.SourceBuilder; 4 | import com.greenpineyu.fel.context.FelContext; 5 | import com.greenpineyu.fel.parser.FelNode; 6 | 7 | /** 8 | * @uml.dependency supplier=".script.context.ScriptContext" 9 | */ 10 | public interface Function { 11 | 12 | /** 13 | * 获取函数的名称 14 | * @return 15 | */ 16 | String getName(); 17 | 18 | /** 19 | * 调用函数 20 | * @param arguments 21 | * @return 22 | */ 23 | Object call(FelNode node, FelContext context); 24 | 25 | 26 | 27 | SourceBuilder toMethod(FelNode node,FelContext ctx); 28 | 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/JavaMethod.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | 6 | import com.greenpineyu.fel.compile.FelMethod; 7 | import com.greenpineyu.fel.compile.SourceBuilder; 8 | import com.greenpineyu.fel.compile.VarBuffer; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.function.operator.Dot; 11 | import com.greenpineyu.fel.parser.FelNode; 12 | 13 | /** 14 | * 15 | * 此类用于保存用户注册的java method。 16 | * 17 | * @author Administrator 18 | * 19 | */ 20 | public class JavaMethod implements Function { 21 | 22 | /** 23 | * 方法名称 24 | */ 25 | private String name; 26 | 27 | /** 28 | * 对象,如果是静态方法,对象为null 29 | */ 30 | private Object obj; 31 | 32 | /** 33 | * java method 34 | */ 35 | private Method method; 36 | 37 | public JavaMethod(String name,Method method,Object obj) { 38 | this.name = name; 39 | this.method = method; 40 | this.obj = obj; 41 | } 42 | 43 | 44 | public Object call(FelNode node, FelContext context) { 45 | // Dot.clearNullNode(node); 46 | Object[] args = CommonFunction.evalArgs(node, context); 47 | return Dot.invoke(obj, method, args); 48 | } 49 | 50 | 51 | public String getName() { 52 | return name; 53 | } 54 | 55 | 56 | public SourceBuilder toMethod(FelNode node, FelContext context) { 57 | StringBuilder code = new StringBuilder(); 58 | String classOrObjCode = getClassOrObjCode(); 59 | code.append(classOrObjCode); 60 | code.append("."); 61 | String methodName = method.getName(); 62 | code.append(methodName); 63 | StringBuilder methodParams = getParamsCode(node, context); 64 | code.append("(").append(methodParams).append(")"); 65 | FelMethod returnMe = new FelMethod(method 66 | .getReturnType(), code.toString()); 67 | return returnMe; 68 | } 69 | 70 | private String getClassOrObjCode() { 71 | if(obj == null){ 72 | Class cls = method.getDeclaringClass(); 73 | return cls.getCanonicalName(); 74 | }else{ 75 | String varName = VarBuffer.push(obj); 76 | return varName; 77 | } 78 | } 79 | 80 | private StringBuilder getParamsCode(FelNode node, FelContext context) { 81 | StringBuilder methodParams = new StringBuilder(); 82 | List params = node.getChildren(); 83 | boolean hasParam = params != null && !params.isEmpty(); 84 | Class[] paramTypes = method.getParameterTypes(); 85 | if (hasParam) { 86 | // 有参数 87 | for (int i = 0; i < paramTypes.length; i++) { 88 | Class paramType = paramTypes[i]; 89 | FelNode p = params.get(i); 90 | String paramCode = Dot.getParamCode(paramType, p, context); 91 | methodParams.append(paramCode); 92 | if(i iterator = node.getChildren().iterator(); iterator 37 | .hasNext();) { 38 | Object child = iterator.next(); 39 | if (child instanceof FelNode) { 40 | FelNode childNode = (FelNode) child; 41 | child = childNode.eval(context); 42 | } 43 | if (child instanceof String) { 44 | if (returnMe == null) { 45 | returnMe = child; 46 | continue; 47 | } 48 | returnMe = returnMe + (String) child; 49 | } 50 | if (child instanceof Number) { 51 | if (returnMe == null) { 52 | returnMe = child; 53 | continue; 54 | } 55 | Number value = (Number) child; 56 | if (returnMe instanceof Number) { 57 | Number r = (Number) returnMe; 58 | returnMe = toDouble(r) + toDouble(value); 59 | }else if(returnMe instanceof String){ 60 | String r = (String) returnMe; 61 | returnMe=r+value; 62 | } 63 | } 64 | } 65 | if(returnMe instanceof Number){ 66 | return NumberUtil.parseNumber(returnMe.toString()); 67 | } 68 | return returnMe; 69 | } 70 | 71 | 72 | public String getName() { 73 | return "+"; 74 | } 75 | 76 | 77 | public FelMethod toMethod(FelNode node, FelContext ctx) { 78 | Class type = null; 79 | List children = node.getChildren(); 80 | StringBuilder sb = new StringBuilder(); 81 | if (children.size() == 2) { 82 | FelNode left = children.get(0); 83 | SourceBuilder lm = left.toMethod(ctx); 84 | appendArg(sb, lm,ctx,left); 85 | Class leftType = lm.returnType(ctx, left); 86 | 87 | FelNode right = children.get(1); 88 | sb.append("+"); 89 | SourceBuilder rm = right.toMethod(ctx); 90 | Class rightType = rm.returnType(ctx, right); 91 | if(CharSequence.class.isAssignableFrom(leftType)){ 92 | type = leftType; 93 | } else if (CharSequence.class.isAssignableFrom(rightType)) { 94 | type = rightType; 95 | }else if(ReflectUtil.isPrimitiveOrWrapNumber(leftType) 96 | &&ReflectUtil.isPrimitiveOrWrapNumber(rightType)){ 97 | type = NumberUtil.arithmeticClass(leftType, rightType); 98 | }else { 99 | //不支持的类型,返回字符串。 100 | type = String.class; 101 | } 102 | appendArg(sb, rm,ctx,right); 103 | 104 | } else if (children.size() == 1) { 105 | FelNode right = children.get(0); 106 | SourceBuilder rm = right.toMethod(ctx); 107 | Class rightType = rm.returnType(ctx, right); 108 | if(ReflectUtil.isPrimitiveOrWrapNumber(rightType)){ 109 | appendArg(sb, rm,ctx,right); 110 | } 111 | type = rightType; 112 | } 113 | 114 | // appendArg(sb, rm,ctx,right); 115 | FelMethod m = new FelMethod(type, sb.toString()); 116 | return m; 117 | } 118 | 119 | 120 | private void appendArg(StringBuilder sb, SourceBuilder argMethod,FelContext ctx,FelNode node) { 121 | Class t = argMethod.returnType(ctx, node); 122 | sb.append("("); 123 | if (ReflectUtil.isPrimitiveOrWrapNumber(t) 124 | || CharSequence.class.isAssignableFrom(t)) { 125 | // 数值型和字符型时,直接添加 126 | sb.append(argMethod.source(ctx, node)); 127 | } else { 128 | sb.append("ObjectUtils.toString(").append(argMethod.source(ctx, node)) 129 | .append(")"); 130 | } 131 | sb.append(")"); 132 | } 133 | 134 | /** 135 | * 加法 136 | * 137 | * @param left 138 | * @param right 139 | * @return 140 | */ 141 | public static Object add(Object left, Object right){ 142 | if(left == null || right == null){ 143 | throw new NullPointerException("调用add()方法出错!,原因:当前参数为空"); 144 | } 145 | try { 146 | if (left instanceof Object[]){ 147 | left = NumberUtil.calArray(left); 148 | } 149 | if (right instanceof Object[]){ 150 | right = NumberUtil.calArray(right); 151 | } 152 | 153 | if (NumberUtil.isFloatingPointNumber(left) || NumberUtil.isFloatingPointNumber(right)) { 154 | double l = NumberUtil.toDouble(left); 155 | double r = NumberUtil.toDouble(right); 156 | return new Double(l + r); 157 | } 158 | 159 | if(left instanceof BigInteger && right instanceof BigInteger){ 160 | BigInteger l = NumberUtil.toBigInteger(left); 161 | BigInteger r = NumberUtil.toBigInteger(right); 162 | return l.add(r); 163 | } 164 | 165 | if(left instanceof BigDecimal || right instanceof BigDecimal){ 166 | BigDecimal l = NumberUtil.toBigDecimal(left); 167 | BigDecimal r = NumberUtil.toBigDecimal(right); 168 | return l.add(r); 169 | } 170 | 171 | if (left instanceof String && right instanceof Date) { 172 | return left + Add.DATE_FORMAT.format((Date) right); 173 | } else if (left instanceof Date && right instanceof String) { 174 | return Add.DATE_FORMAT.format((Date) left) + right; 175 | } 176 | 177 | BigInteger l = NumberUtil.toBigInteger(left); 178 | BigInteger r = NumberUtil.toBigInteger(right); 179 | BigInteger result = l.add(r); 180 | return NumberUtil.narrowBigInteger(left, right, result); 181 | } catch (Exception e) { 182 | return ObjectUtils.toString(left).concat(ObjectUtils.toString(right)); 183 | } 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/And.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.common.Null; 6 | import com.greenpineyu.fel.common.NumberUtil; 7 | import com.greenpineyu.fel.compile.FelMethod; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.exception.EvalException; 11 | import com.greenpineyu.fel.function.StableFunction; 12 | import com.greenpineyu.fel.function.TolerantFunction; 13 | import com.greenpineyu.fel.parser.FelNode; 14 | 15 | /** 16 | * 逻辑操作符 17 | */ 18 | public class And extends StableFunction { 19 | 20 | // private final String operator; 21 | // 22 | // private LogicalOperator(String operator) { 23 | // this.operator = operator; 24 | // } 25 | // 26 | // public static final String AND_STR = "AND"; 27 | // public static final String AND2_STR = "&&"; 28 | // public static final String OR_STR = "OR"; 29 | // public static final String OR2_STR = "||"; 30 | // 31 | // public static final LogicalOperator AND; 32 | // public static final LogicalOperator AND2; 33 | // public static final LogicalOperator OR; 34 | // public static final LogicalOperator OR2; 35 | // 36 | // static { 37 | // AND = new LogicalOperator(AND_STR); 38 | // AND2 = new LogicalOperator(AND2_STR); 39 | // OR = new LogicalOperator(OR_STR); 40 | // OR2 = new LogicalOperator(OR2_STR); 41 | // } 42 | 43 | public String toJavaOper() { 44 | // if (AND_STR.equals(this.getName())) { 45 | // return AND2_STR; 46 | // } 47 | // if (OR_STR.equals(this.getName())) { 48 | // return OR2_STR; 49 | // } 50 | return this.getName(); 51 | } 52 | 53 | 54 | public Object call(FelNode node, FelContext context) { 55 | List children = node.getChildren(); 56 | if (children != null && children.size() == 2) { 57 | return logic(context,children); 58 | // Object[] c = children.toArray(); 59 | // if (this == AND || this == AND2) { 60 | // return and(context, c); 61 | // } else if (this == OR || this == OR2) { 62 | // return or(context, c); 63 | // } 64 | // throw new EvalException("未知的逻辑操作符"); 65 | } 66 | throw new EvalException("传入参数数组为空或者参数个数不正确!"); 67 | } 68 | 69 | /** 70 | * AND 和 && 71 | * 72 | * @param left 73 | * @param right 74 | * @return 75 | */ 76 | // private Boolean and(FelContext context, Object[] children) { 77 | // Boolean leftValue = toBoolean(context, children[0]); 78 | // if (!leftValue.booleanValue()) { 79 | // return leftValue; 80 | // } 81 | // return toBoolean(context, children[1]); 82 | // } 83 | 84 | /** 85 | * 求逻辑与(&&) 86 | * @param context 87 | * @param children 88 | * @return 89 | */ 90 | Boolean logic(FelContext context, List children) { 91 | Boolean leftValue = toBoolean(context, children.get(0)); 92 | if (!leftValue.booleanValue()) { 93 | return leftValue; 94 | } 95 | return toBoolean(context, children.get(1)); 96 | } 97 | 98 | // Boolean or(FelContext context, Object[] children) { 99 | // Boolean leftValue = toBoolean(context, children[0]); 100 | // if (leftValue.booleanValue()) { 101 | // return leftValue; 102 | // } 103 | // return toBoolean(context, children[1]); 104 | // } 105 | 106 | Boolean toBoolean(FelContext context, Object node) { 107 | node = TolerantFunction.eval(context, node); 108 | return NumberUtil.toBooleanObj(node); 109 | } 110 | 111 | /** 112 | * AND 和 && 113 | * 114 | * @param left 115 | * @param right 116 | * @return 117 | */ 118 | /* 119 | * private boolean and(Object left, Object right) { boolean l = 120 | * NumberUtil.toBoolean(left); if (!l) { return false; } boolean r = 121 | * NumberUtil.toBoolean(right); if (!r) { return false; } return true; } 122 | */ 123 | 124 | /** 125 | * OR 和 || 126 | * 127 | * @param left 128 | * @param right 129 | * @return 130 | */ 131 | /* 132 | * private boolean or(Object left, Object right) { boolean l = 133 | * NumberUtil.toBoolean(left); if (l) { return true; } boolean r = 134 | * NumberUtil.toBoolean(right); if (r) { return true; } return false; } 135 | */ 136 | 137 | 138 | public String getName() { 139 | return "&&"; 140 | } 141 | 142 | 143 | public FelMethod toMethod(FelNode node, FelContext ctx) { 144 | String code = toBoolean(node, ctx, 0)+this.toJavaOper()+toBoolean(node, ctx, 1); 145 | return new FelMethod(Boolean.class, code); 146 | // List children = node.getChildren(); 147 | // FelNode left = children.get(0); 148 | // FelNode right = children.get(1); 149 | // FelMethod lm = left.toMethod(ctx); 150 | // FelMethod rm = right.toMethod(ctx); 151 | // Class lt = lm.getReturnType(); 152 | // Class rt = rm.getReturnType(); 153 | // 154 | // return null; 155 | } 156 | 157 | public String toBoolean(FelNode node, FelContext ctx, int index) { 158 | List children = node.getChildren(); 159 | FelNode child = children.get(index); 160 | SourceBuilder method = child.toMethod(ctx); 161 | Class type = method.returnType(ctx, child); 162 | if (Boolean.class.isAssignableFrom(type)) { 163 | return "(" + method.source(ctx, child) + ")"; 164 | } 165 | if (String.class.isAssignableFrom(type)) { 166 | return "Boolean.valueOf(" + method.source(ctx, child) + ")"; 167 | } 168 | if (Null.class.isAssignableFrom(type)) { 169 | return "false"; 170 | } 171 | return "false"; 172 | } 173 | 174 | } -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/CollectionGet.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.lang.reflect.Array; 4 | import java.util.Collection; 5 | import java.util.Enumeration; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import com.greenpineyu.fel.Expression; 11 | import com.greenpineyu.fel.FelEngine; 12 | import com.greenpineyu.fel.FelEngineImpl; 13 | import com.greenpineyu.fel.common.NumberUtil; 14 | import com.greenpineyu.fel.common.ObjectUtils; 15 | import com.greenpineyu.fel.compile.FelMethod; 16 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 17 | import com.greenpineyu.fel.compile.SourceBuilder; 18 | import com.greenpineyu.fel.context.FelContext; 19 | import com.greenpineyu.fel.function.StableFunction; 20 | import com.greenpineyu.fel.function.TolerantFunction; 21 | import com.greenpineyu.fel.parser.FelNode; 22 | 23 | /** 24 | * 根据索引获取某个集合的值,相当于List.get(i)方法和array[i]方法。 用于处理array[i],list[i]等表达式, 25 | * 同时也可以处理支持实现了iterator的类,如Set。 26 | * 27 | * @author yuqingsong 28 | * 29 | */ 30 | public class CollectionGet extends StableFunction{ 31 | 32 | 33 | public Object call(FelNode node, FelContext context) { 34 | if(node.getChildCount()>=2){ 35 | Object coll = TolerantFunction.eval(context, node.getChild(0)); 36 | Object index = TolerantFunction.eval(context, node.getChild(1)); 37 | int i = 0; 38 | if(index instanceof Number){ 39 | i = ((Number)index).intValue(); 40 | } 41 | // System.out.println(coll+":"+index); 42 | return get(coll,i); 43 | } 44 | // TODO 说明语法错误。 45 | return null; 46 | } 47 | 48 | 49 | public String getName() { 50 | return "["; 51 | } 52 | 53 | 54 | public SourceBuilder toMethod(FelNode node, FelContext ctx) { 55 | Class type = null; 56 | List children = node.getChildren(); 57 | FelNode left = children.get(0); 58 | SourceBuilder leftMethod = left.toMethod(ctx); 59 | Class leftType = leftMethod.returnType(ctx,left); 60 | 61 | if(!leftType.isArray()&&!List.class.isAssignableFrom(leftType)){ 62 | // 不是数组,也不是list,直接生成 使用与解释执行相同的代码 63 | return InterpreterSourceBuilder.getInstance(); 64 | } 65 | FelNode right = children.get(1); 66 | SourceBuilder rightMethod = right.toMethod(ctx); 67 | Class rightType = rightMethod.returnType(ctx,right); 68 | 69 | String leftSrc = leftMethod.source(ctx,left); 70 | String rightSrc = getRightSrc(ctx, right, rightMethod, rightType); 71 | String src = ""; 72 | if(leftType.isArray()){ 73 | // 获取数组内容 74 | type = leftType.getComponentType(); 75 | src = "("+leftSrc+")["+rightSrc+"]"; 76 | }else if(List.class.isAssignableFrom(leftType)){ 77 | type = Object.class; 78 | src = "("+leftSrc+").get("+rightSrc+")"; 79 | } 80 | return new FelMethod(type,src); 81 | } 82 | 83 | /** 84 | * 获取索引的java代码,如果索引不是int类型,要转换成int类型 85 | * 86 | * @param ctx 87 | * @param right 88 | * 索引对应的节点 89 | * @param rightMethod 90 | * @param rightType 91 | * @return 92 | */ 93 | private String getRightSrc(FelContext ctx, FelNode right, 94 | SourceBuilder rightMethod, Class rightType) { 95 | String rightSrc = ""; 96 | Class[] cls = new Class[] { Integer.class, Short.class, 97 | Character.class, Byte.class, int.class, short.class, 98 | char.class, byte.class }; 99 | boolean isInt = false; 100 | for(int i = 0;i) { 121 | Map map = (Map) object; 122 | Iterator iterator = map.entrySet().iterator(); 123 | return get(iterator, index); 124 | } else if (object instanceof List) { 125 | return ((List) object).get(index); 126 | } else if (object instanceof Object[]) { 127 | return ((Object[]) object)[index]; 128 | } else if (object instanceof Iterator) { 129 | Iterator it = (Iterator) object; 130 | while (it.hasNext()) { 131 | index--; 132 | if (index == -1) { 133 | return it.next(); 134 | } else { 135 | it.next(); 136 | } 137 | } 138 | throw new IndexOutOfBoundsException("Entry does not exist: " 139 | + index); 140 | } else if (object instanceof Collection) { 141 | Iterator iterator = ((Collection) object).iterator(); 142 | return get(iterator, index); 143 | } else if (object instanceof Enumeration) { 144 | Enumeration it = (Enumeration) object; 145 | while (it.hasMoreElements()) { 146 | index--; 147 | if (index == -1) { 148 | return it.nextElement(); 149 | } else { 150 | it.nextElement(); 151 | } 152 | } 153 | throw new IndexOutOfBoundsException("Entry does not exist: " 154 | + index); 155 | } else if (object == null) { 156 | throw new IllegalArgumentException("Unsupported object type: null"); 157 | } else { 158 | try { 159 | return Array.get(object, index); 160 | } catch (IllegalArgumentException ex) { 161 | throw new IllegalArgumentException("Unsupported object type: " 162 | + object.getClass().getName()); 163 | } 164 | } 165 | } 166 | 167 | String[][] a = {{"a","b"},{"c","d"}}; 168 | int[][] num = {{1,2},{3,4}}; 169 | public int[][] getNum() { 170 | return num; 171 | } 172 | 173 | public void setNum(int[][] num) { 174 | this.num = num; 175 | } 176 | 177 | public String[][] getA() { 178 | return a; 179 | } 180 | 181 | public void setA(String[][] a) { 182 | this.a = a; 183 | } 184 | 185 | public static void main(String[] args) throws SecurityException, NoSuchMethodException { 186 | // FelEngine engine = new FelEngineImpl(); 187 | // FelContext ctx = engine.getContext(); 188 | // ctx.set("t", new CollectionValue() ); 189 | // String e = "-t.num[0][1]"; 190 | //// e = "-1"; 191 | // Object value = engine.eval(e); 192 | // Expression exp = engine.compile(e,ctx); 193 | // 194 | // System.out.println(value); 195 | // System.out.println(exp.eval(ctx)); 196 | test(); 197 | 198 | 199 | } 200 | 201 | public static void test(){ 202 | FelEngine engine = new FelEngineImpl(); 203 | FelContext ctx = engine.getContext(); 204 | int[] pInt = new int[]{1,2,3}; 205 | pInt.getClass().getName(); 206 | ctx.set("pInt",pInt); 207 | 208 | Integer[] wInt = new Integer[]{1,2,3}; 209 | ctx.set("wInt",wInt); 210 | 211 | int[][] twoDimension = new int[][]{{1,2},{3,4}}; 212 | ctx.set("twoDimension",twoDimension); 213 | 214 | CollectionGet[][] twoDimensionx = new CollectionGet[1][1]; 215 | ctx.set("twoDimensionx",twoDimensionx); 216 | 217 | assertEval("pInt",engine,pInt); 218 | assertCompile("pInt",engine,pInt); 219 | assertEval("twoDimensionx",engine,twoDimensionx); 220 | assertCompile("twoDimensionx",engine,twoDimensionx); 221 | assertEval("pInt[1]",engine,2); 222 | assertCompile("pInt[1]",engine,2); 223 | 224 | 225 | } 226 | 227 | public static void assertEval(String exp,FelEngine engine,Object expected){ 228 | Object actual = engine.eval(exp); 229 | if(actual instanceof Number && expected instanceof Number){ 230 | assert NumberUtil.toDouble(actual)==NumberUtil.toDouble(expected); 231 | }else{ 232 | assert ObjectUtils.equals(expected, actual); 233 | } 234 | } 235 | public static void assertCompile(String exp,FelEngine engine,Object expected){ 236 | Expression ins = engine.compile(exp, null); 237 | Object actual = ins.eval(engine.getContext()); 238 | if(actual instanceof Number && expected instanceof Number){ 239 | assert NumberUtil.toDouble(actual)==NumberUtil.toDouble(expected); 240 | }else{ 241 | assert ObjectUtils.equals(expected, actual); 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Cond.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.FelEngine; 6 | import com.greenpineyu.fel.compile.FelMethod; 7 | import com.greenpineyu.fel.compile.SourceBuilder; 8 | import com.greenpineyu.fel.context.FelContext; 9 | import com.greenpineyu.fel.exception.ParseException; 10 | import com.greenpineyu.fel.function.StableFunction; 11 | import com.greenpineyu.fel.parser.FelNode; 12 | 13 | /** 14 | * 三元表达式操作符 15 | * 16 | * @author Administrator 17 | * 18 | */ 19 | public class Cond extends StableFunction { 20 | 21 | 22 | 23 | public Object call(FelNode node, FelContext context) { 24 | List args = ensureValid(node); 25 | //cond ? result1 : result2 26 | FelNode cond = args.get(0); 27 | FelNode result1 = args.get(1); 28 | FelNode result2 = args.get(2); 29 | Object eval = cond.eval(context); 30 | // 当cond是boolean型,并且值是true的,返回result1,否则返回result2 31 | if(eval !=null && eval instanceof Boolean){ 32 | Boolean b = (Boolean)eval; 33 | if(b.booleanValue()){ 34 | return result1.eval(context); 35 | } 36 | } 37 | return result2.eval(context); 38 | } 39 | 40 | 41 | public String getName() { 42 | return "?"; 43 | } 44 | 45 | 46 | public SourceBuilder toMethod(FelNode node, FelContext ctx) { 47 | List args = ensureValid(node); 48 | //cond ? result1 : result2 49 | FelNode cond = args.get(0); 50 | FelNode result1 = args.get(1); 51 | FelNode result2 = args.get(2); 52 | SourceBuilder source = cond.toMethod(ctx); 53 | Class class1 = source.returnType(ctx, cond); 54 | StringBuilder sb = new StringBuilder(); 55 | Class type = null; 56 | SourceBuilder r2 = result2.toMethod(ctx); 57 | if(Boolean.class.isAssignableFrom(class1)|| boolean.class.isAssignableFrom(class1)){ 58 | // FIXME 需要判断两个结果中的父类型 59 | sb.append(source.source(ctx, node)); 60 | sb.append("?"); 61 | SourceBuilder r1 = result1.toMethod(ctx); 62 | type = r1.returnType(ctx, result1); 63 | sb.append(r1.source(ctx, result1)); 64 | sb.append(":"); 65 | sb.append(r2.source(ctx, result2)); 66 | }else{ 67 | sb.append(r2.source(ctx, result2)); 68 | type = r2.returnType(ctx, result2); 69 | } 70 | 71 | return new FelMethod(type, sb.toString()); 72 | } 73 | 74 | private List ensureValid(FelNode node) { 75 | List args = node.getChildren(); 76 | if(args==null||args.size()!=3){ 77 | throw new ParseException("不合法的三元表达式"); 78 | } 79 | return args; 80 | } 81 | 82 | public static void main(String[] args) { 83 | String exp = "true?false?2:3:2"; 84 | System.out.println(!(100%3-39.0<27)); 85 | // Object a =6.7-100>39.6 ? 5==5? 4+5:6-1 : !(100%3-39.0<27) ? 8*2-199: 86 | // 100%3; 87 | // System.out.println(a); 88 | exp = "6.7-100>39.6 ? 5==5? 4+5:6-1 : !(100%3-39.0<27) ? 8*2-199: 100%3"; 89 | eval(exp); 90 | } 91 | 92 | private static void eval(String exp) { 93 | FelEngine fel = FelEngine.instance; 94 | Object result = fel.eval(exp); 95 | System.out.println(result); 96 | result = fel.compile(exp, null).eval(null); 97 | System.out.println(result); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Div.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import com.greenpineyu.fel.common.NumberUtil; 4 | 5 | public class Div extends Mul { 6 | 7 | @Override 8 | Object calc(double l, double r) { 9 | return NumberUtil.parseNumber(l / r); 10 | } 11 | 12 | @Override 13 | public String getName() { 14 | return "/"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Dot.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import com.greenpineyu.fel.Expression; 11 | import com.greenpineyu.fel.common.ArrayUtils; 12 | import com.greenpineyu.fel.common.Null; 13 | import com.greenpineyu.fel.common.ReflectUtil; 14 | import com.greenpineyu.fel.compile.FelMethod; 15 | import com.greenpineyu.fel.compile.SourceBuilder; 16 | import com.greenpineyu.fel.context.FelContext; 17 | import com.greenpineyu.fel.function.CommonFunction; 18 | import com.greenpineyu.fel.function.Function; 19 | import com.greenpineyu.fel.parser.FelNode; 20 | import com.greenpineyu.fel.security.SecurityMgr; 21 | 22 | public class Dot implements Function { 23 | 24 | private SecurityMgr securityMgr; 25 | 26 | public SecurityMgr getSecurityMgr() { 27 | return securityMgr; 28 | } 29 | 30 | public void setSecurityMgr(SecurityMgr securityMgr) { 31 | this.securityMgr = securityMgr; 32 | } 33 | 34 | static final Map, Class> PRIMITIVE_TYPES; 35 | static { 36 | PRIMITIVE_TYPES = new HashMap, Class>(); 37 | PRIMITIVE_TYPES.put(Boolean.class, Boolean.TYPE); 38 | PRIMITIVE_TYPES.put(Byte.class, Byte.TYPE); 39 | PRIMITIVE_TYPES.put(Character.class, Character.TYPE); 40 | PRIMITIVE_TYPES.put(Double.class, Double.TYPE); 41 | PRIMITIVE_TYPES.put(Float.class, Float.TYPE); 42 | PRIMITIVE_TYPES.put(Integer.class, Integer.TYPE); 43 | PRIMITIVE_TYPES.put(Long.class, Long.TYPE); 44 | PRIMITIVE_TYPES.put(Short.class, Short.TYPE); 45 | } 46 | public static final String DOT = "."; 47 | 48 | 49 | public String getName() { 50 | return DOT; 51 | } 52 | 53 | 54 | public Object call(FelNode node, FelContext context) { 55 | List children = node.getChildren(); 56 | Object left = children.get(0); 57 | if (left instanceof Expression) { 58 | Expression exp = (Expression) left; 59 | left = exp.eval(context); 60 | } 61 | FelNode right = children.get(1); 62 | FelNode exp = right; 63 | Class[] argsType = new Class[0]; 64 | Object[] args = CommonFunction.evalArgs(right, context); 65 | if (!ArrayUtils.isEmpty(args)) { 66 | argsType = new Class[args.length]; 67 | for (int i = 0; i < args.length; i++) { 68 | if (args[i] == null) { 69 | argsType[i] = Null.class; 70 | continue; 71 | } 72 | argsType[i] = args[i].getClass(); 73 | } 74 | } 75 | Method method = null; 76 | Class cls = left instanceof Class ? (Class) left : left.getClass(); 77 | 78 | String methodName = right.getText(); 79 | method = findMethod(cls, methodName, argsType); 80 | if (method == null) { 81 | String getMethod = "get"; 82 | method = findMethod(cls, getMethod, new Class[] { String.class }); 83 | args = new Object[] { exp.getText() }; 84 | } 85 | if (method != null) { 86 | return invoke(left, method, args); 87 | } 88 | return null; 89 | } 90 | 91 | private Method findMethod(Class cls, String methodName, Class[] argsType) { 92 | Method method = ReflectUtil.findMethod(cls, methodName, argsType); 93 | return getCallableMethod(method); 94 | } 95 | 96 | private Method getMethod(Class cls, String methodName, Class[] argsType) { 97 | Method method = ReflectUtil.getMethod(cls, methodName, argsType); 98 | return getCallableMethod(method); 99 | } 100 | 101 | private Method getCallableMethod(Method m) { 102 | if (m == null || securityMgr.isCallable(m)) { 103 | return m; 104 | } 105 | throw new SecurityException("安全管理器[" + securityMgr.getClass().getSimpleName() + "]禁止调用方法[" + m.toString() + "]"); 106 | } 107 | 108 | /** 109 | * 调用方法 110 | * 111 | * @param obj 112 | * @param method 113 | * @param args 114 | * @return 115 | */ 116 | public static Object invoke(Object obj, Method method, Object[] args) { 117 | try { 118 | return method.invoke(obj, args); 119 | } catch (IllegalArgumentException e) { 120 | e.printStackTrace(); 121 | } catch (IllegalAccessException e) { 122 | e.printStackTrace(); 123 | } catch (InvocationTargetException e) { 124 | e.printStackTrace(); 125 | } 126 | return null; 127 | } 128 | 129 | 130 | public FelMethod toMethod(FelNode node, FelContext context) { 131 | 132 | StringBuilder sb = new StringBuilder(); 133 | List children = node.getChildren(); 134 | FelNode l = children.get(0); 135 | SourceBuilder leftMethod = l.toMethod(context); 136 | Class cls = leftMethod.returnType(context, l); 137 | String leftSrc = leftMethod.source(context, l); 138 | if (cls.isPrimitive()) { 139 | Class wrapperClass = ReflectUtil.toWrapperClass(cls); 140 | // 如果左边返回的值的基本类型,要转成包装类型[eg:((Integer)1).doubleValue()] 141 | sb.append("((").append(wrapperClass.getSimpleName()).append(")").append(leftSrc).append(")"); 142 | } else { 143 | sb.append(leftSrc); 144 | } 145 | sb.append("."); 146 | Method method = null; 147 | FelNode rightNode = children.get(1); 148 | List params = rightNode.getChildren(); 149 | List paramMethods = new ArrayList(); 150 | Class[] paramValueTypes = null; 151 | boolean hasParam = params != null && !params.isEmpty(); 152 | String rightMethod = rightNode.getText(); 153 | String rightMethodParam = ""; 154 | if (hasParam) { 155 | // 有参数 156 | paramValueTypes = new Class[params.size()]; 157 | for (int i = 0; i < params.size(); i++) { 158 | FelNode p = params.get(i); 159 | SourceBuilder paramMethod = p.toMethod(context); 160 | paramMethods.add(paramMethod); 161 | paramValueTypes[i] = paramMethod.returnType(context, p); 162 | } 163 | // 根据参数查找方法 164 | method = findMethod(cls, rightNode.getText(), paramValueTypes); 165 | if (method != null) { 166 | Class[] paramTypes = method.getParameterTypes(); 167 | for (int i = 0; i < paramTypes.length; i++) { 168 | Class paramType = paramTypes[i]; 169 | FelNode p = params.get(i); 170 | String paramCode = getParamCode(paramType, p, context); 171 | rightMethodParam += paramCode + ","; 172 | } 173 | rightMethod = method.getName(); 174 | } 175 | } else { 176 | method = findMethod(cls, rightNode.getText(), new Class[0]); 177 | if (method == null) { 178 | // 当没有找到方法 ,直接使用get方法来获取属性 179 | method = getMethod(cls, "get", new Class[] { String.class }); 180 | if (method != null) { 181 | rightMethod = "get"; 182 | rightMethodParam = "\"" + rightNode.getText() + "\""; 183 | } 184 | } else { 185 | rightMethod = method.getName(); 186 | } 187 | } 188 | 189 | if (method != null) { 190 | } 191 | if (rightMethodParam.endsWith(",")) { 192 | rightMethodParam = rightMethodParam.substring(0, rightMethodParam.length() - 1); 193 | } 194 | rightMethod += "(" + rightMethodParam + ")"; 195 | 196 | sb.append(rightMethod); 197 | 198 | FelMethod returnMe = new FelMethod(method == null ? null : method.getReturnType(), sb.toString()); 199 | return returnMe; 200 | } 201 | 202 | /** 203 | * 获取参数代码 204 | * 205 | * @param paramType 方法声明的参数类型 206 | * @param paramValueType 参数值的类型 207 | * @param paramMethod 208 | * @return 209 | */ 210 | public static String getParamCode(Class paramType, FelNode node, FelContext ctx) { 211 | // 如果类型相等(包装类型与基本类型(int和Integer)也认为是相等 ),直接添加参数。 212 | String paramCode = ""; 213 | SourceBuilder paramMethod = node.toMethod(ctx); 214 | Class paramValueType = paramMethod.returnType(ctx, node); 215 | if (ReflectUtil.isTypeMatch(paramType, paramValueType)) { 216 | paramCode = paramMethod.source(ctx, node); 217 | } else { 218 | // 如果类型不匹配,使用强制转型 219 | String className = null; 220 | Class wrapperClass = ReflectUtil.toWrapperClass(paramType); 221 | if (wrapperClass != null) { 222 | className = wrapperClass.getName(); 223 | } else { 224 | className = paramType.getName(); 225 | } 226 | paramCode = "(" + className + ")" + paramMethod.source(ctx, node); 227 | } 228 | return paramCode; 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Equal.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.List; 5 | 6 | import com.greenpineyu.fel.common.Null; 7 | import com.greenpineyu.fel.common.NumberUtil; 8 | import com.greenpineyu.fel.common.ReflectUtil; 9 | import com.greenpineyu.fel.compile.FelMethod; 10 | import com.greenpineyu.fel.compile.SourceBuilder; 11 | import com.greenpineyu.fel.context.FelContext; 12 | import com.greenpineyu.fel.function.StableFunction; 13 | import com.greenpineyu.fel.function.TolerantFunction; 14 | import com.greenpineyu.fel.parser.FelNode; 15 | 16 | public class Equal extends StableFunction { 17 | 18 | public String getName() { 19 | return "=="; 20 | } 21 | 22 | public Object call(FelNode node, FelContext context) { 23 | List children = node.getChildren(); 24 | if (children != null && children.size() == 2) { 25 | Object left = TolerantFunction.eval(context, children.get(0)); 26 | Object right = TolerantFunction.eval(context, children.get(1)); 27 | return Boolean.valueOf(compare(left, right)); 28 | } 29 | throw new NullPointerException("传入参数数组为空或者参数个数不正确!"); 30 | } 31 | 32 | boolean compare(Object left, Object right) { 33 | return equals(left, right); 34 | } 35 | 36 | public static boolean equals(Object left, Object right) { 37 | if (left == null && right == null) { 38 | return true; 39 | } else if (left == null || right == null) { 40 | return false; 41 | } else if (left.getClass().equals(right.getClass())) { 42 | return left.equals(right); 43 | } else if (left instanceof BigDecimal || right instanceof BigDecimal) { 44 | return NumberUtil.toBigDecimal(left).compareTo( 45 | NumberUtil.toBigDecimal(right)) == 0; 46 | } else if (NumberUtil.isFloatingPointNumber(left) 47 | || NumberUtil.isFloatingPointNumber(right)) { 48 | return NumberUtil.toDouble(left) == NumberUtil.toDouble(right); 49 | } else if (left instanceof Number || right instanceof Number 50 | || left instanceof Character || right instanceof Character) { 51 | return NumberUtil.toLong(left) == NumberUtil.toLong(right); 52 | } else if (left instanceof Boolean || right instanceof Boolean) { 53 | return NumberUtil.toBoolean(left) == NumberUtil.toBoolean(right); 54 | } else if (left instanceof String || right instanceof String) { 55 | return left.toString().equals(right.toString()); 56 | } 57 | return left.equals(right); 58 | } 59 | 60 | public FelMethod toMethod(FelNode node, FelContext ctx) { 61 | String operator = this.getName(); 62 | return toMethod(node, ctx, operator); 63 | } 64 | 65 | private FelMethod toMethod(FelNode node, FelContext ctx, String operator) { 66 | StringBuilder sb = buildRelationExpr(node, ctx, operator); 67 | if(sb.length()==0){ 68 | String left = getChildCode(node, ctx,0); 69 | String right = getChildCode(node, ctx, 1); 70 | String toMethod = toMethod(left, right); 71 | sb.append(toMethod); 72 | } 73 | return new FelMethod(Boolean.class, sb.toString()); 74 | } 75 | 76 | String toMethod(String left, String right) { 77 | return "ObjectUtils.equals(" + left + "," + right + ")"; 78 | } 79 | 80 | public static String getChildCode(FelNode node, FelContext ctx,int index) { 81 | List children = node.getChildren(); 82 | FelNode child = children.get(index); 83 | SourceBuilder leftM = child.toMethod(ctx); 84 | String code = "(" + leftM.source(ctx, child) + ")"; 85 | return code; 86 | } 87 | 88 | public static StringBuilder buildRelationExpr(FelNode node, FelContext ctx, 89 | String operator) { 90 | List child = node.getChildren(); 91 | FelNode leftNode = child.get(0); 92 | FelNode rightNode = child.get(1); 93 | SourceBuilder leftM = leftNode.toMethod(ctx); 94 | SourceBuilder rightM = rightNode.toMethod(ctx); 95 | Class leftType = leftM.returnType(ctx, leftNode); 96 | Class rightType = rightM.returnType(ctx, rightNode); 97 | String left = "(" + leftM.source(ctx, leftNode) + ")"; 98 | String right = "(" +rightM.source(ctx, rightNode) + ")"; 99 | 100 | StringBuilder sb = new StringBuilder(); 101 | // 只要有一个是数值型,就将另一个也转成值型。 102 | if(ReflectUtil.isPrimitiveNumber(leftType)&&ReflectUtil.isPrimitiveNumber(leftType)){ 103 | //如果左右都是基本数值类型,直接==运算就行了。 104 | sb.append(left).append(operator).append(right); 105 | }else if (Number.class.isAssignableFrom(leftType)) { 106 | sb.append(left); 107 | sb.append(operator); 108 | appendNumber(rightType, right, sb); 109 | } else if (Number.class.isAssignableFrom(rightType)) { 110 | appendNumber(leftType, left, sb); 111 | sb.append(operator); 112 | sb.append(right); 113 | } else if (Boolean.class.isAssignableFrom(leftType)) { 114 | sb.append(left); 115 | sb.append(operator); 116 | appendBoolean(rightType, right, sb); 117 | } else if (Boolean.class.isAssignableFrom(rightType)) { 118 | appendBoolean(leftType, left, sb); 119 | sb.append(operator); 120 | sb.append(right); 121 | } else if (String.class.isAssignableFrom(leftType)) { 122 | sb.append("StringUtils.equals(" + left + ",ObjectUtils.toString(" 123 | + right + "))"); 124 | } else if (String.class.isAssignableFrom(rightType)) { 125 | sb.append("StringUtils.equals(ObjectUtils.toString(" + right + ")," 126 | + left + ")"); 127 | } 128 | return sb; 129 | } 130 | 131 | static public void appendNumber(Class type, String src, StringBuilder sb) { 132 | if (Number.class.isAssignableFrom(type)) { 133 | // 当type是数值型时,使用toString 134 | sb.append(src); 135 | } else if (String.class.isAssignableFrom(type)) { 136 | // 当type是字符型时,转成double型 137 | sb.append("NumberUtil.toDouble(" + src + ")"); 138 | } else if(Null.class.isAssignableFrom(type)){ 139 | sb.append("Double.MIN_VALUE"); 140 | }else{ 141 | // 当type是Object时,this.equals 142 | // FIXME 143 | } 144 | } 145 | 146 | static public void appendBoolean(Class type, String src, StringBuilder sb) { 147 | if (Boolean.class.isAssignableFrom(type)) { 148 | // 当type是Boolean时,使用toString 149 | sb.append(src); 150 | } else if (String.class.isAssignableFrom(type)) { 151 | // 当type是字符型时,转成double型 152 | sb.append("Boolean.valueOf(" + src + ")"); 153 | } else { 154 | // 当type是Object时,this.equals 155 | // FIXME 156 | } 157 | } 158 | 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/GreaterThan.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import com.greenpineyu.fel.common.NumberUtil; 4 | 5 | public class GreaterThan extends LessThen { 6 | 7 | 8 | 9 | @Override 10 | public String getName() { 11 | return ">"; 12 | } 13 | 14 | /** 15 | * 大于 > 16 | * 17 | * @param left 18 | * @param right 19 | * @return 20 | */ 21 | @SuppressWarnings({ 22 | "unchecked", "rawtypes" }) 23 | @Override 24 | public boolean compare(Object left, Object right) { 25 | if(left == right){ 26 | return false; 27 | } 28 | 29 | if(left == null || right == null){ 30 | return false; 31 | } 32 | 33 | if(left instanceof Number && right instanceof Number){ 34 | return NumberUtil.toDouble((Number)left)>NumberUtil.toDouble((Number)right); 35 | } 36 | 37 | if (left instanceof Comparable && right instanceof Comparable) { 38 | return ((Comparable)left).compareTo(right)>0; 39 | } 40 | // TODO 是返回false还是抛出异常? 41 | return false; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/GreaterThenEqual.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import com.greenpineyu.fel.common.NumberUtil; 4 | 5 | public class GreaterThenEqual extends LessThen { 6 | 7 | @Override 8 | public String getName() { 9 | return ">="; 10 | } 11 | 12 | /** 13 | * 大于等于 14 | * @see com.greenpineyu.fel.function.operator.RelationalOperator#compare(java.lang.Object, 15 | * java.lang.Object) 16 | */ 17 | @SuppressWarnings({ 18 | "rawtypes", "unchecked" }) 19 | @Override 20 | public boolean compare(Object left, Object right) { 21 | if(left == right){ 22 | return true; 23 | } 24 | 25 | if(left == null || right == null){ 26 | return false; 27 | } 28 | 29 | if(left instanceof Number && right instanceof Number){ 30 | return NumberUtil.toDouble((Number)left)>=NumberUtil.toDouble((Number)right); 31 | } 32 | 33 | if(left instanceof Comparable && right instanceof Comparable){ 34 | return ((Comparable)left).compareTo(right)>=0; 35 | } 36 | // TODO 是返回false还是抛出异常? 37 | return false; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/LessThen.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import static com.greenpineyu.fel.function.operator.Equal.appendNumber; 4 | 5 | import java.util.List; 6 | 7 | import com.greenpineyu.fel.FelEngine; 8 | import com.greenpineyu.fel.common.NumberUtil; 9 | import com.greenpineyu.fel.compile.FelMethod; 10 | import com.greenpineyu.fel.compile.SourceBuilder; 11 | import com.greenpineyu.fel.context.FelContext; 12 | import com.greenpineyu.fel.function.Function; 13 | import com.greenpineyu.fel.function.TolerantFunction; 14 | import com.greenpineyu.fel.parser.FelNode; 15 | import com.greenpineyu.fel.parser.Stable; 16 | 17 | /** 18 | * 包名 .script.function.operator 类名 RelationalOperator.java 创建日期 Oct 26, 19 | * 20103:04:25 PM 作者 版权 20 | */ 21 | public class LessThen implements Stable,Function { 22 | 23 | // private final String operator; 24 | 25 | // private RelationalOperator(String operator) { 26 | // this.operator = operator; 27 | // } 28 | // 29 | // public static final String LESSTHEN_STR = "<"; 30 | // public static final String GREATERTHAN_STR = ">"; 31 | // public static final String LESSTHENOREQUALS_STR = "<="; 32 | // public static final String GREATERTHANOREQUALS_STR = ">="; 33 | // 34 | // public static final RelationalOperator LESSTHEN; 35 | // public static final RelationalOperator GREATERTHAN; 36 | // public static final RelationalOperator LESSTHENOREQUALS; 37 | // public static final RelationalOperator GREATERTHANOREQUALS; 38 | 39 | // static { 40 | // LESSTHEN = new RelationalOperator(LESSTHEN_STR); 41 | // GREATERTHAN = new RelationalOperator(GREATERTHAN_STR); 42 | // LESSTHENOREQUALS = new RelationalOperator(LESSTHENOREQUALS_STR); 43 | // GREATERTHANOREQUALS = new RelationalOperator(GREATERTHANOREQUALS_STR); 44 | // } 45 | 46 | 47 | public Object call(FelNode node, FelContext context) { 48 | List children = node.getChildren(); 49 | if(children!=null && children.size()==2){ 50 | Object left = TolerantFunction.eval(context,children.get(0)); 51 | Object right = TolerantFunction.eval(context,children.get(1)); 52 | return compare(left, right); 53 | } 54 | throw new NullPointerException("传入参数数组为空或者参数个数不正确!"); 55 | } 56 | 57 | 58 | // 59 | // public Object call(Object[] arguments) { 60 | // boolean result = false; 61 | // if(arguments != null && arguments.length == 2){ 62 | // Object left = arguments[0]; 63 | // Object right = arguments[1]; 64 | // if(this == LESSTHEN){ 65 | // result = lessThan(left, right); 66 | // }else if(this == GREATERTHAN){ 67 | // result = greaterThan(left, right); 68 | // }else if(this == LESSTHENOREQUALS){ 69 | // result = lessThanOrEqual(left, right); 70 | // }else if(this == GREATERTHANOREQUALS){ 71 | // result = greaterThanOrEqual(left, right); 72 | // } 73 | // return new Boolean(result); 74 | // } 75 | // throw new NullPointerException("传入参数数组为空或者参数个数不正确!"); 76 | // } 77 | 78 | /** 79 | * 小于 80 | * 81 | * @param left 82 | * @param right 83 | * @return 84 | */ 85 | @SuppressWarnings({ 86 | "rawtypes", "unchecked" }) 87 | public boolean compare(Object left, Object right) { 88 | if(left == right){ 89 | return false; 90 | } 91 | 92 | if(left == null || right == null){ 93 | return false; 94 | } 95 | 96 | if(left instanceof Number && right instanceof Number){ 97 | return NumberUtil.toDouble((Number)left) 0; 157 | } 158 | }else{ 159 | return left == null?true:false; 160 | } 161 | return false; 162 | } 163 | */ 164 | 165 | public static StringBuilder buildRelationExpr(FelNode node, FelContext ctx, 166 | String operator) { 167 | List child = node.getChildren(); 168 | FelNode leftNode = child.get(0); 169 | FelNode rightNode = child.get(1); 170 | SourceBuilder leftM = leftNode.toMethod(ctx); 171 | SourceBuilder rightM = rightNode.toMethod(ctx); 172 | Class leftType = leftM.returnType(ctx, leftNode); 173 | Class rightType = rightM.returnType(ctx, rightNode); 174 | String left = "(" + leftM.source(ctx, leftNode) + ")"; 175 | String right = "(" +rightM.source(ctx, rightNode) + ")"; 176 | 177 | StringBuilder sb = new StringBuilder(); 178 | // 只要有一个是数值型,就将另一个也转成值型。 179 | if (Number.class.isAssignableFrom(leftType)) { 180 | sb.append(left); 181 | sb.append(operator); 182 | appendNumber(rightType, right, sb); 183 | } else if (Number.class.isAssignableFrom(rightType)) { 184 | appendNumber(leftType, left, sb); 185 | sb.append(operator); 186 | sb.append(right); 187 | } else if (Comparable.class.isAssignableFrom(leftType)&&Comparable.class.isAssignableFrom(rightType)) { 188 | sb.append("NumberUtil.compare(" + left + ","+ right + ")"+operator+"0"); 189 | } else { 190 | throw new UnsupportedOperationException("类型" + leftType + "与类型" + rightType + "不支持比较操作。"); 191 | } 192 | return sb; 193 | } 194 | 195 | /** 196 | * 小于等于 <= 197 | * 198 | * @param left 199 | * @param right 200 | * @return 201 | */ 202 | /* private boolean lessThanOrEqual(Object left, Object right) { 203 | return EqualsOperator.equals(left, right) || lessThan(left, right); 204 | }*/ 205 | 206 | /** 207 | * 大于等于 >= 208 | * 209 | * @param left 210 | * @param right 211 | * @return 212 | */ 213 | /* private boolean greaterThanOrEqual(Object left, Object right) { 214 | return EqualsOperator.equals(left, right) || greaterThan(left, right); 215 | }*/ 216 | 217 | public String getName() { 218 | return "<"; 219 | } 220 | 221 | 222 | public FelMethod toMethod(FelNode node, FelContext ctx) { 223 | StringBuilder code = buildRelationExpr(node, ctx, this.getName()); 224 | return new FelMethod(Boolean.class, code.toString()); 225 | } 226 | 227 | public boolean stable() { 228 | return true; 229 | } 230 | 231 | public static void main(String[] args) { 232 | FelEngine engine = FelEngine.instance; 233 | System.out.println(engine.eval("6>=5")); 234 | 235 | } 236 | 237 | 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/LessThenEqual.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import com.greenpineyu.fel.common.NumberUtil; 4 | 5 | public class LessThenEqual extends LessThen { 6 | 7 | @Override 8 | public String getName() { 9 | return "<="; 10 | } 11 | 12 | /** 13 | * 小于等于 14 | * @see com.greenpineyu.fel.function.operator.RelationalOperator#compare(java.lang.Object, 15 | * java.lang.Object) 16 | */ 17 | @SuppressWarnings({ 18 | "rawtypes", "unchecked" }) 19 | @Override 20 | public boolean compare(Object left, Object right) { 21 | if(left == right){ 22 | return true; 23 | } 24 | 25 | if(left == null || right == null){ 26 | return false; 27 | } 28 | 29 | if(left instanceof Number && right instanceof Number){ 30 | return NumberUtil.toDouble((Number)left)<=NumberUtil.toDouble((Number)right); 31 | } 32 | 33 | if(left instanceof Comparable && right instanceof Comparable){ 34 | return ((Comparable)left).compareTo(right)<=0; 35 | } 36 | // TODO 是返回false还是抛出异常? 37 | return false; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Mod.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import com.greenpineyu.fel.common.NumberUtil; 4 | 5 | public class Mod extends Mul { 6 | 7 | @Override 8 | Object calc(double l, double r) { 9 | return NumberUtil.parseNumber(l % r); 10 | } 11 | 12 | @Override 13 | public String getName() { 14 | return "%"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Mul.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.common.NumberUtil; 6 | import com.greenpineyu.fel.common.ReflectUtil; 7 | import com.greenpineyu.fel.compile.FelMethod; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.exception.CompileException; 11 | import com.greenpineyu.fel.exception.EvalException; 12 | import com.greenpineyu.fel.function.StableFunction; 13 | import com.greenpineyu.fel.parser.FelNode; 14 | 15 | /** 16 | * 包名 .script.function.operator 17 | * 类名 MultiplicativeOperator.java 18 | * 创建日期 Oct 26, 20102:47:15 PM 19 | * 作者 20 | * 版权 21 | */ 22 | public class Mul extends StableFunction{ 23 | 24 | // private String operator; 25 | // 26 | // private MultiplicativeOperator(String operator) { 27 | // this.operator = operator; 28 | // } 29 | 30 | 31 | 32 | // public static final String MUL_STR = "*"; 33 | // 34 | // public static final String DIV_STR = "/"; 35 | // 36 | // public static final String MOD_STR = "%"; 37 | // 38 | // public static final MultiplicativeOperator MUL; 39 | // 40 | // public static final MultiplicativeOperator DIV; 41 | // 42 | // public static final MultiplicativeOperator MOD; 43 | 44 | // static { 45 | // MUL = new MultiplicativeOperator(MUL_STR); 46 | // DIV = new MultiplicativeOperator(DIV_STR); 47 | // MOD = new MultiplicativeOperator(MOD_STR); 48 | // } 49 | 50 | /*public Object call(Object[] arguments) { 51 | if(arguments != null && arguments.length == 2){ 52 | Object left = arguments[0]; 53 | Object right = arguments[1]; 54 | if(this == MUL){ 55 | return multiply(left, right); 56 | }else if(this == DIV){ 57 | return divide(left, right); 58 | }else if(this == MOD){ 59 | return mod(left, right); 60 | } 61 | } 62 | throw new NullPointerException("传入参数数组为空或者参数个数不正确!"); 63 | }*/ 64 | 65 | 66 | public Object call(FelNode node, FelContext context) { 67 | List children = node.getChildren(); 68 | if (children.size() == 2) { 69 | FelNode left = children.get(0); 70 | Object leftValue = left.eval(context); 71 | FelNode right = children.get(1); 72 | Object rightValue = right.eval(context); 73 | if (leftValue instanceof Number && rightValue instanceof Number) { 74 | double l = NumberUtil.toDouble(leftValue); 75 | double r = NumberUtil.toDouble(rightValue); 76 | // Object calc = null; 77 | return calc(l, r); 78 | // throw new EvalException("执行"+this.operator+"出错,未知的操作符"); 79 | } 80 | throw new EvalException("执行"+this.getName()+"出错,参数必须是数值型"); 81 | } 82 | throw new EvalException("执行"+this.getName()+"出错,参数数量必须为2。"); 83 | } 84 | 85 | Object calc(double l, double r) { 86 | return NumberUtil.parseNumber(l * r); 87 | } 88 | 89 | /** 90 | * 乘法 91 | * @param left 92 | * @param right 93 | * @return 94 | */ 95 | /*public static Object multiply(Object left, Object right) { 96 | if (left == null || right == null) { 97 | throw new NullPointerException("调用multiply()方法出错!,原因:当前参数为空"); 98 | } 99 | try { 100 | if (left instanceof Object[]){ 101 | left = NumberUtil.calArray(left); 102 | } 103 | if (right instanceof Object[]){ 104 | right = NumberUtil.calArray(right); 105 | } 106 | if (left.equals("∞") || right.equals("∞")) 107 | return "∞"; 108 | 109 | if (NumberUtil.isFloatingPointNumber(left) || NumberUtil.isFloatingPointNumber(right)) { 110 | double l = NumberUtil.toDouble(left); 111 | double r = NumberUtil.toDouble(right); 112 | return new Double(l * r); 113 | } 114 | if (left instanceof BigInteger && right instanceof BigInteger) { 115 | BigInteger l = NumberUtil.toBigInteger(left); 116 | BigInteger r = NumberUtil.toBigInteger(right); 117 | return l.multiply(r); 118 | } 119 | if (left instanceof BigDecimal || right instanceof BigDecimal) { 120 | BigDecimal l = NumberUtil.toBigDecimal(left); 121 | BigDecimal r = NumberUtil.toBigDecimal(right); 122 | return l.multiply(r); 123 | } 124 | BigInteger l = NumberUtil.toBigInteger(left); 125 | BigInteger r = NumberUtil.toBigInteger(right); 126 | BigInteger result = l.multiply(r); 127 | return NumberUtil.narrowBigInteger(left, right, result); 128 | } catch (Exception e) { 129 | throw new NumberFormatException("调用multiply()方法出错!,原因:解析参数对象出错!"); 130 | } 131 | }*/ 132 | 133 | /** 134 | * 除法 135 | * @param left 136 | * @param right 137 | * @return 138 | */ 139 | /*public static Object divide(Object left, Object right) { 140 | if (left == null || right == null) { 141 | throw new NullPointerException("调用divide()方法出错!,原因:当前参数为空"); 142 | } 143 | try { 144 | if (left instanceof Object[]){ 145 | left = NumberUtil.calArray(left); 146 | } 147 | if (right instanceof Object[]){ 148 | right = NumberUtil.calArray(right); 149 | } 150 | if (left.equals("∞") || right.equals("∞")) { 151 | return "∞"; 152 | } 153 | 154 | if (NumberUtil.isFloatingPointNumber(left) || NumberUtil.isFloatingPointNumber(right)) { 155 | double l = NumberUtil.toDouble(left); 156 | double r = NumberUtil.toDouble(right); 157 | if (r == 0.0) { 158 | // throw new ArithmeticException("/"); 159 | return "∞"; // 被除数是零时返回无穷大 160 | } 161 | return new Double(l / r); 162 | } 163 | if (left instanceof Integer && right instanceof Integer || left instanceof Long && right instanceof Long) { 164 | Number r = (Number) right; 165 | if (r.intValue() == 0) { 166 | return "∞"; 167 | } 168 | Number l = (Number) left; 169 | return new Double(l.doubleValue() / r.intValue()); 170 | } 171 | if (left instanceof BigInteger && right instanceof BigInteger) { 172 | BigInteger l = NumberUtil.toBigInteger(left); 173 | BigInteger r = NumberUtil.toBigInteger(right); 174 | return l.divide(r); 175 | } 176 | //默认使用浮点运算,使用整型运算会导致略去小数位的问题 177 | // if (left instanceof BigDecimal || right instanceof BigDecimal) { 178 | BigDecimal l = NumberUtil.toBigDecimal(left); 179 | BigDecimal r = NumberUtil.toBigDecimal(right); 180 | BigDecimal d = l.divide(r,8,BigDecimal.ROUND_DOWN); 181 | return d; 182 | // } 183 | // BigInteger l = NumberUtil.toBigInteger(left); 184 | // BigInteger r = NumberUtil.toBigInteger(right); 185 | 186 | // BigInteger result = l.divide(r); 187 | // return NumberUtil.narrowBigInteger(left, right, result); 188 | } catch (Exception e) { 189 | throw new EvalException(left + "/" + right + "运算出错", e); 190 | } 191 | }*/ 192 | 193 | /** 194 | * 除于 195 | * @param left 196 | * @param right 197 | * @return 198 | */ 199 | /*private Object mod(Object left, Object right) { 200 | if (left == null || right == null) { 201 | throw new NullPointerException("调用mod()方法出错!,原因:当前参数为空"); 202 | } 203 | try { 204 | if (left instanceof Object[]){ 205 | left = NumberUtil.calArray(left); 206 | } 207 | if (right instanceof Object[]){ 208 | right = NumberUtil.calArray(right); 209 | } 210 | if (left.equals("∞") || right.equals("∞")) 211 | return "∞"; 212 | 213 | if (NumberUtil.isFloatingPointNumber(left) || NumberUtil.isFloatingPointNumber(right)) { 214 | double l = NumberUtil.toDouble(left); 215 | double r = NumberUtil.toDouble(right); 216 | if (r == 0.0) { 217 | throw new ArithmeticException("%"); 218 | } 219 | return new Double(l % r); 220 | } 221 | if (left instanceof BigInteger && right instanceof BigInteger) { 222 | BigInteger l = NumberUtil.toBigInteger(left); 223 | BigInteger r = NumberUtil.toBigInteger(right); 224 | return l.mod(r); 225 | } 226 | if (left instanceof BigDecimal || right instanceof BigDecimal) { 227 | BigDecimal l = NumberUtil.toBigDecimal(left); 228 | BigDecimal r = NumberUtil.toBigDecimal(right); 229 | BigDecimal remainder = l.subtract(l.divide(r,BigDecimal.ROUND_DOWN).multiply(r)); 230 | return remainder; 231 | } 232 | BigInteger l = NumberUtil.toBigInteger(left); 233 | BigInteger r = NumberUtil.toBigInteger(right); 234 | BigInteger result = l.mod(r); 235 | return NumberUtil.narrowBigInteger(left, right, result); 236 | } catch (Exception e) { 237 | throw new NumberFormatException("调用mod()方法出错!,原因:解析参数对象出错!"); 238 | } 239 | }*/ 240 | 241 | public String getName() { 242 | return "*"; 243 | } 244 | 245 | public FelMethod toMethod(FelNode node, FelContext ctx) { 246 | String code = ""; 247 | FelNode left = node.getChildren().get(0); 248 | FelNode right = node.getChildren().get(1); 249 | SourceBuilder lm = left.toMethod(ctx); 250 | Class leftType = lm.returnType(ctx, left); 251 | 252 | SourceBuilder rm = right.toMethod(ctx); 253 | Class rightType = lm.returnType(ctx, right); 254 | Class type = null; 255 | if(ReflectUtil.isPrimitiveOrWrapNumber(leftType) 256 | &&ReflectUtil.isPrimitiveOrWrapNumber(rightType)){ 257 | type = NumberUtil.arithmeticClass(leftType, rightType); 258 | }else{ 259 | throw new CompileException("不支持的类型["+ReflectUtil.getClassName(leftType) 260 | +"、"+ReflectUtil.getClassName(rightType)+"]。["+this.getName()+"]运算只支持数值类型"); 261 | } 262 | code = "("+lm.source(ctx, left)+")"+this.getName()+"("+rm.source(ctx, right)+")"; 263 | FelMethod m = new FelMethod(type, code); 264 | return m; 265 | } 266 | 267 | public boolean stable() { 268 | return true; 269 | } 270 | 271 | 272 | } 273 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/NotEqual.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | public class NotEqual extends Equal { 4 | 5 | @Override 6 | boolean compare(Object left, Object right) { 7 | return equals(left, right)==false; 8 | } 9 | 10 | @Override 11 | String toMethod(String left, String right) { 12 | return "ObjectUtils.notEqual(" + left + "," + right + ")"; 13 | } 14 | 15 | @Override 16 | public String getName() { 17 | return "!="; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/NotOper.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.FelEngine; 6 | import com.greenpineyu.fel.compile.SourceBuilder; 7 | import com.greenpineyu.fel.context.FelContext; 8 | import com.greenpineyu.fel.function.StableFunction; 9 | import com.greenpineyu.fel.parser.FelNode; 10 | 11 | /** 12 | * 取反操作符 13 | * 14 | */ 15 | public class NotOper extends StableFunction { 16 | 17 | 18 | 19 | public Object call(FelNode node, FelContext context) { 20 | List children = node.getChildren(); 21 | Object eval = children.get(0).eval(context); 22 | if(eval!=null && eval instanceof Boolean){ 23 | return !(Boolean)eval; 24 | } 25 | return null; 26 | } 27 | 28 | 29 | public String getName() { 30 | return "!"; 31 | } 32 | 33 | 34 | public SourceBuilder toMethod(FelNode node, FelContext ctx) { 35 | return new SourceBuilder() { 36 | 37 | 38 | public String source(FelContext ctx, FelNode node) { 39 | List children = node.getChildren(); 40 | FelNode child = children.get(0); 41 | String src = ""; 42 | SourceBuilder builder = child.toMethod(ctx); 43 | Class returnType = builder.returnType(ctx, child); 44 | if(boolean.class.isAssignableFrom(returnType)||Boolean.class.isAssignableFrom(returnType)){ 45 | src = "!("+builder.source(ctx, child)+")"; 46 | }else{ 47 | // FIXME 抛出编译异常 48 | } 49 | return src; 50 | } 51 | 52 | 53 | public Class returnType(FelContext ctx, FelNode node) { 54 | return Boolean.class; 55 | } 56 | }; 57 | } 58 | 59 | public static void main(String[] args) { 60 | FelEngine fel = FelEngine.instance; 61 | FelContext ctx = fel.getContext(); 62 | ctx.set("b", false); 63 | Object r = fel.compile("!b",ctx).eval(ctx); 64 | System.out.println(r); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Or.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.context.FelContext; 6 | import com.greenpineyu.fel.parser.FelNode; 7 | 8 | public class Or extends And { 9 | 10 | /** 11 | * 求逻辑或(||) 12 | * @see com.greenpineyu.fel.function.operator.And#logic(com.greenpineyu.fel.context.FelContext, java.util.List) 13 | */ 14 | Boolean logic(FelContext context, List children) { 15 | Boolean leftValue = toBoolean(context, children.get(0)); 16 | if (leftValue.booleanValue()) { 17 | return leftValue; 18 | } 19 | return toBoolean(context, children.get(1)); 20 | } 21 | 22 | @Override 23 | public String getName() { 24 | return "||"; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/function/operator/Sub.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.function.operator; 2 | 3 | import java.util.List; 4 | 5 | import com.greenpineyu.fel.common.NumberUtil; 6 | import com.greenpineyu.fel.common.ReflectUtil; 7 | import com.greenpineyu.fel.compile.FelMethod; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.exception.CompileException; 11 | import com.greenpineyu.fel.exception.EvalException; 12 | import com.greenpineyu.fel.function.StableFunction; 13 | import com.greenpineyu.fel.parser.FelNode; 14 | 15 | public class Sub extends StableFunction { 16 | 17 | 18 | private void appendArg(StringBuilder sb, SourceBuilder argMethod,FelContext ctx,FelNode node) { 19 | Class t = argMethod.returnType(ctx, node); 20 | sb.append("("); 21 | if (ReflectUtil.isPrimitiveOrWrapNumber(t)) { 22 | // 数值型和字符型时,直接添加 23 | sb.append(argMethod.source(ctx, node)); 24 | } else if (CharSequence.class.isAssignableFrom(t)) { 25 | // FIXME 处理1-"1"的 26 | } 27 | sb.append(")"); 28 | } 29 | 30 | public FelMethod toMethod(FelNode node, FelContext ctx) { 31 | List children = node.getChildren(); 32 | StringBuilder sb = new StringBuilder(); 33 | Class type = null; 34 | if (children.size() == 2) { 35 | //left 36 | FelNode left = children.get(0); 37 | SourceBuilder lm = left.toMethod(ctx); 38 | Class leftType = lm.returnType(ctx, left); 39 | appendArg(sb, lm,ctx,left); 40 | 41 | //right 42 | FelNode right = children.get(1); 43 | SourceBuilder rm = right.toMethod(ctx); 44 | Class rightType = rm.returnType(ctx, right); 45 | sb.append("-"); 46 | appendArg(sb, rm,ctx,right); 47 | 48 | //returnType 49 | if(ReflectUtil.isPrimitiveOrWrapNumber(leftType) 50 | &&ReflectUtil.isPrimitiveOrWrapNumber(rightType)){ 51 | type = NumberUtil.arithmeticClass(leftType, rightType); 52 | }else{ 53 | throw new CompileException("不支持的类型["+ReflectUtil.getClassName(leftType) 54 | +"、"+ReflectUtil.getClassName(rightType)+"]。减[-]运算只支持数值类型"); 55 | } 56 | } else if (children.size() == 1) { 57 | FelNode right = children.get(0); 58 | SourceBuilder rm = right.toMethod(ctx); 59 | Class rightType = rm.returnType(ctx, right); 60 | sb.append("-"); 61 | appendArg(sb, rm,ctx,right); 62 | if(ReflectUtil.isPrimitiveOrWrapNumber(rightType)){ 63 | type = rightType; 64 | } 65 | } 66 | // sb.append("-"); 67 | // SourceBuilder rm = right.toMethod(ctx); 68 | // appendArg(sb, rm,ctx,right); 69 | FelMethod m = new FelMethod(type, sb.toString()); 70 | return m; 71 | } 72 | 73 | public String getName() { 74 | return "-"; 75 | } 76 | 77 | public Object call(FelNode node, FelContext context) { 78 | List children = node.getChildren(); 79 | if (children.size() == 2) { 80 | FelNode left = children.get(0); 81 | Object leftValue = left.eval(context); 82 | FelNode right = children.get(1); 83 | Object rightValue = right.eval(context); 84 | if (leftValue instanceof Number && rightValue instanceof Number) { 85 | double l = NumberUtil.toDouble(leftValue); 86 | double r = NumberUtil.toDouble(rightValue); 87 | return NumberUtil.parseNumber(l - r); 88 | // if (NumberUtil.isFloatingPoint(left) 89 | // || NumberUtil.isFloatingPoint(right)) { 90 | // } 91 | // return NumberUtil.parseNumber(((Number) leftValue).longValue() 92 | // - ((Number) rightValue).longValue()); 93 | } 94 | throw new EvalException("执行减法出错,参数必须是数值型"); 95 | } 96 | if (children.size() == 1) { 97 | FelNode right = children.get(0); 98 | Object rightValue = right.eval(context); 99 | if (rightValue instanceof Number) { 100 | if (NumberUtil.isFloatingPoint(rightValue)) { 101 | return NumberUtil.toDouble(rightValue) * -1; 102 | } 103 | return NumberUtil.parseNumber(((Number) rightValue).longValue() * -1); 104 | } 105 | throw new EvalException("执行减法出错,参数必须是数值型"); 106 | } 107 | throw new EvalException("执行减法出错,参数长度必须是1或2"); 108 | } 109 | 110 | public static void main(String[] args) { 111 | int a = -(1); 112 | System.out.println(a); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/interpreter/ConstInterpreter.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.interpreter; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | public class ConstInterpreter implements Interpreter { 7 | 8 | private Object value; 9 | 10 | public ConstInterpreter(FelContext context, FelNode node) { 11 | this.value = node.eval(context); 12 | } 13 | 14 | public Object interpret(FelContext context, FelNode node) { 15 | return value; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/interpreter/Interpreter.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.interpreter; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | /** 7 | * 解析器,用于解析AstNode的值 8 | * @author yqs 9 | * 10 | */ 11 | public interface Interpreter { 12 | 13 | /** 14 | * @param context 15 | * @return 16 | */ 17 | Object interpret(FelContext context, FelNode node); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/interpreter/ProxyInterpreter.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.interpreter; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | /** 7 | * 代理解释器,用于保存节点 8 | * @author yuqingsong 9 | * 10 | */ 11 | public class ProxyInterpreter implements Interpreter{ 12 | 13 | private Interpreter inte; 14 | 15 | private FelNode node; 16 | public ProxyInterpreter(Interpreter inte,FelNode node){ 17 | this.inte = inte; 18 | this.node = node; 19 | } 20 | public Object interpret(FelContext context, FelNode node) { 21 | return inte.interpret(context, this.node); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/optimizer/ConstExpOpti.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.optimizer; 2 | 3 | import com.greenpineyu.fel.common.Null; 4 | import com.greenpineyu.fel.common.ReflectUtil; 5 | import com.greenpineyu.fel.compile.SourceBuilder; 6 | import com.greenpineyu.fel.compile.VarBuffer; 7 | import com.greenpineyu.fel.context.FelContext; 8 | import com.greenpineyu.fel.parser.ConstNode; 9 | import com.greenpineyu.fel.parser.FelNode; 10 | 11 | /** 12 | * 当表达式是常量表达式,对表达式进行优化。 13 | * 14 | * @author yuqingsong 15 | * 16 | */ 17 | public class ConstExpOpti implements Optimizer { 18 | 19 | 20 | public FelNode call(FelContext ctx, FelNode node) { 21 | if (node instanceof ConstNode) { 22 | final Object value = node.eval(ctx); 23 | 24 | // 重新构建常量节点的java源码 25 | node.setSourcebuilder(new SourceBuilder() { 26 | 27 | 28 | public String source(FelContext ctx, FelNode node) { 29 | // Class type = returnType(ctx, node); 30 | return VarBuffer.push(value, Object.class); 31 | } 32 | 33 | 34 | public Class returnType(FelContext ctx, FelNode node) { 35 | if (value != null) { 36 | Class cls = value.getClass(); 37 | if (cls.isPrimitive()) { 38 | return ReflectUtil.toWrapperClass(cls); 39 | } 40 | return cls; 41 | } 42 | return Null.class; 43 | } 44 | }); 45 | } 46 | return node; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/optimizer/ConstOpti.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.optimizer; 2 | 3 | import java.util.List; 4 | 5 | import org.antlr.runtime.CommonToken; 6 | import org.antlr.runtime.Token; 7 | 8 | import com.greenpineyu.fel.context.FelContext; 9 | import com.greenpineyu.fel.function.Function; 10 | import com.greenpineyu.fel.function.operator.And; 11 | import com.greenpineyu.fel.function.operator.Or; 12 | import com.greenpineyu.fel.parser.ConstNode; 13 | import com.greenpineyu.fel.parser.FelNode; 14 | import com.greenpineyu.fel.parser.FunNode; 15 | 16 | /** 17 | * 常量节点优化,优化表达式中的常量部分。 18 | * 表达式:"1+2+var",当var是变量时,可以优化成"3+var";当var是常量,其值为3时,可以优化成"6" 19 | * 20 | * @author yuqingsong 21 | * 22 | */ 23 | public class ConstOpti implements Optimizer { 24 | 25 | 26 | 27 | public FelNode call(FelContext ctx, FelNode node) { 28 | if(node.stable()){ 29 | Object value = node.getInterpreter().interpret(ctx, node); 30 | return newConstNode(node, value); 31 | }else{ 32 | List children = node.getChildren(); 33 | if (children != null) { 34 | // 是否进行过短路优化 35 | boolean isLogicOptimized = false; 36 | if (node instanceof FunNode) { 37 | FunNode n = (FunNode) node; 38 | Function fun = n.getFun(); 39 | if (fun instanceof And) { 40 | List args = node.getChildren(); 41 | FelNode left = args.get(0); 42 | FelNode right = args.get(1); 43 | boolean isOr = fun instanceof Or; 44 | // 短路的判断值,or使用True来判断,and使用false来判断 45 | Boolean result = isOr; 46 | // if (isOr) { 47 | FelNode constNode = toShortCutConst(node, ctx, left, 48 | result); 49 | if (constNode != null) { 50 | return constNode; 51 | } 52 | constNode = toShortCutConst(node, ctx, right, result); 53 | if (constNode != null) { 54 | return constNode; 55 | } 56 | // else if (right.stable()) { 57 | // Object rightValue = node.getInterpreter() 58 | // .interpret(ctx, right); 59 | // if (result.equals(right)) { 60 | // isLogicOptimized = true; 61 | // return newConstNode(node, rightValue); 62 | // } 63 | // } 64 | // }else{ 65 | // if(left.stable()){ 66 | // Object leftValue = 67 | // node.getInterpreter().interpret(ctx, 68 | // left); 69 | // if (Boolean.FALSE.equals(leftValue)) { 70 | // children.remove(1); 71 | // children.set(0, newConstNode(left, leftValue)); 72 | // } 73 | // }else if(right.stable()){ 74 | // Object rightValue = 75 | // node.getInterpreter().interpret(ctx, 76 | // right); 77 | // if(Boolean.FALSE.equals(right)) { 78 | // children.remove(1); 79 | // children.set(0, newConstNode(right, rightValue)); 80 | // } 81 | // } 82 | // } 83 | } 84 | } 85 | if (!isLogicOptimized) { 86 | for (int i = 0; i < children.size(); i++) { 87 | FelNode c = children.get(i); 88 | children.set(i, this.call(ctx, c)); 89 | } 90 | } 91 | } 92 | return node; 93 | } 94 | } 95 | 96 | 97 | private FelNode toShortCutConst(FelNode node, FelContext ctx, FelNode left, 98 | Boolean result) { 99 | FelNode constNode = null; 100 | if (left.stable()) { 101 | Object leftValue = node.getInterpreter().interpret(ctx, left); 102 | if (result.equals(leftValue)) { 103 | constNode = newConstNode(node, leftValue); 104 | } 105 | } 106 | return constNode; 107 | } 108 | 109 | @SuppressWarnings("unused") 110 | private void setConstValue(List children, FelNode left, 111 | Object leftValue) { 112 | children.remove(1); 113 | children.set(0, newConstNode(left, leftValue)); 114 | } 115 | 116 | 117 | private FelNode newConstNode(FelNode node, Object value) { 118 | Token token = new ConstOptToken(node); 119 | token.setText(node.getText()); 120 | return new ConstNode(token, value); 121 | } 122 | 123 | } 124 | 125 | /** 126 | * 常量节点,用于保存原节点 127 | * 128 | * @author yuqingsong 129 | * 130 | */ 131 | @SuppressWarnings("serial") 132 | class ConstOptToken extends CommonToken{ 133 | @SuppressWarnings("unused") 134 | private final FelNode node; 135 | ConstOptToken(FelNode node){ 136 | super(-1,node.getText()); 137 | this.node = node; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/optimizer/Interpreters.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.optimizer; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.greenpineyu.fel.context.FelContext; 8 | import com.greenpineyu.fel.interpreter.Interpreter; 9 | import com.greenpineyu.fel.parser.AbstFelNode; 10 | import com.greenpineyu.fel.parser.FelNode; 11 | 12 | 13 | /** 14 | * 设置节点的解释器 15 | * @author yuqingsong 16 | * 17 | */ 18 | public class Interpreters implements Optimizer { 19 | 20 | private Map inteMap; 21 | { 22 | inteMap = new HashMap(); 23 | } 24 | public FelNode call(FelContext ctx,FelNode node) { 25 | List nodes = AbstFelNode.getNodes(node); 26 | for (FelNode n : nodes) { 27 | String text = n.getText(); 28 | Interpreter inte = inteMap.get(text); 29 | if(inte!=null){ 30 | n.setInterpreter(inte); 31 | } 32 | } 33 | return node; 34 | } 35 | 36 | public void add(String name,Interpreter inter){ 37 | inteMap.put(name, inter); 38 | } 39 | 40 | public static void main(String[] args) { 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/optimizer/Optimizer.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.optimizer; 2 | 3 | import com.greenpineyu.fel.context.FelContext; 4 | import com.greenpineyu.fel.parser.FelNode; 5 | 6 | /** 7 | * 优化器 8 | * @author yuqingsong 9 | * 10 | */ 11 | public interface Optimizer { 12 | 13 | 14 | FelNode call(FelContext ctx, FelNode node); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/optimizer/VarVisitOpti.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.optimizer; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 7 | import com.greenpineyu.fel.compile.SourceBuilder; 8 | import com.greenpineyu.fel.compile.SourceGeneratorImpl; 9 | import com.greenpineyu.fel.compile.VarBuffer; 10 | import com.greenpineyu.fel.context.FelContext; 11 | import com.greenpineyu.fel.context.MapContext; 12 | import com.greenpineyu.fel.context.Var; 13 | import com.greenpineyu.fel.interpreter.Interpreter; 14 | import com.greenpineyu.fel.parser.AbstFelNode; 15 | import com.greenpineyu.fel.parser.FelNode; 16 | import com.greenpineyu.fel.parser.VarAstNode; 17 | 18 | /** 19 | * 对访问节点进行优化,直接从Var中取变量 20 | * 21 | * @author yuqingsong 22 | * 23 | */ 24 | public class VarVisitOpti implements Optimizer { 25 | 26 | /** 27 | * 用于保存变量 28 | */ 29 | private Map varMap; 30 | 31 | 32 | public VarVisitOpti(Var... vars) { 33 | varMap = new MapContext(); 34 | if (vars != null) { 35 | for (Var var : vars) { 36 | if (var != null) { 37 | varMap.put(var.getName(), var); 38 | } 39 | } 40 | } 41 | } 42 | 43 | public VarVisitOpti() { 44 | } 45 | 46 | 47 | public FelNode call(FelContext ctx, FelNode node) { 48 | List nodes = AbstFelNode.getNodes(node, 49 | SourceGeneratorImpl.varsFilter); 50 | for (FelNode varNode : nodes) { 51 | if (varNode instanceof VarAstNode) { 52 | final VarAstNode n = (VarAstNode) varNode; 53 | if (n.isDefaultInterpreter()) { 54 | // 当解释器是自身时,才能进行优化 55 | // 要先设置解释器,原因是createSourceBuilder会使用解释器。 56 | n.setInterpreter(createInterpreter()); 57 | n.setSourcebuilder(createVarSourceBuilder(n)); 58 | } 59 | } 60 | } 61 | return node; 62 | } 63 | 64 | private Interpreter createInterpreter() { 65 | return new Interpreter() { 66 | 67 | public Object interpret(FelContext context, FelNode node) { 68 | Var var = getVar(context, node); 69 | return var != null ? var.getValue() : null; 70 | } 71 | }; 72 | } 73 | 74 | private SourceBuilder createVarSourceBuilder(final VarAstNode n) { 75 | return new SourceBuilder() { 76 | 77 | private String src = null; 78 | private Class returnType = null; 79 | 80 | 81 | public String source(FelContext ctx, FelNode node) { 82 | if (src == null) { 83 | Var var = getVar(ctx, node); 84 | String varFieldName = VarBuffer.push(var); 85 | Class type = returnType(ctx, node); 86 | src = VarAstNode.getVarFullCode(type, varFieldName 87 | + ".getValue()"); 88 | } 89 | return src; 90 | } 91 | 92 | 93 | public Class returnType(FelContext ctx, FelNode node) { 94 | if(returnType == null){ 95 | returnType = InterpreterSourceBuilder.getInstance() 96 | .returnType(ctx, node); 97 | } 98 | return returnType; 99 | } 100 | }; 101 | } 102 | 103 | private Var getVar(FelContext context, FelNode node) { 104 | Var var = null; 105 | if (varMap != null) { 106 | var = varMap.get(node.getText()); 107 | } 108 | if (var == null) { 109 | // 如果varMap中没有节点,从context中取。 110 | var = context.getVar(node.getText()); 111 | } 112 | return var; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/AbstFelNode.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | import org.antlr.runtime.Token; 8 | import org.antlr.runtime.tree.CommonTree; 9 | import org.antlr.runtime.tree.Tree; 10 | 11 | import com.greenpineyu.fel.common.Callable; 12 | import com.greenpineyu.fel.compile.SourceBuilder; 13 | import com.greenpineyu.fel.context.FelContext; 14 | import com.greenpineyu.fel.interpreter.Interpreter; 15 | 16 | public abstract class AbstFelNode extends CommonTree implements FelNode, Interpreter { 17 | 18 | /** 19 | * 解析器,用于解析节点的值 20 | */ 21 | protected Interpreter interpreter; 22 | 23 | /** 24 | * 默认的解析器 25 | */ 26 | protected Interpreter defaultInter; 27 | 28 | 29 | protected SourceBuilder builder; 30 | 31 | 32 | @SuppressWarnings("unchecked") 33 | public List getChildren() { 34 | return this.children; 35 | } 36 | 37 | public AbstFelNode(Token token) { 38 | super(token); 39 | } 40 | 41 | public AbstFelNode() { 42 | 43 | } 44 | 45 | { 46 | // 解释器设置成this 47 | this.defaultInter = this; 48 | resetInterpreter(); 49 | // 源码构建器设置成this 50 | // resetSourceBuilder(); 51 | } 52 | 53 | 54 | @SuppressWarnings("unchecked") 55 | public AbstFelNode(CommonTree node) { 56 | super(node); 57 | if (node.getChildren() != null) { 58 | this.children = new ArrayList(node.getChildren()); 59 | for (int i = 0; i < this.children.size(); i++) { 60 | Tree object = (Tree) this.children.get(i); 61 | object.setParent(this); 62 | } 63 | } 64 | } 65 | 66 | 67 | 68 | public String toString() { 69 | return this.getText(); 70 | } 71 | 72 | 73 | 74 | 75 | public void setChild(int index, FelNode node) { 76 | if (node instanceof Tree) { 77 | super.setChild(index, node); 78 | } else { 79 | throw new IllegalArgumentException("类型必须是" + Tree.class); 80 | } 81 | 82 | } 83 | 84 | 85 | 86 | 87 | public Object eval(FelContext context) { 88 | return interpreter.interpret(context, this); 89 | // if (cached) { 90 | // return cacheValue; 91 | // } 92 | // Object eval = interpreter.interpret(context, this); 93 | // if (fixed) { 94 | // cacheValue = eval; 95 | // cached = true; 96 | // } 97 | // return eval; 98 | } 99 | 100 | // abstract public Object evalWithoutCache(FelContext context); 101 | 102 | 103 | public static List getNodes(FelNode node) { 104 | List returnMe = new ArrayList(); 105 | getNodes(node, returnMe,null); 106 | return returnMe; 107 | } 108 | 109 | public static List getNodes(FelNode node,Callable filter) { 110 | List returnMe = new ArrayList(); 111 | getNodes(node, returnMe, filter); 112 | return returnMe; 113 | } 114 | 115 | public static void getNodes(FelNode node, List returnMe,Callable filter) { 116 | if (node != null) { 117 | if(filter==null){ 118 | returnMe.add(node); 119 | }else if (filter.call(node)) { 120 | returnMe.add(node); 121 | } 122 | List nodeChildren = node.getChildren(); 123 | if (nodeChildren != null) { 124 | for (Iterator iterator = nodeChildren.iterator(); iterator.hasNext();) { 125 | try { 126 | FelNode child = iterator.next(); 127 | getNodes(child, returnMe, filter); 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | 136 | 137 | 138 | public Interpreter getInterpreter() { 139 | return this.interpreter; 140 | } 141 | 142 | 143 | public void setInterpreter(Interpreter interpreter) { 144 | this.interpreter = interpreter; 145 | } 146 | 147 | 148 | public void resetInterpreter() { 149 | this.interpreter = this.defaultInter; 150 | } 151 | 152 | /** 153 | * 是否默认的解释器 154 | * 155 | * @return 156 | */ 157 | 158 | public boolean isDefaultInterpreter(){ 159 | return this.interpreter == this.defaultInter; 160 | } 161 | 162 | 163 | 164 | 165 | public Object interpret(FelContext context, FelNode node) { 166 | throw new UnsupportedOperationException("还没有实现[2011-1-13]"); 167 | } 168 | 169 | 170 | public SourceBuilder toMethod(FelContext ctx){ 171 | return this.builder; 172 | } 173 | 174 | 175 | public void setSourcebuilder(SourceBuilder builder) { 176 | this.builder = builder; 177 | } 178 | 179 | 180 | public boolean stable() { 181 | return false; 182 | } 183 | 184 | public boolean isChildrenStable() { 185 | if(this.children!=null){ 186 | // 子节点有一个不是稳定的,就返回false 187 | for (int i = 0; i < children.size(); i++) { 188 | FelNode child = (FelNode) children.get(i); 189 | if(!child.stable()){ 190 | return false; 191 | } 192 | } 193 | } 194 | return true; 195 | } 196 | 197 | 198 | // public void resetSourceBuilder(){ 199 | // this.builder = this; 200 | // } 201 | 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/AbstFelParser.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | 4 | import org.antlr.runtime.Parser; 5 | import org.antlr.runtime.RecognitionException; 6 | import org.antlr.runtime.RecognizerSharedState; 7 | import org.antlr.runtime.TokenStream; 8 | 9 | import com.greenpineyu.fel.exception.ParseException; 10 | 11 | public abstract class AbstFelParser extends Parser { 12 | @Override 13 | public void emitErrorMessage(String msg) { 14 | throw new ParseException(msg); 15 | } 16 | 17 | public AbstFelParser(TokenStream input) { 18 | super(input); 19 | } 20 | 21 | public AbstFelParser(TokenStream input, RecognizerSharedState state) { 22 | super(input, state); 23 | } 24 | 25 | @Override 26 | public void displayRecognitionError(String tokenNames[], RecognitionException e) { 27 | String hdr = getErrorHeader(e); 28 | String msg = getErrorMessage(e, tokenNames); 29 | emitErrorMessage("解析表达式[" + e.input.toString() + "]出错:" + hdr + " " + msg); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/AntlrParser.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.util.List; 6 | 7 | import org.antlr.runtime.ANTLRInputStream; 8 | import org.antlr.runtime.CommonTokenStream; 9 | import org.antlr.runtime.ParserRuleReturnScope; 10 | import org.antlr.runtime.RecognitionException; 11 | import org.antlr.runtime.tree.CommonTree; 12 | 13 | import com.greenpineyu.fel.FelEngine; 14 | import com.greenpineyu.fel.common.Callable; 15 | import com.greenpineyu.fel.exception.ParseException; 16 | import com.greenpineyu.fel.function.Function; 17 | import com.greenpineyu.fel.function.operator.Dot; 18 | 19 | /** 20 | * 使用Antlr进行语法分析 21 | * @author yuqingsong 22 | * 23 | */ 24 | public class AntlrParser implements Parser { 25 | 26 | public static final Callable funFilter = new Callable() { 27 | 28 | public Boolean call(FelNode... node) { 29 | FelNode n = node[0]; 30 | if(n == null){ 31 | return false; 32 | } 33 | boolean isFun = n instanceof FunNode; 34 | if(isFun){ 35 | if (n instanceof CommonTree) { 36 | CommonTree treeNode = (CommonTree) n; 37 | CommonTree p = treeNode.parent; 38 | if(p!=null){ 39 | if(Dot.DOT.equals(p.getText())){ 40 | // 点运算符后的函数节点不是真正意义上的变量节点。 41 | isFun = p.getChildren().get(0)==n; 42 | } 43 | } 44 | } 45 | } 46 | return isFun; 47 | } 48 | }; 49 | 50 | private final FelEngine engine; 51 | 52 | public AntlrParser(FelEngine engine){ 53 | this.engine = engine; 54 | } 55 | 56 | public FelNode parse(String exp) { 57 | if (exp == null || "".equals(exp)) { 58 | return null; 59 | } 60 | ByteArrayInputStream is = new ByteArrayInputStream(exp.getBytes()); 61 | ANTLRInputStream input = null; 62 | try { 63 | input = new ANTLRInputStream(is); 64 | } catch (IOException e) { 65 | e.printStackTrace(); 66 | } 67 | FelLexer lexer = new FelLexer(input); 68 | CommonTokenStream tokens = new CommonTokenStream(lexer); 69 | FelParser parser = new FelParser(tokens); 70 | parser.setTreeAdaptor(new NodeAdaptor()); 71 | ParserRuleReturnScope r = null; 72 | try { 73 | r = parser.program(); 74 | } catch (RecognitionException e) { 75 | throw new ParseException(e.getMessage(), e); 76 | } 77 | if (r != null) { 78 | Object tree = r.getTree(); 79 | if (tree instanceof FelNode) { 80 | initFun((FelNode)tree); 81 | return (FelNode) tree; 82 | } 83 | } 84 | return null; 85 | } 86 | 87 | public void initFun(FelNode node){ 88 | List nodes = AbstFelNode.getNodes(node, funFilter); 89 | if(nodes!=null){ 90 | for (FelNode n : nodes) { 91 | FunNode funNode = (FunNode)n; 92 | funNode.initFun(this.engine.getFunMgr()); 93 | Function fun = funNode.getFun(); 94 | if (fun instanceof Dot) { 95 | Dot dot = (Dot) fun; 96 | dot.setSecurityMgr(this.engine.getSecurityMgr()); 97 | } 98 | } 99 | } 100 | } 101 | 102 | 103 | public boolean verify(String exp) { 104 | try { 105 | parse(exp); 106 | } catch (Exception e) { 107 | e.printStackTrace(); 108 | return false; 109 | } 110 | return true; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/ConstNode.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import org.antlr.runtime.Token; 4 | 5 | import com.greenpineyu.fel.common.Null; 6 | import com.greenpineyu.fel.common.ReflectUtil; 7 | import com.greenpineyu.fel.compile.FelMethod; 8 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 9 | import com.greenpineyu.fel.compile.SourceBuilder; 10 | import com.greenpineyu.fel.compile.VarBuffer; 11 | import com.greenpineyu.fel.context.FelContext; 12 | 13 | /** 14 | * 常量节点 15 | * 16 | * @author yqs 17 | * 18 | */ 19 | public class ConstNode extends AbstFelNode { 20 | 21 | private Object value; 22 | 23 | public ConstNode(Token token, Object value) { 24 | super(token); 25 | this.value = value; 26 | } 27 | 28 | public Object interpret(FelContext context, FelNode node) { 29 | return value; 30 | } 31 | 32 | public SourceBuilder toMethod(FelContext ctx) { 33 | if (this.builder != null) { 34 | return this.builder; 35 | } 36 | if (!this.isDefaultInterpreter()) { 37 | return InterpreterSourceBuilder.getInstance(); 38 | } 39 | return new FelMethod(this.getValueType(), this.toJavaSrc(ctx)); 40 | } 41 | 42 | public Class getValueType() { 43 | Class t = null; 44 | if (value == null) { 45 | t = Null.class; 46 | } else { 47 | t = value.getClass(); 48 | } 49 | return t; 50 | } 51 | 52 | public String toJavaSrc(FelContext ctx) { 53 | if (value == null) { 54 | return "null"; 55 | } 56 | if (value instanceof String) { 57 | return "\"" + value + "\""; 58 | } 59 | if (ReflectUtil.isPrimitiveOrWrapNumber(getValueType())) { 60 | return value.toString(); 61 | } 62 | return VarBuffer.push(value); 63 | } 64 | 65 | public boolean stable() { 66 | return true; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/FelNode.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import java.util.List; 4 | 5 | import org.antlr.runtime.tree.Tree; 6 | 7 | import com.greenpineyu.fel.Expression; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.interpreter.Interpreter; 11 | 12 | /** 13 | * 解析后的节点,组成表达式的元素都会被解析成节点。 14 | * @author yqs 15 | * 16 | */ 17 | public interface FelNode extends Expression, Tree ,Stable{ 18 | 19 | /** 20 | * 获取子节点 21 | */ 22 | List getChildren(); 23 | 24 | /** 25 | * 重置解释器 26 | * @return 27 | */ 28 | 29 | void resetInterpreter(); 30 | 31 | /** 32 | * 节点中的解释器是否默认的解释器 33 | * @return 34 | */ 35 | boolean isDefaultInterpreter(); 36 | 37 | Interpreter getInterpreter(); 38 | 39 | void setInterpreter(Interpreter interpreter); 40 | 41 | void setSourcebuilder(SourceBuilder builder); 42 | 43 | 44 | SourceBuilder toMethod(FelContext ctx); 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/FunNode.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import org.antlr.runtime.Token; 4 | import org.antlr.runtime.tree.CommonTree; 5 | 6 | import com.greenpineyu.fel.compile.FelMethod; 7 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | import com.greenpineyu.fel.exception.EvalException; 11 | import com.greenpineyu.fel.function.Function; 12 | import com.greenpineyu.fel.function.FunMgr; 13 | 14 | /** 15 | * 函数节点 16 | * 17 | * @author yqs 18 | * 19 | */ 20 | public class FunNode extends AbstFelNode { 21 | private Function fun; 22 | 23 | public Function getFun() { 24 | return fun; 25 | } 26 | 27 | private static final Function NOT_FOUND_FUN = new Function() { 28 | 29 | 30 | public String getName() { 31 | return "未知函数"; 32 | } 33 | 34 | 35 | public Object call(FelNode node, FelContext context) { 36 | throw new EvalException("找不到函数[" + node.getText() + "]", null); 37 | } 38 | 39 | 40 | public FelMethod toMethod(FelNode node, FelContext ctx) { 41 | return null; 42 | } 43 | }; 44 | 45 | public FunNode(CommonTree node) { 46 | super(node); 47 | } 48 | 49 | public FunNode(Token token) { 50 | super(token); 51 | 52 | } 53 | 54 | // { 55 | // initFun(); 56 | // } 57 | 58 | 59 | public Object interpret(FelContext context, FelNode node) { 60 | return fun.call(this, context); 61 | } 62 | 63 | 64 | public void initFun(FunMgr funMgr) { 65 | fun = funMgr.getFun(getText()); 66 | if (fun == null) { 67 | fun = NOT_FOUND_FUN; 68 | } 69 | } 70 | 71 | 72 | public SourceBuilder toMethod(FelContext ctx) { 73 | if(this.builder!=null){ 74 | return builder; 75 | } 76 | if(!this.isDefaultInterpreter()){ 77 | return InterpreterSourceBuilder.getInstance(); 78 | } 79 | return this.fun.toMethod(this,ctx); 80 | } 81 | 82 | 83 | public boolean stable() { 84 | if(this.fun instanceof Stable){ 85 | // 函数是稳定的,并且参数是稳定的 86 | return ((Stable)fun).stable()&&this.isChildrenStable(); 87 | } 88 | return false; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/NodeAdaptor.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import org.antlr.runtime.Token; 4 | import org.antlr.runtime.tree.CommonTree; 5 | import org.antlr.runtime.tree.CommonTreeAdaptor; 6 | 7 | import com.greenpineyu.fel.common.NumberUtil; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.FelContext; 10 | 11 | public class NodeAdaptor extends CommonTreeAdaptor { 12 | @Override 13 | public Object create(Token token) { 14 | if (token == null) { 15 | return new AbstFelNode(token){ 16 | 17 | @Override 18 | public SourceBuilder toMethod(FelContext ctx) { 19 | return null; 20 | }}; 21 | } 22 | // System.out.println(token.getText()); 23 | 24 | /* 25 | Dot 26 | LikeIn 27 | Logical 28 | Equals 29 | Relational 30 | Additive 31 | Multiplicative 32 | Identifier 33 | FloatingPointLiteral 34 | CharacterLiteral 35 | StringLiteral 36 | BooleanLiteral 37 | HexLiteral 38 | OctalLiteral 39 | DecimalLiteral 40 | */ 41 | Object returnMe = null; 42 | int type = token.getType(); 43 | String text = token.getText(); 44 | switch (type) { 45 | case FelParser.Identifier: 46 | if("null".equals(text)){ 47 | // returnMe = AbstFelNode.NULL; 48 | returnMe = new ConstNode(token, null); 49 | } else { 50 | returnMe = new VarAstNode(token); 51 | } 52 | break; 53 | 54 | /* 函数、操作符 开始 */ 55 | case FelParser.Dot://. 56 | case FelParser.Additive:// +、- 57 | case FelParser.Multiplicative:// *、/ 58 | case FelParser.Equals:// ==、!= 59 | case FelParser.Relational:// >、<、>=、<= 60 | case FelParser.And:// AND 61 | case FelParser.Or:// OR 62 | case FelParser.Ques: 63 | case FelParser.Bracket: 64 | case FelParser.Not: 65 | returnMe = new FunNode(token); 66 | break; 67 | /* 函数、操作符 结束 */ 68 | 69 | /* 常量开始 */ 70 | case FelParser.DecimalLiteral: 71 | // 数字-10进制 72 | returnMe = NumberUtil.parseNumber(new Long(text)); 73 | break; 74 | case FelParser.HexLiteral: 75 | // 数字-16进制 76 | String num = text; 77 | if(text.startsWith("0x")||text.startsWith("0X")){ 78 | num = text.substring(2); 79 | } 80 | returnMe = NumberUtil.parseNumber(new Long(Long.parseLong(num, 16))); 81 | break; 82 | case FelParser.OctalLiteral: 83 | // 数字-8进制 84 | returnMe = NumberUtil.parseNumber(new Long(Long.parseLong(text, 8))); 85 | break; 86 | 87 | case FelParser.FloatingPointLiteral: 88 | // 浮点型 89 | returnMe = new Double(text); 90 | break; 91 | case FelParser.BooleanLiteral: 92 | // 布尔值 93 | returnMe = Boolean.valueOf(text); 94 | break; 95 | case FelParser.CharacterLiteral: 96 | case FelParser.StringLiteral: 97 | // 字符串 98 | // 出掉字符串两端的单引号和双引号 99 | returnMe = text.substring(1, text.length() - 1); 100 | break; 101 | /* 常量结束 */ 102 | default: 103 | break; 104 | } 105 | if (returnMe == null) { 106 | // 不能正确解析 107 | return CommonTree.INVALID_NODE; 108 | } 109 | if (returnMe instanceof CommonTree) { 110 | return returnMe; 111 | } 112 | return new ConstNode(token, returnMe); 113 | } 114 | 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/Parser.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | /** 4 | * 用于分析表达式 5 | * 6 | * @author yuqingsong 7 | * 8 | */ 9 | public interface Parser { 10 | 11 | /** 12 | * 将表达式解析成节点 13 | * 14 | * @param exp 15 | * @return 16 | */ 17 | FelNode parse(String exp); 18 | 19 | /** 20 | * 检验表达式是否合法 21 | * @param exp 22 | * @return 23 | */ 24 | boolean verify(String exp); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/Stable.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | public interface Stable { 4 | 5 | /** 6 | * 此节点的值是否固定不变 7 | * 如果每次求节点值都相同,说明此节点是稳定的。 8 | * @return 9 | */ 10 | boolean stable(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/parser/VarAstNode.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.parser; 2 | 3 | import org.antlr.runtime.Token; 4 | import org.antlr.runtime.tree.CommonTree; 5 | 6 | import com.greenpineyu.fel.common.ReflectUtil; 7 | import com.greenpineyu.fel.compile.InterpreterSourceBuilder; 8 | import com.greenpineyu.fel.compile.SourceBuilder; 9 | import com.greenpineyu.fel.context.AbstractContext; 10 | import com.greenpineyu.fel.context.ArrayCtx; 11 | import com.greenpineyu.fel.context.FelContext; 12 | import com.greenpineyu.fel.function.operator.Dot; 13 | 14 | public class VarAstNode extends AbstFelNode { 15 | private final String text; 16 | 17 | public VarAstNode(Token token) { 18 | super(token); 19 | this.text = token.getText(); 20 | } 21 | 22 | 23 | public String getText() { 24 | return this.text; 25 | } 26 | 27 | 28 | public Object interpret(FelContext context, FelNode node) { 29 | return context.get(text); 30 | } 31 | 32 | public static boolean isVar(FelNode n) { 33 | if (n == null) { 34 | return false; 35 | } 36 | boolean isVar = n instanceof VarAstNode; 37 | if (isVar) { 38 | if (n instanceof CommonTree) { 39 | CommonTree treeNode = (CommonTree) n; 40 | CommonTree p = treeNode.parent; 41 | if (p != null) { 42 | if (Dot.DOT.equals(p.getText())) { 43 | // 点运算符后的变量节点不是真正意义上的变量节点。 44 | isVar = p.getChildren().get(0) == n; 45 | } 46 | } 47 | 48 | } 49 | } 50 | return isVar; 51 | } 52 | 53 | { 54 | this.builder = new SourceBuilder() { 55 | 56 | 57 | public String source(FelContext ctx, FelNode node) { 58 | if(!node.isDefaultInterpreter()){ 59 | // 用户自定义解析器 60 | return InterpreterSourceBuilder.getInstance().source(ctx, node); 61 | } 62 | Class type = returnType(ctx, node); 63 | String varName = node.getText(); 64 | String getVarCode = "context.get(\""+varName+"\")"; 65 | if (ctx instanceof ArrayCtx) { 66 | ArrayCtx c = (ArrayCtx) ctx; 67 | getVarCode = "((context instanceof ArrayCtx)?((ArrayCtx)context).get(" 68 | + c.getIndex(varName) 69 | + "):context.get(\"" 70 | + varName + "\"))"; 71 | } 72 | 73 | String code = getVarFullCode(type, getVarCode); 74 | return code; 75 | } 76 | 77 | 78 | public Class returnType(FelContext ctx, FelNode node) { 79 | Class type = AbstractContext.getVarType(node.getText(),ctx); 80 | if(type == null){ 81 | type = InterpreterSourceBuilder.getInstance().returnType(ctx, node); 82 | } 83 | return type; 84 | } 85 | }; 86 | } 87 | 88 | public static String getVarFullCode(Class type, String getVarCode) { 89 | String typeName = type.getCanonicalName(); 90 | boolean isNumber = Number.class.isAssignableFrom(type); 91 | String code = ""; 92 | if (ReflectUtil.isPrimitiveOrWrapNumber(type)) { 93 | code = "((" + typeName + ")" + getVarCode + ")"; 94 | } else if (isNumber) { 95 | // 当float转double时,会丢失精度 96 | code = "((" + typeName + ")" + getVarCode + ").doubleValue()"; 97 | } else { 98 | code = "((" + typeName + ")" + getVarCode + ")"; 99 | } 100 | return code; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/security/RegexSecurityMgr.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.security; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | import java.util.regex.Pattern; 8 | 9 | import com.greenpineyu.fel.Fel; 10 | 11 | public class RegexSecurityMgr implements SecurityMgr { 12 | 13 | private Map callableMap; 14 | private Map uncallableMap; 15 | 16 | { 17 | callableMap = new HashMap(); 18 | uncallableMap = new HashMap(); 19 | } 20 | 21 | public RegexSecurityMgr(Set callables, Set uncallables) { 22 | convert(callables, this.callableMap); 23 | convert(uncallables, this.uncallableMap); 24 | } 25 | 26 | /** 27 | * 编译成正则表达式,保存到Map中 28 | * @param callableSet 29 | * @param callableMapDest 30 | */ 31 | private void convert(Set src, Map dest) { 32 | if (src == null) { 33 | return; 34 | } 35 | for (String reg : src) { 36 | Pattern pattern = Pattern.compile(toRegex(reg)); 37 | dest.put(reg, pattern); 38 | } 39 | } 40 | 41 | /** 42 | * 将用户传递的表达式,转换成正则表达式(eg:java.lang.*转换成^java\.lang\..*$) 43 | * @param regex 44 | * @return 45 | */ 46 | private String toRegex(String regex) { 47 | char[] chars = regex.toCharArray(); 48 | StringBuilder sb = new StringBuilder("^"); 49 | for (int i = 0; i < chars.length; i++) { 50 | char c = chars[i]; 51 | switch (c) { 52 | case '.': 53 | case '$': 54 | case '(': 55 | case ')': 56 | sb.append('\\'); 57 | sb.append(c); 58 | break; 59 | case '*': 60 | sb.append(".*"); 61 | break; 62 | default: 63 | sb.append(c); 64 | break; 65 | } 66 | } 67 | sb.append("$"); 68 | return sb.toString(); 69 | } 70 | 71 | /** 72 | * 获取方法签名(eg:java.lang.System.exit(int)) 73 | * @return 74 | */ 75 | private String getSignature(Method m) { 76 | StringBuilder name = new StringBuilder(); 77 | Class cls = m.getDeclaringClass(); 78 | name.append(cls.getCanonicalName()).append("."); 79 | name.append(m.getName()).append("("); 80 | Class[] params = m.getParameterTypes(); 81 | for (int i = 0; i < params.length; i++) { 82 | Class paramCls = params[i]; 83 | String canonicalName = paramCls.getCanonicalName(); 84 | if (canonicalName.startsWith("java.lang")) { 85 | canonicalName = canonicalName.substring(canonicalName.lastIndexOf(".") + 1); 86 | } 87 | name.append(canonicalName); 88 | if (i < params.length - 1) { 89 | name.append(","); 90 | } 91 | } 92 | name.append(")"); 93 | return name.toString(); 94 | } 95 | 96 | private boolean isMatch(Map m, String input) { 97 | for (Map.Entry entry : m.entrySet()) { 98 | if (entry.getValue().matcher(input).find()) { 99 | return true; 100 | } 101 | } 102 | return false; 103 | } 104 | 105 | /* 106 | * 107 | *允许通过方法中包含参数方法,则允许访问。 108 | *不允许通过方法中包含参数方法,则不允许访问。 109 | *如果同时包含,则返回不允许通过方法的测试结果。 110 | * @see com.greenpineyu.fel.security.ReflectMgr#isCallable(java.lang.reflect.Method) 111 | */ 112 | 113 | public boolean isCallable(Method m) { 114 | String method = getSignature(m); 115 | if (isMatch(uncallableMap, method)) { 116 | return false; 117 | } 118 | if (callableMap.isEmpty()) { 119 | return true; 120 | } 121 | return isMatch(callableMap, method); 122 | } 123 | 124 | public static void main(String[] args) { 125 | // Object eval = Fel.eval("$(System).getProperty('user.home')"); 126 | // System.out.println(eval); 127 | 128 | // 会抛出异常 129 | Fel.eval("$(System).exit(1)"); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/security/SecurityMgr.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.security; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public interface SecurityMgr { 6 | 7 | /** 8 | * 是否允许访问某个方法 9 | * @param m 10 | * @return 11 | */ 12 | boolean isCallable(Method m); 13 | 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/greenpineyu/fel/security/SecurityMgrImpl.java: -------------------------------------------------------------------------------- 1 | package com.greenpineyu.fel.security; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | public class SecurityMgrImpl implements SecurityMgr { 8 | 9 | private Set callableSet; 10 | private Set uncallableSet; 11 | 12 | { 13 | callableSet = new HashSet(); 14 | uncallableSet = new HashSet(); 15 | } 16 | 17 | /** 18 | * 判断原则,以可访问方法列表为首要依据(包含目标方法表示允许访问,否则不允许),不可访问方法列表为次要依据 19 | * 当允许访问方法列表为空时,以不可访问方法列表为依据。 20 | * 21 | * @see com.greenpineyu.fel.security.ReflectMgr#isCallable(java.lang.reflect.Method) 22 | */ 23 | 24 | public boolean isCallable(Method m) { 25 | if (callableSet.isEmpty()) { 26 | return !uncallableSet.contains(m); 27 | } 28 | return callableSet.contains(m); 29 | } 30 | /* 31 | 32 | 33 | public void addCallable(Method m) { 34 | this.callableSet.add(m); 35 | } 36 | 37 | 38 | public void addUncallable(Method m) { 39 | this.uncallableSet.add(m); 40 | } 41 | 42 | 43 | public void removeCallable(Method m) { 44 | this.callableSet.remove(m); 45 | } 46 | 47 | 48 | public void removeUncallable(Method m) { 49 | this.uncallableSet.remove(m); 50 | 51 | } 52 | 53 | 54 | public Set getCallables() { 55 | return new HashSet(this.callableSet); 56 | } 57 | 58 | 59 | public Set getUnCallables() { 60 | return new HashSet(this.uncallableSet); 61 | } 62 | 63 | public static void main(String[] args) { 64 | Object eval = Fel.eval("$(System).getProperty('user.home')"); 65 | System.out.println(eval); 66 | // 会抛出异常 67 | Fel.eval("$(System).exit(1)"); 68 | }*/ 69 | 70 | } 71 | --------------------------------------------------------------------------------