From 969b0b1b2dff15ecfd4280f84afe2a6633bc2ae2 Mon Sep 17 00:00:00 2001 From: Helen Shanchuk Date: Thu, 20 Dec 2018 22:30:57 +0300 Subject: [PATCH 01/13] Added pure-python pycalc implementation and unit tests --- final_task/pycalc/__init__.py | 0 final_task/pycalc/evaluator.py | 72 ++++++++++++++++++++ final_task/pycalc/importmodules.py | 27 ++++++++ final_task/pycalc/operators.py | 48 +++++++++++++ final_task/pycalc/parser.py | 105 +++++++++++++++++++++++++++++ final_task/pycalc/pycalc.py | 34 ++++++++++ final_task/pycalc/validator.py | 66 ++++++++++++++++++ final_task/tests/__init__.py | 0 final_task/tests/unit_tests.py | 75 +++++++++++++++++++++ 9 files changed, 427 insertions(+) create mode 100644 final_task/pycalc/__init__.py create mode 100644 final_task/pycalc/evaluator.py create mode 100644 final_task/pycalc/importmodules.py create mode 100644 final_task/pycalc/operators.py create mode 100644 final_task/pycalc/parser.py create mode 100644 final_task/pycalc/pycalc.py create mode 100644 final_task/pycalc/validator.py create mode 100644 final_task/tests/__init__.py create mode 100644 final_task/tests/unit_tests.py diff --git a/final_task/pycalc/__init__.py b/final_task/pycalc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/final_task/pycalc/evaluator.py b/final_task/pycalc/evaluator.py new file mode 100644 index 0000000..e0d214c --- /dev/null +++ b/final_task/pycalc/evaluator.py @@ -0,0 +1,72 @@ +from pycalc.operators import Operator, Function, Constant +from pycalc.parser import Parser +from pycalc.importmodules import FunctionParser +from pycalc.validator import Validator + + +def infix_to_postfix(parsed_exp): + stack = [] + postfix_list = [] + for token in parsed_exp: + if isinstance(token, Operator) or isinstance(token, Function): + if token.name == '(': + stack.append(token) + elif token.name == ')': + while stack and stack[-1].name != '(': + postfix_list.append(stack.pop()) + if stack: + stack.pop() + else: + if not token.associativity == 1: + while stack and token.priority < stack[-1].priority: + postfix_list.append(stack.pop()) + else: + while stack and token.priority <= stack[-1].priority: + postfix_list.append(stack.pop()) + stack.append(token) + elif isinstance(token, Function): + stack.append(token) + elif isinstance(token, Constant): + postfix_list.append(token) + elif Parser.is_number(token): + postfix_list.append(token) + else: + raise ValueError(f'name {token} is not defined') + while stack: + postfix_list.append(stack.pop()) + return postfix_list + + +def calculate(exp): + stack = [] + parser = Parser() + parsed_exp = parser.parse_expression(exp) + polish = infix_to_postfix(parsed_exp) + if all(isinstance(token, Operator) for token in polish): + raise ValueError('not valid input') + for token in polish: + if isinstance(token, Operator) or isinstance(token, Function) or isinstance(token, Constant): + if isinstance(token, Function) and len(polish) == 1: + stack.append(token.func()) + elif isinstance(token, Function): + x = stack.pop() + if type(x) is list: + res = token.func(*x) + else: + res = token.func(*[x]) + stack.append(res) + elif isinstance(token, Constant): + stack.append(token.func) + elif not token.is_binary: + x = stack.pop() + stack.append(token.func(x)) + else: + try: + y, x = stack.pop(), stack.pop() + stack.append(token.func(x, y)) + except Exception as e: + raise ValueError(f' binary operation must have two operands {e}') + + else: + stack.append(float(token)) + return stack[0] diff --git a/final_task/pycalc/importmodules.py b/final_task/pycalc/importmodules.py new file mode 100644 index 0000000..22e608e --- /dev/null +++ b/final_task/pycalc/importmodules.py @@ -0,0 +1,27 @@ +import importlib +from pycalc.operators import Function, Constant + + +class FunctionParser: + functions_dict = {} + constants_dict = {} + + def __init__(self): + self.parse_modules(['math']) + self.functions_dict['pow'] = Function(object, 6, 1, True, pow) + self.functions_dict['abs'] = Function(object, 6, 1, True, abs) + self.functions_dict['round'] = Function(object, 6, 1, True, round) + + def parse_modules(self, modules): + ''' Method that parse module names array and add to dictionary their name as a key and + callable object as a value. + :param modules: Array of modules names. + ''' + for module in modules: + modul = importlib.import_module(module) + for object in vars(modul): + if object[0:2] != '__': + if isinstance(vars(modul)[object], (int, float, complex)): + self.constants_dict[object] = Constant(object, 6, 1, True, vars(modul)[object]) + else: + self.functions_dict[object] = Function(object, 6, 1, True, vars(modul)[object]) \ No newline at end of file diff --git a/final_task/pycalc/operators.py b/final_task/pycalc/operators.py new file mode 100644 index 0000000..1f68f9a --- /dev/null +++ b/final_task/pycalc/operators.py @@ -0,0 +1,48 @@ +class Operator: + def __init__(self, name, priority, associativity, is_binary, func): + self.priority = priority + self.associativity = associativity + self.func = func + self.name = name + self.is_binary = is_binary + + +class Function: + def __init__(self, name, priority, associativity, is_binary, func): + self.priority = priority + self.associativity = associativity + self.func = func + self.name = name + self.is_binary = is_binary + + +class Constant: + def __init__(self, name, priority, associativity, is_binary, func): + self.priority = priority + self.associativity = associativity + self.func = func + self.name = name + self.is_binary = is_binary + + +operators_dict = { + '>=': Operator('>=', 0, 1, True, lambda x, y: x >= y), + '<=': Operator('<=', 0, 1, True, lambda x, y: x <= y), + '==': Operator('==', 0, 1, True, lambda x, y: x == y), + '!=': Operator('!=', 0, 1, True, lambda x, y: x != y), + '>': Operator('>', 0, 1, True, lambda x, y: x > y), + '<': Operator('<', 0, 1, True, lambda x, y: x >= y), + ',': Operator(',', 1, 1, True, lambda x, y: [x, y]), + '+': Operator('+', 2, 1, True, lambda x, y: x+y), + '-': Operator('-', 2, 1, True, lambda x, y: x-y), + ')': Operator(')', -1, 1, False, None), + '(': Operator('(', -1, 1, False, None), + '*': Operator('*', 3, 1, True, lambda x, y: x*y), + '/': Operator('/', 3, 1, True, lambda x, y: x/y), + '%': Operator('%', 3, 1, True, lambda x, y: x % y), + '//': Operator('//',3, 1,True, lambda x, y: x // y), + 'unary_minus': Operator('unary_minus', 4, 1, False, lambda x: -x), + 'unary_plus': Operator('unary_plus', 4, 1, False, lambda x: x), + '^': Operator('^', 5, 2, True, lambda x, y: x**y), +} + diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py new file mode 100644 index 0000000..ded651b --- /dev/null +++ b/final_task/pycalc/parser.py @@ -0,0 +1,105 @@ +from pycalc.operators import operators_dict, Operator, Function, Constant +from pycalc.validator import Validator +from pycalc.importmodules import FunctionParser +functions_dict = {} +const_dict = {} + + +class Parser: + def __init__(self): + self.func_parser = FunctionParser() + + @staticmethod + def is_number(s): + """ Returns True is string is a number. """ + if isinstance(s, Operator) or isinstance(s, Function) or isinstance(s, Constant) or s == 'pow': + return False + return s.replace('.', '', 1).isdigit() + + @staticmethod + def is_operator(s): + return s in operators_dict + + @staticmethod + def is_function(s): + return s in FunctionParser.functions_dict + + @staticmethod + def is_constant(s): + return s in FunctionParser.constants_dict + + @staticmethod + def add_multiply_sign(lexem_list): + for i in range(1, len(lexem_list)): + if isinstance(lexem_list[i], Function) and not isinstance(lexem_list[i-1], Operator): + lexem_list.insert(i, operators_dict['*']) + elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': + lexem_list.insert(i, operators_dict['*']) + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): + lexem_list.insert(i, operators_dict['*']) + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': + lexem_list.insert(i, operators_dict['*']) + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): + lexem_list.insert(i, operators_dict['*']) + return lexem_list + + def parse_expression(self, exp): + exp = Validator.pre_tokinaze(exp) + exp.replace(" ", "") + lexem_array = [] + start_index = 0 + end_index = len(exp) + while start_index != len(exp): + substring = exp[start_index:end_index] + if Parser.is_number(substring): + lexem_array.append(substring) + start_index, end_index = end_index, len(exp) + elif Parser.is_operator(substring): + operator = operators_dict[substring] + lexem_array.append(operator) + + start_index, end_index = end_index, len(exp) + elif Parser.is_constant(substring): + lexem_array.append(self.func_parser.constants_dict[substring]) + start_index, end_index = end_index, len(exp) + elif Parser.is_function(substring): + lexem_array.append(self.func_parser.functions_dict[substring]) + start_index, end_index = end_index, len(exp) + else: + end_index -= 1 + lex_list =Parser.add_multiply_sign(lexem_array) + unary_signs = Parser.find_unary_signs(lex_list) + final_lexem_list = Parser.remove_redundant_unary_signs(unary_signs, lex_list) + + return final_lexem_list + + @staticmethod + def find_unary_signs(lexem_list): + final_list = [] + for i in range(len(lexem_list)): + if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: + final_list.append(0) + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not (Parser.is_constant(lexem_list[i-1]) or Parser.is_number(lexem_list[i-1])) \ + and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): + final_list.append(i) + lexems_with_indicies = enumerate(lexem_list) + lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) + for unary_sign in lexems_filter: + lexem_list[unary_sign[0]] = operators_dict['unary_plus'] if unary_sign[1] == '+' else operators_dict['unary_minus'] + return lexems_filter + + @staticmethod + def remove_redundant_unary_signs(lexems_with_indicies, lex_list): + final_index = len(lexems_with_indicies)-1 + while final_index != -1: + last_index, last_sign = lexems_with_indicies[final_index] + prev_index, prev_sign = lexems_with_indicies[final_index - 1] + if last_index - 1 == prev_index and last_sign.name == prev_sign.name: + lex_list[prev_index:last_index + 1] = [operators_dict['unary_plus']] + lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['+'])] + elif last_index - 1 == prev_index and last_sign != prev_sign: + lex_list[prev_index: last_index + 1] = [operators_dict['unary_minus']] + lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['-'])] + final_index -= 1 + return lex_list + diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py new file mode 100644 index 0000000..abce9aa --- /dev/null +++ b/final_task/pycalc/pycalc.py @@ -0,0 +1,34 @@ +import argparse +import sys +from pycalc.importmodules import FunctionParser +from pycalc.evaluator import calculate + + +def get_args(): + '''This function parses and return arguments passed in''' + parser = argparse.ArgumentParser( + description='Script retrieves schedules from a given server') + parser.add_argument( + 'expression', help='') + + parser.add_argument( + '-m', '--use-modules', nargs='+', help='', required=False) + return parser.parse_args() + + +def main(): + try: + # args = get_args() + # parser = FunctionParser() + # if args.use_modules: + # parser.parse_modules(args.use_modules) + # parser.parse_modules(['time']) + # result = calculate(args.expression) + # print(calculate('time()')) + # print(f'{result}') + + + except Exception as e: + print(f"ERROR: {e}") + sys.exit(1) + diff --git a/final_task/pycalc/validator.py b/final_task/pycalc/validator.py new file mode 100644 index 0000000..bf4155c --- /dev/null +++ b/final_task/pycalc/validator.py @@ -0,0 +1,66 @@ +import re + + +class Validator: + spaces_reg = '\s+' + sign_arr = ['<', '>', '=', '!'] + + @staticmethod + def normalize_string(str): + ''' Method that normalize string with expression. If we have more than one space between symbol, + it change multiply spaces with one space. + :param str: String with a math expression. + :return : Normalized string with a math expression. + ''' + return re.sub(Validator.spaces_reg, ' ', str).strip() + + @staticmethod + def pre_tokinaze(str): + ''' Method that do a number of operations before tokenization. + :param str: String with a math expression. + :return : Amended string with a math expression. + ''' + str.lower() + if Validator.par_check(str): + normalize_str = Validator.normalize_string(str) + valid_string = Validator.validate_string(normalize_str).replace(" ", "") + return valid_string + else: + raise ValueError('Brackets not balanced') + + @staticmethod + def par_check(expression): + ''' Method that check for validity of brackets. + :param expression: String with math expression. + :return : True or False, depends on validity of brackets of a given expression. + ''' + mapping = dict(zip('({[', ')}]')) + queue = [] + for letter in expression: + if letter in mapping: + queue.append(mapping[letter]) + elif letter not in mapping.values(): + continue + elif not (queue and letter == queue.pop()): + return False + return not queue + + + @staticmethod + def validate_string(str): + ''' Method that raise error if string with a math expression is not valid. + :param str: String with a math expression. + :return : string with a math expression if it is valid. + ''' + indices = enumerate(str) + for i, char in indices: + if char in Validator.sign_arr: + if str[i + 1] == ' ' and str[i + 2] == '=': + raise ValueError('invalid syntax') + elif char.isdigit() and i != len(str) - 1: + if str[i + 1] == ' ' and str[i + 2].isdigit(): + raise ValueError('invalid syntax') + + return str + + diff --git a/final_task/tests/__init__.py b/final_task/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py new file mode 100644 index 0000000..ce608b6 --- /dev/null +++ b/final_task/tests/unit_tests.py @@ -0,0 +1,75 @@ +import unittest +from pycalc.parser import Parser +from pycalc.validator import Validator +from pycalc.importmodules import FunctionParser +from pycalc.operators import operators_dict +from pycalc.evaluator import calculate + + +class TestLexerMethods(unittest.TestCase): + def setUp(self): + self.parser = Parser() + self.function_parser = FunctionParser() + self.operator = operators_dict['+'] + self.lexem_indicies = [(0, operators_dict['-']),(1, operators_dict['-']), (2, operators_dict['-'])] + self.lex_arr = [ operators_dict['-'], operators_dict['-'], operators_dict['-'], '3'] + + def test_is_number_method(self): + self.assertEqual(Parser.is_number('3.03'), True) + self.assertEqual(Parser.is_number('3.o'), False) + self.assertEqual(Parser.is_number(self.operator), False) + + def test_is_operator_method(self): + self.assertEqual(Parser.is_operator('+'), True) + self.assertEqual(Parser.is_operator('12'), False) + + def test_is_function_method(self): + self.assertEqual(Parser.is_function('sin'), True) + self.assertEqual(Parser.is_function('sin1wq'), False) + + def test_is_constant_method(self): + self.assertEqual(Parser.is_constant('pi'), True) + self.assertEqual(Parser.is_constant('21'), False) + + def test_find_unary_signs_methods(self): + self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), [(0, operators_dict['-']), + (1, operators_dict['-']), (2, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], + operators_dict['-'], '3',operators_dict[')']]), + [(1, operators_dict['-']),(2, operators_dict['-']), (3, operators_dict['-'])]) + + def test_add_multiply_sign(self): + self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), + ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], self.function_parser.functions_dict['sin']]) + + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], '4', operators_dict[')']]), + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) + self.assertEqual(Parser.add_multiply_sign(['5',operators_dict['('], '4', operators_dict[')']]), + ['5', operators_dict['*'],operators_dict['('], '4', operators_dict[')']]) + + def test_par_checker(self): + self.assertFalse(Validator.par_check('(()')) + self.assertFalse(Validator.par_check('(()))')) + self.assertFalse(Validator.par_check('(()}')) + self.assertTrue(Validator.par_check('((((()))))')) + self.assertTrue(Validator.par_check('3')) + self.assertTrue(Validator.par_check('((1 + 2))')) + + def test_validation(self): + expressions = ["2 >= 4 5", "2 > = 45", "3 ! = 4", "2 < = 4", "2 = = 4 5"] + for expression in expressions: + with self.assertRaises(ValueError) as context_manager: + Validator.validate_string(expression) + self.assertIn("invalid syntax", str(context_manager.exception)) + self.assertEqual(Validator.validate_string("2 >= 45"), "2 >= 45") + + def test_calculate(self): + exp = 'sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0^2.0))))--cos(1.0)--cos(0.0)^3.0)' + self.assertEqual(calculate(exp), 0.5361064001012784) + self.assertEqual(calculate('(3+(4*5)/10)+pow(3,2)'), 14.0) + + def test_parse_expression(self): + self.assertEqual(self.parser.parse_expression('sin(5)*3'), + [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], operators_dict['*'], '3']) \ No newline at end of file From c4b4da574d07dbd32d4da10429399b8cd9283435 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Thu, 20 Dec 2018 23:18:47 +0300 Subject: [PATCH 02/13] Updated codebase --- final_task/pycalc/pycalc.py | 16 ++++++++-------- final_task/setup.py | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py index abce9aa..a359ad8 100644 --- a/final_task/pycalc/pycalc.py +++ b/final_task/pycalc/pycalc.py @@ -18,14 +18,14 @@ def get_args(): def main(): try: - # args = get_args() - # parser = FunctionParser() - # if args.use_modules: - # parser.parse_modules(args.use_modules) - # parser.parse_modules(['time']) - # result = calculate(args.expression) - # print(calculate('time()')) - # print(f'{result}') + args = get_args() + parser = FunctionParser() + if args.use_modules: + parser.parse_modules(args.use_modules) + parser.parse_modules(['time']) + result = calculate(args.expression) + print(calculate('time()')) + print(f'{result}') except Exception as e: diff --git a/final_task/setup.py b/final_task/setup.py index e69de29..2c7f451 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -0,0 +1,14 @@ +from setuptools import setup, find_packages + +setup( + name='pycalc', + version='1.0', + packages=find_packages(), + __version__='1.0', + entry_points={ + 'console_scripts':[ + 'pycalc = pycalc.main:main', + ] + }, + + ) From 3ceda31f7f1d451969274a7cf9bc4d65d56d2768 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Thu, 20 Dec 2018 23:24:06 +0300 Subject: [PATCH 03/13] Updated codebase --- final_task/setup.py | 2 +- final_task/tests/unit_tests.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/final_task/setup.py b/final_task/setup.py index 2c7f451..222eec9 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -7,7 +7,7 @@ __version__='1.0', entry_points={ 'console_scripts':[ - 'pycalc = pycalc.main:main', + 'pycalc = pycalc.pycalc:main', ] }, diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index ce608b6..dfe2d97 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -67,9 +67,9 @@ def test_validation(self): def test_calculate(self): exp = 'sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0^2.0))))--cos(1.0)--cos(0.0)^3.0)' - self.assertEqual(calculate(exp), 0.5361064001012784) + self.assertEqual(calculate(exp), 0.5361064001012783) self.assertEqual(calculate('(3+(4*5)/10)+pow(3,2)'), 14.0) def test_parse_expression(self): self.assertEqual(self.parser.parse_expression('sin(5)*3'), - [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], operators_dict['*'], '3']) \ No newline at end of file + [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], operators_dict['*'], '3']) From fc61bd2c4a8c2109f65e45fbd3ddd15b0a18c567 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Thu, 20 Dec 2018 23:26:36 +0300 Subject: [PATCH 04/13] Updated codebase --- final_task/pycalc/pycalc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py index a359ad8..b170623 100644 --- a/final_task/pycalc/pycalc.py +++ b/final_task/pycalc/pycalc.py @@ -24,7 +24,6 @@ def main(): parser.parse_modules(args.use_modules) parser.parse_modules(['time']) result = calculate(args.expression) - print(calculate('time()')) print(f'{result}') From f76c09e78c3dc0f65807c1dc14e0cafe50c5d991 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 01:33:39 +0300 Subject: [PATCH 05/13] Fixed bugs with constants --- final_task/pycalc/evaluator.py | 7 +++++++ final_task/pycalc/operators.py | 9 +++++---- final_task/pycalc/parser.py | 5 ++++- final_task/pycalc/pycalc.py | 1 - final_task/pycalc/validator.py | 5 +++-- final_task/setup.py | 3 +-- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/final_task/pycalc/evaluator.py b/final_task/pycalc/evaluator.py index e0d214c..c945b10 100644 --- a/final_task/pycalc/evaluator.py +++ b/final_task/pycalc/evaluator.py @@ -2,6 +2,7 @@ from pycalc.parser import Parser from pycalc.importmodules import FunctionParser from pycalc.validator import Validator +from inspect import getfullargspec def infix_to_postfix(parsed_exp): @@ -45,10 +46,13 @@ def calculate(exp): if all(isinstance(token, Operator) for token in polish): raise ValueError('not valid input') for token in polish: + print(polish) if isinstance(token, Operator) or isinstance(token, Function) or isinstance(token, Constant): if isinstance(token, Function) and len(polish) == 1: + print('im in elif isinstance(token, Function) and len(polish) == 1:') stack.append(token.func()) elif isinstance(token, Function): + print('im in elif lif isinstance(token, Function)') x = stack.pop() if type(x) is list: res = token.func(*x) @@ -56,11 +60,14 @@ def calculate(exp): res = token.func(*[x]) stack.append(res) elif isinstance(token, Constant): + print('im in elif isinstance(token, Constant)') stack.append(token.func) elif not token.is_binary: + print('im in elseelif not token.is_binary: {}'.format(token.name)) x = stack.pop() stack.append(token.func(x)) else: + print('im in else') try: y, x = stack.pop(), stack.pop() stack.append(token.func(x, y)) diff --git a/final_task/pycalc/operators.py b/final_task/pycalc/operators.py index 1f68f9a..30b6a1a 100644 --- a/final_task/pycalc/operators.py +++ b/final_task/pycalc/operators.py @@ -40,9 +40,10 @@ def __init__(self, name, priority, associativity, is_binary, func): '*': Operator('*', 3, 1, True, lambda x, y: x*y), '/': Operator('/', 3, 1, True, lambda x, y: x/y), '%': Operator('%', 3, 1, True, lambda x, y: x % y), - '//': Operator('//',3, 1,True, lambda x, y: x // y), - 'unary_minus': Operator('unary_minus', 4, 1, False, lambda x: -x), - 'unary_plus': Operator('unary_plus', 4, 1, False, lambda x: x), - '^': Operator('^', 5, 2, True, lambda x, y: x**y), + '//': Operator('//', 3, 1, True, lambda x, y: x // y), + 'unary_minus': Operator('unary_minus', 5, 1, False, lambda x: -x), + 'unary_plus': Operator('unary_plus', 5, 1, False, lambda x: x), + '^': Operator('^', 4, 2, True, lambda x, y: x**y), } + diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index ded651b..aa958f6 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -41,6 +41,8 @@ def add_multiply_sign(lexem_list): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): lexem_list.insert(i, operators_dict['*']) + elif isinstance(lexem_list[i], Constant) and isinstance(lexem_list[i-1], Constant): + lexem_list.insert(i, operators_dict['*']) return lexem_list def parse_expression(self, exp): @@ -79,9 +81,10 @@ def find_unary_signs(lexem_list): for i in range(len(lexem_list)): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) - elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not (Parser.is_constant(lexem_list[i-1]) or Parser.is_number(lexem_list[i-1])) \ + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) + print(final_list) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) for unary_sign in lexems_filter: diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py index b170623..37af080 100644 --- a/final_task/pycalc/pycalc.py +++ b/final_task/pycalc/pycalc.py @@ -26,7 +26,6 @@ def main(): result = calculate(args.expression) print(f'{result}') - except Exception as e: print(f"ERROR: {e}") sys.exit(1) diff --git a/final_task/pycalc/validator.py b/final_task/pycalc/validator.py index bf4155c..2692dff 100644 --- a/final_task/pycalc/validator.py +++ b/final_task/pycalc/validator.py @@ -3,7 +3,7 @@ class Validator: spaces_reg = '\s+' - sign_arr = ['<', '>', '=', '!'] + sign_arr = ['<', '>', '=', '!', '/'] @staticmethod def normalize_string(str): @@ -57,10 +57,11 @@ def validate_string(str): if char in Validator.sign_arr: if str[i + 1] == ' ' and str[i + 2] == '=': raise ValueError('invalid syntax') + elif char == '/' and str[i + 1] == ' ' and str[i + 2] == '/': + raise ValueError('invalid syntax') elif char.isdigit() and i != len(str) - 1: if str[i + 1] == ' ' and str[i + 2].isdigit(): raise ValueError('invalid syntax') - return str diff --git a/final_task/setup.py b/final_task/setup.py index 222eec9..09c8037 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -6,9 +6,8 @@ packages=find_packages(), __version__='1.0', entry_points={ - 'console_scripts':[ + 'console_scripts': [ 'pycalc = pycalc.pycalc:main', ] }, - ) From 2596c3d78c9a7a5cbdcfd1b0a6c7f7f5979e8c56 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 01:37:41 +0300 Subject: [PATCH 06/13] Removed print statements --- final_task/pycalc/evaluator.py | 6 ------ final_task/pycalc/parser.py | 1 - 2 files changed, 7 deletions(-) diff --git a/final_task/pycalc/evaluator.py b/final_task/pycalc/evaluator.py index c945b10..79e53ad 100644 --- a/final_task/pycalc/evaluator.py +++ b/final_task/pycalc/evaluator.py @@ -46,13 +46,10 @@ def calculate(exp): if all(isinstance(token, Operator) for token in polish): raise ValueError('not valid input') for token in polish: - print(polish) if isinstance(token, Operator) or isinstance(token, Function) or isinstance(token, Constant): if isinstance(token, Function) and len(polish) == 1: - print('im in elif isinstance(token, Function) and len(polish) == 1:') stack.append(token.func()) elif isinstance(token, Function): - print('im in elif lif isinstance(token, Function)') x = stack.pop() if type(x) is list: res = token.func(*x) @@ -60,14 +57,11 @@ def calculate(exp): res = token.func(*[x]) stack.append(res) elif isinstance(token, Constant): - print('im in elif isinstance(token, Constant)') stack.append(token.func) elif not token.is_binary: - print('im in elseelif not token.is_binary: {}'.format(token.name)) x = stack.pop() stack.append(token.func(x)) else: - print('im in else') try: y, x = stack.pop(), stack.pop() stack.append(token.func(x, y)) diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index aa958f6..9a0c371 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -84,7 +84,6 @@ def find_unary_signs(lexem_list): elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) - print(final_list) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) for unary_sign in lexems_filter: From 933108dfeac3364afaa940c272a1a4b0d5b66d80 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 01:59:36 +0300 Subject: [PATCH 07/13] Fixed style issues --- final_task/pycalc/importmodules.py | 3 ++- final_task/pycalc/parser.py | 20 +++++++++++++------- final_task/pycalc/validator.py | 5 +---- final_task/setup.py | 4 +--- final_task/tests/unit_tests.py | 24 +++++++++++++----------- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/final_task/pycalc/importmodules.py b/final_task/pycalc/importmodules.py index 22e608e..3d0cbc9 100644 --- a/final_task/pycalc/importmodules.py +++ b/final_task/pycalc/importmodules.py @@ -24,4 +24,5 @@ def parse_modules(self, modules): if isinstance(vars(modul)[object], (int, float, complex)): self.constants_dict[object] = Constant(object, 6, 1, True, vars(modul)[object]) else: - self.functions_dict[object] = Function(object, 6, 1, True, vars(modul)[object]) \ No newline at end of file + self.functions_dict[object] = Function(object, 6, 1, True, vars(modul)[object]) + diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 9a0c371..77d3e44 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -33,13 +33,17 @@ def add_multiply_sign(lexem_list): for i in range(1, len(lexem_list)): if isinstance(lexem_list[i], Function) and not isinstance(lexem_list[i-1], Operator): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': + elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) + and lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Constant) and isinstance(lexem_list[i-1], Constant): lexem_list.insert(i, operators_dict['*']) @@ -81,7 +85,8 @@ def find_unary_signs(lexem_list): for i in range(len(lexem_list)): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) - elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and + not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) lexems_with_indicies = enumerate(lexem_list) @@ -97,11 +102,12 @@ def remove_redundant_unary_signs(lexems_with_indicies, lex_list): last_index, last_sign = lexems_with_indicies[final_index] prev_index, prev_sign = lexems_with_indicies[final_index - 1] if last_index - 1 == prev_index and last_sign.name == prev_sign.name: - lex_list[prev_index:last_index + 1] = [operators_dict['unary_plus']] - lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['+'])] + lex_list[prev_index:last_index + 1] = [operators_dict['unary_plus']] + lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['+'])] elif last_index - 1 == prev_index and last_sign != prev_sign: lex_list[prev_index: last_index + 1] = [operators_dict['unary_minus']] lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['-'])] final_index -= 1 return lex_list + diff --git a/final_task/pycalc/validator.py b/final_task/pycalc/validator.py index 2692dff..f393dda 100644 --- a/final_task/pycalc/validator.py +++ b/final_task/pycalc/validator.py @@ -2,7 +2,6 @@ class Validator: - spaces_reg = '\s+' sign_arr = ['<', '>', '=', '!', '/'] @staticmethod @@ -12,7 +11,7 @@ def normalize_string(str): :param str: String with a math expression. :return : Normalized string with a math expression. ''' - return re.sub(Validator.spaces_reg, ' ', str).strip() + return re.sub('\s+', ' ', str).strip() @staticmethod def pre_tokinaze(str): @@ -45,7 +44,6 @@ def par_check(expression): return False return not queue - @staticmethod def validate_string(str): ''' Method that raise error if string with a math expression is not valid. @@ -64,4 +62,3 @@ def validate_string(str): raise ValueError('invalid syntax') return str - diff --git a/final_task/setup.py b/final_task/setup.py index 09c8037..a6f57f4 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -6,8 +6,6 @@ packages=find_packages(), __version__='1.0', entry_points={ - 'console_scripts': [ - 'pycalc = pycalc.pycalc:main', - ] + 'console_scripts': ['pycalc = pycalc.pycalc:main',] }, ) diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index dfe2d97..ad34f85 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -12,7 +12,7 @@ def setUp(self): self.function_parser = FunctionParser() self.operator = operators_dict['+'] self.lexem_indicies = [(0, operators_dict['-']),(1, operators_dict['-']), (2, operators_dict['-'])] - self.lex_arr = [ operators_dict['-'], operators_dict['-'], operators_dict['-'], '3'] + self.lex_arr = [operators_dict['-'], operators_dict['-'], operators_dict['-'], '3'] def test_is_number_method(self): self.assertEqual(Parser.is_number('3.03'), True) @@ -32,22 +32,23 @@ def test_is_constant_method(self): self.assertEqual(Parser.is_constant('21'), False) def test_find_unary_signs_methods(self): - self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), [(0, operators_dict['-']), - (1, operators_dict['-']), (2, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), + [(0, operators_dict['-']), (1, operators_dict['-']), (2, operators_dict['-'])]) self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], - operators_dict['-'], '3',operators_dict[')']]), - [(1, operators_dict['-']),(2, operators_dict['-']), (3, operators_dict['-'])]) + operators_dict['-'], '3',operators_dict[')']]), [(1, operators_dict['-']),(2, operators_dict['-']), + (3, operators_dict['-'])]) def test_add_multiply_sign(self): self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), - ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) + ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], self.function_parser.functions_dict['sin']]) + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], self.function_parser.functions_dict['sin']]) self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], '4', operators_dict[')']]), - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) - self.assertEqual(Parser.add_multiply_sign(['5',operators_dict['('], '4', operators_dict[')']]), - ['5', operators_dict['*'],operators_dict['('], '4', operators_dict[')']]) + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', + operators_dict[')']]) + self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]),['5', operators_dict['*'], + operators_dict['('], '4', operators_dict[')']]) def test_par_checker(self): self.assertFalse(Validator.par_check('(()')) @@ -72,4 +73,5 @@ def test_calculate(self): def test_parse_expression(self): self.assertEqual(self.parser.parse_expression('sin(5)*3'), - [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], operators_dict['*'], '3']) + [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], + operators_dict['*'], '3']) From 35b864a3ff73bf133f83e9e1c17e5ce32f531073 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 02:04:41 +0300 Subject: [PATCH 08/13] Fixed style issues --- final_task/pycalc/parser.py | 14 +++++++------- final_task/tests/unit_tests.py | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 77d3e44..58d8ba8 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -33,16 +33,16 @@ def add_multiply_sign(lexem_list): for i in range(1, len(lexem_list)): if isinstance(lexem_list[i], Function) and not isinstance(lexem_list[i-1], Operator): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) + elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) \ and lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Constant) and isinstance(lexem_list[i-1], Constant): @@ -85,9 +85,9 @@ def find_unary_signs(lexem_list): for i in range(len(lexem_list)): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) - elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and - not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ - and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and \ + not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ + and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index ad34f85..bc1d33a 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -32,22 +32,22 @@ def test_is_constant_method(self): self.assertEqual(Parser.is_constant('21'), False) def test_find_unary_signs_methods(self): - self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), + self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), \ [(0, operators_dict['-']), (1, operators_dict['-']), (2, operators_dict['-'])]) - self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], - operators_dict['-'], '3',operators_dict[')']]), [(1, operators_dict['-']),(2, operators_dict['-']), - (3, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'],operators_dict['-'], \ + '3', operators_dict[')']]), [(1, operators_dict['-']),(2, operators_dict['-']), \ + (3, operators_dict['-'])]) def test_add_multiply_sign(self): - self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), + self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), \ ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], self.function_parser.functions_dict['sin']]) - - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], '4', operators_dict[')']]), - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), \ + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], \ + self.function_parser.functions_dict['sin']]) + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], '4', operators_dict[')']]), \ + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', \ operators_dict[')']]) - self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]),['5', operators_dict['*'], + self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]),['5', operators_dict['*'], \ operators_dict['('], '4', operators_dict[')']]) def test_par_checker(self): @@ -73,5 +73,5 @@ def test_calculate(self): def test_parse_expression(self): self.assertEqual(self.parser.parse_expression('sin(5)*3'), - [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], + [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], \ operators_dict['*'], '3']) From e72ed62f1432746e9319785ba51fd9a26df97cfb Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 02:15:01 +0300 Subject: [PATCH 09/13] Fixed style issues --- final_task/pycalc/parser.py | 6 +++++- final_task/tests/unit_tests.py | 29 ++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 58d8ba8..1e79a3b 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -92,7 +92,11 @@ def find_unary_signs(lexem_list): lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) for unary_sign in lexems_filter: - lexem_list[unary_sign[0]] = operators_dict['unary_plus'] if unary_sign[1] == '+' else operators_dict['unary_minus'] + lexem_list[unary_sign[0]] = operators_dict['unary_plus'] \if unary_sign[1] == '+' else operators_dict['unary_minus'] + if unary_sign[1] == '+': + lexem_list[unary_sign[0]] = operators_dict['unary_plus'] + else: + lexem_list[unary_sign[0]] = operators_dict['unary_minus'] return lexems_filter @staticmethod diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index bc1d33a..6d5069a 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -32,23 +32,29 @@ def test_is_constant_method(self): self.assertEqual(Parser.is_constant('21'), False) def test_find_unary_signs_methods(self): - self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), \ - [(0, operators_dict['-']), (1, operators_dict['-']), (2, operators_dict['-'])]) - self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'],operators_dict['-'], \ - '3', operators_dict[')']]), [(1, operators_dict['-']),(2, operators_dict['-']), \ + self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], \ + operators_dict['-'], '3']), \ + [(0, operators_dict['-']), (1, operators_dict['-']), \ + (2, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], \ + operators_dict['-'], '3', operators_dict[')']]), \ + [(1, operators_dict['-']),(2, operators_dict['-']), \ (3, operators_dict['-'])]) def test_add_multiply_sign(self): self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), \ - ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), \ + ['4', operators_dict['*'], \ + self.function_parser.functions_dict['sin']]) + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], \ + self.function_parser.functions_dict['sin']]), \ [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], \ self.function_parser.functions_dict['sin']]) - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], '4', operators_dict[')']]), \ - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', \ + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], \ + '4', operators_dict[')']]), [operators_dict['('], '4', \ + operators_dict[')'], operators_dict['*'], operators_dict['('], '4', \ operators_dict[')']]) - self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]),['5', operators_dict['*'], \ - operators_dict['('], '4', operators_dict[')']]) + self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]), ['5', \ + operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) def test_par_checker(self): self.assertFalse(Validator.par_check('(()')) @@ -67,7 +73,8 @@ def test_validation(self): self.assertEqual(Validator.validate_string("2 >= 45"), "2 >= 45") def test_calculate(self): - exp = 'sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0^2.0))))--cos(1.0)--cos(0.0)^3.0)' + exp = 'sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0^2.0)))) \ + --cos(1.0)--cos(0.0)^3.0)' self.assertEqual(calculate(exp), 0.5361064001012783) self.assertEqual(calculate('(3+(4*5)/10)+pow(3,2)'), 14.0) From 52a2002e5e9561c55a29f655670f7d7e2aa5d3dd Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 02:17:40 +0300 Subject: [PATCH 10/13] Fixed parser issue --- final_task/pycalc/parser.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 1e79a3b..2e20a4e 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -92,11 +92,10 @@ def find_unary_signs(lexem_list): lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) for unary_sign in lexems_filter: - lexem_list[unary_sign[0]] = operators_dict['unary_plus'] \if unary_sign[1] == '+' else operators_dict['unary_minus'] - if unary_sign[1] == '+': - lexem_list[unary_sign[0]] = operators_dict['unary_plus'] - else: - lexem_list[unary_sign[0]] = operators_dict['unary_minus'] + if unary_sign[1] == '+': + lexem_list[unary_sign[0]] = operators_dict['unary_plus'] + else: + lexem_list[unary_sign[0]] = operators_dict['unary_minus'] return lexems_filter @staticmethod From 54e946d5e9227e5e76b84b9456ae2fd5dadff007 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 02:38:58 +0300 Subject: [PATCH 11/13] Fixed style issues --- final_task/pycalc/importmodules.py | 1 - final_task/pycalc/operators.py | 1 - final_task/pycalc/parser.py | 20 +++++++------- final_task/pycalc/pycalc.py | 16 +++++------ final_task/pycalc/validator.py | 3 +- final_task/tests/unit_tests.py | 44 +++++++++++++++--------------- 6 files changed, 40 insertions(+), 45 deletions(-) diff --git a/final_task/pycalc/importmodules.py b/final_task/pycalc/importmodules.py index 3d0cbc9..450b205 100644 --- a/final_task/pycalc/importmodules.py +++ b/final_task/pycalc/importmodules.py @@ -25,4 +25,3 @@ def parse_modules(self, modules): self.constants_dict[object] = Constant(object, 6, 1, True, vars(modul)[object]) else: self.functions_dict[object] = Function(object, 6, 1, True, vars(modul)[object]) - diff --git a/final_task/pycalc/operators.py b/final_task/pycalc/operators.py index 30b6a1a..0f8bb4f 100644 --- a/final_task/pycalc/operators.py +++ b/final_task/pycalc/operators.py @@ -46,4 +46,3 @@ def __init__(self, name, priority, associativity, is_binary, func): '^': Operator('^', 4, 2, True, lambda x, y: x**y), } - diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 2e20a4e..2b3dcd3 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -34,13 +34,15 @@ def add_multiply_sign(lexem_list): if isinstance(lexem_list[i], Function) and not isinstance(lexem_list[i-1], Operator): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) \ - and lexem_list[i-1].name == ')': + and lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): + (isinstance(lexem_list[i-1], Constant) or + Parser.is_number(lexem_list[i-1])): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')': + isinstance(lexem_list[i-1], Operator) and + lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): @@ -73,7 +75,7 @@ def parse_expression(self, exp): start_index, end_index = end_index, len(exp) else: end_index -= 1 - lex_list =Parser.add_multiply_sign(lexem_array) + lex_list = Parser.add_multiply_sign(lexem_array) unary_signs = Parser.find_unary_signs(lex_list) final_lexem_list = Parser.remove_redundant_unary_signs(unary_signs, lex_list) @@ -86,8 +88,8 @@ def find_unary_signs(lexem_list): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and \ - not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ - and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): + not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ + and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) @@ -105,12 +107,10 @@ def remove_redundant_unary_signs(lexems_with_indicies, lex_list): last_index, last_sign = lexems_with_indicies[final_index] prev_index, prev_sign = lexems_with_indicies[final_index - 1] if last_index - 1 == prev_index and last_sign.name == prev_sign.name: - lex_list[prev_index:last_index + 1] = [operators_dict['unary_plus']] - lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['+'])] + lex_list[prev_index:last_index + 1] = [operators_dict['unary_plus']] + lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['+'])] elif last_index - 1 == prev_index and last_sign != prev_sign: lex_list[prev_index: last_index + 1] = [operators_dict['unary_minus']] lexems_with_indicies[final_index - 1: final_index + 1] = [(prev_index, operators_dict['-'])] final_index -= 1 return lex_list - - diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py index 37af080..af70295 100644 --- a/final_task/pycalc/pycalc.py +++ b/final_task/pycalc/pycalc.py @@ -18,15 +18,13 @@ def get_args(): def main(): try: - args = get_args() - parser = FunctionParser() - if args.use_modules: - parser.parse_modules(args.use_modules) - parser.parse_modules(['time']) - result = calculate(args.expression) - print(f'{result}') - + args = get_args() + parser = FunctionParser() + if args.use_modules: + parser.parse_modules(args.use_modules) + parser.parse_modules(['time']) + result = calculate(args.expression) + print(f'{result}') except Exception as e: print(f"ERROR: {e}") sys.exit(1) - diff --git a/final_task/pycalc/validator.py b/final_task/pycalc/validator.py index f393dda..9b731b4 100644 --- a/final_task/pycalc/validator.py +++ b/final_task/pycalc/validator.py @@ -11,7 +11,7 @@ def normalize_string(str): :param str: String with a math expression. :return : Normalized string with a math expression. ''' - return re.sub('\s+', ' ', str).strip() + return re.sub(r'\s+', ' ', str).strip() @staticmethod def pre_tokinaze(str): @@ -61,4 +61,3 @@ def validate_string(str): if str[i + 1] == ' ' and str[i + 2].isdigit(): raise ValueError('invalid syntax') return str - diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index 6d5069a..972d737 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -11,7 +11,7 @@ def setUp(self): self.parser = Parser() self.function_parser = FunctionParser() self.operator = operators_dict['+'] - self.lexem_indicies = [(0, operators_dict['-']),(1, operators_dict['-']), (2, operators_dict['-'])] + self.lexem_indicies = [(0, operators_dict['-']), (1, operators_dict['-']), (2, operators_dict['-'])] self.lex_arr = [operators_dict['-'], operators_dict['-'], operators_dict['-'], '3'] def test_is_number_method(self): @@ -32,28 +32,28 @@ def test_is_constant_method(self): self.assertEqual(Parser.is_constant('21'), False) def test_find_unary_signs_methods(self): - self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], \ - operators_dict['-'], '3']), \ - [(0, operators_dict['-']), (1, operators_dict['-']), \ - (2, operators_dict['-'])]) - self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], \ - operators_dict['-'], '3', operators_dict[')']]), \ - [(1, operators_dict['-']),(2, operators_dict['-']), \ - (3, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], + operators_dict['-'], '3']), + [(0, operators_dict['-']), (1, operators_dict['-']), + (2, operators_dict['-'])]) + self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], + operators_dict['-'], '3', operators_dict[')']]), + [(1, operators_dict['-']), (2, operators_dict['-']), + (3, operators_dict['-'])]) def test_add_multiply_sign(self): - self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), \ - ['4', operators_dict['*'], \ - self.function_parser.functions_dict['sin']]) - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], \ - self.function_parser.functions_dict['sin']]), \ - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], \ - self.function_parser.functions_dict['sin']]) - self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], \ - '4', operators_dict[')']]), [operators_dict['('], '4', \ - operators_dict[')'], operators_dict['*'], operators_dict['('], '4', \ - operators_dict[')']]) - self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]), ['5', \ + self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), + ['4', operators_dict['*'], + self.function_parser.functions_dict['sin']]) + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], + self.function_parser.functions_dict['sin']]), + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], + self.function_parser.functions_dict['sin']]) + self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], + '4', operators_dict[')']]), [operators_dict['('], '4', + operators_dict[')'], operators_dict['*'], operators_dict['('], '4', + operators_dict[')']]) + self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]), ['5', operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) def test_par_checker(self): @@ -80,5 +80,5 @@ def test_calculate(self): def test_parse_expression(self): self.assertEqual(self.parser.parse_expression('sin(5)*3'), - [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], \ + [self.function_parser.functions_dict['sin'], operators_dict['('], '5', operators_dict[')'], operators_dict['*'], '3']) From 8bed59df0fb6bca52f21be5f8a87ada2233712f9 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Fri, 21 Dec 2018 02:53:53 +0300 Subject: [PATCH 12/13] Fixed style issues --- final_task/pycalc/operators.py | 1 - final_task/pycalc/parser.py | 10 ++++++---- final_task/setup.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/final_task/pycalc/operators.py b/final_task/pycalc/operators.py index 0f8bb4f..ecf8c91 100644 --- a/final_task/pycalc/operators.py +++ b/final_task/pycalc/operators.py @@ -45,4 +45,3 @@ def __init__(self, name, priority, associativity, is_binary, func): 'unary_plus': Operator('unary_plus', 5, 1, False, lambda x: x), '^': Operator('^', 4, 2, True, lambda x, y: x**y), } - diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index 2b3dcd3..aa31a78 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -41,11 +41,12 @@ def add_multiply_sign(lexem_list): Parser.is_number(lexem_list[i-1])): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - isinstance(lexem_list[i-1], Operator) and + isinstance(lexem_list[i-1], Operator) and \ lexem_list[i-1].name == ')': lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function): + not isinstance(lexem_list[i-1], Operator) \ + and not isinstance(lexem_list[i-1], Function): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Constant) and isinstance(lexem_list[i-1], Constant): lexem_list.insert(i, operators_dict['*']) @@ -88,8 +89,9 @@ def find_unary_signs(lexem_list): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and \ - not (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) \ - and not (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): + not (isinstance(lexem_list[i-1], Constant) + or Parser.is_number(lexem_list[i-1])) and not \ + (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): final_list.append(i) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) diff --git a/final_task/setup.py b/final_task/setup.py index a6f57f4..014bce4 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -6,6 +6,6 @@ packages=find_packages(), __version__='1.0', entry_points={ - 'console_scripts': ['pycalc = pycalc.pycalc:main',] + 'console_scripts': ['pycalc = pycalc.pycalc:main', ] }, ) From 67ee13548804ae2e0c8224045c83aa5ccf13c0e0 Mon Sep 17 00:00:00 2001 From: lenashanchuk Date: Sat, 22 Dec 2018 00:16:56 +0300 Subject: [PATCH 13/13] Fixed style errors --- final_task/pycalc/parser.py | 21 +++++++++------------ final_task/setup.py | 18 ++++++++++-------- final_task/tests/unit_tests.py | 23 ++++++++++------------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/final_task/pycalc/parser.py b/final_task/pycalc/parser.py index aa31a78..476a0c8 100644 --- a/final_task/pycalc/parser.py +++ b/final_task/pycalc/parser.py @@ -33,20 +33,18 @@ def add_multiply_sign(lexem_list): for i in range(1, len(lexem_list)): if isinstance(lexem_list[i], Function) and not isinstance(lexem_list[i-1], Operator): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) \ - and lexem_list[i-1].name == ')': + elif (isinstance(lexem_list[i], Function) and isinstance(lexem_list[i-1], Operator) and + lexem_list[i-1].name == ')'): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - isinstance(lexem_list[i-1], Operator) and \ - lexem_list[i-1].name == ')': + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): lexem_list.insert(i, operators_dict['*']) - elif isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and \ - not isinstance(lexem_list[i-1], Operator) \ - and not isinstance(lexem_list[i-1], Function): + elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name == '(' and + not isinstance(lexem_list[i-1], Operator) and not isinstance(lexem_list[i-1], Function)): lexem_list.insert(i, operators_dict['*']) elif isinstance(lexem_list[i], Constant) and isinstance(lexem_list[i-1], Constant): lexem_list.insert(i, operators_dict['*']) @@ -88,10 +86,9 @@ def find_unary_signs(lexem_list): for i in range(len(lexem_list)): if i == 0 and isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']: final_list.append(0) - elif (isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and \ - not (isinstance(lexem_list[i-1], Constant) - or Parser.is_number(lexem_list[i-1])) and not \ - (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')'): + elif ((isinstance(lexem_list[i], Operator) and lexem_list[i].name in ['+', '-']) and not + (isinstance(lexem_list[i-1], Constant) or Parser.is_number(lexem_list[i-1])) and not + (isinstance(lexem_list[i-1], Operator) and lexem_list[i-1].name == ')')): final_list.append(i) lexems_with_indicies = enumerate(lexem_list) lexems_filter = list(filter(lambda x: x[0] in final_list, lexems_with_indicies)) diff --git a/final_task/setup.py b/final_task/setup.py index 014bce4..8be2bb6 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -1,11 +1,13 @@ from setuptools import setup, find_packages setup( - name='pycalc', - version='1.0', - packages=find_packages(), - __version__='1.0', - entry_points={ - 'console_scripts': ['pycalc = pycalc.pycalc:main', ] - }, - ) + name='pycalc', + version='1.0', + packages=find_packages(), + __version__='1.0', + entry_points={ + 'console_scripts': [ + 'pycalc = pycalc.pycalc:main' + ] + }, +) diff --git a/final_task/tests/unit_tests.py b/final_task/tests/unit_tests.py index 972d737..5b52e80 100644 --- a/final_task/tests/unit_tests.py +++ b/final_task/tests/unit_tests.py @@ -34,27 +34,24 @@ def test_is_constant_method(self): def test_find_unary_signs_methods(self): self.assertEqual(Parser.find_unary_signs([operators_dict['-'], operators_dict['-'], operators_dict['-'], '3']), - [(0, operators_dict['-']), (1, operators_dict['-']), - (2, operators_dict['-'])]) + [(0, operators_dict['-']), (1, operators_dict['-']), (2, operators_dict['-'])]) self.assertEqual(Parser.find_unary_signs([operators_dict['('], operators_dict['-'], operators_dict['-'], operators_dict['-'], '3', operators_dict[')']]), - [(1, operators_dict['-']), (2, operators_dict['-']), - (3, operators_dict['-'])]) + [(1, operators_dict['-']), (2, operators_dict['-']), (3, operators_dict['-'])]) def test_add_multiply_sign(self): self.assertEqual(Parser.add_multiply_sign(['4', self.function_parser.functions_dict['sin']]), - ['4', operators_dict['*'], - self.function_parser.functions_dict['sin']]) + ['4', operators_dict['*'], self.function_parser.functions_dict['sin']]) self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], self.function_parser.functions_dict['sin']]), - [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], - self.function_parser.functions_dict['sin']]) + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], + self.function_parser.functions_dict['sin']]) self.assertEqual(Parser.add_multiply_sign([operators_dict['('], '4', operators_dict[')'], operators_dict['('], - '4', operators_dict[')']]), [operators_dict['('], '4', - operators_dict[')'], operators_dict['*'], operators_dict['('], '4', - operators_dict[')']]) - self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]), ['5', - operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) + '4', operators_dict[')']]), + [operators_dict['('], '4', operators_dict[')'], operators_dict['*'], operators_dict['('], '4', + operators_dict[')']]) + self.assertEqual(Parser.add_multiply_sign(['5', operators_dict['('], '4', operators_dict[')']]), + ['5', operators_dict['*'], operators_dict['('], '4', operators_dict[')']]) def test_par_checker(self): self.assertFalse(Validator.par_check('(()'))