def parserule(self, rule_str): class State: matching_static = 0 matching_converter = 1 matching_name = 2 ignore_char = 3 failed = 4 done = 5 state = State.matching_static static_buf = "" conv_buf = "" name_buf = "" self.valid = False self.matcher = CombiMatcher() rule_str += ' ' rule_length = len(rule_str) for i in range(rule_length): c = rule_str[i] do_store_static = False do_store_converter_and_name = False if state == State.matching_static: if c == '\\': state = State.ignore_char elif c == '<': state = State.matching_converter do_store_static = True elif i == rule_length -1: state = State.done do_store_static = True else: static_buf += c elif state == State.matching_converter: if c == ':': state = State.matching_name elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._": conv_buf += c else: state = State.failed elif state == State.matching_name: if c == '>': state = State.matching_static do_store_converter_and_name = True elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._": name_buf += c else: state = State.failed elif state == State.ignore_char: state = State.matching_static elif state == State.failed: pass elif state == State.done: pass # store static buffer if needed by state if do_store_static: if len(static_buf) > 0: self.__add_static_matcher(static_buf) static_buf = "" # store converter if needed by state if do_store_converter_and_name: if len(conv_buf) > 0 \ and len(name_buf) > 0: self.__add_dynamic_matcher(conv_buf, name_buf) conv_buf = "" name_buf = "" if state is State.done: self.valid = True else: self.valid = False self.matcher = None
class Rule(object): def __init__(self, rule_str, extra_converters = {}): self.valid = False self.matcher = None self.rule_str = None global _converters self.converters = _converters self.converters.update(extra_converters) self.setrule(rule_str) def setrule(self, rule_str): self.parserule(rule_str) if not self.isvalid(): self.rule_str = None raise InvalidRule("Invalid rule: '%s'" % rule_str) self.rule_str = rule_str def rule(self): return self.rule_str def parserule(self, rule_str): class State: matching_static = 0 matching_converter = 1 matching_name = 2 ignore_char = 3 failed = 4 done = 5 state = State.matching_static static_buf = "" conv_buf = "" name_buf = "" self.valid = False self.matcher = CombiMatcher() rule_str += ' ' rule_length = len(rule_str) for i in range(rule_length): c = rule_str[i] do_store_static = False do_store_converter_and_name = False if state == State.matching_static: if c == '\\': state = State.ignore_char elif c == '<': state = State.matching_converter do_store_static = True elif i == rule_length -1: state = State.done do_store_static = True else: static_buf += c elif state == State.matching_converter: if c == ':': state = State.matching_name elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._": conv_buf += c else: state = State.failed elif state == State.matching_name: if c == '>': state = State.matching_static do_store_converter_and_name = True elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._": name_buf += c else: state = State.failed elif state == State.ignore_char: state = State.matching_static elif state == State.failed: pass elif state == State.done: pass # store static buffer if needed by state if do_store_static: if len(static_buf) > 0: self.__add_static_matcher(static_buf) static_buf = "" # store converter if needed by state if do_store_converter_and_name: if len(conv_buf) > 0 \ and len(name_buf) > 0: self.__add_dynamic_matcher(conv_buf, name_buf) conv_buf = "" name_buf = "" if state is State.done: self.valid = True else: self.valid = False self.matcher = None def __add_static_matcher(self, string): m = StaticStringMatcher(string) self.matcher.add(m) def __add_dynamic_matcher(self, converter, name): m = self.__get_matcher(converter) if m is None: return None self.matcher.add(m, name) def __get_matcher(self, converter): c = self.converters.get(converter, None) m = c() return m def isvalid(self): return self.valid def test(self, check_str): if not self.valid: return None result = TestResult(self) result.setmatch(False) if check_str is not None and len(check_str) > 0: for char in check_str: s = self.matcher.feed(char) if s: result.setmatch(True) else: result.setmatch(False) break if not self.matcher.full_match(): result.setmatch(False) v = self.matcher.getvalue() if v is not None: result.setparams(v) self.matcher.reset() return result