其他分享
首页 > 其他分享> > govaluate规则引擎原理解析

govaluate规则引擎原理解析

作者:互联网

序言

首先明确引入规则引擎的目的是, 从 if... else ...中解放出来。规则引擎可依据不同项目进行选型,本次主要分享bsp中使用到的govaluate规则引擎。

其输入为规则表达式和k-v键值对条件对象,通过规则引擎执行表达式,得到表达式的结果。

AST

Abstract Syntax Tree简称AST,中文叫做抽象语法树。

 

govaluate首先将表达式构建出一颗ast。举个例子:比如规则表达式为 1+foo+4*boo>0

 

exp := "1+foo+4*boo>0" expression, err := govaluate.NewEvaluableExpression(exp)

构建步骤

构建树时的流程图如下:

 

parseTokens

parserToken后,我们可以得到一堆token:

 

 

 

checkBalance

检查小括号是否成对出现

 

 

  

checkExpressionSyntax

check token之间是否符合预设规则,核心是函数getLexerStateForToken

 

 

  

check当前的token是否是上一个token的合法值,合法值是预设的,比如NUMERIC的合法值是后面这些:

 

 

 

optimizeTokens

优化token,主要是编译一下正则

 

planStages

构建ast、优化ast为avl tree、预计算。

planStages这个大步骤内部大概分成了planTokens、reorderStages、elideLiterals这三个小步骤

 

 

 

planTokens

给定一个规划器,创建一个函数来评估运算符的特定优先级,并将其链接到其他递归解析更高优先级的函数。

它用func做不同运算符的优先级计算,原理是func接收struct作为参数,而参数中的next为这个函数连接的下一个优先级的func。

 

 

其中核心函数为planPrecedenceLevel

 

 

这个func优先级打印出来是这样的:

 

有了运算符优先级之后,对于具体的节点,会继续看节点类型,比如是func,accesser还是valueType,valueType的节点对于不同的详细类型也有不同策略,比如数字节点会构建一个Node,而小括号节点会直接parser下一个token来构建优先级更高的树。

如valueType构建Node在planValue里具体体现为:

 

 

对于不同的运算符,在这个函数链上会下沉构建出优先级比较高的节点,保证符合数学计算的规律。

planToken执行完后,会变成这样一颗树:

 

 

例子体现为

 

 

 

reorderStages

这里主要把ast重排序,让ast由普通tree变成avl tree(Adelson-Velsky Landis Tree 自平衡二叉查找树)

 

重排序的过程是把相同优先级的节点进行旋转,第一步是交换左右节点:

 

 

 

第二步是LL左旋:

 

 

这样就平衡了

elideLiterals

这个步骤是看叶子节点是否为LITERAL(本例可以暂且理解为数字类型的值),遍历整个树中的所有运算符,省略两边都是LITERAL的运算符。比如这棵树:

 

 

在这个阶段,各个子节点会进行dfs(Depth First Search 深度优先搜索)预计算。

 

各符号对应的算子如下:

 

 

至此第一阶段的逻辑梳理完毕,即ast构建完成。

 

Evaluate

Evaluate的主要功能即把k-v键值对条件对象填入ast,进行计算,得到一个interface类型的结果。

 

 

不足

 

弱类型

 

govaluate所有数字类型都是被解析为float64进行计算的,这么玩写代码爽了,但是当你用1+2+9做表达式时,可能会得到一个类型为fload64的interface{}结果。

参数会去除转义符

比如这段代码:

 

 

理论上结果应该含有转义符,实际上结果是:

 

标签:优先级,ast,运算符,token,引擎,构建,govaluate,解析,节点
来源: https://www.cnblogs.com/apperception/p/16399821.html