gal

package module
v6.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2022 License: Apache-2.0 Imports: 7 Imported by: 0

README

Go Eval

gal gal

A simplistic expression parser and evaluator in Go.

This is a research project.

Short link to repo Readme:

Short URL

Examples

Check the tests for ideas of usage and capability.

Simple:

func main() {
    expr := `trunc(tan(10 + sin(cos(3*4.4))) 6)`
    gal.Parse(expr).Eval() // returns 3.556049
}

Advanced example, with user-defined functions and variables redefined once.
In this case, the expression is parsed once but evaluate twice:

// see TestWithVariablesAndFunctions() in gal_test.go for full code
func main() {
    // first of all, parse the expression (once only)
    expr := `double(:val1:) + triple(:val2:)`
    parsedExpr := gal.Parse(expr)

    // step 1: define funcs and vars and Eval the expression
    funcs := gal.Functions{
        "double": func(args ...gal.Value) gal.Value {
            value := args[0].(gal.Numberer)
            return value.Number().Multiply(gal.NewNumber(2))
        },
        "triple": func(args ...gal.Value) gal.Value {
            value := args[0].(gal.Numberer)
            return value.Number().Multiply(gal.NewNumber(3))
        },
    }

    vars := gal.Variables{
        ":val1:": gal.NewNumber(4),
        ":val2:": gal.NewNumber(5),
    }

    // returns 4 * 2 + 5 * 3 == 23
    parsedExpr.Eval(
        gal.WithVariables(vars),
        gal.WithFunctions(funcs),
    )

    // step 2: re-define funcs and vars and Eval the expression again
    // note that we do not need to parse the expression again, only just evaluate it
    funcs = gal.Functions{
        "double": func(args ...gal.Value) gal.Value {
            value := args[0].(gal.Numberer)
            return value.Number().Divide(gal.NewNumber(2))
        },
        "triple": func(args ...gal.Value) gal.Value {
            value := args[0].(gal.Numberer)
            return value.Number().Divide(gal.NewNumber(3))
        },
    }

    vars = gal.Variables{
        ":val1:": gal.NewNumber(2),
        ":val2:": gal.NewNumber(6),
    }

    // returns 2 / 2 + 6 / 3 == 3 this time
    parsedExpr.Eval(
        gal.WithVariables(vars),
        gal.WithFunctions(funcs),
    )
}

Numbers

Numbers implement arbitrary precision fixed-point decimal arithmetic with shopspring/decimal.

Supported operations

  • Operators: + - * / % ** << >>
    • Precedence, highest to lowest:
      • **
      • * / %
      • + -
      • << >>
    • Note: Go classifies bit shift operators with the higher *.
  • Types: String, Number
  • Associativity with parentheses
  • Functions:
    • Pre-defined: pi, cos, floor, sin, sqrt, trunc, and more (see function.go: Eval())
    • User-defined, injected via WithFunctions()
  • Variables, defined as :variable_name: and injected via WithVariables()

Functions

Function names are case-insensitive.

A function can optionally accept one or more space-separated arguments, but it must return a single Value.

User function definitions are passed as a map[string]FunctionalValue using WithFunctions when calling Eval from Tree.

This allows parsing the expression once with Parse and run Tree.Eval multiple times with different user function definitions.

Variables

Variable names are case-sensitive.

Values are passed as a map[string]Value using WithVariables when calling Eval from Tree.

This allows parsing the expression once with Parse and run Tree.Eval multiple times with different variable values.

High level design

Expressions are parsed in two stages:

  • Transformation into a Tree of Values and Operators.
  • Evaluation of the Tree for calculation.

Notes:

  • a Tree may contain one or more sub-Trees (recursively or not) to hold functions or to express associativity.
  • Calculation is performed in successive rounds of decreased operator precedence. This is to enforce natural associativity.

Code structure

The main entry point is Parse in gal.go.

Parse instantiates a TreeBuilder. It subsequently calls TreeBuilder's FromExpr method to create a parsed Tree representation of the expression to be evaluated.

Finally, Tree's Eval method performs the evaluation of the Tree and returns the resultant Value to gal.go's Eval function.

To do

A number of TODO's exist throughout the code.

The next priorities are:

  • review TODO's

Documentation

Index

Constants

View Source
const Pi51199 = "" /* 51199-byte string literal not displayed */

Pi51197 returns Pi with 51197 decimal digits.

Variables

This section is empty.

Functions

func WithFunctions

func WithFunctions(funcs Functions) treeOption

WithFunctions is a functional parameter for Tree evaluation. It provides user-defined functions.

func WithVariables

func WithVariables(vars Variables) treeOption

WithVariables is a functional parameter for Tree evaluation. It provides user-defined variables.

Types

type Function

type Function struct {
	Name   string
	BodyFn FunctionalValue
	Args   []Tree
}

func NewFunction

func NewFunction(name string, bodyFn FunctionalValue, args ...Tree) Function

func (Function) Equal

func (f Function) Equal(other Function) bool

func (Function) Eval

func (f Function) Eval(opts ...treeOption) Value

type FunctionalValue

type FunctionalValue func(...Value) Value

func PreDefinedFunction

func PreDefinedFunction(name string) FunctionalValue

PreDefinedFunction returns a pre-defined function body if known. It returns `nil` when no pre-defined function exists by the specified name. This signals the Evaluator to attempt to find a user defined function.

func UserDefinedFunction

func UserDefinedFunction(name string, userFunctions Functions) FunctionalValue

UserDefinedFunction is a helper function that returns the definition of the provided function name from the supplied userFunctions.

func (FunctionalValue) String

func (fv FunctionalValue) String() string

type Functions

type Functions map[string]FunctionalValue

Functions holds the definition of user-defined functions.

func (Functions) Function

func (f Functions) Function(name string) FunctionalValue

Function returns the function definition of the function of the specified name.

type Number

type Number struct {
	// contains filtered or unexported fields
}

func NewNumber

func NewNumber(i int64) Number

func NewNumberFromFloat

func NewNumberFromFloat(f float64) Number

func NewNumberFromString

func NewNumberFromString(s string) (Number, error)

func ToNumber added in v6.0.2

func ToNumber(val Value) Number

func (Number) Add

func (n Number) Add(other Value) Value

func (Number) Cos

func (n Number) Cos() Number

func (Number) Divide

func (n Number) Divide(other Value) Value

func (Number) Equal

func (n Number) Equal(other Number) bool

func (Number) Factorial

func (n Number) Factorial() Number

func (Number) Float64 added in v6.0.2

func (n Number) Float64() float64

func (Number) Floor

func (n Number) Floor() Number

func (Number) Int64 added in v6.0.2

func (n Number) Int64() int64

func (Number) LShift

func (n Number) LShift(other Value) Value

func (Number) Mod

func (n Number) Mod(other Value) Value

func (Number) Multiply

func (n Number) Multiply(other Value) Value

func (Number) Neg

func (n Number) Neg() Number

func (Number) Number

func (n Number) Number() Number

func (Number) PowerOf

func (n Number) PowerOf(other Value) Value

func (Number) RShift

func (n Number) RShift(other Value) Value

func (Number) Sin

func (n Number) Sin() Number

func (Number) Sqrt

func (n Number) Sqrt() Number

func (Number) String

func (n Number) String() string

func (Number) Sub

func (n Number) Sub(other Value) Value

func (Number) Tan

func (n Number) Tan() Number

func (Number) Trunc

func (n Number) Trunc(precision int32) Number

type Numberer

type Numberer interface {
	Number() Number
}

type Operator

type Operator string
const (
	Plus     Operator = "+"
	Minus    Operator = "-"
	Multiply Operator = "*"
	Divide   Operator = "/"
	Modulus  Operator = "%"
	Power    Operator = "**"
	LShift   Operator = "<<"
	RShift   Operator = ">>"
)

func (Operator) String

func (o Operator) String() string

type String

type String struct {
	// contains filtered or unexported fields
}

func NewString

func NewString(s string) String

func (String) Add

func (s String) Add(other Value) Value

func (String) Divide

func (s String) Divide(other Value) Value

func (String) Equal

func (s String) Equal(other String) bool

func (String) LShift

func (s String) LShift(Value) Value

func (String) Mod

func (s String) Mod(Value) Value

func (String) Multiply

func (s String) Multiply(other Value) Value

func (String) Number

func (s String) Number() Number

func (String) PowerOf

func (s String) PowerOf(Value) Value

func (String) RShift

func (s String) RShift(Value) Value

func (String) String

func (s String) String() string

func (String) Sub

func (s String) Sub(other Value) Value

type Stringer

type Stringer interface {
	String() string
}

type Tree

type Tree []entry

func Parse

func Parse(expr string) Tree

Example: Parse("blah").Eval(WithVariables(...), WithFunctions(...)) This allows to parse an expression and then use the resulting Tree for multiple evaluations with different variables provided.

func (Tree) Calc

func (tree Tree) Calc(isOperatorInPrecedenceGroup func(Operator) bool, cfg *treeConfig) Tree

Calc is a reduction operation that calculates the Value of sub-expressions contained in this Tree, based on operator precedence. When isOperatorInPrecedenceGroup returns true, the operator is calculated and the resultant Value is inserted in _replacement_ of the terms (elements) of this Tree that where calculated. For instance, a tree representing the expression '2 + 5 * 4 / 2' with an operator precedence of 'multiplicativeOperators' would read the Tree left to right and return a new Tree that represents: '2 + 10' where 10 was calculated (and reduced) from 5 * 4 = 20 / 2 = 10.

func (Tree) CleanUp

func (tree Tree) CleanUp() Tree

CleanUp performs simplification operations before calculating this tree.

func (Tree) Eval

func (tree Tree) Eval(opts ...treeOption) Value

Eval evaluates this tree and returns its value. It accepts optional functional parameters to supply user-defined entities such as functions and variables.

func (Tree) FullLen

func (tree Tree) FullLen() int

FullLen returns the total number of non 'Tree-type' elements in the tree.

func (Tree) Split

func (tree Tree) Split() []Tree

Split divides a Tree trunk at points where two consecutive entries are present without an operator in between.

func (Tree) TrunkLen

func (tree Tree) TrunkLen() int

type TreeBuilder

type TreeBuilder struct{}

func NewTreeBuilder

func NewTreeBuilder() *TreeBuilder

func (TreeBuilder) FromExpr

func (tb TreeBuilder) FromExpr(expr string) (Tree, error)

type Undefined

type Undefined struct {
	// contains filtered or unexported fields
}

func NewUndefined

func NewUndefined() Undefined

func NewUndefinedWithReasonf

func NewUndefinedWithReasonf(format string, a ...interface{}) Undefined

func (Undefined) Add

func (Undefined) Add(Value) Value

func (Undefined) Divide

func (Undefined) Divide(Value) Value

func (Undefined) Equal

func (u Undefined) Equal(other Undefined) bool

func (Undefined) LShift

func (Undefined) LShift(Value) Value

func (Undefined) Mod

func (Undefined) Mod(Value) Value

func (Undefined) Multiply

func (Undefined) Multiply(Value) Value

func (Undefined) PowerOf

func (Undefined) PowerOf(Value) Value

func (Undefined) RShift

func (Undefined) RShift(Value) Value

func (Undefined) String

func (u Undefined) String() string

func (Undefined) Sub

func (Undefined) Sub(Value) Value

type Value

type Value interface {
	Add(Value) Value
	Sub(Value) Value
	Multiply(Value) Value
	Divide(Value) Value
	PowerOf(Value) Value
	Mod(Value) Value
	LShift(Value) Value
	RShift(Value) Value
	Stringer
	// contains filtered or unexported methods
}

func Cos

func Cos(args ...Value) Value

Cos returns the cosine.

func Factorial

func Factorial(args ...Value) Value

Factorial returns the factorial of the provided argument.

func Floor

func Floor(args ...Value) Value

return the floor.

func Pi

func Pi(args ...Value) Value

Pi returns the Value of math.Pi.

func PiLong added in v6.0.2

func PiLong(args ...Value) Value

PiLong returns a value of Pi with many more digits than Pi.

func Sin

func Sin(args ...Value) Value

Sin returns the sine.

func Sqrt

func Sqrt(args ...Value) Value

Sqrt returns the square root.

func Tan

func Tan(args ...Value) Value

Tan returns the tangent.

func Trunc

func Trunc(args ...Value) Value

type Variable

type Variable struct {
	Name string
}

func NewVariable

func NewVariable(name string) Variable

func (Variable) String

func (v Variable) String() string

type Variables

type Variables map[string]Value

Variables holds the value of user-defined variables.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL