codster303
codster303

Reputation: 33

Evaluating Infix Expressions Using Stacks in Python: I cant find my error

after looking at this code for 2 days i decided to get some help. this is my fist time asking a question so please bear with me.

my coding experience is minimal and my knowledge goes about as far as the code shown, try to keep things simple.

for a class i'm taking i have to write code to correctly perform order of operations this is my finished code:

import operator

class stack:
    def __init__(self):
        self._stack = []

    def __len__(self):
        return len(self._stack)

    def is_empty(self):
        return len(self._stack) == 0

    def push(self, e):
        self._stack.append(e)

    def top(self):
        if self.is_empty():
            print ('stack is empty')
        return self._stack[-1]

    def pop(self):
        if self.is_empty():
            print ('stack is empty')
            return
        return self._stack.pop()

def apply(a,b,c):

    ops2 = {"+": operator.add,
           "-": operator.sub,
           "*": operator.mul,
           "/": operator.truediv }
    op_char = c
    op_func = ops2[op_char]
    result = op_func(float(a), float(b))
    return result

user = '6 - 5 ( 5 - 3 ) * (4 + 2 )' 
#user = input("Enter an expression: ")
print(user)
exp = user.split()
nums = '1234567890'
ops = ['*', '/', '+', '-']
par = ['(', ')']

num = stack()
op = stack()

for each in exp:
    print(each)
    if each in nums:
        num.push(each)

    if  each == par[0]:
        op.push(each)

    if each in ops:            
        if each == ops[2] or ops[3]:
            op.push(each)

        if each == ops[0] or ops[1]:
                while op.top() == (ops[2] or ops[3]) and len(op) > 0 and len(num) >= 2:
                    ans = apply(num.pop(),num.pop(),op.pop())
                    num.push(ans)   
                    op.push(each)
    if each == par[1]:
        while op.top() != "(":
            ans = apply(num.pop(),num.pop(),op.pop()) # this line is poping the empty stack
            num.push(ans)
        op.pop()

while op.is_empty() != True:
    ans = apply(num.pop(),num.pop(),op.pop())
    num.push(ans)
print(ans)

or so i thought... when i run this i get a stack is empty error from the if each == par[1] loop and i can not figure out why. the expression i used is suppose to equal -6.0 any help is appreciated.

edit: after changing the code i am in a similar situation and assume that i made a error in pushing or poping somewhere. After walking through the code again i still cant find the error. Again, any help is appreciated.

Upvotes: 3

Views: 443

Answers (1)

Justin O Barber
Justin O Barber

Reputation: 11601

I'm afraid other issues exist with this code (which you will discover once you fix the following), but the problem you refer to in your question comes from your pop method:

def pop(self):
    if self.is_empty():
        print ('stack is empty')  # still proceeds to the next line
    return self._stack.pop()  # won't work if self._stack is empty

This raises an IndexError because you cannot pop from an empty list, and your return statement will be run whether the list is empty or not. Perhaps you are after something like the following (?):

def pop(self):
    if self.is_empty():
        print ('stack is empty')
        return  # now you need to deal with the returned None value
    return self._stack.pop()  # only if not empty

Upvotes: 3

Related Questions