/// <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); } }