@org.junit.Test
public void testDemo() throws Exception{
String express = "10 * 10 + 1 + 2 * 3 + 5 * 2";
ExpressRunner runner = new ExpressRunner();
Object r = runner.execute(express,null, null, false,false);
Assert.assertTrue("表达式计算", r.toString().equalsIgnoreCase("117"));
System.out.println("表达式计算:" + express + " = " + r);
}
安装好maven 执行eclipse命令,导入eclipse 之后,运行 com.ql.util.express.test.ExpressTest 单元测试
可以运行处结果:
表达式计算:10 * 10 + 1 + 2 * 3 + 5 * 2 = 117
/**
* 执行一段文本
* @param expressString 程序文本
* @param context 执行上下文
* @param errorList 输出的错误信息List
* @param isCache 是否使用Cache中的指令集
* @param isTrace 是否输出详细的执行指令信息
* @return
* @throws Exception
*/
public Object execute(String expressString, IExpressContext<String,Object> context,
List<String> errorList, boolean isCache, boolean isTrace) throws Exception ;
我们为了要看到运行的过程,修改把ExpressRunner的构造函数,以及execute的参数中: isTrace =true,重新执行下这个单元测试。
@org.junit.Test
public void testDemo() throws Exception{
String express = "10 * 10 + 1 + 2 * 3 + 5 * 2";
ExpressRunner runner = new ExpressRunner(false,true); // 显示执行编译过程
Object r = runner.execute(express,null, null, false,true); // 显示指令执行过程
Assert.assertTrue("表达式计算", r.toString().equalsIgnoreCase("117"));
System.out.println("表达式计算:" + express + " = " + r);
}
日志信息:
[2012-02-20 22:07:07,844] [main] (ExpressParse.java:486) DEBUG com.ql.util.express.parse.ExpressParse -
执行的表达式:10 * 10 + 1 + 2 * 3 + 5 * 2
[2012-02-20 22:07:07,844] [main] (ExpressParse.java:487) DEBUG com.ql.util.express.parse.ExpressParse -
单词分解结果:{10},{*},{10},{+},{1},{+},{2},{*},{3},{+},{5},{*},{2}
[2012-02-20 22:07:07,844] [main] (ExpressParse.java:491) DEBUG com.ql.util.express.parse.ExpressParse -
预处理后结果:{10},{*},{10},{+},{1},{+},{2},{*},{3},{+},{5},{*},{2}
[2012-02-20 22:07:07,860] [main] (ExpressParse.java:502) DEBUG com.ql.util.express.parse.ExpressParse -
单词分析结果:
10:CONST_INTEGER,*:*,10:CONST_INTEGER,+:+,1:CONST_INTEGER,+:+,
2:CONST_INTEGER,*:*,3:CONST_INTEGER,+:+,5:CONST_INTEGER,*:*,
2:CONST_INTEGER
[2012-02-20 22:07:07,860] [main] (ExpressParse.java:506) DEBUG com.ql.util.express.parse.ExpressParse -
Block拆分后的结果:
1: main:FUNCTION_DEFINE FUNCTION_DEFINE
2: 10:CONST_INTEGER CONST
2: *:* *
2: 10:CONST_INTEGER CONST
2: +:+ +
2: 1:CONST_INTEGER CONST
2: +:+ +
2: 2:CONST_INTEGER CONST
2: *:* *
2: 3:CONST_INTEGER CONST
2: +:+ +
2: 5:CONST_INTEGER CONST
2: *:* *
2: 2:CONST_INTEGER CONST
[2012-02-20 22:07:07,860] [main] (ExpressParse.java:511) DEBUG com.ql.util.express.parse.ExpressParse -
语句拆分后的结果:
1: main:FUNCTION_DEFINE FUNCTION_DEFINE
2: ;:; STAT_SEMICOLON_EOF
3: 10:CONST_INTEGER CONST
3: *:* *
3: 10:CONST_INTEGER CONST
3: +:+ +
3: 1:CONST_INTEGER CONST
3: +:+ +
3: 2:CONST_INTEGER CONST
3: *:* *
3: 3:CONST_INTEGER CONST
3: +:+ +
3: 5:CONST_INTEGER CONST
3: *:* *
3: 2:CONST_INTEGER CONST
[2012-02-20 22:07:07,860] [main] (ExpressParse.java:520) DEBUG com.ql.util.express.parse.ExpressParse -
最后的语法树:
1: main:FUNCTION_DEFINE FUNCTION_DEFINE
2: ;:; STAT_SEMICOLON_EOF
3: +:+ EXPRESS_LEVEL5
4: +:+ EXPRESS_LEVEL5
5: +:+ EXPRESS_LEVEL5
6: *:* EXPRESS_LEVEL4
7: 10:CONST_INTEGER CONST
7: 10:CONST_INTEGER CONST
6: 1:CONST_INTEGER CONST
5: *:* EXPRESS_LEVEL4
6: 2:CONST_INTEGER CONST
6: 3:CONST_INTEGER CONST
4: *:* EXPRESS_LEVEL4
5: 5:CONST_INTEGER CONST
5: 2:CONST_INTEGER CONST
[2012-02-20 22:07:07,860] [main] (ExpressRunner.java:491) DEBUG com.ql.util.express.ExpressRunner -
1:LoadData 10
2:LoadData 10
3:OP : * OPNUMBER[2]
4:LoadData 1
5:OP : + OPNUMBER[2]
6:LoadData 2
7:LoadData 3
8:OP : * OPNUMBER[2]
9:OP : + OPNUMBER[2]
10:LoadData 5
11:LoadData 2
12:OP : * OPNUMBER[2]
13:OP : + OPNUMBER[2]
[2012-02-20 22:15:36,090] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 10
[2012-02-20 22:15:36,090] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 10
[2012-02-20 22:15:36,090] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - *(10,10)
[2012-02-20 22:15:36,105] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 1
[2012-02-20 22:15:36,105] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - +(100,1)
[2012-02-20 22:15:36,105] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 2
[2012-02-20 22:15:36,105] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 3
[2012-02-20 22:15:36,105] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - *(2,3)
[2012-02-20 22:15:36,105] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - +(101,6)
[2012-02-20 22:15:36,105] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 5
[2012-02-20 22:15:36,105] [main] (InstructionConstData.java:25) DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 2
[2012-02-20 22:15:36,105] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - *(5,2)
[2012-02-20 22:15:36,105] [main] (InstructionOperator.java:40) DEBUG com.ql.util.express.instruction.detail.Instruction - +(107,10)
表达式计算:10 * 10 + 1 + 2 * 3 + 5 * 2 = 117
由这个简单的例子,我们看到了整个QL的执行过程:
单词分解-->单词类型分析-->语法分析-->生成运行期指令集合-->执行生成的指令集合。
其中前4个过程涉及语法的匹配运算等非常耗时,所以我们看到了 execute方法的 isCache 是否使用Cache中的指令集参数,它可以缓存前四个过程。
即把 expressString 本地缓存乘一段指令,第二次重复执行的时候直接执行指令,极大的提高了性能。