private IEnumerable <IFormulaToken> CompleteFunctionsBackwards(IEnumerable <IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var nextToken = context[0]; var token = context[1]; // attach parentheses to function if (token is IFormulaFunction) { // missing function argument if (!(nextToken is FormulaNodeParentheses)) { yield break; } SetOrigin(token, new[] { token, nextToken }); yield return(token); continue; } // yield unattached parentheses if (nextToken is FormulaNodeParentheses) { yield return(nextToken); } // yield any other token if (token != null && !(token is FormulaNodeParentheses)) { yield return(token); } } }
/// <remarks>Compare <see cref="InterpretNumbers"/>. </remarks> private IEnumerable <IFormulaToken> CompleteNumbers(IEnumerable <IFormulaToken> tokens) { var numberTokens = new List <IFormulaToken>(); var decimalSeparators = 0; foreach (var token in tokens.WithContext().Select(context => context[1])) { // append digit if (token is FormulaNodeNumber) { numberTokens.Add(token); continue; } // append decimal separator if (token is FormulaTokenDecimalSeparator) { if (decimalSeparators == 0) { numberTokens.Add(token); decimalSeparators++; continue; } decimalSeparators++; } // create common token of value if (numberTokens.Count != 0) { IFormulaToken commonToken; if (numberTokens.Count == 1) { if (decimalSeparators != 0) { yield break; } commonToken = numberTokens[0]; } else { commonToken = FormulaTreeFactory.CreateNumberNode(default(double)); SetOrigin(commonToken, GetOrigin(numberTokens)); } yield return(commonToken); if (decimalSeparators > 1) { yield break; } numberTokens.Clear(); decimalSeparators = 0; } // yield any non-number token yield return(token); } }
/// <summary> /// Ensures all parameters are separated by exactly one <see cref="FormulaTokenParameterSeparator"/> and suppresses all occurences of <see cref="FormulaTokenParameterSeparator"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretParameters(IEnumerable <IFormulaToken> tokens) { var expectSeparator = false; foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) { yield break; } var previousToken = context[0]; var token = context[1]; // parameter separator if (token is FormulaTokenParameterSeparator) { if (!expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(token).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_EmptyArgument")); yield break; } expectSeparator = false; continue; } // any argument if (token != null) { if (expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(token).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_ArgumentDoubleValue")); yield break; } yield return(token); expectSeparator = true; continue; } // last token if (token == null && !expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(previousToken).End), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_EmptyArgument")); yield break; } } }
/// <summary> /// Attaches the children of <see cref="FormulaNodeUnaryFunction"/> and <see cref="FormulaNodeBinaryFunction"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretFunctions(IEnumerable <IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) { yield break; } var previousToken = context[0]; var token = context[1]; // attach argument to function if (previousToken is IFormulaFunction) { if (!(token is FormulaTokenParameter)) { SetParsingError( source: Range.Empty(GetOrigin(previousToken).End), message: AppResourcesHelper.Get("FormulaInterpreter_Function_Empty")); yield break; } var unaryFunctionToken = previousToken as FormulaNodeUnaryFunction; if (unaryFunctionToken != null) { var unaryParameterToken = (FormulaTokenUnaryParameter)token; unaryFunctionToken.Child = unaryParameterToken.Parameter; } var binaryFunctionToken = previousToken as FormulaNodeBinaryFunction; if (binaryFunctionToken != null) { var binaryParameterToken = (FormulaTokenBinaryParameter)token; binaryFunctionToken.FirstChild = binaryParameterToken.FirstParameter; binaryFunctionToken.SecondChild = binaryParameterToken.SecondParameter; } SetOrigin(previousToken, new[] { previousToken, token }); yield return(previousToken); continue; } // yield any other token if (token != null && !(token is IFormulaFunction)) { yield return(token); } } }
/// <summary> /// Resolves the ambiguity between <see cref="FormulaNodeSubtract"/> and <seealso cref="FormulaNodeNegativeSign"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretMinusTokenForward(IEnumerable <IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var previousToken = context[0]; var token = context[1]; // handle minus token var minusToken = token as FormulaNodeSubtract; if (minusToken != null) { token = InterpretMinusToken(previousToken, minusToken); } if (token != null) { yield return(token); } } }
/// <summary> /// Resolves the ambiguity between <see cref="FormulaNodeSubtract"/> and <seealso cref="FormulaNodeNegativeSign"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretMinusTokenBackwards(IEnumerable <IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var nextToken = context[0]; var token = context[1]; // handle minus token var minusToken = nextToken as FormulaNodeSubtract; if (minusToken != null) { nextToken = InterpretMinusToken(token, minusToken); yield return(nextToken); } // yield any non minus token if (token != null && !(token is FormulaNodeSubtract)) { yield return(token); } } }
/// <remarks>Compare <see cref="InterpretNumbers"/>. </remarks> private IEnumerable<IFormulaToken> CompleteNumbers(IEnumerable<IFormulaToken> tokens) { var numberTokens = new List<IFormulaToken>(); var decimalSeparators = 0; foreach (var token in tokens.WithContext().Select(context => context[1])) { // append digit if (token is FormulaNodeNumber) { numberTokens.Add(token); continue; } // append decimal separator if (token is FormulaTokenDecimalSeparator) { if (decimalSeparators == 0) { numberTokens.Add(token); decimalSeparators++; continue; } decimalSeparators++; } // create common token of value if (numberTokens.Count != 0) { IFormulaToken commonToken; if (numberTokens.Count == 1) { if (decimalSeparators != 0) yield break; commonToken = numberTokens[0]; } else { commonToken = FormulaTreeFactory.CreateNumberNode(default(double)); SetOrigin(commonToken, GetOrigin(numberTokens)); } yield return commonToken; if (decimalSeparators > 1) yield break; numberTokens.Clear(); decimalSeparators = 0; } // yield any non-number token yield return token; } }
/// <summary> /// Ensures all parameters are separated by exactly one <see cref="FormulaTokenParameterSeparator"/> and suppresses all occurences of <see cref="FormulaTokenParameterSeparator"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretParameters(IEnumerable<IFormulaToken> tokens) { var expectSeparator = false; foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) yield break; var previousToken = context[0]; var token = context[1]; // parameter separator if (token is FormulaTokenParameterSeparator) { if (!expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(token).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_EmptyArgument")); yield break; } expectSeparator = false; continue; } // any argument if (token != null) { if (expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(token).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_ArgumentDoubleValue")); yield break; } yield return token; expectSeparator = true; continue; } // last token if (token == null && !expectSeparator) { SetParsingError( source: Range.Empty(GetOrigin(previousToken).End), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_EmptyArgument")); yield break; } } }
/// <remarks>Compare <see cref="InterpretBrackets"/>. </remarks> private IEnumerable<IFormulaToken> CompleteBrackets(IEnumerable<IFormulaToken> tokens, bool forward = true) { var parenthesesTokens = new Stack<List<IFormulaToken>>(); var parentheses = new Stack<IFormulaToken>(); foreach (var context in tokens.WithContext()) { var previousToken = context[0]; var token = context[1]; var parenthesisToken = token as FormulaTokenParenthesis; if (parenthesisToken != null) { if (forward ? parenthesisToken.IsOpening : parenthesisToken.IsClosing) { parenthesesTokens.Push(new List<IFormulaToken>()); parenthesesTokens.Peek().Add(token); parentheses.Push(FormulaTreeFactory.CreateParenthesesNode(null)); } else { // unmatched bracket if (parenthesesTokens.Count == 0) yield break; parenthesesTokens.Peek().Add(token); var commonToken = parentheses.Pop(); CompleteChildren(commonToken, parenthesesTokens.Pop()); if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return commonToken; } } continue; } // complete incomplete parentheses if (token == null) { while (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(previousToken); var commonToken = parentheses.Pop(); CompleteChildren(commonToken, parenthesesTokens.Pop()); if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return commonToken; } } continue; } // dismiss tokens inside parentheses if (parenthesesTokens.Count != 0) continue; // yield any token outside parentheses yield return token; } }
/// <remarks>Compare <see cref="InterpretBrackets"/>. </remarks> private IEnumerable <IFormulaToken> CompleteBrackets(IEnumerable <IFormulaToken> tokens, bool forward = true) { var parenthesesTokens = new Stack <List <IFormulaToken> >(); var parentheses = new Stack <IFormulaToken>(); foreach (var context in tokens.WithContext()) { var previousToken = context[0]; var token = context[1]; var parenthesisToken = token as FormulaTokenParenthesis; if (parenthesisToken != null) { if (forward ? parenthesisToken.IsOpening : parenthesisToken.IsClosing) { parenthesesTokens.Push(new List <IFormulaToken>()); parenthesesTokens.Peek().Add(token); parentheses.Push(FormulaTreeFactory.CreateParenthesesNode(null)); } else { // unmatched bracket if (parenthesesTokens.Count == 0) { yield break; } parenthesesTokens.Peek().Add(token); var commonToken = parentheses.Pop(); CompleteChildren(commonToken, parenthesesTokens.Pop()); if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return(commonToken); } } continue; } // complete incomplete parentheses if (token == null) { while (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(previousToken); var commonToken = parentheses.Pop(); CompleteChildren(commonToken, parenthesesTokens.Pop()); if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return(commonToken); } } continue; } // dismiss tokens inside parentheses if (parenthesesTokens.Count != 0) { continue; } // yield any token outside parentheses yield return(token); } }
/// <summary> /// Attaches the children of <see cref="FormulaNodeUnaryFunction"/> and <see cref="FormulaNodeBinaryFunction"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretFunctions(IEnumerable<IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) yield break; var previousToken = context[0]; var token = context[1]; // attach argument to function if (previousToken is IFormulaFunction) { if (!(token is FormulaTokenParameter)) { SetParsingError( source: Range.Empty(GetOrigin(previousToken).End), message: AppResourcesHelper.Get("FormulaInterpreter_Function_Empty")); yield break; } var unaryFunctionToken = previousToken as FormulaNodeUnaryFunction; if (unaryFunctionToken != null) { var unaryParameterToken = (FormulaTokenUnaryParameter) token; unaryFunctionToken.Child = unaryParameterToken.Parameter; } var binaryFunctionToken = previousToken as FormulaNodeBinaryFunction; if (binaryFunctionToken != null) { var binaryParameterToken = (FormulaTokenBinaryParameter) token; binaryFunctionToken.FirstChild = binaryParameterToken.FirstParameter; binaryFunctionToken.SecondChild = binaryParameterToken.SecondParameter; } SetOrigin(previousToken, new[] { previousToken, token }); yield return previousToken; continue; } // yield any other token if (token != null && !(token is IFormulaFunction)) { yield return token; } } }
private IEnumerable<IFormulaToken> CompleteFunctionsBackwards(IEnumerable<IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var nextToken = context[0]; var token = context[1]; // attach parentheses to function if (token is IFormulaFunction) { // missing function argument if (!(nextToken is FormulaNodeParentheses)) yield break; SetOrigin(token, new[] { token, nextToken }); yield return token; continue; } // yield unattached parentheses if (nextToken is FormulaNodeParentheses) yield return nextToken; // yield any other token if (token != null && !(token is FormulaNodeParentheses)) yield return token; } }
/// <summary> /// Maps all opening and closing parentheses and packs them with their interpreted children into <see cref="FormulaTokenParameter"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretBrackets(IEnumerable <IFormulaToken> tokens) { var parenthesesTokens = new Stack <List <IFormulaToken> >(); var parentheses = new Stack <IFormulaToken>(); foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) { yield break; } var previousToken = context[0]; var token = context[1]; var parenthesisToken = token as FormulaTokenParenthesis; if (parenthesisToken != null) { // handle opening parenthesis if (parenthesisToken.IsOpening) { parenthesesTokens.Push(new List <IFormulaToken>()); parenthesesTokens.Peek().Add(token); if (previousToken is FormulaNodeUnaryFunction) { parentheses.Push(FormulaTokenFactory.CreateUnaryParameterToken(null)); } else if (previousToken is FormulaNodeBinaryFunction) { parentheses.Push(FormulaTokenFactory.CreateBinaryParameterToken(null, null)); } else { parentheses.Push(FormulaTreeFactory.CreateParenthesesNode(null)); } } // handle closing parenthesis else { if (parenthesesTokens.Count == 0) { if (previousToken is IFormulaFunction) { SetParsingError(Range.Empty(GetOrigin(parenthesisToken).Start), AppResourcesHelper.Get("FormulaInterpreter_Function_Empty")); } else { SetParsingError(parenthesisToken, AppResourcesHelper.Get("FormulaInterpreter_Brackets_UnmatchedClosingParenthesis")); } yield break; } parenthesesTokens.Peek().Add(token); // interpret parentheses var commonToken = parentheses.Pop(); InterpretChildren(commonToken, parenthesesTokens.Pop()); if (IsCancellationRequested) { yield break; } if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return(commonToken); } } continue; } // last token if (token == null) { if (parenthesesTokens.Count != 0) { SetParsingError( source: Range.Empty(GetOrigin(parenthesesTokens.Peek().Last()).End), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_UnmatchedOpeningParenthesis")); yield break; } continue; } // stash tokens inside parentheses if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(token); continue; } // yield any token outside parentheses yield return(token); } }
/// <summary> /// Attaches the children of <see cref="FormulaNodePrefixOperator"/> and <see cref="FormulaNodeInfixOperator"/>. /// </summary> private IEnumerable <IFormulaToken> InterpretOperators(IEnumerable <IFormulaToken> tokens, IEnumerable <IFormulaToken> lookAhead) { var pending = new Stack <FormulaTree>(); lookAhead = InterpretMinusTokenForward(lookAhead); var lookAhead2 = lookAhead.GetEnumerator(); foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) { yield break; } var previousToken = context[0]; var token = context[1]; if (token == null) { yield break; } // yield parameter separators if (token is FormulaTokenParameterSeparator) { yield return(token); continue; } var token2 = (FormulaTree)token; var operatorToken = token2 as IFormulaOperator; // advance lookAhead parallel to tokens var nextIndex = GetOrigin(token).End; var nextToken = lookAhead2.FirstOrDefault(token3 => GetOrigin(token3).Start == nextIndex); // stash operators if (operatorToken != null) { if ((previousToken == null || previousToken is FormulaTokenParameterSeparator) && operatorToken is FormulaNodeInfixOperator) { SetParsingError( source: Range.Empty(GetOrigin(token2).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Operator_LeftEmptyInfixOperator")); yield break; } if (nextToken == null || nextToken is FormulaTokenParameterSeparator || nextToken is FormulaNodeInfixOperator) { SetParsingError( source: Range.Empty(GetOrigin(token2).End), message: operatorToken is FormulaNodePrefixOperator ? AppResourcesHelper.Get("FormulaInterpreter_Operator_EmptyPrefixOperator") : AppResourcesHelper.Get("FormulaInterpreter_Operator_RightEmptyInfixOperator")); yield break; } pending.Push(token2); continue; } // merge with pending tokens (regarding operator order) var nextInfixOperatorToken = nextToken as FormulaNodeInfixOperator; if (nextInfixOperatorToken == null || (pending.Count != 0 && ((IFormulaOperator)pending.Peek()).Order >= nextInfixOperatorToken.Order)) { while (pending.Count != 0) { var pendingOperator = pending.Pop(); // attach token to prefix operator var pendingPrefixOperator = pendingOperator as FormulaNodePrefixOperator; if (pendingPrefixOperator != null) { var numberToken = token2 as FormulaNodeNumber; // merge negative sign and number if (numberToken != null && pendingPrefixOperator is FormulaNodeNegativeSign) { numberToken.Value *= -1; SetOrigin(token2, new[] { pendingOperator, token2 }); } else { pendingPrefixOperator.Child = token2; SetOrigin(pendingPrefixOperator, new[] { pendingOperator, token2 }); token2 = pendingOperator; } } // attach token to infix operator var pendingInfixOperator = pendingOperator as FormulaNodeInfixOperator; if (pendingInfixOperator != null) { pendingInfixOperator.LeftChild = pending.Pop(); pendingInfixOperator.RightChild = token2; SetOrigin(pendingInfixOperator, new[] { pendingInfixOperator.LeftChild, pendingOperator, token2 }); token2 = pendingOperator; } } } // stash to infix operator attached tokens if (nextInfixOperatorToken != null) { pending.Push(token2); continue; } // yield finished or unattached tokens yield return(token2); } }
/// <summary> /// Maps all opening and closing parentheses and packs them with their interpreted children into <see cref="FormulaTokenParameter"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretBrackets(IEnumerable<IFormulaToken> tokens) { var parenthesesTokens = new Stack<List<IFormulaToken>>(); var parentheses = new Stack<IFormulaToken>(); foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) yield break; var previousToken = context[0]; var token = context[1]; var parenthesisToken = token as FormulaTokenParenthesis; if (parenthesisToken != null) { // handle opening parenthesis if (parenthesisToken.IsOpening) { parenthesesTokens.Push(new List<IFormulaToken>()); parenthesesTokens.Peek().Add(token); if (previousToken is FormulaNodeUnaryFunction) { parentheses.Push(FormulaTokenFactory.CreateUnaryParameterToken(null)); } else if (previousToken is FormulaNodeBinaryFunction) { parentheses.Push(FormulaTokenFactory.CreateBinaryParameterToken(null, null)); } else { parentheses.Push(FormulaTreeFactory.CreateParenthesesNode(null)); } } // handle closing parenthesis else { if (parenthesesTokens.Count == 0) { if (previousToken is IFormulaFunction) { SetParsingError(Range.Empty(GetOrigin(parenthesisToken).Start), AppResourcesHelper.Get("FormulaInterpreter_Function_Empty")); } else { SetParsingError(parenthesisToken, AppResourcesHelper.Get("FormulaInterpreter_Brackets_UnmatchedClosingParenthesis")); } yield break; } parenthesesTokens.Peek().Add(token); // interpret parentheses var commonToken = parentheses.Pop(); InterpretChildren(commonToken, parenthesesTokens.Pop()); if (IsCancellationRequested) yield break; if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(commonToken); } else { yield return commonToken; } } continue; } // last token if (token == null) { if (parenthesesTokens.Count != 0) { SetParsingError( source: Range.Empty(GetOrigin(parenthesesTokens.Peek().Last()).End), message: AppResourcesHelper.Get("FormulaInterpreter_Brackets_UnmatchedOpeningParenthesis")); yield break; } continue; } // stash tokens inside parentheses if (parenthesesTokens.Count != 0) { parenthesesTokens.Peek().Add(token); continue; } // yield any token outside parentheses yield return token; } }
/// <summary> /// Attaches the children of <see cref="FormulaNodePrefixOperator"/> and <see cref="FormulaNodeInfixOperator"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretOperators(IEnumerable<IFormulaToken> tokens, IEnumerable<IFormulaToken> lookAhead) { var pending = new Stack<FormulaTree>(); lookAhead = InterpretMinusTokenForward(lookAhead); var lookAhead2 = lookAhead.GetEnumerator(); foreach (var context in tokens.WithContext()) { if (IsCancellationRequested) yield break; var previousToken = context[0]; var token = context[1]; if (token == null) yield break; // yield parameter separators if (token is FormulaTokenParameterSeparator) { yield return token; continue; } var token2 = (FormulaTree) token; var operatorToken = token2 as IFormulaOperator; // advance lookAhead parallel to tokens var nextIndex = GetOrigin(token).End; var nextToken = lookAhead2.FirstOrDefault(token3 => GetOrigin(token3).Start == nextIndex); // stash operators if (operatorToken != null) { if ((previousToken == null || previousToken is FormulaTokenParameterSeparator) && operatorToken is FormulaNodeInfixOperator) { SetParsingError( source: Range.Empty(GetOrigin(token2).Start), message: AppResourcesHelper.Get("FormulaInterpreter_Operator_LeftEmptyInfixOperator")); yield break; } if (nextToken == null || nextToken is FormulaTokenParameterSeparator || nextToken is FormulaNodeInfixOperator) { SetParsingError( source: Range.Empty(GetOrigin(token2).End), message: operatorToken is FormulaNodePrefixOperator ? AppResourcesHelper.Get("FormulaInterpreter_Operator_EmptyPrefixOperator") : AppResourcesHelper.Get("FormulaInterpreter_Operator_RightEmptyInfixOperator")); yield break; } pending.Push(token2); continue; } // merge with pending tokens (regarding operator order) var nextInfixOperatorToken = nextToken as FormulaNodeInfixOperator; if (nextInfixOperatorToken == null || (pending.Count != 0 && ((IFormulaOperator) pending.Peek()).Order >= nextInfixOperatorToken.Order)) { while (pending.Count != 0) { var pendingOperator = pending.Pop(); // attach token to prefix operator var pendingPrefixOperator = pendingOperator as FormulaNodePrefixOperator; if (pendingPrefixOperator != null) { var numberToken = token2 as FormulaNodeNumber; // merge negative sign and number if (numberToken != null && pendingPrefixOperator is FormulaNodeNegativeSign) { numberToken.Value *= -1; SetOrigin(token2, new[] {pendingOperator, token2}); } else { pendingPrefixOperator.Child = token2; SetOrigin(pendingPrefixOperator, new[] {pendingOperator, token2}); token2 = pendingOperator; } } // attach token to infix operator var pendingInfixOperator = pendingOperator as FormulaNodeInfixOperator; if (pendingInfixOperator != null) { pendingInfixOperator.LeftChild = pending.Pop(); pendingInfixOperator.RightChild = token2; SetOrigin(pendingInfixOperator, new[] {pendingInfixOperator.LeftChild, pendingOperator, token2}); token2 = pendingOperator; } } } // stash to infix operator attached tokens if (nextInfixOperatorToken != null) { pending.Push(token2); continue; } // yield finished or unattached tokens yield return token2; } }
/// <summary> /// Resolves the ambiguity between <see cref="FormulaNodeSubtract"/> and <seealso cref="FormulaNodeNegativeSign"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretMinusTokenBackwards(IEnumerable<IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var nextToken = context[0]; var token = context[1]; // handle minus token var minusToken = nextToken as FormulaNodeSubtract; if (minusToken != null) { nextToken = InterpretMinusToken(token, minusToken); yield return nextToken; } // yield any non minus token if (token != null && !(token is FormulaNodeSubtract)) yield return token; } }
/// <summary> /// Resolves the ambiguity between <see cref="FormulaNodeSubtract"/> and <seealso cref="FormulaNodeNegativeSign"/>. /// </summary> private IEnumerable<IFormulaToken> InterpretMinusTokenForward(IEnumerable<IFormulaToken> tokens) { foreach (var context in tokens.WithContext()) { var previousToken = context[0]; var token = context[1]; // handle minus token var minusToken = token as FormulaNodeSubtract; if (minusToken != null) token = InterpretMinusToken(previousToken, minusToken); if (token != null) yield return token; } }