Problems with a shunting yard algorithm

前端 未结 4 1191
陌清茗
陌清茗 2020-12-10 07:02

I have successfully implemented a shunting yard algorithm in java. The algorithm itself was simple however I am having trouble with the tokenizer. Currently the algorithm wo

4条回答
  •  盖世英雄少女心
    2020-12-10 07:21

    In your lexer, you can implement this pseudo-logic:

    if (symbol == '-') {
        if (previousToken is a number 
         OR previousToken is an identifier 
         OR previousToken is a function) {
            currentToken = SUBTRACT;
        } else {
            currentToken = NEGATION;
        }
    }
    

    You can set up negation to have a precedence higher than multiply and divide, but lower than exponentiation. You can also set it up to be right associative (just like '^'). Then you just need to integrate the precedence and associativity into the algorithm as described on Wikipedia's page.

    If the token is an operator, o1, then: while there is an operator token, o2, at the top of the stack, and either o1 is left-associative and its precedence is less than or equal to that of o2, or o1 has precedence less than that of o2, pop o2 off the stack, onto the output queue; push o1 onto the stack.

    I ended up implementing this corresponding code:

    } else if (nextToken instanceof Operator) {
        final Operator o1 = (Operator) nextToken;
    
        while (!stack.isEmpty() && stack.peek() instanceof Operator) {
            final Operator o2 = (Operator) stack.peek();
    
            if ((o1.associativity == Associativity.LEFT && o1.precedence <= o2.precedence)
             || (o1.associativity == Associativity.RIGHT && o1.precedence < o2.precedence)) {
                popStackTopToOutput();
            } else {
                break;
            }
        }
    
        stack.push(nextToken);
    }
    

    Austin Taylor is quite right that you only need to pop off one number for a unary operator:

    if (token is operator negate) {
        operand = pop;
        push operand * -1;
    }
    

    Example project:

    https://github.com/Digipom/Calculator-for-Android/

    Further reading:

    http://en.wikipedia.org/wiki/Shunting-yard_algorithm

    http://sankuru.biz/blog/1-parsing-object-oriented-expressions-with-dijkstras-shunting-yard-algorithm

提交回复
热议问题