lexpr/README.md
2022-06-13 04:31:31 +03:00

3.2 KiB

Lexpr - universal expression evaluator

This library can evaluate any types of expressions: math expression, logic expression, simple DSLs.

Installation

go get go.neonxp.dev/lexpr

Usage

ctx := context.Background()
l := lexpr.New(lexpr.WithDefaults())

// Simple math
result1 := <-l.Eval(ctx, `2 + 2 * 2`) // Output channel can return many results
log.Println("Result 1:", result1.Value) // Output: 6

// Helper for exact one result
result2, err := l.OneResult(ctx, `len("test") + 10`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 2:", result2) // Output: 14

// Custom functions
l.SetFunction("add", func(ts *lexpr.TokenStack) error {
 a, okA := ts.Pop().Number() // first func argument
 b, okB := ts.Pop().Number() // second func argument
 if !okA || !okB {
  return fmt.Errorf("Both args must be number")
 }
 ts.Push(lexpr.TokenFromInt(a + b))
 return nil
})
result3, err := l.OneResult(ctx, `add(12, 24) * 2`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 3:", result3) // Output: 72

// JSON extraction via dots and variables
jsonString := `{
 "rootKey1": "value1",
 "rootKey2": {
  "childKey1": "value2",
  "childKey2": "value3"
 },
 "arrayKey": [
  "array value 1",
  "array value 2",
  "array value 3",
  "array value 4"
 ]
}`
key1name := "rootKey1"
l.SetVariable("jsonData", jsonString)
l.SetVariable("key1name", key1name)
result41, err := l.OneResult(ctx, `jsonData.key1name`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 4-1:", result41) // Output: "value1"
result42, err := l.OneResult(ctx, `jsonData.rootKey2.childKey2`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 4-2:", result42) // Output: "value3"
result43, err := l.OneResult(ctx, `jsonData.arrayKey.3`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 4-3:", result43) // Output: "array value 4"

// Logic expressions
result51, err := l.OneResult(ctx, `jsonData.key1name == "value1"`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 5-1:", result51) // Output: 1
result52, err := l.OneResult(ctx, `10 >= 5 || 10 <= 5`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 5-2:", result52) // Output: 1
result53, err := l.OneResult(ctx, `10 >= 5 && 10 <= 5`)
if err != nil {
 log.Fatal(err)
}
log.Println("Result 5-3:", result53) // Output: 0

Default operators

Operator Description Example
JSON operators
. Extract field from json jsonData.key1.0.key2
Math operators
** Power number 3 ** 3 = 27
* Multiple numbers 2 * 4 = 8
/ Divide number 6 / 3 = 2
% Rem of division 5 % 3 = 2
+ Sum 2 + 2 = 4
- Substract 6 - 2 = 4
Logic operators
! Logic not !1 = 0
> More 3 > 2 = 1
>= More or equal 3 >= 3 = 1
< Less 3 < 2 = 0
<= Less or equal 3 <= 3 = 1
== Equal 1==1 = 1
!= Not equal 1!=1 = 0
&& Logic and 3 > 0 && 1 > 0 = 1
` `

Default functions

Function Description Example
max returns max of two values max(1,2) = 2
min returns min of two values max(1,2) = 1
len returns length of string len("test") = 4
atoi converts string to number atoi("123") = 123
itoa converts number to string itoa(123) = "123"

Contribution

PRs are welcome.