Spads 公式解析系统 - Java

来源:互联网 发布:vb精简版下载 编辑:程序博客网 时间:2024/05/16 09:36
很多网络应用中,涉及到一些内部运算的具体求值逻辑并不能够在开发阶段就定下来。这些逻辑需要随着使用,探测用户反应,不断修正。符合的情况,常见的就是网络游戏中的行动收获计算公式,等等。现 Spads 开发组推出了针对此种情况的解析公式系统,供大家使用。

此公式解析系统能够计算各种算术运算、逻辑运算和比较运算,可以连接本地函数,支持括号分级,允许逐级设置公式内临时变量,提供了分支运算符,并且支持 Json 数据格式的运算。系统编写中使用了很多设计方法,包括概念抽取、继承、多态、面向接口设计、枚举、递归、工厂等等。数据结构也使用了好用但少见的双端队列。很适合对应情况的实用以及学习 Java 的设计思路、编程方式。本程序由 Shane Loo LI 设计和编写,所有的细节都注重了运行效率,在很多细节上都制作了数倍优于爪哇(Java)系统类库的方法;由于只需要处理公式,所以语法树结构单一,也因此保证了比现有其它注入语言的代码解释器更高的执行速度。

下面来介绍一下公式解析系统的用法。
首先,公式通过 ?= 来给变量赋值。这种赋值并不是一个运算,而是公式每一行需要且只能出现一次的专属符号。
Result ?= 38 * 6
公式解析系统用 Result 来表示最终的结果。以上公式表示最终的结果为 228 。

本系统支持以下算术运算:
求负 -
加 +
减 -
乘 *
除 /
求余 %
乘方 ^
阶乘 !
比如
Result ?= ((2^5 - (-13)) % 10)!
能够得到 120 。

接下来,让我们看看公式系统的分支控制。
DayCount ?= 31DayCost ?= 58.5Limit ?= 1500Result ?= DayCount * DayCost > Limit ? "超支了!" ~ "没超支"
我们看到整个公式分为四行。每行声明了一个变量。
实际上在这个公式系统中,并不严格要求上边的公式不能够使用下边公式声明的变量,但如果嵌套使用则会抛出异常。
上述公式将得到一个字符串,内容是“超支了”。

支持的有关运算如下:
大于 >
小于 <
等于 =
与 &
或 |
非 -(这个和 C 语言系列的 ! 有所不同)
条件 ?
分支 ~(这个和 C 语言系列的 : 有所不同)

这个系统最重要的特性,就是能够把公式中出现的函数,和本地函数绑定起来。
只需要制作 Function 接口的实现类,并且在 FunctionEnum 对其进行注册,就能够得到一种可以在公式中识别的函数。
我最近学习了“约定优于明示”的思想,近期会将这种 FunctionEnum 配置方式进行一定程度的更改。

比如,我提供了内置函数 TOGETHER ,其含义是以第一个参数为名称,第二个参数为值,构成键值对;第三个参数为名称,第四个参数为值,构成键值对;等等。最终将其组合成 Json 字符串。请看如下公式。
Name ?= "Shane"Level ?= 16Result ?= TOGETHER("name", Name, "graduated", Level > 10 ? "毕业了" ~ "没毕业")
最终结果为 {"name": "Shane", "graduated": "毕业了"}


说了这么多公式解析系统的用法。现在来从编程角度介绍一下如何启用此系统功能。
首先,肯定是要导入 .jar 包。然后参看以下代码。
EvaluatorFactory factory = EvaluatorFactory.INST;Evaluator eva = factory.getEvaluator("Result ?= 28 + 2 / 10.0");ExpValue result = eva.evaluate();System.out.println(result);
或者
String form = "Result ?= 28 + 2 / 10.0";ExpValue result = EvaluatorFactory.INST.getEvaluator(form).evaluate();
首先,计算器工厂是单例的,但以后如果要扩展函数库,则可以改写成多种工厂。获取工厂后,传入公式字符串(多行),以通过工厂获取针对此公式的计算器。然后调用计算器的计算方法,即可获得公式最终的结果。

如有疑问,可以联系 Surmounting@gmail.com

项目包下载地址为: http://download.csdn.net/detail/shanelooli/4726670