/// <summary> /// Transform an infix expression string into /// a postfix expression string /// </summary> public Stack<string> InfixToPostfix(string expression) { var operands = new Stack<Token>(); var postfix = new Stack<Token>(); foreach (Token token in expression.Tokens()) { if (token.IsEmpty) continue; switch (token.Class) { case TokenClass.Name: case TokenClass.Operand: #region Test for uniary operator if (operands.HasItems() && operands.Peek().Class == TokenClass.UniaryPrefix) { switch (operands.Peek().Value) { case "-": // turn a uniary minus and operand into a negative operand operands.Pop(); postfix.Push(token); postfix.Push(new Token("-1")); postfix.Push(new Token("*")); break; case "+": // no change to operand, remove uniary postfix.Push(token); operands.Pop(); break; default: throw new Exception("Unexpected operator"); } #endregion } else { postfix.Push(token); } break; case TokenClass.UniaryPostfix: operands.Push(token); break; case TokenClass.UniaryPrefix: case TokenClass.Function: case TokenClass.OpenBracket: #region Test for uniary operator if (operands.HasItems() && operands.Peek().Class == TokenClass.UniaryPrefix) { switch (operands.Peek().Value) { case "-": // change value, which will get picked up on bracket close token.Value = "-"; operands.Pop(); // remove uniary operands.Push(token); // push bracket break; case "+": operands.Pop(); // remove uniary operands.Push(token); // push bracket break; default: throw new Exception("Unexpected operator"); } #endregion } else { operands.Push(token); } break; case TokenClass.ArgumentSeperator: while (operands.HasItems() && operands.Peek().Class != TokenClass.OpenBracket) { if (operands.Count < 1) throw new Exception("Argument seperator outside of argument list"); postfix.Push(operands.Pop()); } break; case TokenClass.BinaryOperator: while (operands.HasItems() && token.ShouldDisplace(operands.Peek())) { // compare precedence postfix.Push(operands.Pop()); } operands.Push(token); break; case TokenClass.CloseBracket: while (operands.HasItems() && operands.Peek().Class != TokenClass.OpenBracket) { // add inner bracket contents postfix.Push(operands.Pop()); } #region Check for previously caught uniary minus bracket "-(...)" if (operands.HasItems()) { Token ob = operands.Pop(); // check open bracket if (ob.Value == "-") { // invert value postfix.Push(new Token("-1")); postfix.Push(new Token("*")); } } #endregion if (operands.HasItems() && operands.Peek().Class == TokenClass.Function) {// this is actually a function postfix.Push(operands.Pop()); } break; default: throw new Exception("Unexpected token: " + token.Value); } // end of switch } // end of token stream // deal with any remaining operators while (operands.HasItems()) { // compare precedence postfix.Push(operands.Pop()); } var output = new Stack<string>(postfix.Count); foreach (Token t in postfix) output.Push(t.Value.Trim()); return output; }