很早前,实现过一个公式表达式解析模块,大大提升了系统的灵活性。
实现背景
假设用户的需求如下:
如果用户订购的产品是按天收费的,则按使用天数*每天的费用,但不能超过产品设置的最大值,如果使用一天收取1元,一个月最大值为20元,则收费为min((天数*1),20)
采用硬编码的方式实现如下:
if(产品的类型 == 按天收取)
{
计算使用天数
收取费用 = min((使用天数*按天收取的值),产品的最大限制)
}
else if(产品类型 == 。。。)
。。。
如果能使用公式的方式,那么这些只需要在产品的配置上配置为return min((use_days * prod_fee,max_prod_fee)即可,其中use_days、prod_fee和max_prod_fee为模块开放给外部的变量。
实现细节
实现时先预编译公式为内部指令,然后在计算费用的时候再执行内部指令。
实现架构如下:
业务模块初始化流程:
业务模块执行流程:
编译采用了bison和flex工具,首先将公式串解析成树,如1+1,树形式为
对分析后的树进行后缀方式遍历,那么此树将被分析成11+
在执行时利用两个堆栈,一个保留运算符,一个保留数据,逐个从编译后的指令串中解析执行,对运算符根据优先级保留在运算符栈中,数据保存在数据栈中
最后实现了if语句,多行语句等功能,由于采用了预编译技术和绑定变量地址技术,执行效率非常高