Postfix evaluating incorrectly

119 Views Asked by At

-2^2 (infix notation) should translate to -2 2 ^ (postfix notation). It does as expected however when evaluating that postfix it evaluates to 4 not -4 which is what is expected.

I'm using Lua and here's my precedence & associativity tables:

-- Precedence table for different operators
local PRECEDENCE = {
    [Token.Type.MINUS] = 0,
    [Token.Type.PLUS] = 0,
    [Token.Type.ASTERIK] = 1,
    [Token.Type.SLASH] = 1,
    [Token.Type.CARET] = 2,
    [Token.Type.UMINUS] = 3
}

-- Associativity table for different operators
-- 0 = LTR (Left To Right)
-- 1 = RTL (Right To Left)
local ASSOCIATIVITY = {
    [Token.Type.MINUS] = 0,
    [Token.Type.PLUS] = 0,
    [Token.Type.ASTERIK] = 0,
    [Token.Type.SLASH] = 0,
    [Token.Type.CARET] = 1,
    [Token.Type.UMINUS] = 1
}

When trying to evaluate -2^2 my output queue looks like this:

{
  2,
  UMINUS,
  2,
  CARET
}

Here's my parser. It's worth noting that queue and stack are "classes" with their respective functionality.

--[[
    Parse tokens
]]
function Parser:parse()
    self:preprocess() -- Convert valid MINUS tokens into UMINUS
    
    while (self.token) do
        local token = self.token
        
        if (token.type == Token.Type.NUMBER) then
            self.queue:enqueue(tonumber(token.value))
        elseif (isOperator(token)) then -- PLUS, MINUS, SLASH, ASTERIK, UMINUS, CARET
            while (not self.stack:isEmpty()
                and ASSOCIATIVITY[token.type]
                and PRECEDENCE[token.type]
                and ASSOCIATIVITY[self.stack:top().type]
                and PRECEDENCE[self.stack:top().type]
                and ((ASSOCIATIVITY[token.type] == 0 and PRECEDENCE[token.type] <= PRECEDENCE[self.stack:top().type])
                    or (ASSOCIATIVITY[token.type] == 1 and PRECEDENCE[token.type] < PRECEDENCE[self.stack:top().type]))) do
                self.queue:enqueue(self.stack:pop())
            end
            self.stack:push(token)
        elseif (token.type == Token.Type.LPAREN) then
            self.stack:push(token)
        elseif (token.type == Token.Type.RPAREN) then
            while (self.stack:top().type ~= Token.Type.LPAREN) do
                self.queue:enqueue(self.stack:pop())
            end
            self.stack:pop()
        end
        self:next() -- Move to the next token
    end
    while (not self.stack:isEmpty()) do
        self.queue:enqueue(self.stack:pop())
    end
    return self.queue
end

What am I doing wrong? I tried an online calculator here and I also get 4 yet I know the correct output should be -4 for that expression.

1

There are 1 best solutions below

0
luther On

To get the result you expect, the carat must have a higher precedence than unary minus. That's how it works in Lua's operator precedence. The postfix notation for -2^2 should actually be 2 2 ^ UMINUS. Remember that the square of any real number is always positive. You could just swap the precedence levels:

[Token.Type.CARET] = 3,
[Token.Type.UMINUS] = 2,