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