|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
try:
|
|
|
|
unicode(0)
|
|
|
|
except NameError:
|
|
|
|
# py3
|
|
|
|
unicode = str
|
|
|
|
unichr = chr
|
|
|
|
|
|
|
|
|
|
|
|
class Syllable(object):
|
|
|
|
"""Hangul syllable interface"""
|
|
|
|
|
|
|
|
MIN = ord('가')
|
|
|
|
MAX = ord('힣')
|
|
|
|
|
|
|
|
def __init__(self, char=None, code=None):
|
|
|
|
if char is None and code is None:
|
|
|
|
raise TypeError('__init__ takes char or code as a keyword argument (not given)')
|
|
|
|
if char is not None and code is not None:
|
|
|
|
raise TypeError('__init__ takes char or code as a keyword argument (both given)')
|
|
|
|
if char:
|
|
|
|
code = ord(char)
|
|
|
|
if not self.MIN <= code <= self.MAX:
|
|
|
|
raise TypeError('__init__ expected Hangul syllable but {0} not in [{1}..{2}]'.format(code, self.MIN, self.MAX))
|
|
|
|
self.code = code
|
|
|
|
|
|
|
|
@property
|
|
|
|
def index(self):
|
|
|
|
return self.code - self.MIN
|
|
|
|
|
|
|
|
@property
|
|
|
|
def initial(self):
|
|
|
|
return self.index // 588
|
|
|
|
|
|
|
|
@property
|
|
|
|
def vowel(self):
|
|
|
|
return (self.index // 28) % 21
|
|
|
|
|
|
|
|
@property
|
|
|
|
def final(self):
|
|
|
|
return self.index % 28
|
|
|
|
|
|
|
|
@property
|
|
|
|
def char(self):
|
|
|
|
return unichr(self.code)
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.char
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return '''<Syllable({}({}),{}({}),{}({}),{}({}))>'''.format(
|
|
|
|
self.code, self.char, self.initial, '', self.vowel, '', self.final, '')
|
|
|
|
|
|
|
|
|
|
|
|
class Transliter(object):
|
|
|
|
"""General transliting interface"""
|
|
|
|
|
|
|
|
def __init__(self, rule):
|
|
|
|
self.rule = rule
|
|
|
|
|
|
|
|
def translit(self, text):
|
|
|
|
"""Translit text to romanized text
|
|
|
|
|
|
|
|
:param text: Unicode string or unicode character iterator
|
|
|
|
"""
|
|
|
|
result = []
|
|
|
|
pre = None, None
|
|
|
|
now = None, None
|
|
|
|
for c in text:
|
|
|
|
try:
|
|
|
|
post = c, Syllable(c)
|
|
|
|
except TypeError:
|
|
|
|
post = c, None
|
|
|
|
|
|
|
|
if now[0] is not None:
|
|
|
|
out = self.rule(now, pre=pre, post=post)
|
|
|
|
if out is not None:
|
|
|
|
result.append(out)
|
|
|
|
|
|
|
|
pre = now
|
|
|
|
now = post
|
|
|
|
|
|
|
|
if now is not None:
|
|
|
|
out = self.rule(now, pre=pre, post=(None, None))
|
|
|
|
if out is not None:
|
|
|
|
result.append(out)
|
|
|
|
|
|
|
|
return ''.join(result)
|