def choose_endings_stress(func, i): p = i.parts # local keys = [ # local 'nom-sg', 'gen-sg', 'dat-sg', 'acc-sg', 'ins-sg', 'prp-sg', # 'srt-sg', 'nom-pl', 'gen-pl', 'dat-pl', 'acc-pl', 'ins-pl', 'prp-pl', # 'srt-pl', ] # list for j, key in enumerate(keys): if _.has_key(p.endings, key) and type(p.endings[key]) == list: # type stress = i.stress_schema['ending'][ key] and stressed or unstressed # local p.endings[key] = p.endings[key][stress] # end # end if i.adj and i.gender == 'n': stress = i.stress_schema['ending'][ 'srt-sg-n'] and stressed or unstressed # local p.endings['srt-sg'] = p.endings['srt-sg'][stress] # end _.ends(module, func)
def init_result(func, i): # export r = i.result # local r['stem_type'] = i.stem.type # for testcases r['stress_type'] = i.stress_type # for categories -- is really used? r['dev'] = dev_prefix index.get_zaliznyak(i) additional_arguments(i) if i.noun: forward_gender_animacy(i) # end if i.adj: if _.contains(i.rest_index, ['⊠', '%(x%)', '%(х%)', '%(X%)', '%(Х%)']): r['краткая'] = '⊠' elif _.contains(i.rest_index, ['✕', '×', 'x', 'х', 'X', 'Х']): r['краткая'] = '✕' elif _.contains(i.rest_index, ['%-', '—', '−']): r['краткая'] = '−' else: r['краткая'] = '1' # end # end if not _.has_key(r, 'error_category') and i.word.cleared != i.base: r['error_category'] = 'Ошибка в шаблоне "сущ-ru" (слово не совпадает с заголовком статьи)' # end forward.forward_args(i) _.ends(module, func)
def angle_brackets(func, i): # export angle_index = _.extract(i.rest_index, '%<([^>]+)%>') # local if angle_index: if not i.pt: i.output_gender = i.gender i.output_animacy = i.animacy # end i.orig_index = i.index i.index = angle_index pt_backup = i.pt # local noun_parse.extract_gender_animacy(i) i.pt = pt_backup if e.has_error(i): return _.ends(module, func) # end _.log_value(i.adj, 'i.adj') if i.adj: # fixme: Для прилагательных надо по-особенному? init_stem.init_stem(i) if e.has_error(i): return _.ends(module, func) # end # end # end _.ends(module, func)
def run_gender(func, i): r = i.result # local if _.contains(i.rest_index, '0'): # todo: move to special function # local keys keys = [ # todo: depend on `calc_sg` and `calc_pl` 'nom-sg', 'gen-sg', 'dat-sg', 'acc-sg', 'ins-sg', 'prp-sg', 'nom-pl', 'gen-pl', 'dat-pl', 'acc-pl', 'ins-pl', 'prp-pl', ] # list for j, key in enumerate(keys): r[key] = i.word.stressed # end return _.ends(module, func) # end p.generate_parts(i) res.generate_result(i) _.ends(module, func)
def run(func, i): # export # todo: move this `if` block inside `run_info` and run it recursively? :) if i.variations: _.log_info("Случай с вариациями '//'") i1 = i.variations[0] # local i2 = i.variations[1] # local run_info(i1) run_info(i2) i.result = v.join_forms(i1.result, i2.result) # todo: form.join_variations() # todo: check for errors inside variations elif i.plus: _.log_info("Случай с '+'") plus = [] # list # local for j, sub_info in enumerate(i.plus): run_info(sub_info) plus.append(sub_info.result) # end i.result = v.plus_forms(plus) # todo: form.plus_out_args() else: _.log_info('Стандартный случай без вариаций') run_info(i) # end if i.noun: noun_forms.special_cases( i) # todo: move to `run/result/generate_result` # end forward.forward_args(i) _.log_table(i.result, "i.result") _.ends(module, func)
def fill_other_pronoun_noun_endings(func, endings): mn_genders = ['m', 'n'] # local # INFO: Replace "ы" to "и" stem_type = '4-sibilant' # local for j, gender in enumerate(mn_genders): endings[gender][stem_type]['ins-sg'] = 'им' # end for j, gender in enumerate(genders): endings[gender][stem_type]['nom-pl'] = 'и' endings[gender][stem_type]['gen-pl'] = 'их' endings[gender][stem_type]['dat-pl'] = 'им' endings[gender][stem_type]['ins-pl'] = 'ими' endings[gender][stem_type]['prp-pl'] = 'их' # end # INFO: Other Replace endings['n'][stem_type]['nom-sg'] = ['е', 'о'] for j, gender in enumerate(mn_genders): endings[gender][stem_type]['gen-sg'] = ['его', 'ого'] endings[gender][stem_type]['dat-sg'] = ['ему', 'ому'] endings[gender][stem_type]['prp-sg'] = ['ем', 'ом'] # end endings['f'][stem_type]['gen-sg'] = ['ей', 'ой'] endings['f'][stem_type]['dat-sg'] = ['ей', 'ой'] endings['f'][stem_type]['ins-sg'] = ['ей', 'ой'] endings['f'][stem_type]['prp-sg'] = ['ей', 'ой'] stem_type = '6-vowel' for j, gender in enumerate(mn_genders): endings[gender][stem_type]['gen-sg'] = 'его' endings[gender][stem_type]['dat-sg'] = 'ему' # end _.ends(module, func)
def apply_adj_specific_1_2(func, i): # export p = i.parts # local if i.calc_sg: if not _.endswith(p.stems['srt-sg'], 'нн'): # todo: log some error? return _.ends(module, func) # end if _.contains(i.rest_index, ['%(1%)', '①']): if i.gender == 'm': _.replace(p.stems, 'srt-sg', 'нн$', 'н') # end # end # end if _.contains(i.rest_index, ['%(2%)', '②']): if i.calc_sg: _.replace(p.stems, 'srt-sg', 'нн$', 'н') # end if i.calc_pl: _.replace(p.stems, 'srt-pl', 'нн$', 'н') # end # end _.ends(module, func)
def loc_case(func, i): # Местный падеж r = i.result # local if _.contains(i.index, 'П2') or _.contains(i.index, 'П₂'): loc = r['dat-sg'] # local loc = _.replaced(loc, '́ ', '') loc = _.replaced(loc, 'ё', 'е') loc = _.replaced(loc, '({vowel})({consonant}*)$', '%1́ %2') loc = remove_stress_if_one_syllable(loc) # = export. r['loc-sg'] = loc loc_prep = _.extract(i.index, 'П2%((.+)%)') # local if not loc_prep: loc_prep = _.extract(i.index, 'П₂%((.+)%)') # end if not loc_prep: loc_prep = 'в, на' # end r['loc-sg'] = '(' + loc_prep + ') ' + r['loc-sg'] if _.contains(i.index, '%[П'): r['loc-sg'] = r['loc-sg'] + ' //<br />' + r['prp-sg'] # end # end if _.has_value(i.args, 'М'): r['loc-sg'] = i.args['М'] # end _.ends(module, func)
def extract_stress_type(func, i): # export # OLD: Старая версия кода: # # local stress_regexp = "([abcdef][′']?[′']?)" # # local stress_regexp2 = '(' + stress_regexp + '.*//.*' + stress_regexp + ')' # stress_regexp = '(' + stress_regexp + '(% ?.*))' # i.stress_type = _.extract(i.rest_index, stress_regexp2) # if not i.stress_type: # i.stress_type = _.extract(i.rest_index, stress_regexp) # # end # local stress_type, allowed_stress_types # INFO: Извлечение ударения из оставшейся части индекса: i.stress_type = _.extract(i.rest_index, "([abcdef][′']?[′']?[/]?[abc]?[′']?[′']?)") # INFO: Замена особых апострофов в ударении на обычные: if i.stress_type: i.stress_type = _.replaced(i.stress_type, '′', "'") # end # INFO: Список допустимых схем ударений: allowed_stress_types = { # todo: special variables for that? 'a', "a'", 'b', "b'", 'c', 'd', "d'", 'e', 'f', "f'", "f''", 'a/a', 'a/b', 'a/c', "a/a'", "a/b'", "a/c'", "a/c''", 'b/a', 'b/b', 'b/c', "b/a'", "b/b'", "b/c'", "b/c''", } # INFO: Если ударение есть и оно не из допустимого списка -- это ошибка if i.stress_type and not _.equals(i.stress_type, allowed_stress_types): e.add_error(i, 'Ошибка: Неправильная схема ударения: ' + i.stress_type) # end _.ends(module, func)
def generate_result(func, i): # export r = i.result # local init_forms.init_forms(i) if i.adj: init_forms.init_srt_forms(i) # end _.log_table(r, 'i.result') common_forms.fix_stress(i) if i.adj and i.calc_pl: # `calc_pl` -- чтобы считать их только один раз, а не для каждого рода adj_forms.add_comparative(i) # end for key, value in r.items(): # replace 'ё' with 'е' when unstressed # if _.contains_once(i.stem.unstressed, 'ё') and _.contains(value, '́ ') and _.contains(i.rest_index, 'ё'): -- trying to bug-fix if _.contains_once(value, 'ё') and _.contains(value, '́ ') and _.contains(i.rest_index, 'ё'): if i.adj and _.contains(i.stress_type, "a'") and i.gender == 'f' and key == 'srt-sg': r[key] = _.replaced(value, 'ё', 'е') + ' // ' + _.replaced(value, '́', '') else: r[key] = _.replaced(value, 'ё', 'е') # обычный случай # end # end # end if i.noun: noun_forms.apply_obelus(i) # end common_forms.choose_accusative_forms(i) common_forms.second_ins_case(i) if i.noun: noun_forms.apply_specific_3(i) # end for key, value in r.items(): # INFO Удаляем ударение, если только один слог: r[key] = noun_forms.remove_stress_if_one_syllable(value) # end if i.adj: if i.postfix: # local keys keys = [ 'nom-sg', 'gen-sg', 'dat-sg', 'acc-sg', 'ins-sg', 'prp-sg', 'nom-pl', 'gen-pl', 'dat-pl', 'acc-pl', 'ins-pl', 'prp-pl', ] # list for j, key in enumerate(keys): r[key] = r[key] + 'ся' # end # end # end _.ends(module, func)
def prt_case(func, i): # Разделительный падеж r = i.result # local if _.contains(i.index, 'Р2') or _.contains(i.index, 'Р₂'): r['prt-sg'] = r['dat-sg'] # end if _.has_value(i.args, 'Р'): r['prt-sg'] = i.args['Р'] # end _.ends(module, func)
def init_srt_forms(func, i): # export # todo move to `init_forms` (with if i.adj) ? p = i.parts # local r = i.result # local if i.calc_sg: r['srt-sg'] = p.stems['srt-sg'] + p.endings['srt-sg'] # end if i.calc_pl: r['srt-pl'] = p.stems['srt-pl'] + p.endings['srt-pl'] # end _.ends(module, func)
def apply_noun_specific_1_2(func, i): # export p = i.parts # local if _.contains(i.rest_index, ['%(1%)', '①']): if i.stem.base_type == '1-hard': if i.gender == 'm': p.endings['nom-pl'] = 'а' # end if i.gender == 'n': p.endings['nom-pl'] = 'ы' # end # end if i.stem.base_type == '2-soft': if i.gender == 'm': p.endings['nom-pl'] = 'я' # end if i.gender == 'n': p.endings['nom-pl'] = 'и' # end # end if _.equals(i.stem.type, ['3-velar', '4-sibilant']): # Replace "ы" to "и" if i.gender == 'n': p.endings['nom-pl'] = 'и' # end # end # end if _.contains(i.rest_index, ['%(2%)', '②']): if i.stem.base_type == '1-hard': if i.gender == 'm': p.endings['gen-pl'] = ['', ''] # end if i.gender == 'n': p.endings['gen-pl'] = ['ов', 'ов'] # end if i.gender == 'f': p.endings['gen-pl'] = {'ей', 'ей'} # end # end if i.stem.base_type == '2-soft': if i.gender == 'm': p.endings['gen-pl'] = ['ь', 'ь'] # end if i.gender == 'n': p.endings['gen-pl'] = ['ев', 'ёв'] # end if i.gender == 'f': p.endings['gen-pl'] = {'ей', 'ей'} # end # end if _.equals( i.stem.type, ['4-sibilant', '5-letter-ц']): # Replace unstressed "о" to "е" if i.gender == 'n': p.endings['gen-pl'][unstressed] = 'ев' # end # end # # Possibly we don't need this: # # Replace "ов", "ев", "ёв" and null to "ей" # if i.stem.type = {'4-sibilant'}} # if i.gender == 'n': p.endings['gen-pl'] = ['ей', 'ей'] # if i.gender == 'm': p.endings['gen-pl'][stressed] = 'ей' # # end # # Replace "ь" to "й" # if i.stem.type = ['6-vowel', '7-letter-и']} # if i.gender == 'm': p.endings['gen-pl'][stressed] = ['й', 'й'] # # end # # Replace "ей" to "ев/ёв", and "ь,ей" to "й" # if i.stem.type = ['6-vowel', '7-letter-и']} # if i.gender == 'f': p.endings['gen-pl'][unstressed] = ['ев', 'ёв'] # if i.gender == 'm': p.endings['gen-pl'][stressed] = ['й', 'й'] # # end # # # end _.ends(module, func)
def prepare(func, i): # export # INFO: Generates `.endings` and `.stems` # todo: logging information endings.get_endings(i) # todo: logging information i.parts.stems = dict() # dict stress_apply.apply_stress_type(i) _.log_table(i.parts.stems, 'i.parts.stems') _.log_table(i.parts.endings, 'i.parts.endings') _.ends(module, func)
def apply_specific_3(func, i): # export r = i.result # local # Специфика по (3) if _.contains(i.rest_index, '%(3%)') or _.contains(i.rest_index, '③'): if _.endswith(r['prp-sg'], 'и'): r['prp-sg'] = r['prp-sg'] + ' //<br />' + _.replaced(r['prp-sg'], 'и$', 'е') # end if i.gender == 'f' and _.endswith(r['dat-sg'], 'и'): r['dat-sg'] = r['dat-sg'] + ' //<br />' + _.replaced(r['dat-sg'], 'и$', 'е') # end # end _.ends(module, func)
def second_ins_case(func, i): # export r = i.result # local # Второй творительный if i.gender == 'f' and i.calc_sg: ins_sg2 = _.replaced(r['ins-sg'], 'й$', 'ю') # local if ins_sg2 != r['ins-sg']: _.log_info( 'Замена "й" на "ю" для второго творительного женского рода') r['ins-sg2'] = ins_sg2 # end # end _.ends(module, func)
def voc_case(func, i): # Звательный падеж r = i.result # local if _.has_value(i.args, 'З'): r['voc-sg'] = i.args['З'] elif _.contains(i.index, 'З'): if _.endswith(i.word.unstressed, ['а', 'я']): r['voc-sg'] = r['gen-pl'] else: r['error'] = 'Ошибка: Для автоматического звательного падежа, слово должно оканчиваться на -а/-я' # end # end _.ends(module, func)
def fix_stress(func, i): # export r = i.result # local # Add stress if there is no one if i.calc_sg and _.contains_several( r['nom-sg'], '{vowel}') and not _.contains(r['nom-sg'], '[́ ё]'): # perhaps this is redundant for nom-sg? _.replace(r, 'nom-sg', '({vowel})({consonant}*)$', '%1́ %2') # end if i.calc_pl and _.contains_several( r['gen-pl'], '{vowel+ё}') and not _.contains(r['gen-pl'], '[́ ё]'): _.replace(r, 'gen-pl', '({vowel})({consonant}*)$', '%1́ %2') # end _.ends(module, func)
def forward_args(func, i): # export # INFO: Используется дважды -- при инициализации, и потом в самом конце # local keys, args r = i.result # local args = i.args keys = [ 'nom-sg', 'gen-sg', 'dat-sg', 'acc-sg', 'ins-sg', 'prp-sg', 'nom-sg2', 'gen-sg2', 'dat-sg2', 'acc-sg2', 'ins-sg2', 'prp-sg2', 'nom-pl', 'gen-pl', 'dat-pl', 'acc-pl', 'ins-pl', 'prp-pl', 'nom-pl2', 'gen-pl2', 'dat-pl2', 'acc-pl2', 'ins-pl2', 'prp-pl2', 'voc-sg', 'loc-sg', 'prt-sg', 'srt-sg-m', 'srt-sg-f', 'srt-sg-n', 'srt-pl', 'comparative', 'comparative2' ] # list for j, key in enumerate(keys): if _.has_value(args, key): if args[key] == '-': r[key] = args[key] else: r[key] = args[key] + '<sup>△</sup>' # end # end # end keys = [ 'П', 'Пр', 'Сч', 'hide-text', 'зачин', 'слоги', 'дореф', 'скл', 'зализняк', 'зализняк1', 'чередование', 'pt', 'st', 'затрудн', 'клитика', 'коммент', 'тип', 'степень', ] # list for j, key in enumerate(keys): if _.has_value(args, key): r[key] = args[key] # end # end if _.has_key(r, 'слоги'): if not _.contains(r['слоги'], '%<'): r['слоги'] = syllables.get_syllables(r['слоги']) # end else: r['слоги'] = i.word.unstressed # fixme: может всё-таки stressed? # end _.ends(module, func)
def choose_accusative_forms(func, i): # export p = i.parts # local r = i.result # local if i.calc_sg: r['acc-sg-in'] = '' # todo: remove this? r['acc-sg-an'] = '' if i.gender == 'm' or (i.gender == 'n' and i.output_gender == 'm'): if i.animacy == 'in': r['acc-sg'] = r['nom-sg'] elif i.animacy == 'an': r['acc-sg'] = r['gen-sg'] else: r['acc-sg-in'] = r['nom-sg'] r['acc-sg-an'] = r['gen-sg'] # end elif i.gender == 'f': if i.stem.type == '8-third': r['acc-sg'] = r['nom-sg'] else: r['acc-sg'] = p.stems['acc-sg'] + p.endings[ 'acc-sg'] # todo: don't use `parts` here? # end elif i.gender == 'n': r['acc-sg'] = r['nom-sg'] # end # end if i.calc_pl: r['acc-pl-in'] = '' # todo: remove this? r['acc-pl-an'] = '' if i.animacy == 'in': r['acc-pl'] = r['nom-pl'] elif i.animacy == 'an': r['acc-pl'] = r['gen-pl'] else: r['acc-pl-in'] = r['nom-pl'] r['acc-pl-an'] = r['gen-pl'] # end # end _.ends(module, func)
def init_stem(func, i): # export # todo rename to `init_stem` # INFO: Исходное слово без ударения: i.word.unstressed = _.replaced(i.word.stressed, '́ ', '') # todo: move outside this function # INFO: Исходное слово вообще без ударений (в т.ч. без грависа): i.word.cleared = _.replaced( _.replaced(_.replaced(i.word.unstressed, '̀', ''), 'ѐ', 'е'), 'ѝ', 'и') if i.adj: if _.endswith(i.word.stressed, 'ся'): i.postfix = True i.stem.unstressed = _.replaced(i.word.unstressed, '{vowel}[йяе]ся$', '') i.stem.stressed = _.replaced(i.word.stressed, '{vowel}́ ?[йяе]ся$', '') else: i.stem.unstressed = _.replaced(i.word.unstressed, '{vowel}[йяе]$', '') i.stem.stressed = _.replaced(i.word.stressed, '{vowel}́ ?[йяе]$', '') # end else: # INFO: Удаляем окончания (-а, -е, -ё, -о, -я, -й, -ь), чтобы получить основу: i.stem.unstressed = _.replaced(i.word.unstressed, '[аеёийоьыя]$', '') i.stem.stressed = _.replaced(i.word.stressed, '[аеёийоьыя]́ ?$', '') # end _.log_value(i.word.unstressed, 'i.word.unstressed') _.log_value(i.stem.unstressed, 'i.stem.unstressed') _.log_value(i.stem.stressed, 'i.stem.stressed') # INFO: Случай, когда не указано ударение у слова: several_vowels = _.contains_several(i.word.stressed, '{vowel+ё}') # local has_stress = _.contains(i.word.stressed, '[́ ё]') # local if several_vowels and not has_stress: _.log_info('Ошибка: Не указано ударение в слове') e.add_error(i, 'Ошибка: Не указано ударение в слове') i.result.error_category = 'Ошибка в шаблоне "сущ-ru" (не указано ударение в слове)' # end _.ends(module, func)
def additional_arguments(func, i): r = i.result # local # RU (склонение) if _.contains(i.rest_index, '0'): r['скл'] = 'не' elif i.adj: r['скл'] = 'а' elif i.pronoun: r['скл'] = 'мс' elif _.endswith(i.word.unstressed, '[ая]'): r['скл'] = '1' else: if i.gender == 'm' or i.gender == 'n': r['скл'] = '2' else: r['скл'] = '3' # end # end # RU (чередование) if _.contains(i.index, '%*'): r['чередование'] = '1' # end if i.pt: r['pt'] = '1' # end # RU ("-" в индексе) # TODO: Здесь может быть глюк, если случай глобального `//` и `rest_index` пуст (а исходный `index` не подходит, т.к. там может быть не тот дефис -- в роде) if i.rest_index: if _.contains(i.rest_index, ['%-', '—', '−']): r['st'] = '1' r['затрудн'] = '1' # end else: pass # TODO # end _.ends(module, func)
def add_comparative(func, i): # export # todo: move to `modify` (и сделать через основы и окончания) r = i.result # local if _.contains(i.rest_index, '~'): r['comparative'] = '-' return _.ends(module, func) # end if i.stem.type == '3-velar': new_stem = i.stem.unstressed if _.endswith(new_stem, 'к'): new_stem = _.replaced(new_stem, 'к$', 'ч') elif _.endswith(new_stem, 'г'): new_stem = _.replaced(new_stem, 'г$', 'ж') elif _.endswith(new_stem, 'х'): new_stem = _.replaced(new_stem, 'х$', 'ш') else: pass # todo: some error here # end # ударение на предпоследний слог: new_stem = _.replaced(new_stem, '({vowel})({consonant}*)$', '%1́ %2') r['comparative'] = new_stem + 'е' else: if _.contains(i.rest_index, ['%(2%)', '②']): # todo: special variable for this r['comparative'] = i.parts.stems['nom-pl'] + 'ее' r['comparative2'] = i.parts.stems['nom-pl'] + 'ей' else: if _.equals(i.stress_type, ['a', 'a/a']): r['comparative'] = i.stem.stressed + 'ее' r['comparative2'] = i.stem.stressed + 'ей' else: r['comparative'] = i.stem.unstressed + 'е́е' r['comparative2'] = i.stem.unstressed + 'е́й' # end # end # end _.ends(module, func)
def forward_gender_animacy(func, i): r = i.result # local # Род: genders = dict(m='муж', f='жен', n='ср', mf='мж', mn='мс', fm='жм', fn='жс', nm='см', nf='сж') # dict # local if i.common_gender: r['род'] = 'общ' elif i.output_gender: r['род'] = genders[i.output_gender] elif i.gender: r['род'] = genders[i.gender] else: pass # end # Одушевлённость: animacies = dict() # dict # local animacies['in'] = 'неодуш' animacies['an'] = 'одуш' animacies['in//an'] = 'неодуш-одуш' animacies['an//in'] = 'одуш-неодуш' if i.output_animacy: r['кат'] = animacies[i.output_animacy] else: r['кат'] = animacies[i.animacy] # end _.ends(module, func)
def get_stress_schema(func, i): # export if _.contains(i.rest_index, '0'): _.log_info('Игнорируем схему ударения для случая "0"') i.stress_schema = dict() # dict return _.ends(module, func) # end unit = '' # todo: get from i.unit ? if i.adj: unit = 'adj' elif i.pronoun: unit = 'pronoun' else: unit = 'noun' # end _.log_value(unit, 'unit') _.log_value(i.unit, 'i.unit') stress_schemas = json_load( '../modules/dev/dev_py/ru/declension/data/stress/' + unit + '.json') stress_schema = stress_schemas[i.stress_type] # local # ручное клонирование схемы ударения, т.к. потом через mw.clone не работает # ошибка: "table from mw.loadData is read-only" i.stress_schema = dict() # dict types = ['stem', 'ending'] # local for j, type in enumerate(types): i.stress_schema[type] = dict() # dict for case, value in stress_schema[type].items(): i.stress_schema[type][case] = value # end # end _.log_table(i.stress_schema['stem'], "i.stress_schema['stem']") _.log_table(i.stress_schema['ending'], "i.stress_schema['ending']") _.ends(module, func)
def special_cases(func, i): # export prt_case(i) loc_case(i) voc_case(i) _.ends(module, func)
def transform(func, i): # export # local stem_stress_schema p = i.parts # local # apply special cases (1) or (2) in index if i.adj: adj_circles.apply_adj_specific_1_2(i) # end # *** для случая с расстановкой ударения (см. ниже) # # local orig_stem = i.stem.unstressed # if _.contains(i.rest_index, ['%(2%)', '②']): # orig_stem = _.replaced(p.stems['gen-pl'], '́ ', '') -- удаляем ударение для случая "сапожок *d(2)" # mw.log('> Another `orig_stem`: ' + str(orig_stem)) # # end # reducable i.rest_index = degree.apply_specific_degree(i) reducable.apply_specific_reducable(i, i.gender, i.rest_index, False) if not _.equals(i.stress_type, ["f", "f'"]) and _.contains( i.rest_index, '%*'): _.log_info( 'Обработка случая на препоследний слог основы при чередовании') orig_stem = i.stem.unstressed if i.forced_stem: orig_stem = i.forced_stem # end for key, stem in p.stems.items(): # mw.log(' - ' + key + ' -> ' + stem) # mw.log('Ударение на основу?') # mw.log(i.stress_schema['stem'][key]) stem_stress_schema = i.stress_schema['stem'] if not _.contains(stem, '[́ ё]') and _.has_key( stem_stress_schema, key) and stem_stress_schema[key]: # *** случай с расстановкой ударения (см. выше) # "Дополнительные правила об ударении", стр. 34 old_value = p.stems[key] # mw.log('> ' + key + ' (old): ' + str(old_value)) if p.stems[ key] != orig_stem: # попытка обработать наличие беглой гласной (не знаю, сработает ли всегда) p.stems[key] = _.replaced( stem, '({vowel})({consonant}*)({vowel})({consonant}*)$', '%1́ %2%3%4') if not _.contains( p.stems[key], '[́ ё]'): # если предпоследнего слога попросту нет # сделаем хоть последний ударным p.stems[key] = _.replaced(stem, '({vowel})({consonant}*)$', '%1́ %2') # end else: p.stems[key] = _.replaced(stem, '({vowel})({consonant}*)$', '%1́ %2') # end # mw.log('> ' + key + ' (new): ' + str(p.stems[key])) mw.log(' - ' + key + ': "' + str(old_value) + '" -> "' + str(p.stems[key]) + '"') # end # end # end if i.calc_pl: # Специфика по "ё" if _.contains(i.rest_index, 'ё') and not _.contains( p.endings['gen-pl'], '{vowel+ё}') and not _.contains( p.stems['gen-pl'], 'ё'): p.stems['gen-pl'] = _.replaced(p.stems['gen-pl'], 'е́?([^е]*)$', 'ё%1') i.rest_index = i.rest_index + 'ё' # ??? # end # end _.ends(module, func)
def apply_obelus(func, i): # export if _.contains(i.rest_index, '÷'): i.result['obelus'] = '1' # end _.ends(module, func)
def parse(func, base, args, frame): # export i = a.AttrDict() # AttrDict # local i.word = a.AttrDict() # AttrDict i.stem = a.AttrDict() # AttrDict i.parts = a.AttrDict() # AttrDict i.result = a.AttrDict() # AttrDict i.result.error = '' i.has_index = True # изначально предполагаем, что индекс есть # INFO: Достаём значения из параметров: i.base = base i.args = args i.frame = frame i.lang = mw.text.trim(args['lang']) i.unit = mw.text.trim(args['unit']) i.index = mw.text.trim(args['индекс']) i.word.stressed = mw.text.trim(args['слово']) i.noun = (i.unit == 'noun') _.log_value(i.index, 'i.index') _.log_value(i.word.stressed, 'i.word.stressed') # mw.log('') # mw.log('==================================================') # mw.log('args: ' + str(i.index) + ' | ' + str(i.word.stressed)) # mw.log('--------------------------------------------------') _.log_info('Получение информации о роде и одушевлённости') if i.noun: # fixme noun_parse.extract_gender_animacy(i) if e.has_error(i): return _.returns(module, func, i) # end # Будем расчитывать оба числа сразу вместе i.calc_sg = True i.calc_pl = True _.log_value(i.gender, 'i.gender') _.log_value(i.animacy, 'i.animacy') _.log_value(i.common_gender, 'i.common_gender') _.log_value(i.adj, 'i.adj') _.log_value(i.pronoun, 'i.pronoun') else: i.gender = '' # fixme i.animacy = '' # fixme i.adj = True # fixme i.rest_index = i.index # fixme # Будем расчитывать позже по отдельности i.calc_sg = False i.calc_pl = False # end _.log_value(i.pt, 'i.pt') _.log_value(i.rest_index, 'i.rest_index') # INFO: stem, stem.stressed, etc. init_stem.init_stem(i) if e.has_error(i): return _.returns(module, func, i) # end if i.noun: # INFO: Случай, если род или одушевлённость не указаны: if (not i.gender or not i.animacy) and not i.pt: # INFO: Не показываем ошибку, просто считаем, что род или одушевлённость *ещё* не указаны return _.returns(module, func, i) # end # end # INFO: Проверяем случай с вариациями: variations = mw.text.split(i.rest_index, '//') # local n_variations = a.table_len(variations) # local if n_variations == 1: # INFO: Дополнительных вариаций нет if _.contains(i.animacy, '//'): # INFO: Случаи 'in//an' и 'an//in' v.process_animacy_variations(i) return _.returns(module, func, i) # TODO: А что если in//an одновременно со следующими случаями "[]" или "+" # end # _.log_info('Случай с "+" (несколько составных частей слова через дефис)') plus_index = mw.text.split(i.rest_index, '%+') # local plus_words = mw.text.split(i.word.stressed, '-') # local n_plus = a.table_len(plus_index) # local if n_plus > 1: v.process_plus(i, plus_words, plus_index) return _.returns(module, func, i) # end if i.noun: angle.angle_brackets(i) if e.has_error(i): return _.returns(module, func, i) # end # end if _.contains(i.rest_index, '%[%([12]%)%]') or _.contains( i.rest_index, '%[[①②]%]'): v.process_brackets_variations(i) return _.returns(module, func, i) # end elif n_variations == 2: # INFO: Вариации "//" для ударения (и прочего индекса) _.log_info('> Случай с вариациями //') if _.contains(i.animacy, '//'): # INFO: Если используются вариации одновременно и отдельно для одушевлённости и ударения e.add_error( i, 'Ошибка: Случай с несколькими "//" пока не реализован. Нужно реализовать?' ) return _.returns(module, func, i) # end v.process_full_variations(i, variations) return _.returns(module, func, i) else: # INFO: Какая-то ошибка, слишком много "//" в индексе e.add_error(i, 'Ошибка: Слишком много частей для "//"') return _.returns(module, func, i) # end _.ends(module, func) return p.process(i)
def get_stem_type(func, i): # export # INFO: Определение типа основы word = i.word.unstressed # local stem = i.stem.unstressed # local i.stem.type = '' if _.endswith(stem, '[гкх]'): i.stem.type = '3-velar' elif _.endswith(stem, '[жчшщ]'): i.stem.type = '4-sibilant' elif _.endswith(stem, 'ц'): i.stem.type = '5-letter-ц' elif _.endswith(stem, ['[йь]', '[аоеёуыэюя]']): i.stem.type = '6-vowel' elif _.endswith(stem, 'и'): i.stem.type = '7-letter-и' else: if i.adj: if _.endswith(word, ['ый', 'ой', 'ая', 'ое', 'ые']): i.stem.type = '1-hard' elif _.endswith(word, ['ий', 'яя', 'ее', 'ие']): i.stem.type = '2-soft' # end elif i.gender == 'm': if stem == word or _.endswith(word, 'ы'): i.stem.type = '1-hard' elif _.endswith(word, 'путь'): i.stem.type = '8-third' elif _.endswith(word, 'ь') or _.endswith(word, 'и'): i.stem.type = '2-soft' elif _.endswith(word, 'а'): i.stem.type = '1-hard' # i.gender = 'f' ?? elif _.endswith(word, 'я'): i.stem.type = '2-soft' # i.gender = 'f' ?? # end elif i.gender == 'f': if _.endswith(word, 'а') or _.endswith(word, 'ы'): i.stem.type = '1-hard' elif _.endswith(word, 'я'): i.stem.type = '2-soft' elif _.endswith(word, 'и') and _.contains( i.rest_index, '2'): # todo: а что если нет индекса?? i.stem.type = '2-soft' elif _.endswith(word, 'и') and _.contains(i.rest_index, '8'): i.stem.type = '8-third' elif _.endswith(word, 'ь'): # conflict in pl i.stem.type = '8-third' # end elif i.gender == 'n': if _.endswith(word, 'о') or _.endswith(word, 'а'): i.stem.type = '1-hard' elif _.endswith(word, 'мя') or _.endswith(word, 'мена'): i.stem.type = '8-third' elif _.endswith(word, 'е') or _.endswith(word, 'я'): i.stem.type = '2-soft' # end # end # end # if gender == 'm': # if _.endswith(word, ['а', 'я']): # i.gender = 'f' # # end # # end if i.gender == 'f' and i.stem.type == '4-sibilant' and _.endswith( word, 'ь'): i.stem.type = '8-third' # end if i.stem.type == '': i.stem.type = '1-hard' # e.add_error(i, 'Неизвестный тип основы') -- fixme ? # return _.ends(module, func) # end # INFO: Выбор подходящего `stem_type` из двух базовых типов: '1-hard' и '2-soft' i.stem.base_type = get_stem_base_type(i) _.ends(module, func)