public double Calculate(string formulaText, IDictionary <string, double> variables) { if (string.IsNullOrEmpty(formulaText)) { throw new ArgumentNullException("formulaText"); } if (variables == null) { throw new ArgumentNullException("variables"); } if (!caseSensitive) { variables = EngineUtil.ConvertVariableNamesToLowerCase(variables); } VerifyVariableNames(variables); // Add the reserved variables to the dictionary foreach (ConstantInfo constant in ConstantRegistry) { variables.Add(constant.ConstantName, constant.Value); } if (IsInFormulaCache(formulaText, null, out var function)) { return(function(variables)); } else { Operation operation = BuildAbstractSyntaxTree(formulaText, new ConstantRegistry(caseSensitive)); function = BuildFormula(formulaText, null, operation); return(function(variables)); } }
public double Calculate(string formulaText, Dictionary <string, double> variables) { if (formulaText == null) { throw new ArgumentNullException("formulaText"); } if (variables == null) { throw new ArgumentNullException("variables"); } variables = EngineUtil.ConvertVariableNamesToLowerCase(variables); VerifyVariableNames(variables); // Add the reserved variables to the dictionary foreach (ConstantInfo constant in ConstantRegistry) { variables.Add(constant.ConstantName, constant.Value); } if (IsInFormulaCache(formulaText)) { Func <Dictionary <string, double>, double> formula = executionFormulaCache[formulaText]; return(formula(variables)); } else { Operation operation = BuildAbstractSyntaxTree(formulaText); Func <Dictionary <string, double>, double> function = BuildFormula(formulaText, operation); return(function(variables)); } }
/// <summary> /// Verify a collection of variables to ensure that all the variable names are valid. /// Users are not allowed to overwrite reserved variables or use function names as variables. /// If an invalid variable is detected an exception is thrown. /// </summary> /// <param name="variables">The colletion of variables that must be verified.</param> private void VerifyVariableNames(Dictionary <string, double> variables) { foreach (string variableName in variables.Keys) { if (EngineUtil.IsReservedVariable(variableName)) { throw new ArgumentException(string.Format("The name \"{0}\" is a reservered variable name that cannot be overwritten.", variableName), "variables"); } if (FunctionRegistry.IsFunctionName(variableName)) { throw new ArgumentException(string.Format("The name \"{0}\" is a function name. Parameters cannot have this name.", variableName), "variables"); } } }
public Operation Build(IList <Token> tokens) { resultStack.Clear(); operatorStack.Clear(); foreach (Token token in tokens) { object value = token.Value; switch (token.TokenType) { case TokenType.Integer: resultStack.Push(new IntegerConstant((int)token.Value)); break; case TokenType.FloatingPoint: resultStack.Push(new FloatingPointConstant((double)token.Value)); break; case TokenType.Text: if (EngineUtil.IsFunctionName((string)token.Value)) { operatorStack.Push(token); } else { resultStack.Push(new Variable((string)token.Value)); } break; case TokenType.LeftBracket: operatorStack.Push(token); break; case TokenType.RightBracket: PopOperations(true, token); break; case TokenType.Operation: Token operation1Token = token; char operation1 = (char)operation1Token.Value; if (operatorStack.Count == 0) { operatorStack.Push(operation1Token); } else { Token operation2Token = operatorStack.Peek(); bool isFunctionOnTopOfStack = operation2Token.TokenType == TokenType.Text; if (!isFunctionOnTopOfStack) { char operation2 = (char)operation2Token.Value; if ((IsLeftAssociativeOperation(operation1) && operationPrecedence[operation1] <= operationPrecedence[operation2]) || (operationPrecedence[operation1] < operationPrecedence[operation2])) { operatorStack.Pop(); operatorStack.Push(operation1Token); resultStack.Push(ConvertOperation(operation2Token)); } else { operatorStack.Push(operation1Token); } } else { operatorStack.Pop(); operatorStack.Push(operation1Token); resultStack.Push(ConvertFunction(operation2Token)); } } break; } } PopOperations(false, null); VerifyResultStack(); return(resultStack.First()); }