Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Compile ¶ added in v1.2.0
Compile parses and compiles given input expression to bytecode program.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { env := map[string]interface{}{ "foo": 1, "bar": 99, } program, err := expr.Compile("foo in 1..99 and bar in 1..99", expr.Env(env)) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: true
func Eval ¶
Eval parses, compiles and runs given input.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { output, err := expr.Eval("'hello world'", nil) if err != nil { fmt.Printf("err: %v", err) return } fmt.Printf("%v", output) }
Output: hello world
Example (Error) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { output, err := expr.Eval("(boo + bar]", nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: unexpected token Bracket("]") (1:11) | (boo + bar] | ..........^
Example (Map) ¶
package main import ( "fmt" "strings" "github.com/antonmedv/expr" ) func main() { env := map[string]interface{}{ "foo": 1, "bar": []string{"zero", "hello world"}, "swipe": func(in string) string { return strings.Replace(in, "world", "user", 1) }, } output, err := expr.Eval("swipe(bar[foo])", env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: hello user
Example (Map_method) ¶
package main import ( "fmt" "strings" "github.com/antonmedv/expr" ) func main() { env := mockMapEnv{ "foo": 1, "bar": []string{"zero", "hello world"}, } program, err := expr.Compile("Swipe(bar[foo])", expr.Env(env)) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) } type mockMapEnv map[string]interface{} func (mockMapEnv) Swipe(in string) string { return strings.Replace(in, "world", "user", 1) }
Output: hello user
Example (Matches) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { output, err := expr.Eval(`"a" matches "a("`, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: error parsing regexp: missing closing ): `a(` (1:16) | "a" matches "a(" | ...............^
Example (Struct) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { type C struct{ C int } type B struct{ B *C } type A struct{ A B } env := A{B{&C{42}}} output, err := expr.Eval("A.B.C", env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: 42
Types ¶
type Option ¶ added in v1.3.1
Option for configuring config.
func AllowUndefinedVariables ¶ added in v1.4.0
func AllowUndefinedVariables() Option
AllowUndefinedVariables allows to use undefined variables inside expressions. This can be used with expr.Env option to partially define a few variables. Note what this option is only works in map environment are used, otherwise runtime.fetch will panic as there is no way to get missing field zero value.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { code := `name == nil ? "Hello, world!" : sprintf("Hello, %v!", name)` env := map[string]interface{}{ "sprintf": fmt.Sprintf, } options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v\n", output) env["name"] = "you" // Define variables later on. output, err = expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v\n", output) }
Output: Hello, world! Hello, you!
Example (Zero_value) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { code := `name == "" ? foo + bar : foo + name` // If environment has different zero values, then undefined variables // will have it as default value. env := map[string]string{} options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } env = map[string]string{ "foo": "Hello, ", "bar": "world!", } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: Hello, world!
Example (Zero_value_functions) ¶
package main import ( "fmt" "strings" "github.com/antonmedv/expr" ) func main() { code := `words == "" ? Split("foo,bar", ",") : Split(words, ",")` // Env is map[string]string type on which methods are defined. env := mockMapStringStringEnv{} options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) } type mockMapStringStringEnv map[string]string func (m mockMapStringStringEnv) Split(s, sep string) []string { return strings.Split(s, sep) }
Output: [foo bar]
func AsBool ¶ added in v1.2.0
func AsBool() Option
AsBool tells the compiler to expect boolean result.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { env := map[string]int{ "foo": 0, } program, err := expr.Compile("foo >= 0", expr.Env(env), expr.AsBool()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(bool)) }
Output: true
func AsFloat64 ¶ added in v1.2.0
func AsFloat64() Option
AsFloat64 tells the compiler to expect float64 result.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { program, err := expr.Compile("42", expr.AsFloat64()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(float64)) }
Output: 42
func AsInt64 ¶ added in v1.2.0
func AsInt64() Option
AsInt64 tells the compiler to expect int64 result.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { env := map[string]float64{ "foo": 3, } program, err := expr.Compile("foo + 2", expr.Env(env), expr.AsInt64()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(int64)) }
Output: 5
func Env ¶ added in v1.0.7
func Env(i interface{}) Option
Env specifies expected input of env for type checks. If struct is passed, all fields will be treated as variables, as well as all fields of embedded structs and struct itself. If map is passed, all items will be treated as variables. Methods defined on this type will be available as functions.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { type Segment struct { Origin string } type Passengers struct { Adults int } type Request struct { Segments []*Segment Passengers *Passengers Marker string Meta map[string]interface{} } code := `Segments[0].Origin == "MOW" && Passengers.Adults == 2 && Marker == "test" && Meta["accept"]` program, err := expr.Compile(code, expr.Env(&Request{})) if err != nil { fmt.Printf("%v", err) return } request := &Request{ Segments: []*Segment{ {Origin: "MOW"}, }, Passengers: &Passengers{ Adults: 2, }, Marker: "test", Meta: map[string]interface{}{"accept": true}, } output, err := expr.Run(program, request) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: true
Example (Allow_undefined_variables) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { env := map[string]string{ "greet": "", } program, err := expr.Compile(`greet + name`, expr.Env(env), expr.AllowUndefinedVariables()) if err != nil { fmt.Printf("%v", err) return } params := map[string]string{ "greet": "hello, ", "name": "world", } output, err := expr.Run(program, params) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: hello, world
Example (With_undefined_variables) ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { env := map[string]interface{}{ "foo": 0, "bar": 0, } program, err := expr.Compile(`foo + (bar != nil ? bar : 2)`, expr.Env(env)) if err != nil { fmt.Printf("%v", err) return } request := map[string]interface{}{ "foo": 3, } output, err := expr.Run(program, request) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: 5
func Operator ¶ added in v1.2.0
Operator allows to override binary operator with function.
Example ¶
package main import ( "fmt" "github.com/antonmedv/expr" ) func main() { type Place struct { Code string } type Segment struct { Origin Place } type Helpers struct { PlaceEq func(p Place, s string) bool } type Request struct { Segments []*Segment Helpers } code := `Segments[0].Origin == "MOW" && PlaceEq(Segments[0].Origin, "MOW")` program, err := expr.Compile(code, expr.Env(&Request{}), expr.Operator("==", "PlaceEq")) if err != nil { fmt.Printf("%v", err) return } request := &Request{ Segments: []*Segment{ {Origin: Place{Code: "MOW"}}, }, Helpers: Helpers{PlaceEq: func(p Place, s string) bool { return p.Code == s }}, } output, err := expr.Run(program, request) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) }
Output: true