# Uses the Stack and the BinaryTree interfaces to build an expression tree and evaluate
# an arithmetic expression written in infix, fully parenthesised with parentheses, brackets and braces,
# and built from natural numbers using the binary +, -, * and / operators.             
#
# Written by Eric Martin for COMP9021

from array_stack import *
from binary_tree import *

class FullyParenthesisedExpression():
    def __init__(self, expression = None):
        self.expression = expression
        self.list_of_tokens = []
        if not self.get_list_of_tokens(self.list_of_tokens):
            print('Invalid expression')
            return
        self.stack = ArrayStack()
        self.expression_tree = self.build_expression_tree()
        if not self.expression_tree:
            print('Invalid expression')

    def get_list_of_tokens(self, list_of_tokens):
        reading_number = False
        for c in self.expression:
            if c.isdigit():
                if not reading_number:
                    reading_number = True
                    number = int(c)
                else:
                    number = number * 10 + int(c)
            else:
                if reading_number:
                    list_of_tokens.append(number)
                    reading_number = False
                if c in '+-*/()[]{}':
                    list_of_tokens.append(c)
                elif c != ' ':
                    return False
        if reading_number:
            list_of_tokens.append(number)
        return True
                    
    def build_expression_tree(self):
        for token in self.list_of_tokens:
            if token in list('+-*/([{'):
                self.stack.push(token)
            elif isinstance(token, int):
                self.stack.push(BinaryTree(token))
            else:
                try:
                    second_argument = self.stack.pop()
                    operator = self.stack.pop()
                    first_argument = self.stack.pop()
                    opening_grouping_symbol = self.stack.pop()
                    if token == ')' and opening_grouping_symbol != '(' or \
                       token == ']' and opening_grouping_symbol != '[' or \
                       token == '}' and opening_grouping_symbol != '{':                   
                        raise Exception
                except:
                    return None
                tree = BinaryTree()
                tree.value = operator
                tree.left_node = first_argument
                tree.right_node = second_argument
                self.stack.push(tree)
        if self.stack.is_empty():
            return None
        tree = self.stack.pop()
        if not self.stack.is_empty():
            return None
        return tree

    def evaluate(self):
        return self._evaluate(self.expression_tree)
    
    def _evaluate(self, tree):
        if isinstance(tree.value, int):
            return tree.value
        first_argument = self._evaluate(tree.left_node)
        second_argument = self._evaluate(tree.right_node)
        if first_argument == None or second_argument == None:
            return None
        if tree.value == '+':
            return first_argument + second_argument
        if tree.value == '-':
            return first_argument + second_argument
        if tree.value == '*':
            return first_argument * second_argument
        if tree.value == '/':
            if second_argument == 0:
                print('Division by 0')
                return None
            return first_argument / second_argument


if __name__ == '__main__':
    print('Testing 2:')
    fully_parenthesised_expression = FullyParenthesisedExpression('2')
    print(fully_parenthesised_expression.evaluate())
    print('Testing (2 + 3):')
    fully_parenthesised_expression = FullyParenthesisedExpression('(2 + 3)')
    print(fully_parenthesised_expression.evaluate())
    print('Testing [(2 + 3) / 10]:')
    fully_parenthesised_expression = FullyParenthesisedExpression('[(2 + 3) / 10]')
    print(fully_parenthesised_expression.evaluate())
    print('Testing (12 + [{[13 + (4 + 5)] - 10} / (7 * 8)]):')
    fully_parenthesised_expression = FullyParenthesisedExpression('(12 + [{[13 + (4 + 5)] - 10} / (7 * 8)])')
    print(fully_parenthesised_expression.evaluate())
    

Resource created Monday 19 October 2015, 12:45:46 PM.

file: exercise_2.py


Back to top

COMP9021 15s2 (Principles of Programming) is powered by WebCMS3
CRICOS Provider No. 00098G