from collections import deque from tokens import NumberTokenParser, OperatorTokenParser class ParsingException(Exception): pass class Parser(object): def __init__(self, token_stream): self._token_stream = token_stream self._stack = deque() self._current_list = deque() def parse(self): state = 0 while True: token = self._token_stream.get_token() if(token == "("): if(state == 1): raise ParsingException( "expected operator, not parenthesis: {} (near '{}')".format( self._token_stream._offset , token)) self._stack.append(self._current_list) continue if(NumberTokenParser.can_parse(token)): if(state == 1): raise ParsingException( "expected operator, not number: {} (near '{}')".format( self._token_stream._offset , token)) self._current_list.append(NumberTokenParser(token).parse()) state = 1 continue if(OperatorTokenParser.can_parse(token)): if(state != 1): raise ParsingException( "expected number or parenthesis, not operator: {} (near '{}')".format( self._token_stream._offset , token)) self._current_list.append(OperatorTokenParser(token).parse()) state = 0 continue if(token == ")"): #if(state == 1): # raise ParsingException( # "expected operator, not parenthesis: {} (near '{}')".format( # self._token_stream._offset # , token)) state = 1 result = self.execute_branch(self._current_list) self._current_list = self._stack.pop() continue if(not token): if(self._stack): raise ParsingException("unexpected EOF while parsing") return self.execute_branch(self._current_list) raise ParsingException("unknown token: {} (near '{}')".format(self._token_stream._offset, token)) return self.execute_branch(self._current_list) def execute_branch(self, branch): result = None current_operator = None for element in branch: if(result is None): result = element continue if(not isinstance(element, (float, int, complex))): # Operator current_operator = element continue if(current_operator): result = current_operator(result, element) current_operator = None return result