import logging class SomeSyntaxError(Exception): pass class SyntaxError(SomeSyntaxError): bracket = None idx = -1 def __init__(self, bracket, idx): assert isinstance(bracket, str) assert isinstance(idx, int) self.bracket = bracket self.idx = idx def __str__(self): return 'Wrong bracket "%s" at index %d' % (self.bracket, self.idx) def check_syntax(text): """ Проверяет синтакс скобок. Не учитывает кавычки! """ if not text: return True logger = logging.getLogger('Syntaxer') good_pairs_map = { '{': '}', '[': ']', '(': ')', } _opened_brackets_stack = [] idx = -1 for c in text: idx += 1 if not _opened_brackets_stack: if c in good_pairs_map.values(): raise SyntaxError(c, idx) elif c in good_pairs_map.keys(): _opened_brackets_stack.append(c) logger.debug('First opening bracket: %s at %s' % (c, idx)) continue else: if c in good_pairs_map.keys(): _opened_brackets_stack.append(c) logger.debug('Next opening bracket with %s at %s' % (c, idx)) continue elif c in good_pairs_map.values(): if c == good_pairs_map.get(_opened_brackets_stack[-1]): _opened_brackets_stack.pop() logger.debug('Found closing bracket "%s" at %s' % (c, idx)) continue else: raise SyntaxError(c, idx) if _opened_brackets_stack: raise SomeSyntaxError('Not closed brackets: %d' % len(_opened_brackets_stack)) return True import unittest class SyntaxCheckerTest(unittest.TestCase): def test_ok(self): self.assertTrue(check_syntax('{()}[]')) def test_should_fail_on_wrong_closing_bracket(self): with self.assertRaises(SomeSyntaxError): check_syntax('{[}}') def test_should_fail_on_missing_closing_bracket(self): with self.assertRaises(SomeSyntaxError): check_syntax('{}[') def test_should_fail_on_single_opening_bracket(self): with self.assertRaises(SomeSyntaxError): check_syntax('{') def test_should_fail_on_single_close_bracket(self): with self.assertRaises(SomeSyntaxError): check_syntax(')') if __name__ == '__main__': import sys if len(sys.argv) >= 2: if '-d' in sys.argv[1:]: logging.basicConfig(level=logging.DEBUG) try: if check_syntax(sys.argv[-1]): print('Syntax is ok!') except SomeSyntaxError as ex: print(ex) else: print('Run with string, -d for debug...')