简体   繁体   English

分流码算法解析函数agruments

[英]Shunting-yard algorithm parsing function agruments

I am trying to get my implementation of the shunting-yard algorithm working. 我试图让我的shunting-yard算法的实现工作。 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: 例1:

Input: cbrt ( 8 ) 输入: cbrt ( 8 )

Output: 8 cbrt 输出: 8 cbrt

Output should be: cbrt 8 输出应为: cbrt 8

Example 2: 例2:

Input: cbrt ( 8 ) + sqrt ( 9 ) 输入: cbrt ( 8 ) + sqrt ( 9 )

Output: 8 9 sqrt + cbrt 输出: 8 9 sqrt + cbrt

Output should be: cbrt 8 sqrt 9 + 输出应为: cbrt 8 sqrt 9 +

Example 3: 例3:

Input: 5 + 4 - 9 / 2 ^ 6 * cbrt ( 8 ) 输入: 5 + 4 - 9 / 2 ^ 6 * cbrt ( 8 )

Output: 5 4 + 9 2 6 ^ / 8 cbrt * - 输出: 5 4 + 9 2 6 ^ / 8 cbrt * -

Output should be: 5 4 + 9 2 6 ^ / cbrt 8 * - 输出应为: 5 4 + 9 2 6 ^ / cbrt 8 * -

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. 它作为一个中缀表达式可能看起来像留给读者的练习,但它不是你开始的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM