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