Documentation
¶
Overview ¶
Package expr is a small compile-once / evaluate-many expression engine over decimal.Decimal values.
Compile turns a textual expression into a Program (an RPN bytecode produced by a shunting-yard parser); Program.Eval then runs that program against a decimal.Context and a Vars binding. The split lets callers pay the parsing cost once and reuse the compiled program in hot loops.
Supported syntax:
- Numeric literals (decimal point optional, no scientific notation)
- Identifiers as variable names (look up via the Vars argument)
- Binary operators: + - * / ^
- Unary +/-, parentheses for grouping
The ^ operator is right-associative and binds tighter than * and /; 2^3^2 evaluates to 2^(3^2) = 512, and -2^2 evaluates to -(2^2) = -4.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidExpr is returned when parsing fails. // // Common triggers: empty input, unbalanced parentheses, misplaced // operators, malformed numeric literals, and unfinished expressions // (e.g. a trailing operator with no operand). ErrInvalidExpr = errors.New("invalid expression") // ErrUnknownVar is returned by Eval when the program references a // variable name that the supplied Vars cannot resolve. // // The actual error wraps the variable name in "%w: name", so use // errors.Is to compare against this sentinel. ErrUnknownVar = errors.New("unknown variable") )
Functions ¶
This section is empty.
Types ¶
type MapVars ¶
MapVars is a Vars implementation backed by an ordinary map. It is the fastest way to plug a fixed set of bindings into a Program.
type Program ¶
type Program struct {
// contains filtered or unexported fields
}
Program is a compiled expression ready to be evaluated.
Internally it holds an RPN bytecode plus its constant pool and the list of variable names referenced by the source. A Program is safe to reuse and to share across goroutines as long as no one mutates it (which the public API does not allow). Compile to obtain one.
func Compile ¶
Compile parses input and produces a Program ready for repeated Eval.
The grammar is the one documented on the package: numeric literals, identifier variables, parentheses, unary +/-, and the binary operators +, -, *, /, ^. Whitespace is ignored. ^ is right-associative and binds tighter than * and /.
On success the returned *Program is independent from the input string and safe to reuse. On failure Compile returns nil and ErrInvalidExpr.
func (*Program) Eval ¶
Eval runs the program against ctx and the provided Vars binding, returning the resulting decimal value.
All arithmetic is performed through the decimal package, so every intermediate result is normalized to ctx.Scale and ctx.Mode just as if the caller had used Add / Sub / Mul / Div / Pow directly.
Possible errors:
- ErrInvalidExpr if the program is nil or its bytecode is malformed. A well-formed Compile output should never trigger this at Eval time.
- ErrUnknownVar if vars cannot resolve a referenced name. The wrapped error includes the offending name.
- decimal.ErrDivisionByZero on division by zero.
- decimal.ErrInvalidPow from "^" with a negative base and a non-integer exponent.
- decimal.ErrNonPositiveLog surfaced through "^" when computing ln(base) for non-positive base under a fractional exponent.
A nil Vars is acceptable as long as the program references no variables.
type Vars ¶
type Vars interface {
// Get looks up a single variable by name. It returns the value and
// true on hit, or the zero Decimal and false on miss.
Get(name string) (decimal.Decimal, bool)
}
Vars resolves variable names to decimal values during Eval.
Implementations should return ok = false when the name is unknown so Eval can surface ErrUnknownVar with the offending name attached.