/// <summary> /// Check if the expression needs to be tokenised in multiple cases /// e.g. Check if there is unary, check if parenthesis has multiply symbol /// </summary> private List <string> CheckIfTokenised(char[] tokenList) { List <string> newList = new List <string>(); for (int i = 0; i < tokenList.Length; i++) { char token = tokenList[i]; if (newList.Count != 0) { string topNewToken = newList[newList.Count - 1]; // If more than one digit, then combine with the previous digit if (char.IsDigit(token) && tokenChecker.IsNumber(topNewToken)) { newList[newList.Count - 1] += token; } // If there is an X after a number else if (token.Equals('x') && tokenChecker.IsNumber(topNewToken)) { newList.Add("*"); newList.Add(token.ToString()); } // Add multiply symbol if the token meets one of those cases else if (token.Equals('(') && (tokenChecker.IsNumber(topNewToken) || topNewToken.Equals(")") || topNewToken.Equals("x"))) { newList.Add("*"); newList.Add(token.ToString()); } else { newList.Add(token.ToString()); } } else { newList.Add(token.ToString()); } } // Those methods below can only be executed after adding // symbol process is completed CheckLastBlankNumber(ref newList); CheckMultipleOperators(ref newList); CheckUnary(ref newList); return(newList); }
/// <summary> /// Parse infix to postfix using shunting yard algorithm /// Source: https://en.wikipedia.org/wiki/Shunting-yard_algorithm /// </summary> public static List <string> ParseInfixToPostfix(List <string> tokenList) { TokenChecker tokenChecker = new TokenChecker(); Queue <string> outputQueue = new Queue <string>(); Stack <string> operatorStack = new Stack <string>(); // While there are tokens to be read foreach (string token in tokenList) { string stringToken = token.ToString(); // If the token is a number, push it to the queue if (tokenChecker.IsNumber(stringToken)) { outputQueue.Enqueue(stringToken); } // If the token is 'x', push it to the stack else if (stringToken.ToLower().Contains("x")) { operatorStack.Push(stringToken); } // If the token is an operator, do some logic by checking // operator precedence else if (tokenChecker.IsOperator(stringToken)) { if (operatorStack.Count != 0) { string topOp = operatorStack.Peek(); while (topOp.ToLower().Contains("x") || (Operator.IsGreaterOp(topOp, stringToken)) && topOp != "(") { var currentOp = operatorStack.Pop(); outputQueue.Enqueue(currentOp); if (operatorStack.Count != 0) { topOp = operatorStack.Peek(); } else { break; } } } operatorStack.Push(stringToken); } // If the token is '(', push it to the stack else if (token.Equals("(")) { operatorStack.Push(stringToken); } // If the token is ')', push tokens in stack to the queue // until the token from the stack equals '(' else if (token.Equals(")")) { var currentToken = operatorStack.Peek(); while (!currentToken.Equals("(")) { var opToken = operatorStack.Pop(); outputQueue.Enqueue(opToken); currentToken = operatorStack.Peek(); } if (currentToken.Equals("(")) { operatorStack.Pop(); } } } // Push the rest tokens in the stack to the queue while (operatorStack.Count != 0) { outputQueue.Enqueue(operatorStack.Pop()); } List <string> postfixExp = new List <string>(); while (outputQueue.Any()) { var val = outputQueue.Dequeue(); postfixExp.Add(val); } return(postfixExp); }