govaluate

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2014 License: MIT Imports: 6 Imported by: 0

README

govaluation

Build Status Godoc

Provides support for evaluating arbitrary artithmetic/string expressions.

How do I use it?

You create a new EvaluableExpression, then call "Evaluate" on it.

expression, err = NewEvaluableExpression("10 > 0");
result := expression.Evaluate(nil);

// result is now set to "true", the bool value.

Cool, but how about with parameters?

expression, err = NewEvaluableExpression("foo > 0");

parameters := make(map[string]interface{}, 8)
parameters["foo"] = -1;

result := expression.Evaluate(parameters);
// result is now set to "false", the bool value.

That's cool, but we can almost certainly have done all that in code. What about a complex use case that involves some math?

expression, err = NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90");

parameters := make(map[string]interface{}, 8)
parameters["requests_made"] = 100;
parameters["requests_succeeded"] = 80;

result := expression.Evaluate(parameters);
// result is now set to "false", the bool value.

Or maybe you want to check the status of an alive check ("smoketest") page, which will be a string?

expression, err = NewEvaluableExpression("http_response_body == 'service is ok'");

parameters := make(map[string]interface{}, 8)
parameters["http_response_body"] = "service is ok";

result := expression.Evaluate(parameters);
// result is now set to "true", the bool value.

These examples have all returned boolean values, but it's equally possible to return numeric ones.

expression, err = NewEvaluableExpression("total_mem * mem_used / 100");

parameters := make(map[string]interface{}, 8)
parameters["total_mem"] = 1024;
parameters["mem_used"] = 512;

result := expression.Evaluate(parameters);
// result is now set to "50.0", the float64 value.

Why can't you just write these expressions in code?

Sometimes, you can't know ahead-of-time what an expression looks like. Commonly, you'll have written a monitoring framework which is capable of gathering a bunch of metrics, then evaluating a few expressions to see if any metrics should be alerted upon. Or perhaps you've got a set of data running through your application, and you want to allow your DBA's to run some validations on it before committing it to a database, but neither of you can predict what those validations will be.

A lot of people (myself included, for a long time) wind up writing their own half-baked style of evaluation language that fits their needs, but isn't complete. Or they wind up baking their monitor logic into the actual monitor executable. This library is meant to cover all the normal ALGOL and C-like expressions, so that you don't have to reinvent one of the oldest wheels on a computer.

What operators and types does this support?

Modifiers: + - / *

Comparators: > >= < <= == !=

Logical ops: || &&

Numeric constants, including 64-bit floating point (12345)

String constants (single quotes: 'foobar')

Boolean constants: true false

Parenthesis to control order of evaluation

Future Goals

See the Issues page for details. The biggest goal that interests me is currently implementing unified DB queries. But feel free to suggest other features!

License

This project is licensed under the MIT general use license. You're free to integrate, fork, and play with this code as you feel fit without consulting the author, as long as you provide proper credit to the author in your works.

Activity

If this repository hasn't been updated in a while, it's probably because I don't have any outstanding issues to work on - it's not because I've abandoned the project. If you have questions, issues, or patches; I'm completely open to pull requests, issues opened on github, or emails from out of the blue.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var COMPARATOR_SYMBOLS = map[string]OperatorSymbol{

	"==": EQ,
	"!=": NEQ,
	">":  GT,
	">=": GTE,
	"<":  LT,
	"<=": LTE,
}

Map of all valid comparators, and their string equivalents. Used during parsing of expressions to determine if a symbol is, in fact, a comparator. Also used during evaluation to determine exactly which comparator is being used.

View Source
var LOGICAL_SYMBOLS = map[string]OperatorSymbol{

	"&&": AND,
	"||": OR,
}

Map of all valid logical operators, and their string equivalents. Used during parsing of expressions to determine if a symbol is, in fact, a logical operator. Also used during evaluation to determine exactly which logical operator is being used.

View Source
var MODIFIER_SYMBOLS = map[string]OperatorSymbol{

	"+": PLUS,
	"-": MINUS,
	"*": MULTIPLY,
	"/": DIVIDE,
}

Map of all valid modifiers, and their string equivalents. Used during parsing of expressions to determine if a symbol is, in fact, a modifier. Also used during evaluation to determine exactly which modifier is being used.

Functions

func GetTokenKindString

func GetTokenKindString(kind TokenKind) string

GetTokenKindString returns a string that describes the given TokenKind. e.g., when passed the NUMERIC TokenKind, this returns the string "NUMERIC".

Types

type EvaluableExpression

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

EvaluableExpression represents a set of ExpressionTokens which, taken together, represent an arbitrary expression that can be evaluated down into a single value.

func NewEvaluableExpression

func NewEvaluableExpression(expression string) (*EvaluableExpression, error)

Creates a new EvaluableExpression from the given [expression] string. Returns an error if the given expression has invalid syntax.

func (EvaluableExpression) Evaluate

func (this EvaluableExpression) Evaluate(parameters map[string]interface{}) (interface{}, error)

Evaluate runs the entire expression using the given [parameters]. Each parameter is mapped from a string to a value, such as "foo" = 1.0. If the expression contains a reference to the variable "foo", it will be taken from parameters["foo"].

This function returns errors if the combination of expression and parameters cannot be run, such as if a string parameter is given in an expression that expects it to be a boolean. e.g., "foo == true", where foo is any string. These errors are almost exclusively returned for parameters not being present, or being of the wrong type. Structural problems with the expression (unexpected tokens, unexpected end of expression, etc) are discovered during parsing of the expression in NewEvaluableExpression.

In all non-error circumstances, this returns the single value result of the expression and parameters given. e.g., if the expression is "1 + 1", Evaluate will return 2.0. e.g., if the expression is "foo + 1" and parameters contains "foo" = 2, Evaluate will return 3.0

func (EvaluableExpression) String

func (this EvaluableExpression) String() string

Returns the original expression used to create this EvaluableExpression.

func (EvaluableExpression) Tokens

func (this EvaluableExpression) Tokens() []ExpressionToken

Returns an array representing the ExpressionTokens that make up this expression.

type ExpressionToken

type ExpressionToken struct {
	Kind  TokenKind
	Value interface{}
}

Represents a single parsed token.

type OperatorSymbol

type OperatorSymbol int

Represents the valid symbols for operators.

const (
	EQ OperatorSymbol = iota
	NEQ
	GT
	LT
	GTE
	LTE
	AND
	OR
	PLUS
	MINUS
	MULTIPLY
	DIVIDE
)

type TokenKind

type TokenKind int

Represents all valid types of tokens that a token can be.

const (
	UNKNOWN TokenKind = iota

	NUMERIC
	BOOLEAN
	STRING
	VARIABLE

	COMPARATOR
	LOGICALOP
	MODIFIER

	CLAUSE
	CLAUSE_CLOSE
)

Jump to

Keyboard shortcuts

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