Subversion Repositories LCARS

Rev

Rev 294 | Rev 297 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

1
#!/usr/bin/env python3

'''
Created on 2014-10-20

@author: Thomas 'PointedEars' Lahn <mail@PointedEars.de>
'''

from sys import argv, stderr
from re import findall, DOTALL, match, sub, compile, \
    escape, search
from os.path import basename
from functools import cmp_to_key
from Dictionary import Dictionary, dmsg, \
    sort_dict_alnum_english_key

dictionary = {}

prepositions = {
    "fi'": 'on',
    "na'": 'at|to',
    "t'": 'of'
}

def cli_help():
    print('Usage: {0} TEXT...'.format(basename(argv[0])))

def get_sort_dict_alnum_vulcan_key ():
    letters = list(map(str.lower, [
        " ", 'S', 'T', 'P', 'K', 'R', 'L', 'A', 'Sh', 'O', 'U', 'D',
        'V', 'Kh', 'E', 'H', 'G', 'Ch', 'I', 'N', 'Zh', 'M', 'Y', 'F', 'Z',
        'Th', 'W', 'B', "'", '-']))
    letter_values = dict(map(lambda x: (x[1], x[0]), enumerate(letters)))
    letters_re = compile(r'(?:{0})'.format('|'.join(sorted(letters, key=lambda char:-len(char)))))

    def sort_dict_alnum_vulcan (a, b):
        # split into Vulcan letters
        a = findall(letters_re, sort_dict_alnum_english_key(a))
        b = findall(letters_re, sort_dict_alnum_english_key(b))

        if len(a) < len(b):
            for index, char in enumerate(a):
                diff = letter_values[char] - letter_values[b[index]]
                if diff != 0:
                    return diff
            return -1

        # len(b) <= len(a)
        for index, char in enumerate(b):
            diff = letter_values[a[index]] - letter_values[char]
            if diff != 0:
                return diff

        return 1 if len(b) < len(a) else 0

    return cmp_to_key(sort_dict_alnum_vulcan)

class VulcanDictionary (Dictionary):
    def translate (self, phrase, search_prefix=True, search_plural=True):
        dictionary = self

        translation = super().translate(phrase)
        if translation is not None:
            return translation
        else:
            expr_translation = dictionary.translate_expression(phrase)
            if expr_translation is not None:
                return expr_translation

            if search_prefix:
                # find prefix
                for preposition in prepositions:
                    prefix = match(escape(preposition), phrase)
                    if prefix is not None:
                        prefix_translation = self.translate(prefix.group(0))
                        if prefix_translation is not None:
                            tail = sub(preposition, '', phrase)
                            tail_translation = self.translate(tail, search_prefix=False)
                            if tail_translation is not None:
                                return [prefix_translation, tail_translation]
            elif search_plural:
                # find plural
                suffix = search(r'lar$', phrase)
                if suffix is not None:
                    head = sub(r'lar$', '', phrase)
                    head_translation = self.translate(head, search_prefix=False, search_plural=False)
                    if head_translation is not None:
                        head_translation = dict(head_translation)
                        head_translation['en'] += ' (pl.)'
                        return head_translation

        return None

if __name__ == '__main__':
    if len(argv) < 2:
        print('Nothing to translate.', end='\n\n', file=stderr)
        cli_help()
        exit(1)

    text = ' '.join(argv[1:])

    dictionary = VulcanDictionary(dictionary)
    dictionary.load('vuh-gol-en.dict.zdb.txt', 'vuh')
    dictionary.clean()

#     try:
#         for phrase, data in OrderedDict(sorted(
#             dictionary.items(),
#             key=get_sort_dict_alnum_vulcan_key()
#         )).items():
#             print(phrase, "=", data)
#     except BrokenPipeError:
#         pass

    dmsg("text:", text, min_level=2)
    sentences = findall(r'(?!\s+)(?:.+?\.{1,3}|.+$)', text, DOTALL)
    dmsg("sentences:", sentences, min_level=2)
    for sentence in sentences:
        dmsg("sentence:", sentence, min_level=2)

        clauses = findall(r'(?!\s+)(?:.+?(?:\s+-\s*|\s*[–—]\s*|\.{1,3}|.+$))', sentence, DOTALL)
        dmsg("clauses:", clauses, min_level=2)
        for clause in clauses:
            dmsg("clause:", clause, min_level=2)

            words = findall(r'[^\s.]+', clause)
            dmsg("words:", words, min_level=2)

            offset = 0
            while offset < len(words):
                translation = None

                for i in range(len(words), offset, -1):
                    dmsg("words[{0}:{1}] = {2}".format(offset, i, words[offset:i]), min_level=2)
                    phrase = ' '.join(words[offset:i])

                    dmsg("phrase:", phrase, min_level=2)

                    translation = dictionary.translate(phrase)

                    if translation is not None:
                        dmsg("phrase-translation:", translation, min_level=2)
                        dmsg("words[{0}:{1}] = [\"{2}\"]".format(offset, i, translation), min_level=2)
                        words[offset:i] = [translation]
                        offset += i - offset
                        break

                if translation is None:
                    dmsg("phrase-translation:", translation, min_level=2)
                    offset += 1

            dmsg("words-translation:", words, min_level=2)
            dmsg("words-translation-reduced:",
                list(map(
                    lambda word:
                        word['en']
                        if (hasattr(word, "get") and word.get('en', None) is not None)
                        else word,
                    words)),
                min_level=2)
            # dmsg(dictionary._expressions)