You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expressive is a multi-platform expression parsing and evaluation framework.
Design and Implementation
There are 3 main stages of the parsing/evaluation of an Expression.
Tokenising - this deals with walking through the characters in the expression and matching the items against the known set of Operators, Functions and Values.
Compiling - once the Expression has been tokenised the set of tokens is then used to build a tree of internal IExpression nodes.
Evaluation - each individual IExpression node is then evaluated to determine it's result and eventually the overall result of the top level Expression.
Error handling
The Expression will terminate early in the following situations:
Any part of the tokenising process fails (i.e. unrecognised tokens).
If any of the Functions are supplied with an incorrect number of parameters.
Aggregate operator
Operators can now handle aggregates (i.e. a variable passed in as an array of values will each be enumerated).
Each individual parameter will only be evaluated at the point of being used within its IExpression node. This will prevent parts of an expression being evaluated should the result already be determined (e.g. when the left hand side of an && (logical AND) operator being false).
publicenumExpressiveOptions
{
/// <summary>/// Specifies that no options are set./// </summary>None=1,
/// <summary>/// Specifies case-insensitive matching./// </summary>IgnoreCase=2,
/// <summary>/// No-cache mode. Ignores any pre-compiled expression in the cache./// </summary>NoCache=4,
/// <summary>/// When using Round(), if a number is halfway between two others, it is rounded toward the nearest number that is away from zero./// </summary>RoundAwayFromZero=8,
/// <summary>/// All options are used./// </summary>All=IgnoreCase | NoCache | RoundAwayFromZero,
}
// Use in any combination.varexpression=newExpression("1+2", ExpressiveOptions.IgnoreCase | ExpressiveOptions.NoCache);
varresult=expression.Evaluate();
Custom functions allow you to register your own set of funcitonality in order to extend the current set. There are 2 methods of registering a custom function:
IFunction implementation.
internalclassAbsFunction:IFunction{
#region IFunction Members
publicIDictionary<string,object>Variables{get;set;}publicstringName{get{return"Asin";}}publicobjectEvaluate(IExpression[]parameters){returnMath.Asin(Convert.ToDouble(parameters[0].Evaluate(Variables)));}
#endregion
}varexpression=newExpression("Abs(1)");expression.RegisterFunction(newAbsFunction());varresult=expression.Evaluate();
Lambda callback.
varexpression=newExpression("myfunc(1)");expression.RegisterFunction("myfunc",(p,v)=>{// p = parameters// v = variablesreturnp[0].Evaluate(v);});varresult=expression.Evaluate();
Retrieve referenced variables
Compiles the expression and returns an array of the variable names contained within the expression.
Useful for when an evaluation might take a long time (i.e. a function that deals with a long running background tasks such as loading from the database).