scientific-programming-exer.../exam/ex06/parser.py

92 lines
2.2 KiB
Python

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