public override TokenStream Rewrite(TokenStream tokens)
{
// Token stream needs to be in infix notation.
if (tokens.Notation != TokenNotation.Infix)
{
throw new MathExpressionException("Token stream is not in infix notation.");
}
Queue<Token> output = new Queue<Token>();
Stack<Token> stack = new Stack<Token>();
foreach (Token token in tokens)
{
if (token.IsOperand())
{
output.Enqueue(token);
}
else if (token.Type == TokenType.Function)
{
stack.Push(token);
}
else if (token.Type == TokenType.Separator)
{
while (stack.Count > 0)
{
// Did we encounter a left parenthesis?
if (stack.Peek().Type == TokenType.OpeningParenthesis)
{
break;
}
output.Enqueue(stack.Pop());
}
Debug.Assert(stack.Count != 0, "Left parenthesis is missing from function!");
}
else if (token.IsOperator())
{
while (stack.Count > 0)
{
// Current operator is left asociative and has a precedence less or equal than the operator on the stack,
// OR the current operator right associative and has a precedence less than the operator on the stack.
// This expression should be cleaned up for readability...
bool cond1 = stack.Peek().IsOperator() && token.IsLeftAssociative() && token.GetPrecedence() <= stack.Peek().GetPrecedence();
bool cond2 = stack.Peek().IsOperator() && !token.IsLeftAssociative() && token.GetPrecedence() < stack.Peek().GetPrecedence();
if (cond1 || cond2)
{
output.Enqueue(stack.Pop());
}
else
{
break;
}
}
// Push the current operator onto the stack.
stack.Push(token);
}
else if (token.Type == TokenType.OpeningParenthesis)
{
stack.Push(token);
}
else if (token.Type == TokenType.ClosingParenthesis)
{
bool foundLeftParenthesis = false;
while (stack.Count > 0)
{
if (stack.Peek().Type == TokenType.OpeningParenthesis)
{
foundLeftParenthesis = true;
break;
}
output.Enqueue(stack.Pop());
}
if (!foundLeftParenthesis)
{
throw new MathExpressionException("Missing left parenthesis in expression.");
}
// Pop the left parenthesis from the stack.
stack.Pop();
if (stack.Count > 0)
{
// A function left on the stack?
if (stack.Peek().Type == TokenType.Function)
{
output.Enqueue(stack.Pop());
}
}
}
}
// Pop all operators from the stack.
while (stack.Count > 0)
{
if (stack.Peek().Type == TokenType.OpeningParenthesis)
{
throw new MathExpressionException("Missing right parenthesis in expression.");
}
output.Enqueue(stack.Pop());
}
return new TokenStream(output.ToArray(), TokenNotation.Postfix);
}