Documentation ¶
Overview ¶
Package gval provides a generic expression language with concrete language instances of several basic languages. In gval base language, an Operator involves either unicode letters or unicode punctuations and unicode symbols.
Index ¶
- func Evaluate(expression string, parameter interface{}, opts ...Language) (interface{}, error)
- type Evaluable
- func (e Evaluable) EvalBool(c context.Context, parameter interface{}) (bool, error)
- func (e Evaluable) EvalFloat64(c context.Context, parameter interface{}) (float64, error)
- func (e Evaluable) EvalInt(c context.Context, parameter interface{}) (int, error)
- func (e Evaluable) EvalString(c context.Context, parameter interface{}) (string, error)
- func (e Evaluable) IsConst() bool
- type Language
- func Arithmetic() Language
- func Base() Language
- func Bitmask() Language
- func Constant(name string, value interface{}) Language
- func Full(extensions ...Language) Language
- func Function(name string, function interface{}) Language
- func InfixBoolOperator(name string, f func(a, b bool) (interface{}, error)) Language
- func InfixEvalOperator(name string, f func(a, b Evaluable) (Evaluable, error)) Language
- func InfixNumberOperator(name string, f func(a, b float64) (interface{}, error)) Language
- func InfixOperator(name string, f func(a, b interface{}) (interface{}, error)) Language
- func InfixShortCircuit(name string, f func(a interface{}) (interface{}, bool)) Language
- func InfixTextOperator(name string, f func(a, b string) (interface{}, error)) Language
- func JSON() Language
- func NewLanguage(bases ...Language) Language
- func PostfixOperator(name string, ext func(context.Context, *Parser, Evaluable) (Evaluable, error)) Language
- func Precedence(name string, operatorPrecendence uint8) Language
- func PrefixExtension(r rune, ext func(context.Context, *Parser) (Evaluable, error)) Language
- func PrefixMetaPrefix(r rune, ...) Language
- func PrefixOperator(name string, e Evaluable) Language
- func PropositionalLogic() Language
- func Text() Language
- type Parser
- func (p *Parser) Camouflage(unit string, expected ...rune)
- func (*Parser) Const(value interface{}) Evaluable
- func (p *Parser) Expected(unit string, expected ...rune) error
- func (p *Parser) Next() rune
- func (p *Parser) ParseExpression(c context.Context) (eval Evaluable, err error)
- func (p *Parser) ParseNextExpression(c context.Context) (eval Evaluable, err error)
- func (p *Parser) Peek() rune
- func (p *Parser) Scan() rune
- func (p *Parser) TokenText() string
- func (*Parser) Var(path ...Evaluable) Evaluable
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Evaluate ¶
Evaluate given parameter with given expression in gval full language
Example (Accessor) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) type exampleType struct { Hello string } func (e exampleType) World() string { return "wolrd" } func main() { value, err := gval.Evaluate(`foo.Hello + foo.World()`, map[string]interface{}{ "foo": exampleType{Hello: "hello "}, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // hello world! }
Output:
Example (Arithmetic) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("(requests_made * requests_succeeded / 100) >= 90", map[string]interface{}{ "requests_made": 100, "requests_succeeded": 80, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // false }
Output:
Example (Basic) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("10 > 0", nil) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // true }
Output:
Example (DateComparison) ¶
package main import ( "fmt" "os" "time" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("date(`2014-01-02`) > date(`2014-01-01 23:59:59`)", nil, // define Date comparison because it is not part expression language gval gval.InfixOperator(">", func(a, b interface{}) (interface{}, error) { date1, ok1 := a.(time.Time) date2, ok2 := b.(time.Time) if ok1 && ok2 { return date1.Before(date2), nil } return nil, fmt.Errorf("unexpected operands types (%T) > (%T)", a, b) }), ) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // true }
Output:
Example (Encoding) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate(`(7 < "47" == true ? "hello world!\n\u263a")`+" + ` more text`", nil, gval.Function("strlen", func(args ...interface{}) (interface{}, error) { length := len(args[0].(string)) return (float64)(length), nil })) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // hello world! // ☺ more text }
Output:
Example (FlatAccessor) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) type exampleType struct { Hello string } func (e exampleType) World() string { return "wolrd" } func main() { value, err := gval.Evaluate(`Hello + World()`, exampleType{Hello: "hello "}, ) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // hello world! }
Output:
Example (Float64) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("(mem_used / total_mem) * 100", map[string]interface{}{ "total_mem": 1024, "mem_used": 512, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // 50 }
Output:
Example (Jsonpath) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" "github.com/PaesslerAG/jsonpath" ) func main() { value, err := gval.Evaluate(`$["response-time"]`, map[string]interface{}{ "response-time": 100, }, jsonpath.Language(), ) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // 100 }
Output:
Example (NestedAccessor) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) type exampleType struct { Hello string } func (e exampleType) World() string { return "wolrd" } func main() { value, err := gval.Evaluate(`foo.Hello + foo.World()`, map[string]interface{}{ "foo": struct{ bar exampleType }{ bar: exampleType{Hello: "hello "}, }, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // hello world! }
Output:
Example (NestedParameter) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("foo.bar > 0", map[string]interface{}{ "foo": map[string]interface{}{"bar": -1.}, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // false }
Output:
Example (Parameter) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate("foo > 0", map[string]interface{}{ "foo": -1., }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // false }
Output:
Example (String) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate(`http_response_body == "service is ok"`, map[string]interface{}{ "http_response_body": "service is ok", }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // false }
Output:
Example (Strlen) ¶
package main import ( "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { value, err := gval.Evaluate(`strlen("someReallyLongInputString") <= 16`, nil, gval.Function("strlen", func(args ...interface{}) (interface{}, error) { length := len(args[0].(string)) return (float64)(length), nil })) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Print(value) // Output // false }
Output:
Types ¶
type Evaluable ¶
Evaluable evaluates given parameter
Example ¶
package main import ( "context" "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { eval, err := gval.Full(gval.Constant("maximum_time", 53)). NewEvaluable("response_time <= maximum_time") if err != nil { fmt.Println(err) os.Exit(1) } for i := 50; i < 55; i++ { value, err := eval(context.Background(), map[string]interface{}{ "response_time": i, }) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(value) } // Output // true // true // true // false // false }
Output:
func (Evaluable) EvalFloat64 ¶
EvalFloat64 evaluates given parameter to an int
func (Evaluable) EvalString ¶
EvalString evaluates given parameter to a string
type Language ¶
type Language struct {
// contains filtered or unexported fields
}
Language is an expression language
Example ¶
package main import ( "context" "fmt" "os" "github.com/PaesslerAG/gval" ) func main() { lang := gval.NewLanguage(gval.JSON(), gval.Arithmetic(), //pipe operator gval.PostfixOperator("|", func(c context.Context, p *gval.Parser, pre gval.Evaluable) (gval.Evaluable, error) { post, err := p.ParseExpression(c) if err != nil { return nil, err } return func(c context.Context, v interface{}) (interface{}, error) { v, err := pre(c, v) if err != nil { return nil, err } return post(c, v) }, nil })) eval, err := lang.NewEvaluable(`{"foobar": 50} | foobar + 100`) if err != nil { fmt.Println(err) os.Exit(1) } value, err := eval(context.Background(), nil) if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(value) // Output // 150 }
Output:
func Arithmetic ¶
func Arithmetic() Language
Arithmetic contains base, plus(+), minus(-), divide(/), power(**), negative(-) and numerical order (<=,<,>,>=)
Arithmetic operators expect float64 operands. Called with unfitting input, they try to convert the input to float64. They can parse strings and convert any type of int or float.
func Base ¶
func Base() Language
Base contains equal (==) and not equal (!=), perentheses and general support for variables, constants and functions It contains true, false, (floating point) number, string ("" or “) and char (”) constants
func Bitmask ¶
func Bitmask() Language
Bitmask contains base, bitwise and(&), bitwise or(|) and bitwise not(^).
Bitmask operators expect float64 operands. Called with unfitting input they try to convert the input to float64. They can parse strings and convert any type of int or float.
func Full ¶
Full is the union of Arithmetic, Bitmask, Text, PropositionalLogic, and Json
Operator in: a in b is true iff value a is an element of array b Operator ??: a ?? b returns a if a is not false or nil, otherwise n Operator ?: a ? b : c returns b if bool a is true, otherwise b
Function Date: Date(a) parses string a. a must match RFC3339, ISO8601, ruby date, or unix date
func Function ¶
Function returns a Language with given function. Function has no conversion for input types.
If the function returns an error it must be the last return parameter.
If the function has (without the error) more then one return parameter, it returns them as []interface{}.
func InfixBoolOperator ¶
InfixBoolOperator for two bool values.
func InfixEvalOperator ¶
InfixEvalOperator operates on the raw operands. Therefore it cannot be combined with operators for other operand types.
func InfixNumberOperator ¶
InfixNumberOperator for two number values.
func InfixOperator ¶
InfixOperator for two arbitrary values.
func InfixShortCircuit ¶
InfixShortCircuit operator is called after the left operand is evaluated.
func InfixTextOperator ¶
InfixTextOperator for two text values.
func JSON ¶
func JSON() Language
JSON contains json objects ({string:expression,...}) and json arrays ([expression, ...])
func NewLanguage ¶
NewLanguage returns the union of given Languages as new Language.
func PostfixOperator ¶
func PostfixOperator(name string, ext func(context.Context, *Parser, Evaluable) (Evaluable, error)) Language
PostfixOperator extends a Language
func Precedence ¶
Precedence of operator. The Operator with higher operatorPrecedence is evaluated first.
func PrefixExtension ¶
PrefixExtension extends a Language
func PrefixMetaPrefix ¶
func PrefixMetaPrefix(r rune, ext func(context.Context, *Parser) (call string, alternative func() (Evaluable, error), err error)) Language
PrefixMetaPrefix chooses a Prefix to be executed
func PrefixOperator ¶
PrefixOperator returns a Language with given prefix
func PropositionalLogic ¶
func PropositionalLogic() Language
PropositionalLogic contains base, not(!), and (&&), or (||) and Base.
Propositional operator expect bool operands. Called with unfitting input they try to convert the input to bool. Numbers other than 0 and the strings "TRUE" and "true" are interpreted as true. 0 and the strings "FALSE" and "false" are interpreted as false.
func Text ¶
func Text() Language
Text contains base, lexical order on strings (<=,<,>,>=), regex match (=~) and regex not match (!~)
type Parser ¶
type Parser struct { Language // contains filtered or unexported fields }
Parser parses expressions in a Language into an Evaluable
func (*Parser) Camouflage ¶
Camouflage rewind the last Scan(). The Parser holds the camouflage error until the next Scan() Do not call Rewind() on a camouflaged Parser
func (*Parser) Next ¶
Next reads and returns the next Unicode character. It returns EOF at the end of the source. Do not call Next() on a camouflaged Parser
func (*Parser) ParseExpression ¶
ParseExpression scans an expression into an Evaluable.
func (*Parser) ParseNextExpression ¶
ParseNextExpression scans the expression ignoring following operators
func (*Parser) Peek ¶
Peek returns the next Unicode character in the source without advancing the scanner. It returns EOF if the scanner's position is at the last character of the source. Do not call Peek() on a camouflaged Parser
func (*Parser) Scan ¶
Scan reads the next token or Unicode character from source and returns it. It only recognizes tokens t for which the respective Mode bit (1<<-t) is set. It returns scanner.EOF at the end of the source.