Skip to content

Commit

Permalink
1. 调整EL接口
Browse files Browse the repository at this point in the history
2. 修改文档
  • Loading branch information
juqkai committed Jun 29, 2011
1 parent 5381484 commit 0a21085
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 144 deletions.
85 changes: 48 additions & 37 deletions doc/manual/el/overview.man
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#title: 表达式引擎简介
#author:zozoh(zozohtnt@gmail.com)
#author:wendal(wendal1985@gmail.com)
#author:juqkai(juqkai@gmail.com)
#index:0,1
------------------------------------------------------------------------
为什么需要 EL 表达式引擎
Expand All @@ -15,7 +16,7 @@

但是,"一小撮人"的"一小撮要求"有很多,作为一个小众类库,为什么单单打算支持这个特性呢?
下面是我的理由:
* 这个功能另外一个计划中模块的基础,我们需要它
* 这个功能是其它模块功能的基础,我们需要它
* 可能因此吸引其他的开发者对 Nutz 的兴趣
* 需要嵌入式表达式引擎的人是 Java 开发者的少数人,但是这些人也应该比 Nutz 的用户要多
* 这些人基本上编程水平要强一些
Expand All @@ -35,11 +36,9 @@

它容易使用吗?
{{{<Java>
ElValue val = El.eval("3+4*5");
System.out.println( 23 == val.getInteger().intValue()); // 将打印 true
System.out.println( 23 == El.eval("3+4+5")); // 将打印 true,够简单吧
}}}
表达式接受的是字符串输入,输出是一个 ElValue 接口。 通过这个接口,你能拿到
表达式的计算结果的 Java 形式,以便你后面的程序使用。
表达式接受的是字符串输入,输出则是一个Object对象,而Object对象本身是根据计算结果进行进行了自动封装的。

它功能强大吗?

Expand All @@ -49,8 +48,7 @@
{{{<Java>
Context context = Lang.context();
context.set("a", 10);
ElValue val = El.eval(context, "a*10");
System.out.println(val.getInteger().intValue()); // 将打印 100
System.out.println(El.eval(context, "a*10")); // 将打印 100
}}}
通过 Context 接口,你可以为你的表达式随意设置变量的值。它支持如下类型的 Java 数据
* 整型 - int 或 Integer
Expand All @@ -59,7 +57,7 @@
* 布尔 - boolean 或 Boolean
* 字符串 - String
* 数组 - `T[]`
* 列表 - `List<T>`
* 列表 - `Lst<Ti>`
* 集合 - `Collection<T>`
* Map - `Map<String,?>`
* 普通 Java 对象
Expand All @@ -68,23 +66,20 @@
它速度怎么样?

我觉得它速度不怎么样。它的工作的原理是这样的,每次解析都经过如果下三步
# 解析符号列表
# 将符号列表变成一棵二叉树,并返回根节点
# 从跟节点递归计算
没有将表达式解析成一个后缀表达式,主要是因为从计算来讲,二叉树效率也过得去,
加上个人有点犯懒,想先看看,如果效率实在不能接受再说。

# 解析成后缀表达式形式的一个队列
# 将后缀表达式解析成一棵运算树.
# 对运算树的根结点进行运算.

当然我也提供了一个提升效率的手段,因为如果每次计算都经过这三个步骤当然慢,所以我们可以对它先预编译:
{{{<Java>
BinElObj exp = El.compile("a*10"); // 预编译结果为一个 ElObj
El exp = new El("a*10"); // 预编译结果为一个 ElObj
Context context = Lang.context();
context.set("a", 10);

ElValue val = exp.eval(context);
System.out.println(val.getInteger().intValue()); // 将打印 100

System.out.println(exp.eval(context)); // 将打印 100
}}}
表达式的预编译结果是 BinElObj 对象,它就是是二叉树根节点。
El在实例化时就会对表达式进行预编译,会直接编译成运算树,当调用eval方法时,就不用再耗时的编译动作了.
它的 eval 函数是线程安全的,只要在多个线程内给它不同的 context 就是了。当然,你也
可以在多个线程间共享同一个 Context,那运行起来一定很有趣,不是吗?

Expand All @@ -100,23 +95,36 @@
{*只要支持的操作符,我会让它的优先级以及行为会和 Java 的表达式一致。如果你发现不一致\
别犹豫,给我报 Issue 吧。}

|| 符号 || 权重 || 解释 ||
|| `.` || 100 || 访问对象的属性,或者Map的值,或者函数调用(需要结合后面是否有括号) ||
|| `['abc']` || -- || Java 对象 Map按键值获得值 ||
|| `[3]` || -- || 数字,列表,或者集合的下标访问符号 ||
|| `*` || 50 || 乘 ||
|| `/` || 50 || 整除 ||
|| `%` || 50 || 取模 ||
|| `+` || 10 || 加 ||
|| `-` || 10 || 减 ||
|| `>=` || 5 || 大于等于 ||
|| `<=` || 5 || 小于等于 ||
|| `==` || 5 || 等于 ||
|| `!=` || 5 || 不等于 ||
|| `>` || 5 || 大于 ||
|| `<` || 5 || 小于 ||
|| `&&` || 3 || 逻辑与 ||
|| `||` || 2 || 逻辑或 ||
|| 符号 || 权重 || 解释 ||
|| `()` || 100 || 括号,优先计算 ||
|| `,` || 0 || 逗号,主要是方法参数 ||
|| `.` || 1 || 访问对象的属性,或者Map的值,或者方法调用, 或者自定义函数调用(需要结合后面是否有括号) ||
|| `['abc']` || 1 || Java 对象 Map按键值获得值 ||
|| `[3]` || 1 || 数字,列表,或者集合的下标访问符号 ||
|| `*` || 3 || 乘 ||
|| `/` || 3 || 整除 ||
|| `%` || 3 || 取模 ||
|| `+` || 4 || 加 ||
|| `-` || 4 || 减 ||
|| `-` || 2 || 负 ||
|| `>=` || 6 || 大于等于 ||
|| `<=` || 5 || 小于等于 ||
|| `==` || 7 || 等于 ||
|| `!=` || 6 || 不等于 ||
|| `!` || 7 || 非 ||
|| `>` || 6 || 大于 ||
|| `<` || 6 || 小于 ||
|| `&&` || 11 || 逻辑与 ||
|| `||` || 12 || 逻辑或 ||
|| `?:` || 13 || 三元运算 ||
|| `&` || 8 || 位运算,与 ||
|| `~` || 2 || 位运算,非 ||
|| `|` || 10 || 位运算,或 ||
|| `^` || 9 || 位运算,异或 ||
|| `<<` || 5 || 位运算,左移 ||
|| `>>` || 5 || 位运算,右移 ||
|| `>>>` || 5 || 位运算,无符号右移 ||
|| `&` || 8 || 位运算,与 ||

当然,同任何编程语言一样,表达式也支持 左括号 {*#00A;`(`} 以及 右括号{*#00A;`)`},
来控制表达式的的计算优先级别
Expand All @@ -135,6 +143,9 @@
{{{<JAVA>
System.out.println(El.eval(" abc ".trim()));
// 输出为 abc

System.out.println(El.eval("trim(\" abc \")"));
// 输出为 abc
}}}

Java 对象属性属性访问调用
Expand Down
4 changes: 2 additions & 2 deletions src/org/nutz/el/El.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ public Object eval(Context context) {
* @param val
* @return
*/
public Object eval(String val) {
public static Object eval(String val) {
//逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法)
return eval(null, val);
}

public Object eval(Context context, String val) {
public static Object eval(Context context, String val) {
ShuntingYard sy = new ShuntingYard();
RPN rc = new RPN();
Queue<Object> rpn = sy.parseToRPN(val);
Expand Down

0 comments on commit 0a21085

Please sign in to comment.