goexpr

package
v0.0.0-...-98a29f8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2024 License: Apache-2.0 Imports: 9 Imported by: 0

README

goexpr

golang 表达式引擎,规则引擎,支持自定义函数,自定义中缀操作符,自定义前缀操作符,支持传参以及参数层级嵌套,支持数组,字符串,数字,变量等操作

Golang expression engine, rule engine, support custom functions, custom infix operators, custom prefix operators, support parameter passing and parameter hierarchical nesting, support arrays, strings, numbers, variables and other operations

import (
	"fmt"
	"reflect"
	"testing"
)

func Contain(a, b interface{}) interface{} {
	bStr := fmt.Sprint(b)
	array := reflect.ValueOf(a)
	length := array.Len()
	for i := 0; i < length; i++ {
		aStr := fmt.Sprint(array.Index(i).Interface())
		if bStr == aStr {
			return true
		}
	}
	return false
}

func TestEngine(t *testing.T) {
	exprs := `-4+3>(-9)&&5<4+5&&3NotIN[1,2,4]&&ADD(1,2)<4&&-(#-3-4)<=30&&4>1&&[1,2,4] Contain 4 && ADD(1,2)!=1 && user.name=='kiteee' && user_count>20`
	//exprs = `-------1`
	//exprs=`user.name=='kiteee' && user_count>20`
	//exprs=`user_count>20 && user_count>20`
	//exprs=`#--3*-4-#2`
	//exprs=`-4-#2`
	//exprs = `3NotIN([1,2,3])&&ADD(1,2)<4`
	//exprs = `[1,2,4] Contain 4 IN [true] NotIN [false]`
	eg := NewEngine()
	eg.AddFunc("ADD", func(v ...interface{}) interface{} {
		return floatVal(v[0]) + floatVal(v[1])
	})
	eg.AddPrefix("#", func(v interface{}) interface{} {
		return floatVal(v) * floatVal(v)
	})
	eg.AddInfix("Contain", 30, func(v1, v2 interface{}) interface{} {
		return Contain(v1, v2)
	})
	var params = map[string]interface{}{
		"user": map[string]interface{}{
			"name": "kiteee",
			"age":  50,
		},
		"user_count": 30,
	}
	//eg.SetPriority("NotIN", 30)
	result := eg.Execute(exprs, params)
	fmt.Println(result)
}

func TestSpitExpr(t *testing.T) {
	exprs := `('ssss','aaa',['aaa',bb],[aaa,game notIn values],funa bsna ( sa,ssdf), atype contains (90),type notIn [1,2,4],value >= images ,-add(),[name,add()],-otEs(),[[-aaam,bb],bbb])`
	exprs = `()`
	result := SpitExpr(exprs)
	for _, v := range result {
		fmt.Println(v)
	}
}

func TestGetArgs(t *testing.T) {
	var mp = map[string]interface{}{
		"user": map[string]interface{}{
			"name": "kiteee",
			"age":  50,
		},
	}
	va := GetArg("user.name", mp)
	fmt.Println(va)
}

Documentation

Index

Constants

View Source
const (
	Variable string = "Variable"
	Func     string = "function"
	PreOp    string = "prefixOp"
	InfxOp   string = "infixOp"
	Value    string = "value"
	Array    string = "array"
	Args     string = "funcArgs"
)
View Source
const (
	Trim       string = "Trim"
	IN         string = "IN"
	NotIn      string = "NotIN"
	Like       string = "Like"
	Equal      string = "=="
	Less       string = "<"
	LessEqual  string = "<="
	AboveEqual string = ">="
	Above      string = ">"
	NotEqual   string = "!="
	Add        string = "+"
	Sub        string = "-"
	Mult       string = "*"
	Div        string = "/"
	Rest       string = "%"
	And        string = "&&"
	Or         string = "||"
	Not        string = "!"
	BraktLeft  string = "("
	BraktRight string = ")"
	ArrayLeft  string = "["
	ArrayRight string = "]"
	ItemSpit   string = ","
)

Variables

View Source
var InfixOpSet = map[string]InfixOp{
	Equal: func(v1, v2 interface{}) interface{} {
		return fmt.Sprint(v1) == fmt.Sprint(v2)
	},
	Add: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) + FloatVal(v2)
	},
	Sub: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) - FloatVal(v2)
	},
	Mult: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) * FloatVal(v2)
	},
	Div: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) / FloatVal(v2)
	},
	Rest: func(v1, v2 interface{}) interface{} {
		return int64(FloatVal(v1)) % int64(FloatVal(v2))
	},
	And: func(v1, v2 interface{}) interface{} {
		return v1.(bool) && v2.(bool)
	},
	Or: func(v1, v2 interface{}) interface{} {
		return v1.(bool) || v2.(bool)
	},
	Less: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) < FloatVal(v2)
	},
	LessEqual: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) <= FloatVal(v2)
	},
	AboveEqual: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) >= FloatVal(v2)
	},
	Above: func(v1, v2 interface{}) interface{} {
		return FloatVal(v1) > FloatVal(v2)
	},
	NotEqual: func(v1, v2 interface{}) interface{} {
		return fmt.Sprint(v1) != fmt.Sprint(v2)
	},
	IN: func(v1 interface{}, v2 interface{}) interface{} {
		return in(v1, v2)
	},
	NotIn: func(v1 interface{}, v2 interface{}) interface{} {
		return notIn(v1, v2)
	},
	Like: func(v1 interface{}, v2 interface{}) interface{} {
		return like(v1, v2)
	},
}
View Source
var OpFunctionSet = map[string]FunctionOp{
	Trim: func(v ...interface{}) interface{} {
		v1 := fmt.Sprint(v)
		v1 = strings.Trim(v1, "[")
		v1 = strings.Trim(v1, "]")
		v1 = strings.Replace(v1, " ", "", -1)
		return strings.TrimSpace(v1)
	},
}
View Source
var OpPriority = map[string]int32{
	Mult:       60,
	Div:        60,
	Rest:       60,
	Add:        50,
	Sub:        50,
	Above:      40,
	AboveEqual: 40,
	Less:       40,
	LessEqual:  40,
	Equal:      40,
	NotEqual:   40,
	IN:         30,
	NotIn:      30,
	Like:       30,
	And:        20,
	Or:         10,
}
View Source
var PrefixOpSet = map[string]PrefixOp{
	Not: func(v1 interface{}) interface{} {
		return !v1.(bool)
	},
	Sub: func(v interface{}) interface{} {
		return -FloatVal(v)
	},
}

Functions

func Contain

func Contain(a, b interface{}) interface{}

func FloatVal

func FloatVal(v interface{}) float64

func GetArg

func GetArg(path string, args map[string]interface{}) interface{}

func GetNumber

func GetNumber(str string) (float64, bool)

func Has

func Has(array []string, va string) bool

func SpitExpr

func SpitExpr(exprs string) []string

Types

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

func NewEngine

func NewEngine() *Engine

func (*Engine) AddFunc

func (en *Engine) AddFunc(fname string, op FunctionOp)

func (*Engine) AddInfix

func (en *Engine) AddInfix(fname string, priority int32, op InfixOp)

func (*Engine) AddPrefix

func (en *Engine) AddPrefix(fname string, op PrefixOp)

func (*Engine) CalculateBract

func (eng *Engine) CalculateBract(opStack, nbStack *lls.Stack)

func (*Engine) CalculateStack

func (eng *Engine) CalculateStack(opStack, nbStack *lls.Stack)

func (*Engine) CalculateTop

func (eng *Engine) CalculateTop(opStack, nbStack *lls.Stack)

func (*Engine) Execute

func (en *Engine) Execute(expression string, args map[string]interface{}) interface{}

func (*Engine) GetToken

func (eng *Engine) GetToken(pToken *Token, expr string) *Token

func (*Engine) IsOpToken

func (eng *Engine) IsOpToken(tk *Token) bool

func (*Engine) PushCurOpera

func (eng *Engine) PushCurOpera(curTk *Token, opStack, nbStack *lls.Stack)

func (*Engine) SetPriority

func (en *Engine) SetPriority(infix string, priority int32)

type FunctionOp

type FunctionOp func(v ...interface{}) interface{}

函数运算

type InfixOp

type InfixOp func(v1, v2 interface{}) interface{}

中缀运算

type PrefixOp

type PrefixOp func(v interface{}) interface{}

前缀运算

type Token

type Token struct {
	Value string
	Type  string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL