doc | ||
ast_test.go | ||
ast.go | ||
byte-slider.go | ||
context.go | ||
control.go | ||
func-import.go | ||
func-math.go | ||
go.mod | ||
helpers_test.go | ||
helpers.go | ||
it-range.go | ||
iterator.go | ||
operand-const.go | ||
operand-expr.go | ||
operand-func.go | ||
operand-list.go | ||
operand-selector-case.go | ||
operand-var.go | ||
operator-assign.go | ||
operator-bool.go | ||
operator-but.go | ||
operator-coalesce.go | ||
operator-ctrl.go | ||
operator-fact.go | ||
operator-prod.go | ||
operator-rel.go | ||
operator-selector.go | ||
operator-sign.go | ||
operator-sum.go | ||
parser_test.go | ||
parser.go | ||
README.adoc | ||
sample-export-all.expr | ||
scanner_test.go | ||
scanner.go | ||
simple-func-store.go | ||
simple-var-store.go | ||
symbol.go | ||
term_test.go | ||
term-constuctor-registry.go | ||
term.go | ||
test-funcs.expr | ||
token_test.go | ||
token.go | ||
utils.go |
Expr
1. Expr
Expr is a GO package capable of analysing, interpreting and calculating expressions.
A few examples to get started.
`1.0 / 2` // 0.5
`435 + 105 * 2 - 1` // 644
`4 == (3-1)*(10/5)` // true
`"uno" * (2+1)` // `unounouno`
`2+3 but 5*2` // 10 (1)
`add(add(1+4),3+2,5*(3-2))` // 15 (2)
`a=5; b=2; add(a, b*3)` // 11 (3)
`two=func(){2}; two()` // 2 (4)
`double=func(x){2*x}; a=4+1; two=func() {2}; (double(3+a) + 1) * two()` // 34
`import("./test-funcs.expr"); (double(3+a) + 1) * two()` // 34 (5)
`[1,2,"hello"]` // Mixed types list
`[1,2]+[3]` // append list, result: [1,2,3]
`add([1,[2,2],3,2])` // Deep list sum, result: 10 (2)
`[a=1,b=2,c=3] but a+b+c` // 6
1 | but operator. |
2 | The add() function definition may be changed in the future. |
3 | Multiple expression. Only the last expression value will returned. |
4 | Simple function definition: two() returns 2. |
5 | import() function imports expressions from the specified files. See file test-funcs.expr. |
1.1. Usage
package main
import (
"fmt"
"strings"
"git.portale-stac.it/go-pkg/expr"
)
func main() {
ctx := expr.NewSimpleVarStore()
ctx.SetValue("var", int64(4))
source := `(3-1)*(10/5) == var`
r := strings.NewReader(source)
scanner := expr.NewScanner(r, DefaultTranslations())
parser := expr.NewParser(ctx)
if ast, err := parser.Parse(scanner); err == nil {
if result, err := ast.Eval(ctx); err == nil {
fmt.Printf("%q -> %v [%T]\n", source, result, result)
} else {
fmt.Println("Error calculating the expression:", err)
}
} else {
fmt.Println("Error parsing the expression:", err)
}
}
The above program is equivalent to the following one.
import (
"fmt"
"git.portale-stac.it/go-pkg/expr"
)
func main() {
ctx := expr.NewSimpleVarStore()
ctx.SetValue("var", int64(4))
source := `(3-1)*(10/5) == var`
if result, err := expr.EvalString(ctx, source); err == nil {
fmt.Printf("%q -> %v [%T]\n", source, result, result)
} else {
fmt.Println("Error calculating the expression:", err)
}
}
1.2. Data types
Expr supports numerical, string, relational, boolean expressions, and mixed-type lists.
1.2.1. Numbers
Numbers can be integers (GO int64) or float (GO float64). In mixed operations involving integers and floats, integers are automatically promoted to floats.
Symbol | Operation | Description | Examples |
---|---|---|---|
|
change sign |
Change the sign of values |
|
|
sum |
Add two values |
|
|
subtraction |
Subtract the right value from the left one |
|
|
product |
Multiply two values |
|
|
Division |
Divide the left value by the right one |
|
|
Float division |
Force float division |
|
|
Modulo |
Remainder of the integer division |
|
1.2.2. String
Strings are character sequences enclosed between two double quote "
. Example: "I’m a string"
.
Some arithmetic operators can also be used with strings.
Symbol | Operation | Description | Examples |
---|---|---|---|
|
concatenation |
Join two strings or two stringable values |
|
|
repeat |
Make n copy of a string |
|
1.2.3. Boolean
Boolean data type has two values only: true and false. Relational and Boolean expressions produce Boolean values.
Symbol | Operation | Description | Examples |
---|---|---|---|
|
Equal |
True if the left value is equal to the right one |
|
|
Not Equal |
True if the left value is NOT equal to the right one |
|
|
Less |
True if the left value is less than the right one |
|
|
Less or Equal |
True if the left value is less than or equal to the right one |
|
|
Greater |
True if the left value is greater than the right one |
|
|
Greater or Equal |
True if the left value is greater than or equal to the right one |
|
Symbol | Operation | Description | Examples |
---|---|---|---|
|
Not |
True if the right value is false |
|
|
And |
True if both left and right values are true |
|
|
Or |
True if at least one of the left and right values integers true |
|
Currently, boolean operations are evaluated using short cut evaluation. This means that, if the left expression of operators Example
|
1.2.4. List
TODO: List operations
1.3. Variables
TODO: variables
1.4. Other operations
1.4.1. ;
operator
The semicolon operator ;
is an infixed operator. It evaluates the left expression first and then the right expression. The latter is the final result.
Technically ; is not treated as a real operator. It acts as a separator in lists of expressions.
|
; can be used to set some variables before the final calculation.
|
a=1; b=2; c=3; a+b+c // returns 6
1.4.2. but
operator
but
is an infixed operator. Its operands can be any type of expression. It evaluates the left expression first, then the right expression. The value of the right expression is the final result. Examples: 5 but 2
returns 2, x=2*3 but x-1
returns 5.
but
is very similar to ;
. The only difference is that ;
can’t be used inside parenthesis ;(
and )
.
1.4.3. Assignment operator =
The assignment operator =
is used to define variable in the evaluation context or to change their value (see ExprContext).
The value on the left side of =
must be an identifier. The value on the right side can be any expression and it becomes the result of the assignment operation.
a=15+1 // returns 16
1.4.4. Selector operator ? : ::
The selector operator is very similar to the switch/case/default statement available in many programming languages.
<selector-operator> ::= <expression> "?" <selector-case> { ":" <selector-case> } ["::" <case-value>]
<selector-case> ::= [<list>] <case-value>
<case-value> ::= "{" <multi-expr> "}"
<multi-expr> ::= <expr> {";" <expr>}
1 ? {"a"} : {"b"} // returns "b"
10 ? {"a"} : {"b"} :: {"c"} // returns "c"
10 ? {"a"} :[true, 2+8] {"b"} :: {"c"} // returns "b"
10 ? {"a"} :[true, 2+8] {"b"} ::[10] {"c"} // error: "... case list in default clause"
10 ? {"a"} :[10] {x="b" but x} :: {"c"} // returns "b"
10 ? {"a"} :[10] {x="b"; x} :: {"c"} // returns "b"
10 ? {"a"} : {"b"} // error: "... no case catches the value (10) of the selection expression
1.5. Priorities of operators
The table below shows all supported operators by decreasing priorities.
Priority | Operators | Position | Operation | Operands and results |
---|---|---|---|---|
FACT |
|
Postfix |
Factorial |
integer "!" → integer |
SIGN |
|
Prefix |
Change-sign |
("+"|"-") number → number |
PROD |
|
Infix |
Product |
number "*" number → number |
|
Infix |
String-repeat |
string "*" integer → string |
|
|
Infix |
Division |
number "/" number → number |
|
|
Infix |
Float-division |
number "./" number → float |
|
|
Infix |
Integer-remainder |
integer "%" integer → integer |
|
SUM |
|
Infix |
Sum |
number "+" number → number |
|
Infix |
String-concat |
(string|number) "+" (string|number) → string |
|
|
Infix |
List-join |
list "+" list → list |
|
|
Infix |
Subtraction |
number "-" number → number |
|
|
Infix |
List-difference |
list "-" list → list |
|
RELATION |
|
Infix |
less |
comparable "<" comparable → boolean |
|
Infix |
less-equal |
comparable "<=" comparable → boolean |
|
|
Infix |
greater |
comparable ">" comparable → boolean |
|
|
Infix |
greater-equal |
comparable ">=" comparable → boolean |
|
|
Infix |
equal |
comparable "==" comparable → boolean |
|
|
Infix |
not-equal |
comparable "!=" comparable → boolean |
|
NOT |
|
Prefix |
not |
"not" boolean → boolean |
AND |
|
Infix |
and |
boolean "and" boolean → boolean |
|
Infix |
and |
boolean "&&" boolean → boolean |
|
OR |
|
Infix |
or |
boolean "or" boolean → boolean |
[blue]` |
` |
Infix |
||
or |
boolean " |
" boolean → boolean |
ASSIGN |
|
|
Infix |
assignment |
identifier "=" any → any |
BUT |
1.6. Functions
1.6.1. Function calls
TODO: function calls operations
1.6.2. Function definitions
TODO: function definitions operations
1.6.3. Builtins
TODO: builtins