public override Double Compute() { if (String.IsNullOrWhiteSpace(this.Expression)) { return(Double.NaN); } if (Helper.IsNumericValue(this.Expression)) { return(this.ApplyFunction(Double.Parse(this.Expression))); } var _operatorList = new List <String>(); var _unitList = new List <IComputeUnit>(); try { // prepare int i = 0; while (i < Expression.Length) { var strExpression = Expression.Substring(i); var nextMatch = Regex.Match(strExpression, @"[\+\-*/%([{]"); if (!nextMatch.Success) // must be numeric number { _unitList.Add(new NumericUnit(strExpression)); break; } if (nextMatch.Index == 0) { if (Regex.IsMatch(nextMatch.Value, @"[([{]")) { var subExpression = Helper.GetSubExpression(strExpression); var unit = ExpressionHandler.Parse(subExpression); if (unit == null) { return(Double.NaN); } _unitList.Add(unit); i += subExpression.Length; } else if (Regex.IsMatch(nextMatch.Value, @"[\+\-*/%]")) { Debug.Assert(nextMatch.Index == 0 && nextMatch.Length == 1); _operatorList.Add(strExpression[0].ToString()); i++; } } else { if (Regex.IsMatch(strExpression, @"^[0-9]")) // start with number, it must be a numeric unit { _unitList.Add(new NumericUnit(strExpression.Substring(0, nextMatch.Index))); i += nextMatch.Index; } else // must be a complex unit { var subExpression = Helper.GetSubExpression(strExpression); var unit = ExpressionHandler.Parse(subExpression); if (unit == null) { return(Double.NaN); } _unitList.Add(unit); i += subExpression.Length; } } } // calculate Debug.Assert(_operatorList.Count == _unitList.Count - 1); var operators = new List <String>(); var values = new List <Double>(); Double value = Double.NaN; for (i = 0; i < _operatorList.Count; i++) { if (Double.IsNaN(value)) { value = _unitList[i].Compute(); } if (Double.IsNaN(value)) { return(Double.NaN); } if (_operatorList[i] == "*" || _operatorList[i] == "/" || _operatorList[i] == "%") { if (_operatorList[i] == "*") { value *= _unitList[i + 1].Compute(); } else { var temp = _unitList[i + 1].Compute(); if (temp == 0) { return(Double.NaN); } if (_operatorList[i] == "/") { value /= temp; } else { value %= temp; } } continue; } if (Double.IsNaN(value)) { return(Double.NaN); } if (operators.Any() && operators.Last() == "-") { value *= -1; } values.Add(value); operators.Add(_operatorList[i]); value = Double.NaN; } if (Double.IsNaN(value) && (!_operatorList.Any() || _operatorList.Last() == "+" || _operatorList.Last() == "-")) { value = _unitList.Last().Compute(); } if (!Double.IsNaN(value)) { if (operators.Any() && operators.Last() == "-") { value *= -1; } values.Add(value); } // apply function return(this.ApplyFunction(values.Sum())); } catch { return(Double.NaN); } finally { _operatorList.Clear(); _unitList.Clear(); } }