/// <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); }
/// <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); }