/// <summary> /// Обработать унарную математическую операцию (один токен + операция. Например, -10 - сменить знак у 10 на отрицательный) /// </summary> /// <param name="token">токен</param> /// <param name="mathUnaryOperationToken">токен логической операции</param> /// <returns>результирующий токен или ошибка. Ошибок быть не может</returns> private ICalcToken ProcessUnaryMathOperation(CalcTokenNumber token, CalcTokenMathOperation mathUnaryOperationToken) { // Выполняем унарную операцию - if (mathUnaryOperationToken.MathOperation == CalcMathOperation.UnaryMinus) { token.Value = token.Value * -1; } // Выполняем унарную операцию + if (mathUnaryOperationToken.MathOperation == CalcMathOperation.UnaryPlus) { token.Value = Math.Abs(token.Value); } return(token); }
/// <summary> /// Общий метод извлечения очередного токена. Вызывает метод TryToExtract в классах токенов /// </summary> /// <param name="formula">текст формулы</param> /// <param name="previousToken">предыдущий токен. Null, если это первый токен</param> /// <returns>null - формула разобрана, иначе токен</returns> private ICalcToken TryToExtract(string formula, ICalcToken previousToken) { ICalcToken token; var position = previousToken == null ? 0 : previousToken.GetNextTokenPosition(); if (formula.Length == position) { return(null); // Формула распаршена } if ((token = CalcTokenIfStatement.TryToExtract(formula, position)) != null) { return(token); } if ((token = CalcTokenFormulaSeparator.TryToExtract(formula, position)) != null) { return(token); } if ((token = CalcTokenNumber.TryToExtract(formula, previousToken, position)) != null) { return(token); } if ((token = CalcTokenFormatter.TryToExtract(formula, position)) != null) { return(token); } if ((token = CalcTokenBracket.TryToExtract(formula, position)) != null) { return(token); } if ((token = CalcTokenLogicOperation.TryToExtract(formula, position)) != null) { return(token); } if ((token = CalcTokenMathOperation.TryToExtract(formula, previousToken, position)) != null) { return(token); } if (_tokenizers.Any(tokenizer => (token = tokenizer(formula, position)) != null)) { return(token); } return(new CalcTokenUnknown(position) { Error = FormulaError.UnexpectedSymbols, TokenText = formula[position].ToString(CultureInfo.InvariantCulture) }); }
/// <summary> /// Обработать математическую операцию над двумя токенами /// Для корректного выполнения сравнения "больше, меньше, ..." важен порядок токенов, передаваемых в формулу /// </summary> /// <param name="token1">первый токен</param> /// <param name="token2">второй токен</param> /// <param name="mathOperationToken">токен матеметической операции</param> /// <returns>результирующий токен или ошибка, установленная методом в одном из входных токенов</returns> private ICalcToken ProcessMathOperation(ICalcToken token1, ICalcToken token2, CalcTokenMathOperation mathOperationToken) { double mathResult; var n1 = ((CalcTokenNumber)token1).Value; var n2 = ((CalcTokenNumber)token2).Value; var n1s = n1.ToString(CultureInfo.InvariantCulture); n1 = double.Parse(n1s, CultureInfo.InvariantCulture); var n2s = n2.ToString(CultureInfo.InvariantCulture); n2 = double.Parse(n2s, CultureInfo.InvariantCulture); switch (mathOperationToken.MathOperation) { case CalcMathOperation.Plus: mathResult = n1 + n2; break; case CalcMathOperation.Minus: mathResult = n1 - n2; break; case CalcMathOperation.Multiply: mathResult = n1 * n2; break; case CalcMathOperation.Divide: if ((int)n2 == 0) { token2.Error = FormulaError.DivisionByZero; return(token2); } mathResult = n1 / n2; break; case CalcMathOperation.DivideModulo: if ((int)n2 == 0) { token2.Error = FormulaError.DivisionByZero; return(token2); } mathResult = n1 % n2; break; case CalcMathOperation.DivideInteger: if ((int)n2 == 0) { token2.Error = FormulaError.DivisionByZero; return(token2); } mathResult = (long)(n1 / n2); break; default: mathOperationToken.Error = FormulaError.UnknownMathOperation; return(mathOperationToken); } // Результат возвращаем в стэк return(new CalcTokenNumber(0) { Value = mathResult }); }