Skip to content

Commit

Permalink
evaluate bool expression
Browse files Browse the repository at this point in the history
  • Loading branch information
skyhackvip committed Nov 29, 2023
1 parent 48655d5 commit be5f750
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 15 deletions.
4 changes: 2 additions & 2 deletions core/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (rule *Rule) Parse(ctx *PipelineContext, depends map[string]IFeature) (outp
return
}

var conditionRet = make(map[string]interface{}, 0)
var conditionRet = make(map[string]bool, 0)
for _, condition := range rule.Conditions {
if feature, ok := depends[condition.Feature]; ok {
rs, err := feature.Compare(condition.Operator, condition.Value)
Expand All @@ -67,7 +67,7 @@ func (rule *Rule) Parse(ctx *PipelineContext, depends map[string]IFeature) (outp

//rule.Decision
expr := rule.Decision.Logic
logicRet, err := operator.Evaluate(expr, conditionRet)
logicRet, err := operator.EvaluateBoolExpr(expr, conditionRet)
//某个表达式执行失败会导致最终逻辑执行失败
if err != nil {
return
Expand Down
4 changes: 2 additions & 2 deletions core/conditional.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (conditional ConditionalNode) Parse(ctx *PipelineContext) (*NodeResult, err
depends := ctx.GetFeatures(info.Depends)
var matchBranch bool
for _, branch := range conditional.Branchs { //loop all the branch
var conditionRet = make(map[string]interface{}, 0)
var conditionRet = make(map[string]bool, 0)
for _, condition := range branch.Conditions {
if feature, ok := depends[condition.Feature]; ok {
rs, err := feature.Compare(condition.Operator, condition.Value)
Expand All @@ -55,7 +55,7 @@ func (conditional ConditionalNode) Parse(ctx *PipelineContext) (*NodeResult, err
if len(conditionRet) == 0 { //current branch not match
continue
}
logicRs, err := operator.Evaluate(branch.Decision.Logic, conditionRet)
logicRs, err := operator.EvaluateBoolExpr(branch.Decision.Logic, conditionRet)
if err != nil {
continue
}
Expand Down
32 changes: 21 additions & 11 deletions internal/operator/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,12 @@ import (

// evaluate 计算逻辑表达式的值
func EvaluateBoolExpr(expr string, variables map[string]bool) (bool, error) {
expr = strings.ReplaceAll(expr, " ", "") // 去除空格
if len(expr) == 0 {
return false, fmt.Errorf("empty expression")
}
if !isValid(expr) {
return false, fmt.Errorf("invalid expression")
}

// 将表达式拆分成一个个token
tokens := splitExpression(expr)
tokens, err := splitExpression(expr)
if err != nil {
return false, err
}

// 开始执行逻辑运算
stack := make([]bool, 0)
Expand Down Expand Up @@ -126,7 +122,10 @@ func evaluateOp(b1, b2 bool, op string) bool {

// isValid 检查表达式是否合法
func isValid(expr string) bool {
allowed := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!()+-*%/|&"
if len(expr) == 0 {
return false
}
allowed := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!()+-_*%/|&,"
stack := make([]rune, 0)
for _, ch := range expr {
if ch == '(' {
Expand All @@ -144,9 +143,14 @@ func isValid(expr string) bool {
}

// splitExpression 将表达式拆分为token
func splitExpression(expr string) []string {
func splitExpression(expr string) ([]string, error) {
expr = strings.ReplaceAll(expr, " ", "") // 去除空格
if !isValid(expr) {
return nil, fmt.Errorf("invalid expression")
}
tokens := make([]string, 0)
buf := make([]rune, 0)

for i := 0; i < len(expr); i++ {
ch := rune(expr[i])
if ch == '&' && i < len(expr)-1 && rune(expr[i+1]) == '&' {
Expand All @@ -169,12 +173,18 @@ func splitExpression(expr string) []string {
buf = []rune{}
}
tokens = append(tokens, string(ch))
} else if ch == ',' {
if len(buf) > 0 {
tokens = append(tokens, string(buf))
buf = []rune{}
}
tokens = append(tokens, string(ch))
} else {
buf = append(buf, ch)
}
}
if len(buf) > 0 {
tokens = append(tokens, string(buf))
}
return tokens
return tokens, nil
}
19 changes: 19 additions & 0 deletions internal/operator/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,22 @@ func TestBoolExpr(t *testing.T) {
t.Log(expr, result, err)
t.Log(EvaluateBoolExpr("!(foo&&bar)||!a1", variables))
}

func TestSplit(t *testing.T) {
//t.Log(splitExpression("max(foo,bar)"))
// t.Log(splitExpression("tmax(foo,bar)"))
// t.Log(splitExpression("!max(foo,bar)"))
variables := map[string]bool{
"foo": true,
"bar": false,
}
t.Log(EvaluateExpr("max(foo,bar)", variables))
}

func TestEval(t *testing.T) {
variables := map[string]interface{}{
"foo": 1,
"bar": 2,
}
t.Log(Evaluate("max(foo, bar)", variables))
}

0 comments on commit be5f750

Please sign in to comment.