expr: github.com/antonmedv/expr Index | Examples | Files | Directories

package expr

import "github.com/antonmedv/expr"

Index

Examples

Package Files

expr.go

func Compile Uses

func Compile(input string, ops ...Option) (*vm.Program, error)

Compile parses and compiles given input expression to bytecode program.

Code:

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 Uses

func Eval(input string, env interface{}) (interface{}, error)

Eval parses, compiles and runs given input.

Code:

output, err := expr.Eval("'hello world'", nil)
if err != nil {
    fmt.Printf("err: %v", err)
    return
}

fmt.Printf("%v", output)

Output:

hello world

Code:

output, err := expr.Eval("(boo + bar]", nil)
if err != nil {
    fmt.Printf("%v", err)
    return
}

fmt.Printf("%v", output)

Output:

syntax error: mismatched input ']' expecting ')' (1:11)
 | (boo + bar]
 | ..........^

Code:

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

Code:

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:13)
 | "a" matches "a("
 | ............^

Code:

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

func Parse Uses

func Parse(input string, ops ...Option) (*vm.Program, error)

Parse parses input string to a program.

Deprecated: use expr.Compile instead.

func Run Uses

func Run(program *vm.Program, env interface{}) (interface{}, error)

Run evaluates given bytecode program.

type Option Uses

type Option func(c *conf.Config)

Option for configuring config.

func AllowUndefinedVariables Uses

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.

func AsBool Uses

func AsBool() Option

AsBool tells the compiler to expect boolean result.

Code:

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 Uses

func AsFloat64() Option

AsFloat64 tells the compiler to expect float64 result.

Code:

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 Uses

func AsInt64() Option

AsInt64 tells the compiler to expect int64 result.

Code:

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 Uses

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.

Code:

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

func Operator Uses

func Operator(operator string, fn ...string) Option

Operator allows to override binary operator with function.

Code:

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

Code:

type Segment struct {
    Date time.Time
}
type Request struct {
    Segments []Segment
    Before   func(a, b time.Time) bool
    Date     func(s string) time.Time
}

code := `Date("2001-01-01") < Segments[0].Date`

program, err := expr.Compile(code, expr.Env(&Request{}), expr.Operator("<", "Before"))
if err != nil {
    fmt.Printf("%v", err)
    return
}

request := &Request{
    Segments: []Segment{
        {Date: time.Date(2019, 7, 1, 0, 0, 0, 0, time.UTC)},
    },
    Before: func(a, b time.Time) bool {
        return a.Before(b)
    },
    Date: func(s string) time.Time {
        date, err := time.Parse("2006-01-02", s)
        if err != nil {
            panic(err)
        }
        return date
    },
}

output, err := expr.Run(program, request)
if err != nil {
    fmt.Printf("%v", err)
    return
}

fmt.Printf("%v", output)

Output:

true

func Optimize Uses

func Optimize(b bool) Option

Optimize turns optimizations on or off.

Directories

PathSynopsis
ast
checker
compiler
docgen
internal/conf
internal/file
optimizer
parser
parser/gen
vm
vm/generate

Package expr imports 8 packages (graph) and is imported by 6 packages. Updated 2019-11-13. Refresh now. Tools for package owners.