feat(task2): process equations with "()"
This commit is contained in:
@@ -2,13 +2,38 @@ from collections import deque
|
|||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
from icecream import ic
|
from icecream import ic
|
||||||
|
|
||||||
from math_objects import Operator, Token
|
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]:
|
def translate(tokens: Iterable[Token]) -> Iterable[Token]:
|
||||||
operator_stack: deque[Operator] = deque()
|
operator_stack: deque[Operator] = deque()
|
||||||
|
previous_stacks: deque[deque[Operator]] = deque()
|
||||||
previous_precedence = 0
|
previous_precedence = 0
|
||||||
|
empty_stack = True
|
||||||
|
|
||||||
for token in tokens:
|
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):
|
if not isinstance(token, Operator):
|
||||||
yield token
|
yield token
|
||||||
continue
|
continue
|
||||||
@@ -18,7 +43,8 @@ def translate(tokens: Iterable[Token]) -> Iterable[Token]:
|
|||||||
operator_stack.clear()
|
operator_stack.clear()
|
||||||
previous_precedence = token.precedence
|
previous_precedence = token.precedence
|
||||||
operator_stack.append(token)
|
operator_stack.append(token)
|
||||||
ic(len(operator_stack))
|
if previous_stacks:
|
||||||
|
raise SyntaxError(__left_parenthesis_error)
|
||||||
if operator_stack:
|
if operator_stack:
|
||||||
for item in reversed(operator_stack):
|
for item in reversed(operator_stack):
|
||||||
yield item
|
yield item
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ from tokenizer import tokenize
|
|||||||
|
|
||||||
from math_objects import Token, Integer, Operator
|
from math_objects import Token, Integer, Operator
|
||||||
|
|
||||||
equation: str = "1+ 2+3/3-1"# input()
|
equation: str = "1+0-1/(0+2)"# input()
|
||||||
|
|
||||||
|
if not equation.strip():
|
||||||
|
raise SyntaxError("Пустая строка")
|
||||||
|
|
||||||
tokens: Iterable[Token] = tokenize(equation)
|
tokens: Iterable[Token] = tokenize(equation)
|
||||||
sorted_tokens: Iterable[Token] = translate(tokens)
|
sorted_tokens: Iterable[Token] = translate(tokens)
|
||||||
@@ -18,11 +21,12 @@ for token in sorted_tokens:
|
|||||||
if not isinstance(token, Operator):
|
if not isinstance(token, Operator):
|
||||||
token_stack.append(token)
|
token_stack.append(token)
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
b, a = token_stack.pop(), token_stack.pop()
|
b, a = token_stack.pop(), token_stack.pop()
|
||||||
|
except IndexError:
|
||||||
|
raise SyntaxError
|
||||||
ic(a.value, token.value, b.value)
|
ic(a.value, token.value, b.value)
|
||||||
new_integer = Integer(eval(f"{a.value}{token.value}{b.value}"))
|
new_integer = Integer(eval(f"{a.value}{token.value}{b.value}"))
|
||||||
token_stack.append(new_integer)
|
token_stack.append(new_integer)
|
||||||
|
|
||||||
ic(len(token_stack))
|
|
||||||
|
|
||||||
print(token_stack.pop().value)
|
print(token_stack.pop().value)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from math_objects import Integer, Operator, Parenthesis, Token
|
|||||||
|
|
||||||
def tokenize(string: str) -> Iterable[Token]:
|
def tokenize(string: str) -> Iterable[Token]:
|
||||||
buffer: deque[str] = deque()
|
buffer: deque[str] = deque()
|
||||||
prediction: Optional[Literal["number"]] = None
|
|
||||||
|
|
||||||
def _take_buffer() -> str:
|
def _take_buffer() -> str:
|
||||||
string = "".join(buffer)
|
string = "".join(buffer)
|
||||||
@@ -15,14 +14,10 @@ def tokenize(string: str) -> Iterable[Token]:
|
|||||||
|
|
||||||
for c in string:
|
for c in string:
|
||||||
if c.isdigit():
|
if c.isdigit():
|
||||||
if prediction != "number" and buffer:
|
|
||||||
yield Integer.create_from_string(_take_buffer())
|
|
||||||
prediction = "number"
|
|
||||||
buffer.append(c)
|
buffer.append(c)
|
||||||
elif c in ["+", "-", "*", "/", "(", ")"]:
|
elif c in ["+", "-", "*", "/", "(", ")"]:
|
||||||
if buffer:
|
if buffer:
|
||||||
yield Integer.create_from_string(_take_buffer())
|
yield Integer.create_from_string(_take_buffer())
|
||||||
prediction = None
|
|
||||||
match c:
|
match c:
|
||||||
case "+" | "-":
|
case "+" | "-":
|
||||||
yield Operator(c, precedence=1)
|
yield Operator(c, precedence=1)
|
||||||
@@ -30,7 +25,6 @@ def tokenize(string: str) -> Iterable[Token]:
|
|||||||
yield Operator(c, precedence=2)
|
yield Operator(c, precedence=2)
|
||||||
case _:
|
case _:
|
||||||
yield Parenthesis(c) # type: ignore
|
yield Parenthesis(c) # type: ignore
|
||||||
prediction = None
|
|
||||||
elif c == " ":
|
elif c == " ":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user