@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
单词分解-->单词类型分析-->语法分析-->生成运行期指令集合-->执行生成的指令集合。
其中前4个过程涉及语法的匹配运算等非常耗时,所以我们看到了 execute方法的 isCache 是否使用Cache中的指令集参数,它可以缓存前四个过程 。
即把 expressString 本地缓存乘一段指令,第二次重复执行的时候直接执行指令,极大的提高了性能。