51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
from collections import deque
|
|
from typing import Iterable
|
|
from icecream import ic
|
|
|
|
from math_objects import Operator, Parenthesis, Token
|
|
|
|
__left_parenthesis_error = "__left_parenthesis_error"
|
|
__right_parenthesis_error = "__right_parenthesis_error"
|
|
__empty_parentheses_error = "__empty_parentheses_error"
|
|
|
|
|
|
def translate(tokens: Iterable[Token]) -> Iterable[Token]:
|
|
operator_stack: deque[Operator] = deque()
|
|
previous_stacks: deque[deque[Operator]] = deque()
|
|
previous_precedence = 0
|
|
empty_stack = True
|
|
|
|
for token in tokens:
|
|
if isinstance(token, Parenthesis):
|
|
match token.value:
|
|
case "(":
|
|
previous_stacks.append(operator_stack)
|
|
operator_stack = deque()
|
|
empty_stack = True
|
|
case _:
|
|
if empty_stack:
|
|
raise SystemError(__empty_parentheses_error)
|
|
if operator_stack:
|
|
for item in reversed(operator_stack):
|
|
yield item
|
|
try:
|
|
operator_stack = previous_stacks.pop()
|
|
except IndexError:
|
|
raise SyntaxError(__right_parenthesis_error)
|
|
continue
|
|
empty_stack = False
|
|
if not isinstance(token, Operator):
|
|
yield token
|
|
continue
|
|
if token.precedence <= previous_precedence:
|
|
for item in reversed(operator_stack):
|
|
yield item
|
|
operator_stack.clear()
|
|
previous_precedence = token.precedence
|
|
operator_stack.append(token)
|
|
if previous_stacks:
|
|
raise SyntaxError(__left_parenthesis_error)
|
|
if operator_stack:
|
|
for item in reversed(operator_stack):
|
|
yield item
|