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