这是我参与「第五届青训营 」伴学笔记创作活动的第 6天
一、认识规则引擎
定义
嵌入在应用中的组件,将业务决策从应用中抽离出来,并使用预定义的语义编写决策。接受数据输入,解释业务规则,做出决策
组成
数据输入 -- 支持接受使用预定义的语义编写的规则作为策略集,接受业务的数据作为参数
规则理解 -- 按预先定义的词法正确理解业务规则的语义
规则执行 -- 类型检查
应用场景
风控对抗
活动运营
数据分析及数据清洗
二、编译原理
词法分析
把源代码字符串转化为词法单元Token
基于有限自动机,状态转换
语法分析
在词法分析的基础上,识别语法结构
基于抽象语法树(上下文无关语法)
类型检查
综合检查
- 根据子表达式构造父表达式的类型
运行/编译时检查
- 编译时提前声明
- 执行时根据传入的参数的类型,在执行过程中检查
三、设计一个规则引擎
设计目标
设计一个规则引擎,支持特定的词法、运算符、数据类型和优先级。并且支持基于以上预定义语法的规则表达式的编译和执行。
- 词法分析
- 运算符
- 数据类型
- 优先级
词法分析
参数:由字母数字下划线组成eg:_ab2、user_name
布尔值:true、false
字符串:"abcd"、'abcd'、`abcd`
十进制int:1234
十进制float:123.5
一元运算符:+ -
二元运算符:+ - * / % > < >= <= == !=
逻辑操作符:&& || !
括号:()
语法分析
- 优先级的表达
- 语法树结构
- 递归下降
语法树执行与类型检查
- 语法树执行 -- 后续遍历
- 类型检查 -- 在节点左右子节点执行完成后分别校验类型是否符合预设
四、实现规则引擎
项目地址:简单的规则引擎
运行:
docker-compose up
go run ./main.go
默认端口是 :8888 测试一下
func Compiler(exp string) (*executor.Node, error) {
// 扫描语句
tokenScanner := compiler.NewScanner(exp)
// 词法分析
tokens, err := tokenScanner.Lexer()
if err != nil {
return nil, err
}
// 语法分析
parser := compiler.NewParser(tokens)
err = parser.ParseSyntax()
if err != nil {
return nil, err
}
// 优先级判断
astBuilder := compiler.NewBuilder(parser)
ast, err := astBuilder.Build()
if err != nil {
return nil, err
}
return ast, nil
}
五、总结
本次课程内容非常的偏向语言底层,需要一定编译原理的基础,有利于更好地理解。课后有空多多阅读代码,实现一个web版规则引擎