Reputation:
I am trying to get my implementation of the shunting-yard algorithm working. It works well with numbers and operators. But problems arise when I try and add functions to the input. Because the function argument outputs to the left of the function when it is supposed to output to the right.
Test Program
public class FrontTest
{
public static void main(String[] args)
{
String str = "cbrt ( 8 )";
System.out.println(ShuntTest.infixToPostfix(str));
}
}
Algorithm
import java.util.*;
public class ShuntTest
{
public static String infixToPostfix(String infixStr)
{
Stack<String> operators = new Stack<String>();
Queue<String> output = new LinkedList<String>();
String[] tokens = infixStr.split("[\\s]");
StringBuilder postfixStr = new StringBuilder();
int tokensRemaining = tokens.length;
final String PAREN_LEFT = "[\\(]";
final String PAREN_RIGHT = "[\\)]";
final String FUNCTION_ARGSEP = "[\\;]";
for (int i = 0; i < tokens.length; i++)
{
if (isNumber(tokens[i]))
{
output.offer(tokens[i]);
}
else if (isFunction(tokens[i]))
{
operators.push(tokens[i]);
}
else if (tokens[i].matches(FUNCTION_ARGSEP))
{
while (!operators.empty() && operators.peek().matches(PAREN_RIGHT))
{
output.offer(operators.pop());
if (operators.empty() && !operators.peek().matches(PAREN_RIGHT))
{
throw new RuntimeException("Mismatched Parentheses.");
}
}
}
else if (isOperator(tokens[i]))
{
while (!operators.empty() && ((isOperator(operators.peek())
&& ((isLeftAssociative(tokens[i]) == true && ((operatorPrecedence(tokens[i]) <= operatorPrecedence(operators.peek()))
|| ((isLeftAssociative(tokens[i]) == false && ((operatorPrecedence(tokens[i]) < operatorPrecedence(operators.peek())))))))))))
{
output.offer(operators.pop());
}
operators.push(tokens[i]);
}
else if (!operators.empty() && tokens[i].matches(PAREN_LEFT))
{
operators.push(tokens[i]);
}
else if (!operators.empty() && tokens[i].matches(PAREN_RIGHT))
{
while (!operators.empty() && !operators.peek().matches(PAREN_LEFT))
{
output.offer(operators.pop());
}
if (!operators.empty())
{
operators.pop();
}
else if (!operators.empty() && isFunction(operators.peek()))
{
output.offer(operators.pop());
}
else if (operators.empty())
{
throw new RuntimeException("Mismatched Parentheses.");
}
}
tokensRemaining--;
}
if (tokensRemaining == 0)
{
while (!operators.empty())
{
if (operators.peek().matches(PAREN_LEFT)
|| operators.peek().matches(PAREN_RIGHT))
{
throw new RuntimeException("Mismatched Parentheses.");
}
output.offer(operators.pop());
}
}
while (!output.isEmpty())
{
while (output.size() > 1)
{
postfixStr.append(output.poll() + " ");
}
postfixStr.append(output.poll());
}
return postfixStr.toString();
}
public static boolean isNumber(String str)
{
final String NUMBER = "^0?-?\\+?\\d+(\\.\\d+)?$";
return str.matches(NUMBER) ? true : false;
}
public static boolean isOperator(String str)
{
switch (str)
{
case "^":
case "/":
case "*":
case "+":
case "-":
return true;
default:
return false;
}
}
private static boolean isLeftAssociative(String str)
{
switch (str)
{
case "^":
return false;
case "/":
case "*":
case "+":
case "-":
return true;
default:
throw new IllegalArgumentException("Operator unknown: " + str);
}
}
private static int operatorPrecedence(String str)
{
switch (str)
{
case "^":
return 4;
case "/":
case "*":
return 3;
case "+":
case "-":
return 2;
default:
throw new IllegalArgumentException("Operator unknown: " + str);
}
}
public static boolean isFunction(String str)
{
switch (str)
{
case "sin":
case "cos":
case "tan":
case "sqrt":
case "cbrt":
case "root_of":
return true;
default:
return false;
}
}
}
Example 1:
Input:cbrt ( 8 )
Output:8 cbrt
Output should be:cbrt 8
Example 2:
Input:cbrt ( 8 ) + sqrt ( 9 )
Output:8 9 sqrt + cbrt
Output should be:cbrt 8 sqrt 9 +
Example 3:
Input:5 + 4 - 9 / 2 ^ 6 * cbrt ( 8 )
Output:5 4 + 9 2 6 ^ / 8 cbrt * -
Output should be:5 4 + 9 2 6 ^ / cbrt 8 * -
Upvotes: 1
Views: 970
Reputation: 310884
Think about it. The shunting-yard algorithm converts infix to postfix. However this:
cbrt ( 8 )
isn't an infix expression. It is a prefix expression.
As a postfix expression it would look like this:
8 cbrt
What it might look like as an infix expression is left as an exercise for the reader, but it isn't what you started with.
Upvotes: 2