Question

I am implementing the shunting yard algorithm and I am having trouble handling parenthesis. It works fine with non grouped expressions though. Here's what I have without Parenthesis detection:

public void makePost(String e)
{
    String[] arr = e.split("");
    for(int i = 0; i < arr.length; i++)
    {
        if(arr[i].equals(" "))
        {
            continue;
        }
        Operator o = OperatorList.getOpMap().get(arr[i]);
        if(o == null){
            postfix += " " + arr[i];
            continue;
        }
        if(ops.isEmpty()){
            ops.push(o);
            continue;
        }
        else
        {

            while((!ops.isEmpty()  && (ops.peek().getPresedence() <= o.getPresedence()))){
                postfix += " " + ops.pop();
            }
            ops.push(o);
            continue;
        }

    }
    while(!ops.isEmpty())
    {
        postfix += " " + ops.pop();
    }
    postfix = postfix.trim();

}

ops is the stack that holds Operator objects. There are two types of operators, functions(+,-,* etc) and Parans ("(","["). How would you add parenthesis handling to this? Each time I try, I can't seem to get it to work properly

Here is what I tried:

    public void makePost(String e)
{
    String[] arr = e.split("");
    for(int i = 0; i < arr.length; i++){
        if(arr[i].equals(" ")){
            continue;
        }
        Operator o = OperatorList.getOpMap().get(arr[i]);
        if(o == null){
            postfix += " " + arr[i];
            continue;
        }
        if(ops.isEmpty()){
            ops.push(o);
            continue;
        }
        else
        {
            if(o.isParan())
            {
                Paran p = new Paran(o.toString());
                if(p.isOpen())
                {
                ops.push(o);
                System.out.println(ops);
                continue;
                }else{      
                    while(!ops.isEmpty()){ 
                        if(ops.peek().isParan()){
                            Paran n = new Paran(o.toString());
                            if(n.isOpen()){
                                ops.pop();
                                break;
                            }
                        }
                        postfix += " " + ops.pop();
                    }
                    continue;
                }
            }
            while((!ops.isEmpty()  && (ops.peek().getPresedence() <= o.getPresedence()))){
                postfix += " " + ops.pop();
            }
            ops.push(o);
            continue;
        }

    }
    while(!ops.isEmpty())
    {
        postfix += " " + ops.pop();
    }
    postfix = postfix.trim();

}

I suspect the while loop condition is bad, but I don't know of any proper replacement. It goes on to infinity. This was the cleanest implementation I had. Basically what it is supposed to do is when it encounters an open parenthesis, push it onto the stack. When it hits a closed one, pop everything off the stack onto the output until it hits the open parenthesis. Then it should break, and continue to the next token.

if(o.isParan())
            {
                Paran p = new Paran(o.toString());
                if(p.isOpen())
                {
                ops.push(o);
                System.out.println(ops);
                continue;
                }else{      
                    while(!ops.isEmpty()){ 
                        if(ops.peek().isParan()){
                            Paran n = new Paran(o.toString());
                            if(n.isOpen()){
                                ops.pop();
                                break;
                            }
                        }
                        postfix += " " + ops.pop();
                    }
                    continue;
                }

EDIT: added my attempt

No correct solution

OTHER TIPS

Got it to work! I added a few checks for parenthesis in logical areas, Here is the final:

    public void makePost(String e)
{
    String[] arr = e.split("");
    for(int i = 0; i < arr.length; i++)
    {

        System.out.println(postfix + " " + i + " " + ops);
        if(arr[i].equals(" "))
        {
            continue;
        }
        if(arr[i].equals("(")){
            ops.push(new Paran("("));
            continue;
        }
        if(!ops.isEmpty() && arr[i].equals(")")){
            while(!ops.isEmpty() && !ops.peek().isOpen()){

                postfix += " " + ops.pop();
            }
            ops.pop();
        }
        Operator o = OperatorList.getOpMap().get(arr[i]);
        if(o == null){
            postfix += " " + arr[i];
            continue;
        }
        if(ops.isEmpty()){

            ops.push(o);

            continue;
        }
        else
        {

            while((!ops.isEmpty()  && (ops.peek().getPresedence() <= o.getPresedence()) && !(ops.peek() instanceof Paran))){

                postfix += " " + ops.pop();
            }
            ops.push(o);
            continue;

        }

    }

    while(!ops.isEmpty())
    {

        postfix += " " + ops.pop();
    }

   postfix = postfix.replaceAll("\\s[)]","");


}

I have the replaceall() call because the output kept return closing parenthesis along with the corrent postfix, ex:

2 4 * 7 8 4 * 4 4 5 * ) / ) * ) +

I have no idea why it does that, but I am glad it works

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top