/// <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> /// Обработать логическую операцию над двумя логическими токенами (bool) или двумя числами /// Для корректного выполнения сравнения "больше, меньше, ..." важен порядок токенов, передаваемых в формулу /// </summary> /// <param name="token1">первый токен</param> /// <param name="token2">второй токен</param> /// <param name="logicOperationToken">токен логической операции</param> /// <returns>результирующий токен или ошибка, установленная методом в одном из входных токенов</returns> private ICalcToken ProcessLogicOperation(ICalcToken token1, ICalcToken token2, CalcTokenLogicOperation logicOperationToken) { bool boolResult; if (token1 is CalcTokenNumber && token2 is CalcTokenNumber) { var v1Value = ((CalcTokenNumber)token1).Value; var v2Value = ((CalcTokenNumber)token2).Value; switch (logicOperationToken.LogicOperation) { case CalcLogicOperation.Equal: boolResult = v1Value == v2Value; break; case CalcLogicOperation.Greater: boolResult = v1Value > v2Value; break; case CalcLogicOperation.GreaterOrEqual: boolResult = v1Value >= v2Value; break; case CalcLogicOperation.Less: boolResult = v1Value < v2Value; break; case CalcLogicOperation.LessOrEqual: boolResult = v1Value <= v2Value; break; case CalcLogicOperation.Not: boolResult = v1Value != v2Value; break; default: logicOperationToken.Error = FormulaError.UnknownLogicOperation; return(logicOperationToken); } } else if (token1 is CalcTokenBoolean && token2 is CalcTokenBoolean) { var v1Value = ((CalcTokenBoolean)token1).Value; var v2Value = ((CalcTokenBoolean)token2).Value; switch (logicOperationToken.LogicOperation) { case CalcLogicOperation.And: boolResult = v1Value && v2Value; break; case CalcLogicOperation.Equal: boolResult = v1Value == v2Value; break; case CalcLogicOperation.Not: boolResult = v1Value != v2Value; break; case CalcLogicOperation.Or: boolResult = v1Value || v2Value; break; default: logicOperationToken.Error = FormulaError.UnknownLogicOperation; return(logicOperationToken); } } else { return(new CalcTokenUnknown(0) { Error = FormulaError.CantOperateMathAndLogicValues }); } return(new CalcTokenBoolean(0) { Value = boolResult }); }