- parts = re.split(r'(\|)?([=-])>', rule)
- if len(parts) != 4:
- raise UsageError("Syntax error in variant rule: " + rule)
-
- decompose = parts[1] is None
- src_terms = [self._parse_variant_word(t) for t in parts[0].split(',')]
- repl_terms = (self.norm.transliterate(t.strip()) for t in parts[3].split(','))
-
- # If the source should be kept, add a 1:1 replacement
- if parts[2] == '-':
- for src in src_terms:
- if src:
- for froms, tos in _create_variants(*src, src[0], decompose):
- yield variants.ICUVariant(froms, tos, props)
-
- for src, repl in itertools.product(src_terms, repl_terms):
- if src and repl:
- for froms, tos in _create_variants(*src, repl, decompose):
- yield variants.ICUVariant(froms, tos, props)
-
-
- def _parse_variant_word(self, name):
- name = name.strip()
- match = re.fullmatch(r'([~^]?)([^~$^]*)([~$]?)', name)
- if match is None or (match.group(1) == '~' and match.group(3) == '~'):
- raise UsageError("Invalid variant word descriptor '{}'".format(name))
- norm_name = self.norm.transliterate(match.group(2))
- if not norm_name:
- return None
-
- return norm_name, match.group(1), match.group(3)
-
-
-_FLAG_MATCH = {'^': '^ ',
- '$': ' ^',
- '': ' '}
-
-
-def _create_variants(src, preflag, postflag, repl, decompose):
- if preflag == '~':
- postfix = _FLAG_MATCH[postflag]
- # suffix decomposition
- src = src + postfix
- repl = repl + postfix
-
- yield src, repl
- yield ' ' + src, ' ' + repl
-
- if decompose:
- yield src, ' ' + repl
- yield ' ' + src, repl
- elif postflag == '~':
- # prefix decomposition
- prefix = _FLAG_MATCH[preflag]
- src = prefix + src
- repl = prefix + repl
-
- yield src, repl
- yield src + ' ', repl + ' '
-
- if decompose:
- yield src, repl + ' '
- yield src + ' ', repl
- else:
- prefix = _FLAG_MATCH[preflag]
- postfix = _FLAG_MATCH[postflag]
-
- yield prefix + src + postfix, prefix + repl + postfix