feat(task2): process equations with "()"

This commit is contained in:
2026-04-09 18:25:10 +06:00
parent 391eaa30a8
commit bb5c00c528
3 changed files with 36 additions and 12 deletions

View File

@@ -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

View File

@@ -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
b, a = token_stack.pop(), token_stack.pop() try:
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)

View File

@@ -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: