From bb5c00c528e880a334a239a6d7d07b6b6e6b2aed Mon Sep 17 00:00:00 2001 From: Andrey Golikov Date: Thu, 9 Apr 2026 18:25:10 +0600 Subject: [PATCH] feat(task2): process equations with "()" --- task2/command_translation.py | 30 ++++++++++++++++++++++++++++-- task2/main.py | 12 ++++++++---- task2/tokenizer.py | 6 ------ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/task2/command_translation.py b/task2/command_translation.py index 94b39ee..f25443b 100644 --- a/task2/command_translation.py +++ b/task2/command_translation.py @@ -2,13 +2,38 @@ from collections import deque from typing import Iterable 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]: 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 @@ -18,7 +43,8 @@ def translate(tokens: Iterable[Token]) -> Iterable[Token]: operator_stack.clear() previous_precedence = token.precedence operator_stack.append(token) - ic(len(operator_stack)) + if previous_stacks: + raise SyntaxError(__left_parenthesis_error) if operator_stack: for item in reversed(operator_stack): yield item diff --git a/task2/main.py b/task2/main.py index ff30a5f..af6a298 100644 --- a/task2/main.py +++ b/task2/main.py @@ -7,7 +7,10 @@ from tokenizer import tokenize 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) sorted_tokens: Iterable[Token] = translate(tokens) @@ -18,11 +21,12 @@ for token in sorted_tokens: if not isinstance(token, Operator): token_stack.append(token) 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) new_integer = Integer(eval(f"{a.value}{token.value}{b.value}")) token_stack.append(new_integer) -ic(len(token_stack)) - print(token_stack.pop().value) diff --git a/task2/tokenizer.py b/task2/tokenizer.py index e36ddef..4155598 100644 --- a/task2/tokenizer.py +++ b/task2/tokenizer.py @@ -6,7 +6,6 @@ from math_objects import Integer, Operator, Parenthesis, Token def tokenize(string: str) -> Iterable[Token]: buffer: deque[str] = deque() - prediction: Optional[Literal["number"]] = None def _take_buffer() -> str: string = "".join(buffer) @@ -15,14 +14,10 @@ def tokenize(string: str) -> Iterable[Token]: for c in string: if c.isdigit(): - if prediction != "number" and buffer: - yield Integer.create_from_string(_take_buffer()) - prediction = "number" buffer.append(c) elif c in ["+", "-", "*", "/", "(", ")"]: if buffer: yield Integer.create_from_string(_take_buffer()) - prediction = None match c: case "+" | "-": yield Operator(c, precedence=1) @@ -30,7 +25,6 @@ def tokenize(string: str) -> Iterable[Token]: yield Operator(c, precedence=2) case _: yield Parenthesis(c) # type: ignore - prediction = None elif c == " ": pass else: