示例#1
0
        /// <summary>
        /// Pre-calculates the extra operators (defined at the <see cref="Custom.LeftAssociativeOperators"/> and <see cref="Custom.RightAssociativeOperators"/> for a given math expression.
        /// </summary>
        /// <param name="expression">The math expression to translate.</param>
        /// <param name="rightAssociative">Determines the operator associativity.</param>
        private static void TranslateCustomOperators(ref string expression, bool rightAssociative)
        {
            char? @operator = expression.GetOperator(rightAssociative);

            if (@operator == null)
            {
                return;
            }

            int operatorIndex;

            if (rightAssociative)
            {
                operatorIndex = expression.LastIndexOf(@operator.Value);
            }
            else
            {
                operatorIndex = expression.IndexOf(@operator.Value);
            }

            int    leftIndex             = operatorIndex - 1;
            int    rightIndex            = operatorIndex + 1;
            double?left                  = null;
            double?right                 = null;
            int    replaceLeftIndex      = -1;
            int    replaceRightIndex     = -1;
            bool   isLeftSideExpression  = false;
            bool   hasLeftSideOperator   = false;
            bool   isRightSideExpression = false;
            bool   hasRightSideOperator  = false;

            while (leftIndex >= 0)
            {
                var ls = expression.Substring(leftIndex, operatorIndex - leftIndex).Replace(" ", string.Empty);
                if (ls.Contains(')'))
                {
                    isLeftSideExpression = true;
                }

                if (ls.Contains('+') || ls.Contains('-') || ls.Contains('*') || ls.Contains('/'))
                {
                    hasLeftSideOperator = true;
                }

                if (hasLeftSideOperator && !isLeftSideExpression)
                {
                    break;
                }

                double?computed = null;
                try
                {
                    computed         = Operations.Compute(ls);
                    left             = computed.Value;
                    replaceLeftIndex = leftIndex;
                }
                catch (Exception)
                {
                    if (left != null)
                    {
                        break;
                    }
                }

                leftIndex--;
            }

            while (rightIndex < expression.Length)
            {
                var rs = expression.Substring(operatorIndex + 1, rightIndex - operatorIndex).Replace(" ", string.Empty);
                if (rs.Contains(')'))
                {
                    isRightSideExpression = true;
                }

                if (rs.Contains('+') || rs.Contains('-') || rs.Contains('*') || rs.Contains('/'))
                {
                    hasRightSideOperator = true;
                }

                if (hasRightSideOperator && !isRightSideExpression)
                {
                    break;
                }

                double?computed = null;
                try
                {
                    computed          = Operations.Compute(rs);
                    right             = computed.Value;
                    replaceRightIndex = rightIndex;
                }
                catch (Exception)
                {
                    if (right != null)
                    {
                        break;
                    }
                }

                rightIndex++;
            }

            if (left != null && right != null)
            {
                var    textToReplace = expression.Substring(replaceLeftIndex, replaceRightIndex - replaceLeftIndex + 1);
                string result;
                if (rightAssociative)
                {
                    result = Custom.RightAssociativeOperators[@operator.Value].Invoke(left.Value, right.Value).ToString();
                }
                else
                {
                    result = Custom.LeftAssociativeOperators[@operator.Value].Invoke(left.Value, right.Value).ToString();
                }

                expression = expression.Replace(textToReplace, result);
                TranslateCustomOperators(ref expression, rightAssociative);
            }
        }