/// <summary> /// Распознавание токенов обращения к значению переменной /// </summary> /// <param name="formula">Формула</param> /// <param name="currentTokenPosition">Текущая позиция в формуле (указывает на начало ещё не разобранного токена)</param> /// <returns>Токен</returns> public ICalcToken VariableTokenizer(string formula, int currentTokenPosition) { var token = new CalcTokenNumber(currentTokenPosition); string text = string.Empty; if (formula[currentTokenPosition] != '[' || formula.Length < currentTokenPosition+2) return null; text += formula[currentTokenPosition]; for (var i = currentTokenPosition + 1; i < formula.Length; i++) { if (formula[i] == '[') return new CalcTokenUnknown(currentTokenPosition) { Error = FormulaError.UnexpectedSymbols, TokenText = text }; text += formula[i]; if (formula[i] != ']') continue; if (text.Length == 2) return new CalcTokenUnknown(currentTokenPosition) { Error = FormulaError.UnexpectedSymbols, TokenText = text }; token.TokenText = text; var varAndPanelName = text.Substring(1, text.Length - 2).Split('.'); if (varAndPanelName.Length != 2) return null; var varId = Profile.GetVariableByPanelAndName(varAndPanelName[0], varAndPanelName[1]); if (varId == Guid.Empty) token.Error = FormulaError.TokenPointsAbsentItem; token.Error = FormulaError.Ok; return token; } return new CalcTokenUnknown(currentTokenPosition) { Error = FormulaError.UnexpectedSymbols, TokenText = text }; }
// InputFormula // Как потом раздать результат в другие переменные? Ввести в формулы термин "[R]"? private ICalcToken FormulaResultTokenizer(string formula, int currentTokenPosition) { const string resultTokenText = "[R]"; var token = new CalcTokenNumber(currentTokenPosition) { TokenText = resultTokenText }; return(formula.Substring(currentTokenPosition, 3) != resultTokenText ? null : token); }
/// <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) }); }