/// <summary>
        /// Merge current expression with previous expression and the new operand just got before current expression
        /// </summary>
        /// <param name="prevExpression"></param>
        /// <param name="curExpression"></param>
        /// <param name="newOperand"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        public static bool MergeExpressions(ArithmeticExpression <ICalculator> prevExpression, ref ArithmeticExpression <ICalculator> curExpression, ref ArithmeticOperand <ICalculator> newOperand, ref string errMsg)
        {
            if (prevExpression == null || curExpression == null)
            {
                errMsg += "prevExpression is null or curExpression is null in MergeExpressions.";
                return(false);
            }

            if (prevExpression.Priority() < curExpression.Priority())
            {
                curExpression.AddOperand(newOperand);
                prevExpression.AddOperand(curExpression);
            }
            else if (prevExpression.Priority() > curExpression.Priority())
            {
                prevExpression.AddOperand(newOperand);
                if (prevExpression.ParentExpression != null && prevExpression.ParentExpression.Priority() == curExpression.Priority())
                {
                    prevExpression.ParentExpression.Operators.AddRange(curExpression.Operators);
                    prevExpression.ParentExpression.AddOperands(curExpression.Operands);
                    curExpression = prevExpression.ParentExpression;
                }
                else
                {
                    curExpression.AddOperand(prevExpression);
                }
            }
            else
            {
                prevExpression.AddOperand(newOperand);
                prevExpression.Operators.AddRange(curExpression.Operators);
                prevExpression.AddOperands(curExpression.Operands);
                curExpression = prevExpression;
            }
            newOperand = null;

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Parse string expression to an arithmetic expression object
        /// </summary>
        /// <param name="s"></param>
        /// <param name="endIndex"></param>
        /// <param name="errMsg"></param>
        /// <param name="startIndex"></param>
        /// <param name="recurLevel"></param>
        /// <returns></returns>
        private static ArithmeticExpression <ICalculator> ParseExpression(string s, out int endIndex, out string errMsg, int startIndex = 0, int recurLevel = 0)
        {
            endIndex = startIndex;
            errMsg   = string.Empty;
            ArithmeticExpression <ICalculator> root = null;

            if (!string.IsNullOrWhiteSpace(s) && s.Length > startIndex)
            {
                int index = startIndex;
                ArithmeticExpression <ICalculator> prevExpression = null;
                ArithmeticExpression <ICalculator> curExpression  = null;
                ArithmeticOperand <ICalculator>    newOperand     = null;

                bool prevOperand  = false;
                bool prevOperator = false;

                while (index < s.Length)
                {
                    char c = s[index];
                    // Check operator
                    if (c == '+' || c == '-' || c == '*' || c == '/')
                    {
                        if (curExpression != null)
                        {
                            prevExpression = curExpression;
                        }
                        curExpression = ArithmeticExpressionFactory.CreateArithmeticExpression(c, index, ref prevOperator, ref prevOperand, ref errMsg);
                        if (curExpression == null)
                        {
                            break;
                        }
                        else if (prevExpression != null)
                        {
                            if (!ArithmeticExpressionFactory.MergeExpressions(prevExpression, ref curExpression, ref newOperand, ref errMsg))
                            {
                                break;
                            }
                        }
                        else
                        {
                            prevExpression = curExpression;
                            if (newOperand != null)
                            {
                                curExpression.AddOperand(newOperand);
                                newOperand = null;
                            }
                        }
                    }
                    // Check number
                    else if (c == '(')
                    {
                        int    childEndIndex;
                        string childErrMsg;
                        ArithmeticExpression <ICalculator> childExpression = ParseExpression(s, out childEndIndex, out childErrMsg, index + 1, recurLevel + 1);
                        if (!string.IsNullOrWhiteSpace(childErrMsg))
                        {
                            errMsg += childErrMsg;
                            break;
                        }
                        else if (childExpression == null)
                        {
                            errMsg += $"Expression missing in parentheses: [index: {index}].";
                            break;
                        }
                        else if (prevOperand)
                        {
                            errMsg += $"Operator is missing before character: ( [index: {index}].";
                            break;
                        }
                        else
                        {
                            index      = childEndIndex; // ')'
                            newOperand = new ArithmeticOperand <ICalculator>
                            {
                                Expression = childExpression
                            };
                            prevOperand  = true;
                            prevOperator = false;
                        }
                    }
                    else if (c == ')')
                    {
                        recurLevel--;
                        if (recurLevel < 0)
                        {
                            errMsg += $"Redundant right parenthesis: [index: {index}].";
                        }
                        break;
                    }
                    else if (c >= '0' && c <= '9')
                    {
                        IntCalculator intCalculator = ArithmeticExpressionFactory.CreateCalculator(s, ref index, ref prevOperator, ref prevOperand, ref errMsg) as IntCalculator;
                        if (intCalculator == null)
                        {
                            break;
                        }
                        else
                        {
                            newOperand = new ArithmeticOperand <ICalculator>
                            {
                                SimpleValue = intCalculator
                            };
                        }
                    }
                    // Support spaces
                    else if (c == ' ')
                    {
                    }
                    // Not support characters
                    else
                    {
                        errMsg += $"Illegal characters in the expression: {c} [index: {index}].";
                        break;
                    }

                    if (root == null && curExpression != null)
                    {
                        root = curExpression;
                    }

                    index++;
                }

                if (prevOperator)
                {
                    errMsg += $"Operand is missing at the end of the expressioin.";
                }

                if (index == s.Length && recurLevel > 0)
                {
                    errMsg += $"Missing {recurLevel} right parenthesis.";
                }
                else if (newOperand != null && curExpression != null)
                {
                    curExpression.AddOperand(newOperand);
                    newOperand = null;
                }

                endIndex = index;
            }

            if (!string.IsNullOrEmpty(errMsg))
            {
                root = null;
            }

            if (root != null)
            {
                while (root.ParentExpression != null)
                {
                    root = root.ParentExpression;
                }
            }
            return(root);
        }