Example #1
0
        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));
            }
        }
Example #2
0
        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));
            }
        }
Example #3
0
        /// <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");
                }
            }
        }
Example #4
0
        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());
        }