GO package for analysis and calculation of expressions
Go to file
2024-04-06 03:06:07 +02:00
doc Expression process diagram added 2024-04-04 12:56:43 +02:00
ast_test.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
ast.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
byte-slider.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
context.go Variable reference 2024-04-06 01:00:29 +02:00
control.go present.go -> control.go 2024-04-06 03:01:57 +02:00
func-import.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
func-math.go import() function added 2024-04-02 06:49:16 +02:00
go.mod added go.mod 2024-03-26 08:56:20 +01:00
helpers_test.go Changed SetValue() as SetVar() and GetValue() as GetVar() 2024-04-03 06:29:57 +02:00
helpers.go Changed SetValue() as SetVar() and GetValue() as GetVar() 2024-04-03 06:29:57 +02:00
it-range.go Added Iterator interface and two implementation: list itrator and range iterator 2024-03-30 06:56:12 +01:00
iterator.go Added Iterator interface and two implementation: list itrator and range iterator 2024-03-30 06:56:12 +01:00
operand-const.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
operand-expr.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
operand-func.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
operand-list.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
operand-var.go Changed SetValue() as SetVar() and GetValue() as GetVar() 2024-04-03 06:29:57 +02:00
operator-assign.go Changed SetValue() as SetVar() and GetValue() as GetVar() 2024-04-03 06:29:57 +02:00
operator-bool.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
operator-but.go New operators 'but' and assignment ('=') 2024-03-30 08:09:41 +01:00
operator-coalesce.go Operators '??' and '?=' added 2024-04-03 13:15:25 +02:00
operator-ctrl.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
operator-fact.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
operator-prod.go added operator '%' (division remainder) and test 2024-03-26 09:27:14 +01:00
operator-rel.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
operator-sign.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
operator-sum.go The plus and minus operators now support lists for join and difference respectively 2024-03-30 07:05:22 +01:00
parser_test.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
parser.go parser.go -- Fix: reset to true the firstToken flag after getting a semicolon 2024-04-06 01:32:29 +02:00
README.adoc typo 2024-04-03 13:19:18 +02:00
sample-export-all.expr Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
scanner_test.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
scanner.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
simple-func-store.go SimpleFuncStore is now derived from SimpleVarStore 2024-04-06 01:07:06 +02:00
simple-var-store.go Variable reference 2024-04-06 01:00:29 +02:00
symbol.go Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
term_test.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
term-constuctor-registry.go Added copyrighr note to all sources 2024-03-26 08:45:18 +01:00
term.go Operators '??' and '?=' added 2024-04-03 13:15:25 +02:00
test-funcs.expr Operator '@@' (export-all) added. Experimental include() function also added 2024-04-06 03:06:07 +02:00
token_test.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
token.go Expressions now support function definition 2024-04-02 04:36:03 +02:00
utils.go Expressions now support function definition 2024-04-02 04:36:03 +02:00

Expr

1. Expr

Expr is a GO package capable of analysing, interpreting and calculating expressions.

Examples taken from parser_test.go
`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

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) and float (GO float64). In mixed operations involving integers and floats, integers are automatically promoted to floats.

Table 1. Arithmetic operators
Symbol Operation Description Examples

+ / -

change sign

Change the sign of values

-1 [-1]
-(+2) [-2]

+

sum

Add two values

-1 + 2 [1]
4 + 0.5 [4.5]

-

subtraction

Subtract the right value from the left one

3 - 1 [2]
4 - 0.5 [3.5]

*

product

Multiply two values

-1 * 2 [-2]
4 * 0.5 [2.0]

/

Division

Divide the left value by the right one

-1 / 2 [0]
1.0 / 2 [0.5]

./

Float division

Force float division

-1 ./ 2 [-0.5]

%

Modulo

Remainder of the integer division

5 % 2 [1]

1.2.2. String

Strings are character sequences enclosed between two double quote ". Example: "Im a string".

Some arithmetic operators can also be used with strings.

Table 2. String operators
Symbol Operation Description Examples

+

concatenation

Join to strings or stringable values

"one" + "two" ["onetwo"]
"one" + 2 ["one2"]

*

repeat

Make n copy of a string

"one" * 2 ["oneone"]

1.2.3. Boolean

Boolean data type has two values only: true and false. Relational and Boolean expressions produce Boolean values.

Table 3. Relational operators
Symbol Operation Description Examples

==

Equal

True if the left value is equal to the right one

5 == 2 [false]
"a" == "a" [true]

!=

Not Equal

True if the left value is NOT equal to the right one

5 != 2 [true]
"a" != "a" [false]

<

Less

True if the left value is less than the right one

5 < 2 [false]
"a" < "b" [true]

<=

Less or Equal

True if the left value is less than or equal to the right one

5 <= 2 [false]
"b" <= "b" [true]

>

Greater

True if the left value is greater than the right one

5 > 2 [true]
"a" < "b" [false]

>=

Greater or Equal

True if the left value is greater than or equal to the right one

5 >= 2 [true]
"b" <= "b" [true]

Table 4. Boolean operators
Symbol Operation Description Examples

NOT

Not

True if the right value is false

NOT true [false]
NOT (2 < 1) [true]

AND / &&

And

True if both left and right values are true

false && true [false]
"a" < "b" AND NOT (2 < 1) [true]

OR / ||

Or

True if at least one of the left and right values integers true

false or true [true]
"a" == "b" OR (2 == 1) [false]

Currently, boolean operations are evaluated using short cut evaluation. This means that, if the left expression of operators and and or is sufficient to establish the result of the whole operation, the right expression would not evaluated at all.

Example
2 > (a=1) or (a=8) > 0; a (1)
1 This multi-expression returns 1 because in the first expression the left value of or is true and as a conseguence its right value is not computed. Therefore the a variable only receives the integer 1.

1.2.4. List

TODO: List operations

1.3. Variables

TODO: List operations

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. Its role is as an expression separator in an expression list.

; can be used to set some variables before the final calculation.

Example
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 ; cant be used inside parenthesis.

1.4.3. Assignment operator =

The assignment operator = is used to define variable in the context or to change their value. 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.

1.5. Priorities of operators

The table below shows all supported operators by decreasing priorities.

Table 5. Operators priorities
Priority Operators Position Operation Operands and results

FACT

!

Postfix

Factorial

integer "!" → integer

SIGN

+, -

Prefix

Change-sign

("+"|"-") numbernumber

PROD

*

Infix

Product

number "*" numbernumber

*

Infix

String-repeat

string "*" integerstring

/

Infix

Division

number "/" numbernumber

./

Infix

Float-division

number "./" numberfloat

%

Infix

Integer-remainder

integer "%" integerinteger

SUM

+

Infix

Sum

number "+" numbernumber

+

Infix

String-concat

(string|number) "+" (string|number) → string

+

Infix

List-join

list "+" listlist

-

Infix

Subtraction

number "-" numbernumber

-

Infix

List-difference

list "-" listlist

RELATION

<

Infix

less

comparable "<" comparableboolean

<=

Infix

less-equal

comparable "<=" comparableboolean

>

Infix

greater

comparable ">" comparableboolean

>=

Infix

greater-equal

comparable ">=" comparableboolean

==

Infix

equal

comparable "==" comparableboolean

!=

Infix

not-equal

comparable "!=" comparableboolean

NOT

not

Prefix

not

"not" booleanboolean

AND

and

Infix

and

boolean "and" booleanboolean

&&

Infix

and

boolean "&&" booleanboolean

OR

or

Infix

or

boolean "or" booleanboolean

[blue]`

`

Infix

or

boolean "

" booleanboolean

ASSIGN

=

Infix

assignment

identifier "=" anyany

BUT

1.6. Functions

1.6.1. Function calls

TODO: List operations

1.6.2. Function definitions

TODO: List operations

1.6.3. Builtins

TODO: List operations