Beispiel #1
0
    def test_empty(self):
        stack = Stack()
        self.assertTrue(stack.is_empty(), "Stack should be empty")
        stack.push("word")
        stack.push("sentence")
        stack.pop()
        self.assertFalse(stack.is_empty(), "Stack should not be empty")

        stack = Stack(int)
        self.assertTrue(stack.is_empty(), "Stack should be empty")

        stack.push(0)
        self.assertFalse(stack.is_empty(), "Stack should not be empty")
Beispiel #2
0
def check_parenthesis(expression):
    # the stack for the parenthesis
    parenthesis = Stack()

    # pushing all the left parenthesis in a stack
    for token in tokenize(expression):
        if token == "(":
            parenthesis.push(token)

        # if there's a right parenthesis, check if the stack is empty, that is there is no left parenthesis left
        elif token == ")":
            if parenthesis.is_empty():
                return False
            else:
                parenthesis.pop()

    # at the end, if the stack is empty, return true, all the parenthesis are valid; otherwise, return false
    return parenthesis.is_empty()
Beispiel #3
0
def evaluate_expression(expression):

    assert type(expression) is str, "Expression must be a string object"

    # check for errors in parenthesis
    if not check_parenthesis(expression):
        raise ArithmeticError("Invalid parenthesis")

    # using the global variable operators_priorities
    global operators_priorities

    # tokenizing the expression and initializing the two stack for the operands and the operators
    tokens = tokenize(expression)
    operands = Stack(elements_type=float)
    operators = Stack(elements_type=str)

    # iterating through the the tokens of the expression
    for token in tokens:
        # pushing the token into the right stack
        try:
            # if the token is a number push into operands stack
            operands.push(float(token))
        # if the token is one of these '(', ')', '*', '/', '+' or '-'
        except ValueError:
            try:
                # if the operators' stack is empty, add the token there
                if operators.is_empty():
                    operators.push(token)

                # if the operator is a '(', add the token to the stack
                elif token == "(":
                    operators.push(token)

                # if the operator is a ')', call the adjust_parenthesis method
                elif token == ")":
                    adjust_parenthesis(operands, operators)

                # if the last operator's priority is less than or equal to the priority of the current operator,
                # add the current operator to the stack again
                elif operators_priorities[operators.peek()] <= operators_priorities[token]:
                    operators.push(token)

                # if the last operator's priority is greater than the priority of the current operator,
                # call the method adjust_stacks and push the operator into the operators' stack
                elif operators_priorities[operators.peek()] > operators_priorities[token]:
                    adjust_stacks(operands, operators, token)
                    operators.push(token)
            # if the token is not supported, raise a Value error
            except KeyError:
                raise ValueError("Non supported attribute in the expression")

    # when we went through all the tokens, check if there's only one value left in the operands' stack and 0 operators
    # in the operators' stack, only then we know we are finished
    if operands.size() != 1 and operators.size() != 0:
        # if the finishing property is not true, then we repeat the operation from the adjust_stacks method,
        # while we know that we are finished
        while operands.size() != 1 and operators.size() != 0:
            # popping the last operator with the last two operands
            operator = operators.pop()
            b = operands.pop()
            a = operands.pop()

            # evaluating the value of the simple expression and pushing it back in the stack
            if operator == "*":
                operands.push(a * b)
            elif operator == "/":
                operands.push(a / b)
            elif operator == "+":
                operands.push(a + b)
            elif operator == "-":
                operands.push(a - b)
            # if the operator is not from the supported ones, raise an exception
            else:
                raise ValueError("The attribute you are specifying is not supported")

        # when we are finished, the operands' stack contains only the result from the expression, so we pop it
        return operands.pop()

    # if we know we are finished, we directly pop the result, since the operands' stack contains only the
    # result from the expression
    else:
        return operands.pop()