latinica.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import sys
  2. RULES = [
  3. (('т', 'ь', 'с', 'я'), 't\u0341sá'),
  4. (('т', 'ь', 'с', 'ю'), 't\u0341sú'),
  5. (('т', 'с', 'я'), 'tsá'),
  6. (('т', 'с', 'ю'), 'tsú'),
  7. (('ы', 'й', 'B'), ('ý', -3)),
  8. (('ч', 'ь', 'B'), (-1, -3)),
  9. (('ш', 'ь', 'B'), (-1, -3)),
  10. (('л', 'ь', 'B'), ('lj', -3)),
  11. (('л', 'я', 'я'), (-1, -2, 'á')),
  12. (('л', 'ю', 'ю'), (-1, -2, 'ú')),
  13. (('л', 'я', 'ю'), (-1, -2, 'ú')),
  14. (('л', 'ю', 'я'), (-1, -2, 'á')),
  15. (('н', 'я', 'я'), (-1, -2, 'á')),
  16. (('н', 'ю', 'ю'), (-1, -2, 'ú')),
  17. (('н', 'я', 'ю'), (-1, -2, 'ú')),
  18. (('н', 'ю', 'я'), (-1, -2, 'á')),
  19. (('S', 'е'), (-1, '\u0341')),
  20. (('B', 'е'), (-1, -2, '\u0341')),
  21. (('я', 'я'), (-1, 'á')),
  22. (('ю', 'ю'), (-1, 'ú')),
  23. (('я', 'ю'), (-1, 'ú')),
  24. (('ю', 'я'), (-1, 'á')),
  25. (('д', 'ж'), 'đ'),
  26. #(('к', 'с'), 'x'),
  27. (('ч', 'ь'), (-1, -2)),
  28. (('ш', 'ь'), (-1, -2)),
  29. (('щ', 'ь'), (-1, -2)),
  30. (('C', 'ь'), (-1, '\u0341')),
  31. (('л', 'ё'), (-1, -2)),
  32. (('н', 'я'), (-1, -2)),
  33. (('л', 'я'), (-1, -2)),
  34. (('ш', 'я'), (-1, -2)),
  35. (('щ', 'я'), (-1, -2)),
  36. (('ж', 'я'), (-1, -2)),
  37. (('^C', '^я'), (-1, 'ja')),
  38. (('C', 'я'), (-1, 'ía')),
  39. (('н', 'ю'), (-1, -2)),
  40. (('л', 'ю'), (-1, -2)),
  41. (('ш', 'ю'), (-1, -2)),
  42. (('щ', 'ю'), (-1, -2)),
  43. (('ж', 'ю'), (-1, -2)),
  44. (('^C', '^ю'), (-1, 'ju')),
  45. (('C', 'ю'), (-1, 'íu')),
  46. (('н', 'ё'), (-1, -2)),
  47. (('л', 'ё'), (-1, -2)),
  48. (('ш', 'ё'), (-1, -2)),
  49. (('щ', 'ё'), (-1, -2)),
  50. (('ж', 'ё'), (-1, -2)),
  51. (('^C', '^ё'), (-1, 'jo')),
  52. (('C', 'ё'), (-1, 'ío')),
  53. (('V', 'е'), (-1, -2, '\u0341')),
  54. (('а',), 'a'),
  55. (('б',), 'b'),
  56. (('в',), 'v'),
  57. (('г',), 'g'),
  58. (('д',), 'd'),
  59. (('е',), 'e'),
  60. (('^ё',), ('jo',)),
  61. (('ё',), 'jo'),
  62. (('ж',), 'ž'),
  63. (('з',), 'z'),
  64. (('и',), 'i'),
  65. (('й',), 'j'),
  66. (('к',), 'k'),
  67. (('л',), 'l'),
  68. (('м',), 'm'),
  69. (('н',), 'n'),
  70. (('о',), 'o'),
  71. (('п',), 'p'),
  72. (('р',), 'r'),
  73. (('с',), 's'),
  74. (('т',), 't'),
  75. (('у',), 'u'),
  76. (('ф',), 'f'),
  77. (('х',), 'h'),
  78. (('ц',), 'c'),
  79. (('ч',), 'č'),
  80. (('ш',), 'š'),
  81. (('щ',), 'ŝ'),
  82. (('ъ',), '\''),
  83. (('ы',), 'y'),
  84. (('ь',), '\''),
  85. (('э',), 'ě'),
  86. (('^ю',), ('ju',)),
  87. (('^я',), ('ja',)),
  88. (('ю',), 'ju'),
  89. (('я',), 'ja'),
  90. ('*', (0,))
  91. ]
  92. VOWELS = 'аеёийоуыэюя'
  93. CONSONANTS = 'бвгджзклмнпрстфхцчшщьъ'
  94. def is_vowel(letter):
  95. return letter in VOWELS
  96. def is_consonant(letter):
  97. return letter in CONSONANTS
  98. def is_word_boundary(letter):
  99. return letter in (None, ' ', '.', ',', '!', '?', ':', ';', '/', '&', ')', ']', '}', '\n', '\t')
  100. class Converter:
  101. def __init__(self, source):
  102. self._source = source
  103. self._output = ''
  104. self._position = 0
  105. self._start_position = 0
  106. self._matched_letters = []
  107. def _look(self, n=0, lower=True):
  108. position = self._position + n
  109. if position >= len(self._source)\
  110. or position < 0:
  111. return None
  112. return self._source[position].lower() if lower else self._source[position]
  113. def _match_letter(self, letter, n=0):
  114. letter_ahead = self._look(n)
  115. self._matched_letters.append(letter_ahead)
  116. if not letter_ahead or not letter:
  117. return letter is letter_ahead
  118. if letter[0] == '^':
  119. letter = letter[1]
  120. self._matched_letters.pop()
  121. return self._match_letter(letter, n) and self._look(n, lower=False).isupper()
  122. if letter == '*':
  123. return True
  124. if letter == 'V' and is_vowel(letter_ahead):
  125. return True
  126. elif letter == 'C' and is_consonant(letter_ahead):
  127. return True
  128. elif letter == 'B' and is_word_boundary(letter_ahead):
  129. return True
  130. if letter == letter_ahead:
  131. return True
  132. return False
  133. def _match(self, pattern):
  134. self._matched_letters = []
  135. if pattern[0] == 'S':
  136. if self._position != 0:
  137. return False
  138. pattern = pattern[1:]
  139. for n in range(len(pattern)):
  140. if not self._match_letter(pattern[n], n):
  141. return False
  142. self._start_position = self._position
  143. self._position += len(pattern)
  144. return True
  145. def _convert_letter(self, letter):
  146. if not letter:
  147. return ''
  148. for pattern, replacement in RULES:
  149. if len(pattern) == 1\
  150. and pattern[0] == letter:
  151. return replacement
  152. return letter
  153. def _is_upper(self, n=0):
  154. position = self._start_position + n
  155. if position >= len(self._source)\
  156. or position < 0:
  157. return False
  158. return self._source[position].isupper()
  159. def _insert(self, letters):
  160. buffer = ''
  161. for letter, n in zip(letters, range(len(letters))):
  162. if type(letter) is int:
  163. if letter < 0:
  164. letter = self._convert_letter(self._matched_letters[abs(letter) - 1])
  165. else:
  166. letter = self._matched_letters[letter]
  167. buffer += (letter.capitalize() if letter[0] == 'j' else letter.upper()) if self._is_upper(n) else letter
  168. self._output += buffer
  169. def convert(self):
  170. while True:
  171. for pattern, replacement in RULES:
  172. if self._match(pattern):
  173. self._insert(replacement)
  174. break
  175. if self._match((None,)):
  176. break
  177. return self._output
  178. if __name__ == '__main__':
  179. converter = Converter(sys.stdin.read())
  180. sys.stdout.write(converter.convert())