From 5636ac7523a81c049fd718eab6f9b3c2fba600e8 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Sat, 12 Nov 2022 19:05:50 +0200 Subject: [PATCH 01/13] Add a script that replaces Latin chars with Unicode letters that facilitates reading the Snowball file --- bin/readable_sbl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 bin/readable_sbl diff --git a/bin/readable_sbl b/bin/readable_sbl new file mode 100755 index 00000000..46c4e5a8 --- /dev/null +++ b/bin/readable_sbl @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby + +# Replaces UTF chars and prints SBL files in a more readable way: +# $ bin/readable_sbl ./algorithms/russian.sbl + +# Converts Latin chars into Unicode letters: +# +# define perfective_gerund as ( +# [substring] among ( +# '{v}' +# '{v}{sh}{i}' +# '{v}{sh}{i}{s}{'}' +# ... +# => +# define perfective_gerund as ( +# [substring] among ( +# 'в' +# 'вши' +# 'вшись' +# ... + +def build_chars_map(sbl_file) + chars_hash = {} + File.readlines(sbl_file).each do |line| + char = line.match(/stringdef\s+(\S+)\s+'\{U\+(\S+)\}'/) # E.g.: stringdef zh '{U+0436}' + next if char.nil? + + chars_hash[char[1]] = '' << char[2].to_i(16) # extracts { 'zh': '0436' } => { 'zh': 'ж' } + end + + chars_hash +end + +def readable_sbl_file(sbl_file, chars_map) + File.readlines(sbl_file).map do |line| + readable_line = line + chars_map.each do |latin_letter, real_letter| + readable_line = readable_line.gsub("{#{latin_letter}}", real_letter) + end + readable_line + end.join +end + +sbl_file = ARGV.first.to_s + +puts("Run script with sbl file, e.g.: 'bin/readable_sbl ./algorithms/russian.sbl'") and exit if sbl_file.empty? + +puts("File '#{sbl_file}' doesn't exist") and exit unless File.exist?(sbl_file) + +chars_map = build_chars_map(sbl_file) +puts readable_sbl_file(sbl_file, chars_map) From 65bbdef1f1040e4c9678f4957689977c424896ee Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Thu, 17 Nov 2022 21:42:30 +0200 Subject: [PATCH 02/13] Add Russian stemmer tests and explanation file --- explanations/russian.sbl.explanation | 261 +++++++++++++++++++++++++++ tests/algorithms/Readme.md | 6 + tests/algorithms/russian_test.rb | 128 +++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 explanations/russian.sbl.explanation create mode 100644 tests/algorithms/Readme.md create mode 100644 tests/algorithms/russian_test.rb diff --git a/explanations/russian.sbl.explanation b/explanations/russian.sbl.explanation new file mode 100644 index 00000000..33fd1c85 --- /dev/null +++ b/explanations/russian.sbl.explanation @@ -0,0 +1,261 @@ +stringescapes {} + +/* the 33 Cyrillic letters represented in ASCII characters following the + * conventions of the standard Library of Congress transliteration: */ + +stringdef a '{U+0430}' +stringdef b '{U+0431}' +stringdef v '{U+0432}' +stringdef g '{U+0433}' +stringdef d '{U+0434}' +stringdef e '{U+0435}' +stringdef e" '{U+0451}' +stringdef zh '{U+0436}' +stringdef z '{U+0437}' +stringdef i '{U+0438}' +stringdef i` '{U+0439}' +stringdef k '{U+043A}' +stringdef l '{U+043B}' +stringdef m '{U+043C}' +stringdef n '{U+043D}' +stringdef o '{U+043E}' +stringdef p '{U+043F}' +stringdef r '{U+0440}' +stringdef s '{U+0441}' +stringdef t '{U+0442}' +stringdef u '{U+0443}' +stringdef f '{U+0444}' +stringdef kh '{U+0445}' +stringdef ts '{U+0446}' +stringdef ch '{U+0447}' +stringdef sh '{U+0448}' +stringdef shch '{U+0449}' +stringdef " '{U+044A}' +stringdef y '{U+044B}' +stringdef ' '{U+044C}' +stringdef e` '{U+044D}' +stringdef iu '{U+044E}' +stringdef ia '{U+044F}' + +routines ( mark_regions R2 + perfective_gerund + adjective + adjectival + reflexive + verb + noun + derivational + tidy_up +) + +externals ( stem ) + +integers ( pV p2 ) + +groupings ( v ) + +define v 'аеиоуыэюя' + +define mark_regions as ( + + $pV = limit + $p2 = limit + do ( + gopast v setmark pV gopast non-v + gopast v gopast non-v setmark p2 + ) +) + +backwardmode ( + + define R2 as $p2 <= cursor + + define perfective_gerund as ( + [substring] among ( + 'в' // написа|в проковыля|в + 'вши' // написа|вши заслоня|вши + 'вшись' // написа|вшись обня|вшись + ('а' or 'я' delete) // REGEXP /(.*[ая])вшись|вши|в/ + 'ив' // насыт|ив + 'ивши' // насыт|ивши + 'ившись' // насыт|ившись + 'ыв' // приб|ыв + 'ывши' // приб|ывши + 'ывшись' // приб|ывшись + (delete) // REGEXP /(.*)ывшись|ывши|ыв|ившись|ивши|ив/ + ) + ) + + define adjective as ( + [substring] among ( + 'ее' 'ие' 'ые' 'ое' 'ими' 'ыми' // зелен|ее висевш|ие ароматн|ые испорчен|ое иссохш|ими атласн|ыми + 'ей' 'ий' 'ый' 'ой' 'ем' 'им' // зелен|ей баран|ий аккуратн|ый активн|ой высохш|ем глубок|им + 'ым' 'ом' 'его' 'ого' 'ему' // главн|ым главн|ом бегущ|его главн|ого бывш|ему + 'ому' 'их' 'ых' 'ую' 'юю' 'ая' // богат|ому больш|их бурн|ых бронзов|ую верхн|юю весел|ая + 'яя' // внешн|яя + // and - + 'ою' // - which is somewhat archaic // верн|ою + 'ею' // - soft form of ою // верхн|ею + (delete) + ) + ) + + define adjectival as ( + adjective // cut firstly adjective ending + + /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. + nn, юshch, shch, uюshch can be removed, with a small proportion of + errors. Removing im, uem, enn creates too many errors. + */ + + try ( + [substring] among ( + 'ем' // present passive participle // задава|емые изменя|ем + 'нн' // adjective from past passive participle // беспреста|нно деревя|нными + 'вш' // past active participle // отказа|вшись отделя|вший + 'ющ' 'щ' // present active participle // сталкива|ющихся умоля|ющими спеша|щих блестя|щему + ('а' or 'я' delete) + + // but not 'им' 'уем' // present passive participle + // or 'енн' // adjective from past passive participle + + 'ивш' 'ывш' // past active participle // брод|ивших несб|ывшееся + 'ующ' // present active participle // несуществ|ующий + (delete) + ) + ) + + ) + + define reflexive as ( + [substring] among ( + 'ся' // осек|ся + 'сь' // ввы|сь + (delete) + ) + ) + + define verb as ( + [substring] among ( + 'ла' 'на' 'ете' 'йте' 'ли' 'й' // сдела|ла приня|ла воспита|на потеря|на сдела|ете причиня|ете + // сдела|йте причиня|йте сдела|ли причиня|ли сдела|й причиня|й + 'л' 'ем' 'н' 'ло' 'но' 'ет' 'ют' // сдела|л приня|л воспита|ем потеря|ем сдела|н растеря|н + // сдела|ло причиня|ло сдела|но настоя|но сдела|ет объясня|ет + // сдела|ют объясня|ют + 'ны' 'ть' 'ешь' // сдела|ны потеря|ны сдела|ть потеря|ть сдела|ешь потеря|ешь + + 'нно' // пута|нно постоя|нно + ('а' or 'я' delete) + + 'ила' 'ыла' 'ена' 'ейте' // беспоко|ила прикр|ыла выруч|ена пожал|ейте + 'уйте' 'ите' 'или' 'ыли' 'ей' // пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей + 'уй' 'ил' 'ыл' 'им' 'ым' 'ен' // протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен + 'ило' 'ыло' 'ено' 'ят' 'ует' // став|ило неун|ыло обознач|ено обрат|ят повеств|ует + 'уют' 'ит' 'ыт' 'ены' 'ить' // преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить + 'ыть' 'ишь' 'ую' 'ю' // откр|ыть отправ|ишь отперт|ую отрица|ю + (delete) + /* note the short passive participle tests: + 'на' 'н' 'но' 'ны' + 'ена' 'ен' 'ено' 'ены' + */ + ) + ) + + define noun as ( + [substring] among ( + 'а' 'ев' 'ов' 'ие' 'ье' 'е' // вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е + 'иями' 'ями' 'ами' 'еи' 'ии' // волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии + 'и' 'ией' 'ей' 'ой' 'ий' 'й' // потер|и гармон|ией галере|ей гер|ой ген|ий сара|й + 'иям' 'ям' 'ием' 'ем' 'ам' 'ом' // губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом + 'о' 'у' 'ах' 'иях' 'ях' 'ы' 'ь' // брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь + 'ию' 'ью' 'ю' 'ия' 'ья' 'я' // комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я + (delete) + /* the small class of neuter forms 'ени' 'енем' + 'ена' 'ен' 'енам' 'енами' 'ена{x}' + omitted - they only occur on 12 words. + */ + ) + ) + + define derivational as ( + [substring] R2 among ( + 'ост' // любезностей + 'ость' // любезностью + (delete) + ) + ) + + define tidy_up as ( + [substring] among ( + + 'ейш' // наиполезн|ейший смирен|нейший + 'ейше' // superlative forms // многочислен|нейшее сильн|ейшее + (delete + ['н'] 'н' delete // REGEXP /(.*н)н(ейше|ейш|).*/ + ) + 'н' // смирен|но смирн|о + ('н' delete) // e.g. -nno endings // REGEXP /(.*н)н.*/ + 'ь' // совест|ь + (delete) // with some slight false conflations + ) + ) +) + +define stem as ( + + // Normalise ё to е. The documentation has long suggested the user + // should do this before calling the stemmer - we now do it for them. + do repeat ( goto (['ё']) <- 'е' ) // угнетённый => угнетен + + do mark_regions + backwards setlimit tomark pV for ( + do ( + perfective_gerund or + ( try reflexive + adjectival or verb or noun + ) + ) + try([ 'и' ] delete) // академию => академ + // because noun ending -ию is being treated as verb ending -ю + + do derivational + do tidy_up + ) +) + + + + + + +/* +Russian stemming algorithm: +-------------------------- + +[Step 1] +remove(perfective_gerund) # всплыла ? -> No +OR + remove!(reflexive) # всплыла ? -> No + remove([adjective, adjectival]) # всплыла ? -> No + OR + remove(verb) # вспл|ыла ? -> Yes -> вспл !!But Snowball skips it!! Why?! + OR + remove(noun) + +[Step 2] +remove('и') + +[Step 3] +remove(derivational) + +[Step 4] +remove(tidy_up) + +-------------------------- + +echo "всплыла" | ./stemwords -l ru +=> +всплыл + +Why?! +*/ diff --git a/tests/algorithms/Readme.md b/tests/algorithms/Readme.md new file mode 100644 index 00000000..de7e6535 --- /dev/null +++ b/tests/algorithms/Readme.md @@ -0,0 +1,6 @@ +# Stemmers testing + +For checking the correctness of the stemmer you can run some language test cases, for example: +```sh +ruby ./tests/algorithms/russian_test.rb +``` diff --git a/tests/algorithms/russian_test.rb b/tests/algorithms/russian_test.rb new file mode 100644 index 00000000..39d9e743 --- /dev/null +++ b/tests/algorithms/russian_test.rb @@ -0,0 +1,128 @@ +# Words test set +# https://raw.githubusercontent.com/snowballstem/snowball-data/master/russian/voc.txt + +perfective_gerund = { + 'в' => %w[написа|в проковыля|в], + 'вши' => %w[написа|вши заслоня|вши], + 'вшись' => %w[оберега|вшись обня|вшись], + + 'ив' => %w[насыт|ив], + 'ивши' => %w[насыт|ивши], + 'ившись' => %w[насыт|ившись], + 'ыв' => %w[приб|ыв], + 'ывши' => %w[приб|ывши], + 'ывшись' => %w[незб|ывшись ] +} + +adjective = { + 'ее ие ые ое ими ыми' => %w[зелен|ее висевш|ие ароматн|ые испорчен|ое иссохш|ими атласн|ыми], + 'ей ий ый ой ем им' => %w[зелен|ей баран|ий аккуратн|ый активн|ой высохш|ем глубок|им], + 'ым ом его ого ему' => %w[главн|ым главн|ом бегущ|его главн|ого бывш|ему], + 'ому их ых ую юю ая' => %w[богат|ому больш|их бурн|ых бронзов|ую верхн|юю весел|ая], + 'яя' => %w[внешн|яя], + 'ою' => %w[верн|ою ], + 'ею' => %w[верхн|ею], +} + +adjectival = { + 'ем' => %w[задава|емые изменя|ем], + 'нн' => %w[беспреста|нно деревя|нными], + 'вш' => %w[отказа|вшись отделя|вший], + 'ющ щ' => %w[сталкива|ющихся спеша|щих + умоля|ющими блестя|щему], + + 'ивш ывш' => %w[брод|ивших несб|ывшееся], + 'ующ' => %w[несуществ|ующий] +} + +reflexive = { + 'ся' => %w[осек|ся], + 'сь' => %w[ввы|сь] +} + +verb = { + 'ла на ете йте ли й' => %w[сдела|ла воспита|на сдела|ете сдела|йте сдела|ли сдела|й + приня|ла потеря|на причиня|ете причиня|йте причиня|ли причиня|й], + + 'л ем н ло но ет ют' => %w[сдела|л воспита|ем сдела|н сдела|ло сдела|но сдела|ет сдела|ют + приня|л потеря|ем растеря|н причиня|ло настоя|но объясня|ет объясня|ют], + + 'ны ть ешь' => %w[сдела|ны сдела|ть сдела|ешь + потеря|ны потеря|ть потеря|ешь], + + 'нно' => %w[пута|нно постоя|нно], + + 'ила ыла ена ейте' => %w[беспоко|ила прикр|ыла выруч|ена пожал|ейте вспл|ыла], # вспл|ыла? + 'уйте ите или ыли ей' => %w[пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей], + 'уй ил ыл им ым ен' => %w[протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен], + 'ило ыло ено ят ует' => %w[став|ило неун|ыло обознач|ено обрат|ят повеств|ует], + 'уют ит ыт ены ить' => %w[преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить], + 'ыть ишь ую ю' => %w[откр|ыть отправ|ишь отперт|ую отрица|ю] +} + +noun = { + 'а ев ов ие ье е' => %w[вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е], + 'иями ями ами еи ии' => %w[волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии], + 'и ией ей ой ий й' => %w[потер|и гармон|ией галере|ей гер|ой ген|ий сара|й], + 'иям ям ием ем ам ом' => %w[губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом], + 'о у ах иях ях ы ь' => %w[брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь], + 'ию ью ю ия ья я' => %w[комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я] +} + +derivational = { + 'ост' => %w[любезн|остей], + 'ость' => %w[любезн|остью] +} + +tidy_up = { + 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], + 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], + 'н[н]' => %w[смирен|но смирн|о], + 'ь' => %w[совест|ь] +} + +exceptions = { + # ё => е + 'угнетённый' => 'угнетен', + + # -ию => '' + 'академию' => 'академ' +} + +$all_tests = [] +$errors = [] + +def incorrect_stem_msg(result_stem, word, stem) + "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" +end + +def check_words_set(words_set) + words_set.each do |_rule, test_cases| + test_cases.each do |test_case| + stem, ending = test_case.split('|') + word = [stem, ending].join + $all_tests << word + result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip + $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem + end + end +end + +[ + perfective_gerund, + adjective, + adjectival, + reflexive, + verb, + noun, + derivational, + tidy_up +].each {|words_set| check_words_set(words_set) } + +exceptions.each do |word, stem| + $all_tests << word + result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip + $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem +end + +$errors.empty? ? puts("#{$all_tests.count} test(s) passed successfully!") : puts($errors.join("\n")) From 8fd413883aad79cf346df34b8a167e776ae55b66 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Mon, 12 Dec 2022 20:44:58 +0200 Subject: [PATCH 03/13] Add Ukrainian stemmer --- libstemmer/modules.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libstemmer/modules.txt b/libstemmer/modules.txt index 6940fd17..86ac673f 100644 --- a/libstemmer/modules.txt +++ b/libstemmer/modules.txt @@ -36,6 +36,7 @@ spanish UTF_8,ISO_8859_1 spanish,es,esl,spa swedish UTF_8,ISO_8859_1 swedish,sv,swe tamil UTF_8 tamil,ta,tam turkish UTF_8 turkish,tr,tur +ukrainian UTF_8 ukrainian,uk,ukr yiddish UTF_8 yiddish,yi,yid # Also include the traditional porter algorithm for english. From 940a1fe530dd282c214199e8cbf89cdd6735319c Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Tue, 10 Jan 2023 20:55:10 +0200 Subject: [PATCH 04/13] Add Ukrainian stemmer --- algorithms/ukrainian.sbl | 223 +++++++++++++++++++++++++++++ tests/algorithms/ukrainian_test.rb | 129 +++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 algorithms/ukrainian.sbl create mode 100644 tests/algorithms/ukrainian_test.rb diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl new file mode 100644 index 00000000..ae65bb71 --- /dev/null +++ b/algorithms/ukrainian.sbl @@ -0,0 +1,223 @@ +stringescapes {} + +/* the 33 Ukrainian letters and apostrophe represented by single quote */ + +stringdef a '{U+0430}' +stringdef b '{U+0431}' +stringdef v '{U+0432}' +stringdef gh '{U+0433}' +stringdef g '{U+0491}' +stringdef d '{U+0434}' +stringdef e '{U+0435}' +stringdef ye '{U+0454}' +stringdef zh '{U+0436}' +stringdef z '{U+0437}' +stringdef y '{U+0438}' +stringdef i '{U+0456}' +stringdef yi '{U+0457}' +stringdef i` '{U+0439}' +stringdef k '{U+043A}' +stringdef l '{U+043B}' +stringdef m '{U+043C}' +stringdef n '{U+043D}' +stringdef o '{U+043E}' +stringdef p '{U+043F}' +stringdef r '{U+0440}' +stringdef s '{U+0441}' +stringdef t '{U+0442}' +stringdef u '{U+0443}' +stringdef f '{U+0444}' +stringdef kh '{U+0445}' +stringdef ts '{U+0446}' +stringdef ch '{U+0447}' +stringdef sh '{U+0448}' +stringdef shch '{U+0449}' +stringdef soft '{U+044C}' +stringdef iu '{U+044E}' +stringdef ia '{U+044F}' +stringdef apostrophe '{U+0027}' + +routines ( mark_regions R2 + // perfective_gerund + adjective + adjectival + // reflexive + // verb + // noun + // derivational + // tidy_up +) + +externals ( stem ) + +integers ( pV p2 ) + +groupings ( v ) + +define v '{a}{e}{ye}{y}{i}{yi}{o}{u}{iu}{ia}' + +define mark_regions as ( + + $pV = limit + $p2 = limit + do ( + gopast v setmark pV gopast non-v + gopast v gopast non-v setmark p2 + ) +) + +backwardmode ( + + define R2 as $p2 <= cursor + + // define perfective_gerund as ( + // [substring] among ( + // // '{v}' + // // '{v}{sh}{i}' + // // '{v}{sh}{i}{s}{'}' + // // ('{a}' or '{ia}' delete) + // // '{i}{v}' + // // '{i}{v}{sh}{i}' + // // '{i}{v}{sh}{i}{s}{'}' + // // '{y}{v}' + // // '{y}{v}{sh}{i}' + // // '{y}{v}{sh}{i}{s}{'}' + // // (delete) + // ) + // ) + + define adjective as ( + [substring] among ( + '{soft}{o}{gh}{o}' + (delete) + // '{e}{e}' '{i}{e}' '{y}{e}' '{o}{e}' '{i}{m}{i}' '{y}{m}{i}' + // '{e}{i`}' '{i}{i`}' '{y}{i`}' '{o}{i`}' '{e}{m}' '{i}{m}' + // '{y}{m}' '{o}{m}' '{e}{g}{o}' '{o}{g}{o}' '{e}{m}{u}' + // '{o}{m}{u}' '{i}{kh}' '{y}{kh}' '{u}{iu}' '{iu}{iu}' '{a}{ia}' + // '{ia}{ia}' + // // and - + // '{o}{iu}' // - which is somewhat archaic + // '{e}{iu}' // - soft form of {o}{iu} + // (delete) + ) + ) + + define adjectival as ( + adjective + + /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. + nn, {iu}shch, shch, u{iu}shch can be removed, with a small proportion of + errors. Removing im, uem, enn creates too many errors. + */ + + // try ( + // [substring] among ( + // // '{e}{m}' // present passive participle + // // '{n}{n}' // adjective from past passive participle + // // '{v}{sh}' // past active participle + // // '{iu}{shch}' '{shch}' // present active participle + // // ('{a}' or '{ia}' delete) + + // // //but not '{i}{m}' '{u}{e}{m}' // present passive participle + // // //or '{e}{n}{n}' // adjective from past passive participle + + // // '{i}{v}{sh}' '{y}{v}{sh}'// past active participle + // // '{u}{iu}{shch}' // present active participle + // // (delete) + // ) + // ) + + ) + + // define reflexive as ( + // [substring] among ( + // // '{s}{ia}' + // // '{s}{'}' + // // (delete) + // ) + // ) + + // define verb as ( + // [substring] among ( + // // '{l}{a}' '{n}{a}' '{e}{t}{e}' '{i`}{t}{e}' '{l}{i}' '{i`}' + // // '{l}' '{e}{m}' '{n}' '{l}{o}' '{n}{o}' '{e}{t}' '{iu}{t}' + // // '{n}{y}' '{t}{'}' '{e}{sh}{'}' + + // // '{n}{n}{o}' + // // ('{a}' or '{ia}' delete) + + // // '{i}{l}{a}' '{y}{l}{a}' '{e}{n}{a}' '{e}{i`}{t}{e}' + // // '{u}{i`}{t}{e}' '{i}{t}{e}' '{i}{l}{i}' '{y}{l}{i}' '{e}{i`}' + // // '{u}{i`}' '{i}{l}' '{y}{l}' '{i}{m}' '{y}{m}' '{e}{n}' + // // '{i}{l}{o}' '{y}{l}{o}' '{e}{n}{o}' '{ia}{t}' '{u}{e}{t}' + // // '{u}{iu}{t}' '{i}{t}' '{y}{t}' '{e}{n}{y}' '{i}{t}{'}' + // // '{y}{t}{'}' '{i}{sh}{'}' '{u}{iu}' '{iu}' + // // (delete) + // /* note the short passive participle tests: + // '{n}{a}' '{n}' '{n}{o}' '{n}{y}' + // '{e}{n}{a}' '{e}{n}' '{e}{n}{o}' '{e}{n}{y}' + // */ + // ) + // ) + + // define noun as ( + // [substring] among ( + // // '{a}' '{e}{v}' '{o}{v}' '{i}{e}' '{'}{e}' '{e}' + // // '{i}{ia}{m}{i}' '{ia}{m}{i}' '{a}{m}{i}' '{e}{i}' '{i}{i}' + // // '{i}' '{i}{e}{i`}' '{e}{i`}' '{o}{i`}' '{i}{i`}' '{i`}' + // // '{i}{ia}{m}' '{ia}{m}' '{i}{e}{m}' '{e}{m}' '{a}{m}' '{o}{m}' + // // '{o}' '{u}' '{a}{kh}' '{i}{ia}{kh}' '{ia}{kh}' '{y}' '{'}' + // // '{i}{iu}' '{'}{iu}' '{iu}' '{i}{ia}' '{'}{ia}' '{ia}' + // // (delete) + // /* the small class of neuter forms '{e}{n}{i}' '{e}{n}{e}{m}' + // '{e}{n}{a}' '{e}{n}' '{e}{n}{a}{m}' '{e}{n}{a}{m}{i}' '{e}{n}{a}{x}' + // omitted - they only occur on 12 words. + // */ + // ) + // ) + + // define derivational as ( + // [substring] R2 among ( + // // '{o}{s}{t}' + // // '{o}{s}{t}{'}' + // // (delete) + // ) + // ) + + // define tidy_up as ( + // [substring] among ( + // // '{e}{i`}{sh}' + // // '{e}{i`}{sh}{e}' // superlative forms + // // (delete + // // ['{n}'] '{n}' delete + // // ) + // // '{n}' + // // ('{n}' delete) // e.g. -nno endings + // // '{'}' + // // (delete) // with some slight false conflations + // ) + // ) +) + +define stem as ( + + // Normalise {e"} to {e}. The documentation has long suggested the user + // should do this before calling the stemmer - we now do it for them. + // do repeat ( goto (['{e"}']) <- '{e}' ) + + do mark_regions + backwards setlimit tomark pV for ( + do ( + adjectival + // perfective_gerund or + // ( try reflexive + // adjectival or verb or noun + // ) + ) + // try([ '{i}' ] delete) + // because noun ending -i{iu} is being treated as verb ending -{iu} + + // do derivational + // do tidy_up + ) +) diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb new file mode 100644 index 00000000..4ee607c1 --- /dev/null +++ b/tests/algorithms/ukrainian_test.rb @@ -0,0 +1,129 @@ +# Words test set +# https://raw.githubusercontent.com/snowballstem/snowball-data/master/russian/voc.txt + +# Граматика української мови +# https://uk.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0_%D1%83%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D1%81%D1%8C%D0%BA%D0%BE%D1%97_%D0%BC%D0%BE%D0%B2%D0%B8 + +perfective_gerund = { # DONE + 'в' => %w[подола|в підня|в], + 'вши' => %w[написа|вши підня|вши], + 'вшись' => %w[абсолютизува|вшись підня|вшись], + + 'ивши' => %w[дзвон|ивши], + 'ившись' => %w[дзвон|ившись], + 'ув' => %w[приб|ув], + 'увши' => %w[приб|увши], + 'увшись' => %w[дотикн|увшись] +} + +adjective = { # DONE + 'іше іє і е ими' => %w[зелен|іше послан|іє ароматн|і зіпсован|е зіпсован|ими], + 'іший ий ій им' => %w[зелен|іший зелен|ий великодн|ій глибок|им], # noun: ой =>палеоз|ой perfective_gerund: ем => похапц|ем + 'ого' => %w[ головн|ого ], # noun ім => екстр|ім ом => заїзд|ом + 'ому их у я а' => %w[веснян|ому зелен|их бронзов|у верхн|я весел|а], # !по-весняному? + 'ою' => %w[веснян|ою ], + # noun 'ею' => %w[земл|ею], +} + +adjectival = { + 'ем' => %w[задава|емые изменя|ем], + 'нн' => %w[беспреста|нно деревя|нными], + 'вш' => %w[отказа|вшись отделя|вший], + 'ющ щ' => %w[сталкива|ющихся спеша|щих + умоля|ющими блестя|щему], + + 'ивш ывш' => %w[брод|ивших несб|ывшееся], + 'ующ' => %w[несуществ|ующий] +} + +reflexive = { + 'ся' => %w[осек|ся], + 'сь' => %w[ввы|сь] +} + +verb = { + 'ла на ете йте ли й' => %w[сдела|ла воспита|на сдела|ете сдела|йте сдела|ли сдела|й + приня|ла потеря|на причиня|ете причиня|йте причиня|ли причиня|й], + + 'л ем н ло но ет ют' => %w[сдела|л воспита|ем сдела|н сдела|ло сдела|но сдела|ет сдела|ют + приня|л потеря|ем растеря|н причиня|ло настоя|но объясня|ет объясня|ют], + + 'ны ть ешь' => %w[сдела|ны сдела|ть сдела|ешь + потеря|ны потеря|ть потеря|ешь], + + 'нно' => %w[пута|нно постоя|нно], + + 'ила ыла ена ейте' => %w[беспоко|ила прикр|ыла выруч|ена пожал|ейте вспл|ыла], # вспл|ыла? + 'уйте ите или ыли ей' => %w[пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей], + 'уй ил ыл им ым ен' => %w[протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен], + 'ило ыло ено ят ует' => %w[став|ило неун|ыло обознач|ено обрат|ят повеств|ует], + 'уют ит ыт ены ить' => %w[преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить], + 'ыть ишь ую ю' => %w[откр|ыть отправ|ишь отперт|ую отрица|ю] +} + +noun = { + 'а ев ов ие ье е' => %w[вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е], + 'иями ями ами еи ии' => %w[волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии], + 'и ией ей ой ий й' => %w[потер|и гармон|ией галере|ей гер|ой ген|ий сара|й], + 'иям ям ием ем ам ом' => %w[губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом], + 'о у ах иях ях ы ь' => %w[брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь], + 'ию ью ю ия ья я' => %w[комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я] +} + +derivational = { + 'ост' => %w[любезн|остей], + 'ость' => %w[любезн|остью] +} + +tidy_up = { + 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], + 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], + 'н[н]' => %w[смирен|но смирн|о], + 'ь' => %w[совест|ь] +} + +exceptions = { + # ё => е + 'угнетённый' => 'угнетен', + + # -ию => '' + 'академию' => 'академ' +} + +$all_tests = [] +$errors = [] + +def incorrect_stem_msg(result_stem, word, stem) + "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" +end + +def check_words_set(words_set) + words_set.each do |_rule, test_cases| + test_cases.each do |test_case| + stem, ending = test_case.split('|') + word = [stem, ending].join + $all_tests << word + result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip + $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem + end + end +end + +[ + perfective_gerund, + adjective, + # adjectival, + # reflexive, + # verb, + # noun, + # derivational, + # tidy_up +].each {|words_set| check_words_set(words_set) } + +# exceptions.each do |word, stem| +# $all_tests << word +# result_stem = (`echo "#{word}" | ./stemwords -l uk`).strip +# $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem +# end + +$errors.empty? ? puts("#{$all_tests.count} test(s) passed successfully!") : puts($errors.join("\n")) From feaf1258e11e23cd138bd5eeb84135fadfabac4a Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Tue, 10 Jan 2023 21:57:47 +0200 Subject: [PATCH 05/13] Add Ukrainian stemmer --- bin/readable_sbl | 8 +- bin/utf_to_sbl | 56 +++++++++ explanations/ukrainian.sbl.utf | 223 +++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100755 bin/utf_to_sbl create mode 100755 explanations/ukrainian.sbl.utf diff --git a/bin/readable_sbl b/bin/readable_sbl index 46c4e5a8..ac0163b9 100755 --- a/bin/readable_sbl +++ b/bin/readable_sbl @@ -21,11 +21,17 @@ def build_chars_map(sbl_file) chars_hash = {} + exceptions = ["'"] # apostrophe + File.readlines(sbl_file).each do |line| char = line.match(/stringdef\s+(\S+)\s+'\{U\+(\S+)\}'/) # E.g.: stringdef zh '{U+0436}' next if char.nil? - chars_hash[char[1]] = '' << char[2].to_i(16) # extracts { 'zh': '0436' } => { 'zh': 'ж' } + latin = char[1] + utf = '' << char[2].to_i(16) + next unless exceptions.index(utf).nil? + + chars_hash[latin] = utf # extracts { 'zh': '0436' } => { 'zh': 'ж' } end chars_hash diff --git a/bin/utf_to_sbl b/bin/utf_to_sbl new file mode 100755 index 00000000..f43cf717 --- /dev/null +++ b/bin/utf_to_sbl @@ -0,0 +1,56 @@ +#!/usr/bin/env ruby + +# Replaces Latin chars and prints SBL file: +# $ bin/utf_to_sbl ./explanations/ukrainian.sbl.utf + +# Converts Unicode chars into Latin letters: +# +# define perfective_gerund as ( +# [substring] among ( +# 'вши' +# 'вшись' +# ... +# => +# define perfective_gerund as ( +# [substring] among ( +# '{v}{sh}{i}' +# '{v}{sh}{i}{s}{'}' +# ... + + +def build_chars_map(utf_file) + chars_hash = {} + exceptions = ["'"] # apostrophe + + File.readlines(utf_file).each do |line| + char = line.match(/stringdef\s+(\S+)\s+'\{U\+(\S+)\}'/) # E.g.: stringdef zh '{U+0436}' + next if char.nil? + + latin = char[1] + utf = '' << char[2].to_i(16) + next unless exceptions.index(utf).nil? + + chars_hash[utf] = latin # extracts { 'zh': '0436' } => { 'ж': 'zh' } + end + + chars_hash +end + +def readable_sbl_file(utf_file, chars_map) + File.readlines(utf_file).map do |line| + readable_line = line + chars_map.each do |real_letter, latin_letter| + readable_line = readable_line.gsub(real_letter, "{#{latin_letter}}") + end + readable_line + end.join +end + +utf_file = ARGV.first.to_s + +puts("Run script with 'utf' file, e.g.: 'bin/utf_to_sbl ./explanations/ukrainian.sbl.utf'") and exit if utf_file.empty? + +puts("File '#{utf_file}' doesn't exist") and exit unless File.exist?(utf_file) + +chars_map = build_chars_map(utf_file) +puts readable_sbl_file(utf_file, chars_map) diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf new file mode 100755 index 00000000..d35e0d7b --- /dev/null +++ b/explanations/ukrainian.sbl.utf @@ -0,0 +1,223 @@ +stringescapes {} + +/* the 33 Ukrainian letters and apostrophe represented by single quote */ + +stringdef a '{U+0430}' +stringdef b '{U+0431}' +stringdef v '{U+0432}' +stringdef gh '{U+0433}' +stringdef g '{U+0491}' +stringdef d '{U+0434}' +stringdef e '{U+0435}' +stringdef ye '{U+0454}' +stringdef zh '{U+0436}' +stringdef z '{U+0437}' +stringdef y '{U+0438}' +stringdef i '{U+0456}' +stringdef yi '{U+0457}' +stringdef i` '{U+0439}' +stringdef k '{U+043A}' +stringdef l '{U+043B}' +stringdef m '{U+043C}' +stringdef n '{U+043D}' +stringdef o '{U+043E}' +stringdef p '{U+043F}' +stringdef r '{U+0440}' +stringdef s '{U+0441}' +stringdef t '{U+0442}' +stringdef u '{U+0443}' +stringdef f '{U+0444}' +stringdef kh '{U+0445}' +stringdef ts '{U+0446}' +stringdef ch '{U+0447}' +stringdef sh '{U+0448}' +stringdef shch '{U+0449}' +stringdef soft '{U+044C}' +stringdef iu '{U+044E}' +stringdef ia '{U+044F}' +stringdef apostrophe '{U+0027}' + +routines ( mark_regions R2 + // perfective_gerund + adjective + adjectival + // reflexive + // verb + // noun + // derivational + // tidy_up +) + +externals ( stem ) + +integers ( pV p2 ) + +groupings ( v ) + +define v 'аеєиіїоуюя' + +define mark_regions as ( + + $pV = limit + $p2 = limit + do ( + gopast v setmark pV gopast non-v + gopast v gopast non-v setmark p2 + ) +) + +backwardmode ( + + define R2 as $p2 <= cursor + + // define perfective_gerund as ( + // [substring] among ( + // // 'в' + // // 'вші' + // // 'вшіс{'}' + // // ('а' or 'я' delete) + // // 'ів' + // // 'івші' + // // 'івшіс{'}' + // // 'ив' + // // 'ивші' + // // 'ившіс{'}' + // // (delete) + // ) + // ) + + define adjective as ( + [substring] among ( + 'ього' + (delete) + // 'ее' 'іе' 'ие' 'ое' 'імі' 'имі' + // 'ей' 'ій' 'ий' 'ой' 'ем' 'ім' + // 'им' 'ом' 'еґо' 'оґо' 'ему' + // 'ому' 'іх' 'их' 'ую' 'юю' 'ая' + // 'яя' + // // and - + // 'ою' // - which is somewhat archaic + // 'ею' // - soft form of ою + // (delete) + ) + ) + + define adjectival as ( + adjective + + /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. + nn, юshch, shch, uюshch can be removed, with a small proportion of + errors. Removing im, uem, enn creates too many errors. + */ + + // try ( + // [substring] among ( + // // 'ем' // present passive participle + // // 'нн' // adjective from past passive participle + // // 'вш' // past active participle + // // 'ющ' 'щ' // present active participle + // // ('а' or 'я' delete) + + // // //but not 'ім' 'уем' // present passive participle + // // //or 'енн' // adjective from past passive participle + + // // 'івш' 'ивш'// past active participle + // // 'ующ' // present active participle + // // (delete) + // ) + // ) + + ) + + // define reflexive as ( + // [substring] among ( + // // 'ся' + // // 'с{'}' + // // (delete) + // ) + // ) + + // define verb as ( + // [substring] among ( + // // 'ла' 'на' 'ете' 'йте' 'лі' 'й' + // // 'л' 'ем' 'н' 'ло' 'но' 'ет' 'ют' + // // 'ни' 'т{'}' 'еш{'}' + + // // 'нно' + // // ('а' or 'я' delete) + + // // 'іла' 'ила' 'ена' 'ейте' + // // 'уйте' 'іте' 'ілі' 'илі' 'ей' + // // 'уй' 'іл' 'ил' 'ім' 'им' 'ен' + // // 'іло' 'ило' 'ено' 'ят' 'ует' + // // 'уют' 'іт' 'ит' 'ени' 'іт{'}' + // // 'ит{'}' 'іш{'}' 'ую' 'ю' + // // (delete) + // /* note the short passive participle tests: + // 'на' 'н' 'но' 'ни' + // 'ена' 'ен' 'ено' 'ени' + // */ + // ) + // ) + + // define noun as ( + // [substring] among ( + // // 'а' 'ев' 'ов' 'іе' '{'}е' 'е' + // // 'іямі' 'ямі' 'амі' 'еі' 'іі' + // // 'і' 'іей' 'ей' 'ой' 'ій' 'й' + // // 'іям' 'ям' 'іем' 'ем' 'ам' 'ом' + // // 'о' 'у' 'ах' 'іях' 'ях' 'и' '{'}' + // // 'ію' '{'}ю' 'ю' 'ія' '{'}я' 'я' + // // (delete) + // /* the small class of neuter forms 'ені' 'енем' + // 'ена' 'ен' 'енам' 'енамі' 'ена{x}' + // omitted - they only occur on 12 words. + // */ + // ) + // ) + + // define derivational as ( + // [substring] R2 among ( + // // 'ост' + // // 'ост{'}' + // // (delete) + // ) + // ) + + // define tidy_up as ( + // [substring] among ( + // // 'ейш' + // // 'ейше' // superlative forms + // // (delete + // // ['н'] 'н' delete + // // ) + // // 'н' + // // ('н' delete) // e.g. -nno endings + // // '{'}' + // // (delete) // with some slight false conflations + // ) + // ) +) + +define stem as ( + + // Normalise {e"} to е. The documentation has long suggested the user + // should do this before calling the stemmer - we now do it for them. + // do repeat ( goto (['{e"}']) <- 'е' ) + + do mark_regions + backwards setlimit tomark pV for ( + do ( + adjectival + // perfective_gerund or + // ( try reflexive + // adjectival or verb or noun + // ) + ) + // try([ 'і' ] delete) + // because noun ending -iю is being treated as verb ending -ю + + // do derivational + // do tidy_up + ) +) From 8ffe9a0b332bb7f974083e4c41086b8b0855e482 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Sun, 4 Jun 2023 17:58:51 +0300 Subject: [PATCH 06/13] Add Ukrainian stemmer --- algorithms/ukrainian.sbl | 303 +++++++++++++++++++-------- explanations/russian.sbl.explanation | 4 +- explanations/ukrainian.sbl.utf | 303 +++++++++++++++++++-------- runtime/utilities.c | 4 +- tests/algorithms/russian_test.rb | 2 +- tests/algorithms/ukrainian_test.rb | 240 ++++++++++++++------- 6 files changed, 588 insertions(+), 268 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index ae65bb71..368a341f 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -38,12 +38,12 @@ stringdef ia '{U+044F}' stringdef apostrophe '{U+0027}' routines ( mark_regions R2 - // perfective_gerund + perfective_gerund adjective adjectival - // reflexive - // verb - // noun + reflexive + verb + noun // derivational // tidy_up ) @@ -70,35 +70,62 @@ backwardmode ( define R2 as $p2 <= cursor - // define perfective_gerund as ( - // [substring] among ( - // // '{v}' - // // '{v}{sh}{i}' - // // '{v}{sh}{i}{s}{'}' - // // ('{a}' or '{ia}' delete) - // // '{i}{v}' - // // '{i}{v}{sh}{i}' - // // '{i}{v}{sh}{i}{s}{'}' - // // '{y}{v}' - // // '{y}{v}{sh}{i}' - // // '{y}{v}{sh}{i}{s}{'}' - // // (delete) - // ) - // ) + define perfective_gerund as ( + [substring] among ( + // '{v}' + // '{v}{sh}{i}' + // '{v}{sh}{i}{s}{'}' + // ('{a}' or '{ia}' delete) + // '{i}{v}' + // '{i}{v}{sh}{i}' + // '{i}{v}{sh}{i}{s}{'}' + // '{y}{v}' + // '{y}{v}{sh}{i}' + // '{y}{v}{sh}{i}{s}{'}' + // (delete) + + '{v}' // {d}{o}{n}{a}{p}{y}{s}{a}|{v} {d}{o}{r}{o}{b}{y}|{v} {d}{o}{r}{o}{b}{y}|{v} + '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} {z}{r}{o}{b}{y}|{v}{sh}{y} + '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} + '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} + // ('{a}' or '{ia}' delete) + '{u}{ch}{y}' // {p}{y}{sh}|{u}{ch}{y} {r}{e}{v}|{u}{ch}{y} + '{iu}{ch}{y}' // {s}{ia}|{iu}{ch}{y} {p}{i}{d}{p}{y}{s}{u}|{iu}{ch}{y} + '{iu}{ch}{y}{s}{soft}' // {z}{m}{a}{gh}{a}|{iu}{ch}{y}{s}{soft} + '{iu}{ch}{y}{s}{ia}' // {n}{a}{v}{ch}{a}|{iu}{ch}{y}{s}{ia} + '{a}{ch}{y}' // {b}{a}{ch}|{a}{ch}{y} + '{a}{ch}{y}{s}{soft}' // {b}{a}{ch}|{a}{ch}{y}{s}{soft} + '{a}{ch}{y}{s}{ia}' // {b}{a}{ch}|{a}{ch}{y}{s}{ia} + '{l}{ia}{ch}{y}' // {r}{o}{b}|{l}{ia}{ch}{y} {l}{iu}{b}|{l}{ia}{ch}{y} + '{l}{ia}{ch}{y}{s}{soft}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{soft} + '{l}{ia}{ch}{y}{s}{ia}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{ia} + '{ia}{ch}{y}' // {s}{y}{d}|{ia}{ch}{y} {v}{o}{v}{t}{u}{z}|{ia}{ch}{y} + '{ia}{ch}{y}{s}{soft}' // + '{ia}{ch}{y}{s}{ia}' // + (delete) + ) + ) define adjective as ( [substring] among ( - '{soft}{o}{gh}{o}' - (delete) // '{e}{e}' '{i}{e}' '{y}{e}' '{o}{e}' '{i}{m}{i}' '{y}{m}{i}' - // '{e}{i`}' '{i}{i`}' '{y}{i`}' '{o}{i`}' '{e}{m}' '{i}{m}' - // '{y}{m}' '{o}{m}' '{e}{g}{o}' '{o}{g}{o}' '{e}{m}{u}' - // '{o}{m}{u}' '{i}{kh}' '{y}{kh}' '{u}{iu}' '{iu}{iu}' '{a}{ia}' - // '{ia}{ia}' - // // and - - // '{o}{iu}' // - which is somewhat archaic + // '{e}{i`}' '{o}{i`}' '{e}{m}' + // '{o}{m}' '{e}{g}{o}' '{o}{g}{o}' '{e}{m}{u}' + // '{u}{iu}' '{iu}{iu}' '{a}{ia}' // '{e}{iu}' // - soft form of {o}{iu} // (delete) + + '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' // {z}{e}{l}{e}{n}|{y}{i`} {z}{e}{l}{e}{n}|{o}{gh}{o} {z}{e}{l}{e}{n}|{o}{m}{u} {z}{e}{l}{e}{n}|{y}{m} {z}{e}{l}{e}{n}|{i}{m} + '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' // {z}{e}{l}{e}{n}|{i}{sh}{y}{i`} {z}{e}{l}{e}{n}|{i}{sh}{o}{gh}{o} {z}{e}{l}{e}{n}|{i}{sh}{o}{m}{u} {z}{e}{l}{e}{n}|{i}{sh}{y}{m} {z}{e}{l}{e}{n}|{i}{sh}{i}{m} + '{e}' '{i}{sh}{e}' // {z}{e}{l}{e}{n}|{e} {z}{e}{l}{e}{n}|{i}{sh}{e} + '{a}' '{o}{yi}' '{i}{i`}' '{u}' '{o}{iu}' // {z}{e}{l}{e}{n}|{a} {z}{e}{l}{e}{n}|{o}{yi} {z}{e}{l}{e}{n}|{i}{i`} {z}{e}{l}{e}{n}|{u} {z}{e}{l}{e}{n}|{o}{iu} + '{i}{sh}{a}' '{i}{sh}{o}{yi}' '{i}{sh}{i}{i`}' '{i}{sh}{u}' '{i}{sh}{o}{iu}' // {z}{e}{l}{e}{n}|{i}{sh}{a} {z}{e}{l}{e}{n}|{i}{sh}{o}{yi} {z}{e}{l}{e}{n}|{i}{sh}{i}{i`} {z}{e}{l}{e}{n}|{i}{sh}{u} {z}{e}{l}{e}{n}|{i}{sh}{o}{iu} + '{i}' '{y}{kh}' '{y}{m}{y}' // {z}{e}{l}{e}{n}|{i} {z}{e}{l}{e}{n}|{y}{kh} {z}{e}{l}{e}{n}|{y}{m}{y} + '{i}{sh}{i}' '{i}{sh}{y}{kh}' '{i}{sh}{y}{m}{y}' // {z}{e}{l}{e}{n}|{i}{sh}{i} {z}{e}{l}{e}{n}|{i}{sh}{y}{kh} {z}{e}{l}{e}{n}|{i}{sh}{y}{m}{y} + '{soft}{o}{gh}{o}' '{soft}{o}{m}{u}' // {v}{e}{r}{kh}{n}|{soft}{o}{gh}{o} {v}{e}{r}{kh}{n}|{soft}{o}{m}{u} + '{ia}' '{soft}{o}{yi}' '{iu}' '{soft}{o}{iu}' // {v}{e}{r}{kh}{n}|{ia} {v}{e}{r}{kh}{n}|{soft}{o}{yi} {v}{e}{r}{kh}{n}|{iu} {v}{e}{r}{kh}{n}|{soft}{o}{iu} + '{i}{kh}' '{i}{m}{y}' // {v}{e}{r}{kh}{n}|{i}{kh} {v}{e}{r}{kh}{n}|{i}{m}{y} + (delete) ) ) @@ -110,71 +137,134 @@ backwardmode ( errors. Removing im, uem, enn creates too many errors. */ - // try ( - // [substring] among ( - // // '{e}{m}' // present passive participle - // // '{n}{n}' // adjective from past passive participle - // // '{v}{sh}' // past active participle - // // '{iu}{shch}' '{shch}' // present active participle - // // ('{a}' or '{ia}' delete) + try ( + [substring] among ( + // '{e}{m}' // present passive participle + // '{n}{n}' // adjective from past passive participle + // '{v}{sh}' // past active participle + // '{iu}{shch}' '{shch}' // present active participle + // ('{a}' or '{ia}' delete) - // // //but not '{i}{m}' '{u}{e}{m}' // present passive participle - // // //or '{e}{n}{n}' // adjective from past passive participle + // //but not '{i}{m}' '{u}{e}{m}' // present passive participle + // //or '{e}{n}{n}' // adjective from past passive participle - // // '{i}{v}{sh}' '{y}{v}{sh}'// past active participle - // // '{u}{iu}{shch}' // present active participle - // // (delete) - // ) - // ) + // '{i}{v}{sh}' '{y}{v}{sh}'// past active participle + // '{u}{iu}{shch}' // present active participle + // (delete) + + '{ia}{ch}{y}{i`}' '{ia}{ch}{o}{gh}{o}' '{ia}{ch}{o}{m}{u}' '{ia}{ch}{y}{m}' '{ia}{ch}{i}{m}' // {s}{y}{d}|{ia}{ch}{y}{i`} {s}{y}{d}|{ia}{ch}{o}{gh}{o} {s}{y}{d}|{ia}{ch}{o}{m}{u} {s}{y}{d}|{ia}{ch}{y}{m} {s}{y}{d}|{ia}{ch}{i}{m} + '{ia}{ch}{a}' '{ia}{ch}{e}' '{ia}{ch}{o}{yi}' '{ia}{ch}{i}{i`}' '{ia}{ch}{u}' '{ia}{ch}{o}{iu}' // {s}{y}{d}|{ia}{ch}{a} {s}{y}{d}|{ia}{ch}{e} {s}{y}{d}|{ia}{ch}{o}{yi} {s}{y}{d}|{ia}{ch}{i}{i`} {s}{y}{d}|{ia}{ch}{u} {s}{y}{d}|{ia}{ch}{o}{iu} + '{ia}{ch}{i}' '{ia}{ch}{y}{kh}' '{ia}{ch}{y}{m}{y}' // {s}{y}{d}|{ia}{ch}{i} {s}{y}{d}|{ia}{ch}{y}{kh} {s}{y}{d}|{ia}{ch}{y}{m}{y} + '{a}{ch}{y}{i`}' '{a}{ch}{o}{gh}{o}' '{a}{ch}{o}{m}{u}' '{a}{ch}{y}{m}' '{a}{ch}{i}{m}' // {d}{r}{y}{zh}|{a}{ch}{y}{i`} {d}{r}{y}{zh}|{a}{ch}{o}{gh}{o} {d}{r}{y}{zh}|{a}{ch}{o}{m}{u} {d}{r}{y}{zh}|{a}{ch}{y}{m} {d}{r}{y}{zh}|{a}{ch}{i}{m} + '{a}{ch}{a}' '{a}{ch}{e}' '{a}{ch}{o}{yi}' '{a}{ch}{i}{i`}' '{a}{ch}{u}' '{a}{ch}{o}{iu}' // {d}{r}{y}{zh}|{a}{ch}{a} {d}{r}{y}{zh}|{a}{ch}{e} {d}{r}{y}{zh}|{a}{ch}{o}{yi} {d}{r}{y}{zh}|{a}{ch}{i}{i`} {d}{r}{y}{zh}|{a}{ch}{u} {d}{r}{y}{zh}|{a}{ch}{o}{iu} + '{a}{ch}{i}' '{a}{ch}{y}{kh}' '{a}{ch}{y}{m}{y}' // {d}{r}{y}{zh}|{a}{ch}{i} {d}{r}{y}{zh}|{a}{ch}{y}{kh} {d}{r}{y}{zh} |{a}{ch}{y}{m}{y} + '{iu}{ch}{y}{i`}' '{iu}{ch}{o}{gh}{o}' '{iu}{ch}{o}{m}{u}' '{iu}{ch}{y}{m}' '{iu}{ch}{i}{m}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{gh}{o} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{o}{m}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m} {d}{a}{l}{e}{n}{i}|{iu}{ch}{i}{m} + '{iu}{ch}{a}' '{iu}{ch}{e}' '{iu}{ch}{o}{yi}' '{iu}{ch}{i}{i`}' '{iu}{ch}{u}' '{iu}{ch}{o}{iu}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{a} {d}{a}{l}{e}{n}{i}|{iu}{ch}{e} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{yi} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{i}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{iu} + '{iu}{ch}{i}' '{iu}{ch}{y}{kh}' '{iu}{ch}{y}{m}{y}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{i} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{kh} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m}{y} + '{u}{ch}{y}{i`}' '{u}{ch}{o}{gh}{o}' '{u}{ch}{o}{m}{u}' '{u}{ch}{y}{m}' '{u}{ch}{i}{m}' // {p}{y}{sh}|{u}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{u}{ch}{o}{gh}{o} {p}{y}{sh}|{u}{ch}{o}{m}{u} {p}{y}{sh}|{u}{ch}{y}{m} {p}{y}{sh}|{u}{ch}{i}{m} + '{u}{ch}{a}' '{u}{ch}{e}' '{u}{ch}{o}{yi}' '{u}{ch}{i}{i`}' '{u}{ch}{u}' '{u}{ch}{o}{iu}' // {p}{y}{sh}|{u}{ch}{a} {p}{y}{sh}|{u}{ch}{e} {p}{y}{sh}|{u}{ch}{o}{yi} {p}{y}{sh}|{u}{ch}{i}{i`} {p}{y}{sh}|{u}{ch}{u} {p}{y}{sh}|{u}{ch}{o}{iu} + '{u}{ch}{i}' '{u}{ch}{y}{kh}' '{u}{ch}{y}{m}{y}' // {p}{y}{sh}|{u}{ch}{i} {p}{y}{sh}|{u}{ch}{y}{kh} {p}{y}{sh}|{u}{ch}{y}{m}{y} + '{e}{n}{y}{i`}' '{e}{n}{o}{gh}{o}' '{e}{n}{o}{m}{u}' '{e}{n}{y}{m}' '{e}{n}{i}{m}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} + '{e}{n}{a}' '{e}{n}{e}' '{e}{n}{o}{yi}' '{e}{n}{i}{i`}' '{e}{n}{u}' '{e}{n}{o}{iu}' // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} + '{e}{n}{i}' '{e}{n}{y}{kh}' '{e}{n}{y}{m}{y}' // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} + (delete) + ) + ) ) - // define reflexive as ( - // [substring] among ( - // // '{s}{ia}' - // // '{s}{'}' - // // (delete) - // ) - // ) + define reflexive as ( + [substring] among ( + // '{s}{ia}' + // '{s}{'}' + // (delete) - // define verb as ( - // [substring] among ( - // // '{l}{a}' '{n}{a}' '{e}{t}{e}' '{i`}{t}{e}' '{l}{i}' '{i`}' - // // '{l}' '{e}{m}' '{n}' '{l}{o}' '{n}{o}' '{e}{t}' '{iu}{t}' - // // '{n}{y}' '{t}{'}' '{e}{sh}{'}' - - // // '{n}{n}{o}' - // // ('{a}' or '{ia}' delete) - - // // '{i}{l}{a}' '{y}{l}{a}' '{e}{n}{a}' '{e}{i`}{t}{e}' - // // '{u}{i`}{t}{e}' '{i}{t}{e}' '{i}{l}{i}' '{y}{l}{i}' '{e}{i`}' - // // '{u}{i`}' '{i}{l}' '{y}{l}' '{i}{m}' '{y}{m}' '{e}{n}' - // // '{i}{l}{o}' '{y}{l}{o}' '{e}{n}{o}' '{ia}{t}' '{u}{e}{t}' - // // '{u}{iu}{t}' '{i}{t}' '{y}{t}' '{e}{n}{y}' '{i}{t}{'}' - // // '{y}{t}{'}' '{i}{sh}{'}' '{u}{iu}' '{iu}' - // // (delete) - // /* note the short passive participle tests: - // '{n}{a}' '{n}' '{n}{o}' '{n}{y}' - // '{e}{n}{a}' '{e}{n}' '{e}{n}{o}' '{e}{n}{y}' - // */ - // ) - // ) + '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} + '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} + '{t}{y}{s}{ia}' // {b}{y}|{t}{y}{s}{ia} + '{t}{y}{s}{soft}' // {b}{o}{r}{o}|{t}{y}{s}{soft} + // '{t}{soft}{s}{ia}' // {r}{o}{b}{y}|{t}{soft}{s}{ia} ??? + '{i}{t}{soft}{s}{ia}' // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} + '{t}{e}{s}{ia}' // {b}{a}{v}|{t}{e}{s}{ia} + '{i`}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{s}{ia} + '{i`}{t}{e}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} + '{v}{s}{ia}' '{l}{a}{s}{ia}' '{l}{o}{s}{ia}' '{l}{y}{s}{ia}' // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} + '{v}{s}{soft}' '{l}{a}{s}{soft}' '{l}{o}{s}{soft}' '{l}{y}{s}{soft}' // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} + '{iu}{s}{ia}' '{ye}{sh}{s}{ia}' '{ye}{t}{soft}{s}{ia}' '{ye}{m}{o}{s}{ia}' '{ye}{t}{e}{s}{ia}' '{iu}{t}{soft}{s}{ia}' // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} + '{u}{s}{ia}' '{e}{sh}{s}{ia}' '{e}{t}{soft}{s}{ia}' '{e}{m}{o}{s}{ia}' '{e}{t}{e}{s}{ia}' '{u}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} + '{l}{iu}{s}{ia}' '{y}{sh}{s}{ia}' '{y}{t}{soft}{s}{ia}' '{y}{m}{o}{s}{ia}' '{y}{t}{e}{s}{ia}' '{l}{ia}{t}{soft}{s}{ia}'// {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} + '{yi}{sh}{s}{ia}' '{yi}{t}{soft}{s}{ia}' '{yi}{m}{o}{s}{ia}' '{yi}{t}{e}{s}{ia}' '{ia}{t}{soft}{s}{ia}' // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} + '{a}{t}{soft}{s}{ia}' // {b}{a}{ch}|{a}{t}{soft}{s}{ia} + (delete) + ) + ) - // define noun as ( - // [substring] among ( - // // '{a}' '{e}{v}' '{o}{v}' '{i}{e}' '{'}{e}' '{e}' - // // '{i}{ia}{m}{i}' '{ia}{m}{i}' '{a}{m}{i}' '{e}{i}' '{i}{i}' - // // '{i}' '{i}{e}{i`}' '{e}{i`}' '{o}{i`}' '{i}{i`}' '{i`}' - // // '{i}{ia}{m}' '{ia}{m}' '{i}{e}{m}' '{e}{m}' '{a}{m}' '{o}{m}' - // // '{o}' '{u}' '{a}{kh}' '{i}{ia}{kh}' '{ia}{kh}' '{y}' '{'}' - // // '{i}{iu}' '{'}{iu}' '{iu}' '{i}{ia}' '{'}{ia}' '{ia}' - // // (delete) - // /* the small class of neuter forms '{e}{n}{i}' '{e}{n}{e}{m}' - // '{e}{n}{a}' '{e}{n}' '{e}{n}{a}{m}' '{e}{n}{a}{m}{i}' '{e}{n}{a}{x}' - // omitted - they only occur on 12 words. - // */ - // ) - // ) + define verb as ( + [substring] among ( + // '{n}{a}' '{l}{i}' + // '{l}' '{e}{m}' '{n}' '{n}{o}' '{e}{t}' '{iu}{t}' + // '{n}{y}' '{t}{'}' '{e}{sh}{'}' + + // '{n}{n}{o}' + // ('{a}' or '{ia}' delete) + + // '{i}{l}{a}' '{y}{l}{a}' '{e}{n}{a}' '{e}{i`}{t}{e}' + // '{u}{i`}{t}{e}' '{i}{t}{e}' '{i}{l}{i}' '{y}{l}{i}' '{e}{i`}' + // '{u}{i`}' '{i}{l}' '{y}{l}' '{i}{m}' '{y}{m}' '{e}{n}' + // '{i}{l}{o}' '{y}{l}{o}' '{e}{n}{o}' '{ia}{t}' '{u}{e}{t}' + // '{u}{iu}{t}' '{i}{t}' '{y}{t}' '{e}{n}{y}' '{i}{t}{'}' + // '{y}{t}{'}' '{i}{sh}{'}' '{u}{iu}' + // (delete) + /* note the short passive participle tests: + '{n}{a}' '{n}' '{n}{o}' '{n}{y}' + '{e}{n}{a}' '{e}{n}' '{e}{n}{o}' '{e}{n}{y}' + */ + + '{t}{y}' // {p}{r}{a}{ts}{iu}{v}{a}|{t}{y} + // '{t}{soft}' // {r}{o}{b}{y}|{t}{soft} ??? + '{i}{t}{soft}' // {r}{o}{b}|{i}{t}{soft} + '{t}{e}' // {v}{i}{d}{p}{r}{a}{v}|{t}{e} + '{i`}' // {ch}{y}{t}{a}|{i`} + '{i`}{t}{e}' // {d}{u}{m}{a}|{i`}{t}{e} + '{v}' '{l}{a}' '{l}{o}' '{l}{y}' // {ch}{y}{t}{a}|{v} {ch}{y}{t}{a}|{l}{a} {ch}{y}{t}{a}|{l}{o} {ch}{y}{t}{a}|{l}{y} + '{iu}' '{ye}{sh}' '{ye}' '{ye}{m}{o}' '{ye}{t}{e}' '{iu}{t}{soft}' // {ch}{y}{t}{a}|{iu} {ch}{y}{t}{a}|{ye}{sh} {ch}{y}{t}{a}|{ye} {ch}{y}{t}{a}|{ye}{m}{o} {ch}{y}{t}{a}|{ye}{t}{e} {ch}{y}{t}{a}|{iu}{t}{soft} + '{u}' '{e}{sh}' '{e}' '{e}{m}{o}' '{e}{t}{e}' '{u}{t}{soft}' // {p}{y}{sh}|{u} {p}{y}{sh}|{e}{sh} {p}{y}{sh}|{e} {p}{y}{sh}|{e}{m}{o} {p}{y}{sh}|{e}{t}{e} {p}{y}{sh}|{u}{t}{soft} + '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' // {r}{o}{b}|{l}{iu} {r}{o}{b}|{y}{sh} {r}{o}{b}|{y}{t}{soft} {r}{o}{b}|{y}{m}{o} {r}{o}{b}|{y}{t}{e} {r}{o}{b}|{l}{ia}{t}{soft} + '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' // {s}{t}{o}|{yi}{sh} {s}{t}{o}|{yi}{t}{soft} {s}{t}{o}|{yi}{m}{o} {s}{t}{o}|{yi}{t}{e} {s}{t}{o}|{ia}{t}{soft} + '{a}{t}{soft}' // {b}{a}{ch}|{a}{t}{soft} + (delete) + ) + ) + + define noun as ( + [substring] among ( + // '{a}' '{e}{v}' '{o}{v}' '{i}{e}' '{'}{e}' '{e}' + // '{i}{ia}{m}{i}' '{ia}{m}{i}' '{a}{m}{i}' '{e}{i}' '{i}{i}' + // '{i}' '{i}{e}{i`}' '{e}{i`}' '{o}{i`}' '{i}{i`}' '{i`}' + // '{i}{ia}{m}' '{ia}{m}' '{i}{e}{m}' '{e}{m}' '{a}{m}' '{o}{m}' + // '{o}' '{u}' '{a}{kh}' '{i}{ia}{kh}' '{ia}{kh}' '{y}' '{'}' + // '{i}{iu}' '{'}{iu}' '{iu}' '{i}{ia}' '{'}{ia}' '{ia}' + // (delete) + /* the small class of neuter forms '{e}{n}{i}' '{e}{n}{e}{m}' + '{e}{n}{a}' '{e}{n}' '{e}{n}{a}{m}' '{e}{n}{a}{m}{i}' '{e}{n}{a}{x}' + omitted - they only occur on 12 words. + */ + + '{a}' '{y}' '{i}' '{u}' '{o}{iu}' '{o}' // {v}{o}{d}|{a} {v}{o}{d}|{y} {v}{o}{d}|{i} {v}{o}{d}|{u} {v}{o}{d}|{o}{iu} {v}{o}{d}|{o} + '{a}{m}' '{a}{m}{y}' '{a}{kh}' // {v}{o}{d}|{a}{m} {v}{o}{d}|{a}{m}{y} {v}{o}{d}|{a}{kh} + '{ia}' '{iu}' '{e}{iu}' '{e}' // {p}{i}{s}{n}|{ia} {p}{i}{s}{n}|{iu} {p}{i}{s}{n}|{e}{iu} {p}{i}{s}{n}|{e} + '{ia}{m}' '{ia}{m}{y}' '{ia}{kh}' // {p}{i}{s}{n}|{ia}{m} {p}{i}{s}{n}|{ia}{m}{y} {p}{i}{s}{n}|{ia}{kh} + '{o}{v}{i}' '{o}{m}' // {b}{a}{t}{soft}{k}|{o}{v}{i} {b}{a}{t}{soft}{k}|{o}{m} + '{e}{ts}{soft}' '{e}{m}' // {o}{l}{i}{v}|{e}{ts}{soft} {o}{l}{i}{v}{ts}|{e}{m} + '{e}{n}{soft}' // {z}{e}{l}|{e}{n}{soft} + '{i}{i`}' // {gh}{e}{n}|{i}{i`} + '{i`}' // {s}{a}{r}{a}|{i`} + '{o}{i`}' // {gh}{e}{r}|{o}{i`} + '{soft}' // {s}{o}{v}{i}{s}{t}|{soft} + '{i}{iu}' '{i}{yi}' // {k}{o}{m}{e}{d}|{i}{iu} {k}{o}{m}{e}{d}|{i}{yi} + (delete) + ) + ) // define derivational as ( // [substring] R2 among ( @@ -208,16 +298,47 @@ define stem as ( do mark_regions backwards setlimit tomark pV for ( do ( - adjectival - // perfective_gerund or - // ( try reflexive - // adjectival or verb or noun - // ) + // TEST: + // reflexive + // verb + // noun + + perfective_gerund or + ( try reflexive + adjectival or verb or noun + ) ) - // try([ '{i}' ] delete) + try([ '{i}' ] delete) // because noun ending -i{iu} is being treated as verb ending -{iu} // do derivational // do tidy_up ) ) + + +// ToDo: +// 1. Ґ => Г +// do repeat ( goto (['{g}]) <- '{gh}' ) // {u}{gh}{n}{e}{t}ё{n}{n}ы{i`} => {u}{gh}{n}{e}{t}{e}{n} +// 2. В{y}{d}{a}{l}{y}{t}{y} {v}{s}{i} {t}{y}{p}{y} А{p}{o}{s}{t}{r}{o}{f}{i}{v} 'ʼ` + +// 3. Д{o}{d}{a}{t}{k}{o}{v}{o} {p}{e}{r}{e}{v}{i}{r}{y}{t}{y} {s}{l}{o}{v}{a}: +// {b}{r}{a}{t}{y} +// {b}{e}{r}{u}{t}{soft} + +// {d}{o}{p}{y}{s}{a}{t}{y} +// {d}{o}{p}{y}{sh}{u}{t}{soft} + +// {p}{o}{s}{y}{d}{e}{n}{soft}{k}{y} + +// {l}{i}{k}{a}{r} +// {l}{i}{k}{a}{r}{i}{v} + +// ----- {p}{r}{y}{s}{l}{i}{v}{n}{y}{k}{y}? - {k}{u}{d}{y} {p}{o}{p}{a}{d}{e}? +// {d}{o}{b}{r}{e} - {d}{o}{b}{r}{o} +// {ch}{a}{s}{t}{o} - {ch}{a}{s}{t}{i}{sh}{y}{i`} +// {d}{o}{v}{gh}{o} - {d}{o}{v}{gh}{y}{i`} +// {ch}{y}{s}{t}{o} - {ch}{y}{s}{t}{i}{sh}{y}{i`} + +// {r}{o}{b}{y}{t}{y}{m}{u}{t}{soft} - ? +// {r}{o}{b}{y}{t}{y}{m} diff --git a/explanations/russian.sbl.explanation b/explanations/russian.sbl.explanation index 33fd1c85..e59bdacd 100644 --- a/explanations/russian.sbl.explanation +++ b/explanations/russian.sbl.explanation @@ -119,7 +119,7 @@ backwardmode ( // but not 'им' 'уем' // present passive participle // or 'енн' // adjective from past passive participle - 'ивш' 'ывш' // past active participle // брод|ивших несб|ывшееся + 'ивш' 'ывш' // past active participle // брод|ивших несб|ывш(ее(ся)) 'ующ' // present active participle // несуществ|ующий (delete) ) @@ -129,7 +129,7 @@ backwardmode ( define reflexive as ( [substring] among ( - 'ся' // осек|ся + 'ся' // осек|ся несбывшее|ся 'сь' // ввы|сь (delete) ) diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index d35e0d7b..dbc4a4a7 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -38,12 +38,12 @@ stringdef ia '{U+044F}' stringdef apostrophe '{U+0027}' routines ( mark_regions R2 - // perfective_gerund + perfective_gerund adjective adjectival - // reflexive - // verb - // noun + reflexive + verb + noun // derivational // tidy_up ) @@ -70,35 +70,62 @@ backwardmode ( define R2 as $p2 <= cursor - // define perfective_gerund as ( - // [substring] among ( - // // 'в' - // // 'вші' - // // 'вшіс{'}' - // // ('а' or 'я' delete) - // // 'ів' - // // 'івші' - // // 'івшіс{'}' - // // 'ив' - // // 'ивші' - // // 'ившіс{'}' - // // (delete) - // ) - // ) + define perfective_gerund as ( + [substring] among ( + // 'в' + // 'вші' + // 'вшіс{'}' + // ('а' or 'я' delete) + // 'ів' + // 'івші' + // 'івшіс{'}' + // 'ив' + // 'ивші' + // 'ившіс{'}' + // (delete) + + 'в' // донаписа|в дороби|в дороби|в + 'вши' // написа|вши зроби|вши + 'вшись' // оберіга|вшись спакува|вшись + 'вшися' // оберіга|вшися сподіва|вшися + // ('а' or 'я' delete) ??? + 'учи' // пиш|учи рев|учи + 'ючи' // ся|ючи підпису|ючи + 'ючись' // змага|ючись + 'ючися' // навча|ючися + 'ачи' // бач|ачи + 'ачись' // бач|ачись + 'ачися' // бач|ачися + 'лячи' // роб|лячи люб|лячи + 'лячись' // бав|лячись + 'лячися' // бав|лячися + 'ячи' // сид|ячи вовтуз|ячи + 'ячись' // ??? + 'ячися' // ??? + (delete) + ) + ) define adjective as ( [substring] among ( - 'ього' - (delete) // 'ее' 'іе' 'ие' 'ое' 'імі' 'имі' - // 'ей' 'ій' 'ий' 'ой' 'ем' 'ім' - // 'им' 'ом' 'еґо' 'оґо' 'ему' - // 'ому' 'іх' 'их' 'ую' 'юю' 'ая' - // 'яя' - // // and - - // 'ою' // - which is somewhat archaic + // 'ей' 'ой' 'ем' + // 'ом' 'еґо' 'оґо' 'ему' + // 'ую' 'юю' 'ая' // 'ею' // - soft form of ою // (delete) + + 'ий' 'ого' 'ому' 'им' 'ім' // зелен|ий зелен|ого зелен|ому зелен|им зелен|ім + 'іший' 'ішого' 'ішому' 'ішим' 'ішім' // зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім + 'е' 'іше' // зелен|е зелен|іше + 'а' 'ої' 'ій' 'у' 'ою' // зелен|а зелен|ої зелен|ій зелен|у зелен|ою + 'іша' 'ішої' 'ішій' 'ішу' 'ішою' // зелен|іша зелен|ішої зелен|ішій зелен|ішу зелен|ішою + 'і' 'их' 'ими' // зелен|і зелен|их зелен|ими + 'іші' 'іших' 'ішими' // зелен|іші зелен|іших зелен|ішими + 'ього' 'ьому' // верхн|ього верхн|ьому + 'я' 'ьої' 'ю' 'ьою' // верхн|я верхн|ьої верхн|ю верхн|ьою + 'іх' 'іми' // верхн|іх верхн|іми + (delete) ) ) @@ -110,71 +137,134 @@ backwardmode ( errors. Removing im, uem, enn creates too many errors. */ - // try ( - // [substring] among ( - // // 'ем' // present passive participle - // // 'нн' // adjective from past passive participle - // // 'вш' // past active participle - // // 'ющ' 'щ' // present active participle - // // ('а' or 'я' delete) + try ( + [substring] among ( + // 'ем' // present passive participle + // 'нн' // adjective from past passive participle + // 'вш' // past active participle + // 'ющ' 'щ' // present active participle + // ('а' or 'я' delete) - // // //but not 'ім' 'уем' // present passive participle - // // //or 'енн' // adjective from past passive participle + // //but not 'ім' 'уем' // present passive participle + // //or 'енн' // adjective from past passive participle - // // 'івш' 'ивш'// past active participle - // // 'ующ' // present active participle - // // (delete) - // ) - // ) + // 'івш' 'ивш'// past active participle + // 'ующ' // present active participle + // (delete) + + 'ячий' 'ячого' 'ячому' 'ячим' 'ячім' // сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім + 'яча' 'яче' 'ячої' 'ячій' 'ячу' 'ячою' // сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою + 'ячі' 'ячих' 'ячими' // сид|ячі сид|ячих сид|ячими + 'ачий' 'ачого' 'ачому' 'ачим' 'ачім' // дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім + 'ача' 'аче' 'ачої' 'ачій' 'ачу' 'ачою' // дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою + 'ачі' 'ачих' 'ачими' // дриж|ачі дриж|ачих дриж |ачими + 'ючий' 'ючого' 'ючому' 'ючим' 'ючім' // далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім + 'юча' 'юче' 'ючої' 'ючій' 'ючу' 'ючою' // далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою + 'ючі' 'ючих' 'ючими' // далені|ючі далені|ючих далені|ючими + 'учий' 'учого' 'учому' 'учим' 'учім' // пиш|учий далені|учого пиш|учому пиш|учим пиш|учім + 'уча' 'уче' 'учої' 'учій' 'учу' 'учою' // пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою + 'учі' 'учих' 'учими' // пиш|учі пиш|учих пиш|учими + 'ений' 'еного' 'еному' 'еним' 'енім' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім + 'ена' 'ене' 'еної' 'еній' 'ену' 'еною' // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною + 'ені' 'ених' 'еними' // втрач|ені втрач|ених втрач|еними + (delete) + ) + ) ) - // define reflexive as ( - // [substring] among ( - // // 'ся' - // // 'с{'}' - // // (delete) - // ) - // ) + define reflexive as ( + [substring] among ( + // 'ся' + // 'с{'}' + // (delete) - // define verb as ( - // [substring] among ( - // // 'ла' 'на' 'ете' 'йте' 'лі' 'й' - // // 'л' 'ем' 'н' 'ло' 'но' 'ет' 'ют' - // // 'ни' 'т{'}' 'еш{'}' - - // // 'нно' - // // ('а' or 'я' delete) - - // // 'іла' 'ила' 'ена' 'ейте' - // // 'уйте' 'іте' 'ілі' 'илі' 'ей' - // // 'уй' 'іл' 'ил' 'ім' 'им' 'ен' - // // 'іло' 'ило' 'ено' 'ят' 'ует' - // // 'уют' 'іт' 'ит' 'ени' 'іт{'}' - // // 'ит{'}' 'іш{'}' 'ую' 'ю' - // // (delete) - // /* note the short passive participle tests: - // 'на' 'н' 'но' 'ни' - // 'ена' 'ен' 'ено' 'ени' - // */ - // ) - // ) + 'ся' // осік|ся + 'сь' // недонавчи|сь + 'тися' // би|тися + 'тись' // боро|тись + // 'ться' // роби|ться ??? + 'іться' // подруж|іться + 'теся' // бав|теся + 'йся' // вдума|йся + 'йтеся' // вдума|йтеся + 'вся' 'лася' 'лося' 'лися' // вчи|вся вчи|лася вчи|лося вчи|лися + 'всь' 'лась' 'лось' 'лись' // вчи|всь вчи|лась вчи|лось вчи|лись + 'юся' 'єшся' 'ється' 'ємося' 'єтеся' 'ються' // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються + 'уся' 'ешся' 'еться' 'емося' 'етеся' 'уться' // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться + 'люся' 'ишся' 'иться' 'имося' 'итеся' 'ляться'// див|люся див|ишся див|иться див|имося див|итеся див|ляться + 'їшся' 'їться' 'їмося' 'їтеся' 'яться' // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться + 'аться' // бач|аться + (delete) + ) + ) - // define noun as ( - // [substring] among ( - // // 'а' 'ев' 'ов' 'іе' '{'}е' 'е' - // // 'іямі' 'ямі' 'амі' 'еі' 'іі' - // // 'і' 'іей' 'ей' 'ой' 'ій' 'й' - // // 'іям' 'ям' 'іем' 'ем' 'ам' 'ом' - // // 'о' 'у' 'ах' 'іях' 'ях' 'и' '{'}' - // // 'ію' '{'}ю' 'ю' 'ія' '{'}я' 'я' - // // (delete) - // /* the small class of neuter forms 'ені' 'енем' - // 'ена' 'ен' 'енам' 'енамі' 'ена{x}' - // omitted - they only occur on 12 words. - // */ - // ) - // ) + define verb as ( + [substring] among ( + // 'на' 'лі' + // 'л' 'ем' 'н' 'но' 'ет' 'ют' + // 'ни' 'т{'}' 'еш{'}' + + // 'нно' + // ('а' or 'я' delete) + + // 'іла' 'ила' 'ена' 'ейте' + // 'уйте' 'іте' 'ілі' 'илі' 'ей' + // 'уй' 'іл' 'ил' 'ім' 'им' 'ен' + // 'іло' 'ило' 'ено' 'ят' 'ует' + // 'уют' 'іт' 'ит' 'ени' 'іт{'}' + // 'ит{'}' 'іш{'}' 'ую' + // (delete) + /* note the short passive participle tests: + 'на' 'н' 'но' 'ни' + 'ена' 'ен' 'ено' 'ени' + */ + + 'ти' // працюва|ти + // 'ть' // роби|ть ??? + 'іть' // роб|іть + 'те' // відправ|те + 'й' // чита|й + 'йте' // дума|йте + 'в' 'ла' 'ло' 'ли' // чита|в чита|ла чита|ло чита|ли + 'ю' 'єш' 'є' 'ємо' 'єте' 'ють' // чита|ю чита|єш чита|є чита|ємо чита|єте чита|ють + 'у' 'еш' 'е' 'емо' 'ете' 'уть' // пиш|у пиш|еш пиш|е пиш|емо пиш|ете пиш|уть + 'лю' 'иш' 'ить' 'имо' 'ите' 'лять' // роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять + 'їш' 'їть' 'їмо' 'їте' 'ять' // сто|їш сто|їть сто|їмо сто|їте сто|ять + 'ать' // бач|ать + (delete) + ) + ) + + define noun as ( + [substring] among ( + // 'а' 'ев' 'ов' 'іе' '{'}е' 'е' + // 'іямі' 'ямі' 'амі' 'еі' 'іі' + // 'і' 'іей' 'ей' 'ой' 'ій' 'й' + // 'іям' 'ям' 'іем' 'ем' 'ам' 'ом' + // 'о' 'у' 'ах' 'іях' 'ях' 'и' '{'}' + // 'ію' '{'}ю' 'ю' 'ія' '{'}я' 'я' + // (delete) + /* the small class of neuter forms 'ені' 'енем' + 'ена' 'ен' 'енам' 'енамі' 'ена{x}' + omitted - they only occur on 12 words. + */ + + 'а' 'и' 'і' 'у' 'ою' 'о' // вод|а вод|и вод|і вод|у вод|ою вод|о + 'ам' 'ами' 'ах' // вод|ам вод|ами вод|ах + 'я' 'ю' 'ею' 'е' // пісн|я пісн|ю пісн|ею пісн|е + 'ям' 'ями' 'ях' // пісн|ям пісн|ями пісн|ях + 'ові' 'ом' // батьк|ові батьк|ом + 'ець' 'ем' // олів|ець олівц|ем + 'ень' // зел|ень + 'ій' // ген|ій + 'й' // сара|й + 'ой' // гер|ой + 'ь' // совіст|ь + 'ію' 'ії' // комед|ію комед|ії + (delete) + ) + ) // define derivational as ( // [substring] R2 among ( @@ -208,16 +298,47 @@ define stem as ( do mark_regions backwards setlimit tomark pV for ( do ( - adjectival - // perfective_gerund or - // ( try reflexive - // adjectival or verb or noun - // ) + // TEST: + // reflexive + // verb + // noun + + perfective_gerund or + ( try reflexive + adjectival or verb or noun + ) ) - // try([ 'і' ] delete) + try([ 'і' ] delete) // because noun ending -iю is being treated as verb ending -ю // do derivational // do tidy_up ) ) + + +// ToDo: +// 1. Ґ => Г +// do repeat ( goto (['ґ]) <- 'г' ) // угнетённый => угнетен +// 2. Видалити всі типи Апострофів 'ʼ` + +// 3. Додатково перевірити слова: +// брати +// беруть + +// дописати +// допишуть + +// посиденьки + +// лікар +// лікарів + +// ----- прислівники? - куди попаде? +// добре - добро +// часто - частіший +// довго - довгий +// чисто - чистіший + +// робитимуть - ? +// робитим diff --git a/runtime/utilities.c b/runtime/utilities.c index d7dd218d..20f1ce55 100644 --- a/runtime/utilities.c +++ b/runtime/utilities.c @@ -415,7 +415,7 @@ static int slice_check(struct SN_env * z) { z->p == NULL || z->l > SIZE(z->p)) /* this line could be removed */ { -#if 0 +#if 1 fprintf(stderr, "faulty slice operation:\n"); debug(z, -1, 0); #endif @@ -490,7 +490,7 @@ extern int len_utf8(const symbol * p) { return len; } -#if 0 +#if 1 extern void debug(struct SN_env * z, int number, int line_count) { int i; int limit = SIZE(z->p); diff --git a/tests/algorithms/russian_test.rb b/tests/algorithms/russian_test.rb index 39d9e743..86806ce0 100644 --- a/tests/algorithms/russian_test.rb +++ b/tests/algorithms/russian_test.rb @@ -31,7 +31,7 @@ 'ющ щ' => %w[сталкива|ющихся спеша|щих умоля|ющими блестя|щему], - 'ивш ывш' => %w[брод|ивших несб|ывшееся], + 'ивш ывш' => %w[брод|ивших несб|ывшееся], # несб|ывш(ее(ся)) 'ующ' => %w[несуществ|ующий] } diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb index 4ee607c1..e9f6b687 100644 --- a/tests/algorithms/ukrainian_test.rb +++ b/tests/algorithms/ukrainian_test.rb @@ -4,126 +4,204 @@ # Граматика української мови # https://uk.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0_%D1%83%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D1%81%D1%8C%D0%BA%D0%BE%D1%97_%D0%BC%D0%BE%D0%B2%D0%B8 -perfective_gerund = { # DONE - 'в' => %w[подола|в підня|в], - 'вши' => %w[написа|вши підня|вши], - 'вшись' => %w[абсолютизува|вшись підня|вшись], - - 'ивши' => %w[дзвон|ивши], - 'ившись' => %w[дзвон|ившись], - 'ув' => %w[приб|ув], - 'увши' => %w[приб|увши], - 'увшись' => %w[дотикн|увшись] + +# 1 +# runtime/utilities.c +# comment out 'debug' function: + #if 1 + # fprintf(stderr, "faulty slice operation:\n"); + # debug(z, -1, 0); + + #if 1 + #extern void debug(struct SN_env * z, int number, int line_count) { + +# insert 'debug' where debugging is needed: +# src_c/stem_UTF_8_ukrainian.c +# static int r_perfective_gerund(struct SN_env * z) { + # printf("R1: "); + # printf("R2: "); + # debug(z, -1, 0); + +# 2 +# bin/utf_to_sbl ./explanations/ukrainian.sbl.utf > algorithms/ukrainian.sbl && make + + +# 4 +# ruby tests/algorithms/ukrainian_test.rb +# ./snowball algorithms/ukrainian_test.sbl -syntax +# ./snowball algorithms/english.sbl -syntax + + +perfective_gerund = { + 'в' => %w[донаписа|в дороби|в дороби|в], + 'вши' => %w[написа|вши зроби|вши], + 'вшись' => %w[оберіга|вшись спакува|вшись], + 'вшися' => %w[оберіга|вшися сподіва|вшися], + # (а и ) + 'учи' => %w[пиш|учи рев|учи], + 'ючи' => %w[ся|ючи підпису|ючи], + 'ючись' => %w[змага|ючись], + 'ючися' => %w[навча|ючися], + 'ачи' => %w[бач|ачи], + 'ачись' => %w[бач|ачись], + 'ачися' => %w[бач|ачися], + 'лячи' => %w[роб|лячи люб|лячи], + 'лячись' => %w[бав|лячись], + 'лячися' => %w[бав|лячися], + 'ячи' => %w[сид|ячи вовтуз|ячи], + 'ячись' => %w[], + 'ячися' => %w[] } -adjective = { # DONE - 'іше іє і е ими' => %w[зелен|іше послан|іє ароматн|і зіпсован|е зіпсован|ими], - 'іший ий ій им' => %w[зелен|іший зелен|ий великодн|ій глибок|им], # noun: ой =>палеоз|ой perfective_gerund: ем => похапц|ем - 'ого' => %w[ головн|ого ], # noun ім => екстр|ім ом => заїзд|ом - 'ому их у я а' => %w[веснян|ому зелен|их бронзов|у верхн|я весел|а], # !по-весняному? - 'ою' => %w[веснян|ою ], - # noun 'ею' => %w[земл|ею], +adjective = { + 'ий ого ому им ім' => %w[зелен|ий зелен|ого зелен|ому зелен|им зелен|ім], + 'іший ішого ішому ішим ішім' => %w[зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім], + 'е іше' => %w[зелен|е зелен|іше], + 'а ої ій у ою' => %w[зелен|а зелен|ої зелен|ій зелен|у зелен|ою], + 'іша ішої ішій ішу ішою' => %w[зелен|іша зелен|ішої зелен|ішій зелен|ішу зелен|ішою], + 'і их ими' => %w[зелен|і зелен|их зелен|ими], + 'іші іших ішими' => %w[зелен|іші зелен|іших зелен|ішими], + 'ього ьому' => %w[верхн|ього верхн|ьому], + 'я ьої ю ьою' => %w[верхн|я верхн|ьої верхн|ю верхн|ьою], + 'іх іми' => %w[верхн|іх верхн|іми], } adjectival = { - 'ем' => %w[задава|емые изменя|ем], - 'нн' => %w[беспреста|нно деревя|нными], - 'вш' => %w[отказа|вшись отделя|вший], - 'ющ щ' => %w[сталкива|ющихся спеша|щих - умоля|ющими блестя|щему], - - 'ивш ывш' => %w[брод|ивших несб|ывшееся], - 'ующ' => %w[несуществ|ующий] + # нн => беспреста|нн.о деревя|нн.ыми + 'ячий ячого ячому ячим ячім' => %w[сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім], + 'яча яче ячої ячій ячу ячою' => %w[сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою], + 'ячі ячих ячими' => %w[сид|ячі сид|ячих сид|ячими], + 'ачий ачого ачому ачим ачім' => %w[дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім], + 'ача аче ачої ачій ачу ачою' => %w[дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою], + 'ачі ачих ачими' => %w[дриж|ачі дриж|ачих дриж |ачими], + 'ючий ючого ючому ючим ючім' => %w[далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім], + 'юча юче ючої ючій ючу ючою' => %w[далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою], + 'ючі ючих ючими' => %w[далені|ючі далені|ючих далені|ючими], + 'учий учого учому учим учім' => %w[пиш|учий далені|учого пиш|учому пиш|учим пиш|учім], + 'уча уче учої учій учу учою' => %w[пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою], + 'учі учих учими' => %w[пиш|учі пиш|учих пиш|учими], + 'ений еного еному еним енім' => %w[втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім ], + 'ена ене еної еній ену еною' => %w[втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною], + 'ені ених еними' => %w[втрач|ені втрач|ених втрач|еними], } reflexive = { - 'ся' => %w[осек|ся], - 'сь' => %w[ввы|сь] + 'ся' => %w[осік|ся], + 'сь' => %w[недонавчи|сь], # вчи|сь + 'тися' => %w[би|тися], + 'тись' => %w[боро|тись], + # 'ться' => %w[роби|ться], # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил + 'іться' => %w[подруж|іться], + 'теся' => %w[бав|теся], + 'йся' => %w[вдума|йся], + 'йтеся' => %w[вдума|йтеся], + 'вся лася лося лися' => %w[вчи|вся вчи|лася вчи|лося вчи|лися], + 'всь лась лось лись' => %w[вчи|всь вчи|лась вчи|лось вчи|лись], + 'юся єшся ється ємося єтеся ються' => %w[смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються], + 'уся ешся еться емося етеся уться' => %w[спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться], + 'люся ишся иться имося итеся ляться'=> %w[див|люся див|ишся див|иться див|имося див|итеся див|ляться], + 'їшся їться їмося їтеся яться' => %w[бо|їшся бо|їться бо|їмося бо|їтеся бо|яться], + 'аться' => %w[бач|аться], } verb = { - 'ла на ете йте ли й' => %w[сдела|ла воспита|на сдела|ете сдела|йте сдела|ли сдела|й - приня|ла потеря|на причиня|ете причиня|йте причиня|ли причиня|й], - - 'л ем н ло но ет ют' => %w[сдела|л воспита|ем сдела|н сдела|ло сдела|но сдела|ет сдела|ют - приня|л потеря|ем растеря|н причиня|ло настоя|но объясня|ет объясня|ют], - - 'ны ть ешь' => %w[сдела|ны сдела|ть сдела|ешь - потеря|ны потеря|ть потеря|ешь], - - 'нно' => %w[пута|нно постоя|нно], - - 'ила ыла ена ейте' => %w[беспоко|ила прикр|ыла выруч|ена пожал|ейте вспл|ыла], # вспл|ыла? - 'уйте ите или ыли ей' => %w[пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей], - 'уй ил ыл им ым ен' => %w[протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен], - 'ило ыло ено ят ует' => %w[став|ило неун|ыло обознач|ено обрат|ят повеств|ует], - 'уют ит ыт ены ить' => %w[преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить], - 'ыть ишь ую ю' => %w[откр|ыть отправ|ишь отперт|ую отрица|ю] + 'ти' => %w[працюва|ти], + # 'ть' => %w[роби|ть], # => роб|ить !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил + 'іть' => %w[роб|іть], + 'те' => %w[відправ|те], + 'й' => %w[чита|й], + 'йте' => %w[дума|йте], + 'в ла ло ли' => %w[чита|в чита|ла чита|ло чита|ли], + 'ю єш є ємо єте ють' => %w[чита|ю чита|єш чита|є чита|ємо чита|єте чита|ють], + 'у еш е емо ете уть' => %w[пиш|у пиш|еш пиш|е пиш|емо пиш|ете пиш|уть], + 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], + 'їш їть їмо їте ять' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять], + 'ать' => %w[бач|ать], } noun = { - 'а ев ов ие ье е' => %w[вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е], - 'иями ями ами еи ии' => %w[волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии], - 'и ией ей ой ий й' => %w[потер|и гармон|ией галере|ей гер|ой ген|ий сара|й], - 'иям ям ием ем ам ом' => %w[губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом], - 'о у ах иях ях ы ь' => %w[брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь], - 'ию ью ю ия ья я' => %w[комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я] + 'а и і у ою о' => %w[вод|а вод|и вод|і вод|у вод|ою вод|о], + 'ам ами ах' => %w[вод|ам вод|ами вод|ах], + 'я ю ею е' => %w[пісн|я пісн|ю пісн|ею пісн|е], + 'ям ями ях' => %w[пісн|ям пісн|ями пісн|ях], + 'ові ом' => %w[батьк|ові батьк|ом], + 'ець ем' => %w[олів|ець олівц|ем], # ю олівц|ю - повтор + 'ень' => %w[зел|ень], + 'ій' => %w[ген|ій], + 'й' => %w[сара|й], + 'ой' => %w[гер|ой], + 'ь' => %w[совіст|ь], + 'ію ії' => %w[комед|ію комед|ії], } -derivational = { - 'ост' => %w[любезн|остей], - 'ость' => %w[любезн|остью] -} +# derivational = { +# 'остей' => %w[люб'язн|остей], +# 'ість' => %w[люб'язн|ість] +# } -tidy_up = { - 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], - 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], - 'н[н]' => %w[смирен|но смирн|о], - 'ь' => %w[совест|ь] -} +# tidy_up = { +# 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], +# 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], +# 'н[н]' => %w[смирен|но смирн|о], +# 'ь' => %w[свідоміст|ь] +# } -exceptions = { - # ё => е - 'угнетённый' => 'угнетен', +# exceptions = { +# # ё => е +# 'угнетённый' => 'угнетен', - # -ию => '' - 'академию' => 'академ' -} +# # -ию => '' +# 'академию' => 'академ' +# } $all_tests = [] -$errors = [] +$errors = {} def incorrect_stem_msg(result_stem, word, stem) "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" end -def check_words_set(words_set) +def check_words_set(words_set, set_name) words_set.each do |_rule, test_cases| test_cases.each do |test_case| stem, ending = test_case.split('|') word = [stem, ending].join $all_tests << word - result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip - $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem + + result_stem = (`echo "#{word}" | ./stemwords -l uk`).strip + + $errors[set_name] ||= [] + $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem end end end [ - perfective_gerund, - adjective, - # adjectival, - # reflexive, - # verb, - # noun, - # derivational, - # tidy_up -].each {|words_set| check_words_set(words_set) } + [perfective_gerund, 'perfective_gerund'], + [adjective, 'adjective'], + [adjectival, 'adjectival'], + [reflexive, 'reflexive'], + [verb, 'verb'], + [noun, 'noun'], + # [derivational, 'derivational'], + # [tidy_up, 'tidy_up'] +].each do |words_set, set_name| + check_words_set(words_set, set_name) +end # exceptions.each do |word, stem| # $all_tests << word -# result_stem = (`echo "#{word}" | ./stemwords -l uk`).strip +# result_stem = (`echo "#{word}" | ./stemwords -syntax -l uk `).strip # $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem # end -$errors.empty? ? puts("#{$all_tests.count} test(s) passed successfully!") : puts($errors.join("\n")) +if $errors.empty? + puts("#{$all_tests.count} test(s) passed successfully!") +else + $errors.each do |set_name, errs| + next if errs.empty? + + puts "=== #{set_name}:" + puts(errs.join("\n")) + end +end From 793668524c4b1ba86ec9ad839e94ec5bc81d804a Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Fri, 9 Jun 2023 21:36:45 +0300 Subject: [PATCH 07/13] Add Ukrainian stemmer --- algorithms/ukrainian.sbl | 116 +++++++++------ explanations/ukrainian.sbl.utf | 110 ++++++++------ tests/algorithms/ukrainian_test.rb | 227 +++++++++++++++++++++++------ 3 files changed, 320 insertions(+), 133 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index 368a341f..5604bb1a 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -37,7 +37,7 @@ stringdef iu '{U+044E}' stringdef ia '{U+044F}' stringdef apostrophe '{U+0027}' -routines ( mark_regions R2 +routines ( mark_regions R1 R2 perfective_gerund adjective adjectival @@ -50,7 +50,7 @@ routines ( mark_regions R2 externals ( stem ) -integers ( pV p2 ) +integers ( pV p1 p2 ) groupings ( v ) @@ -59,15 +59,17 @@ define v '{a}{e}{ye}{y}{i}{yi}{o}{u}{iu}{ia}' define mark_regions as ( $pV = limit + $p1 = limit $p2 = limit do ( - gopast v setmark pV gopast non-v + gopast v setmark pV gopast non-v setmark p1 gopast v gopast non-v setmark p2 ) ) backwardmode ( + define R1 as $p1 <= cursor define R2 as $p2 <= cursor define perfective_gerund as ( @@ -88,7 +90,7 @@ backwardmode ( '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} {z}{r}{o}{b}{y}|{v}{sh}{y} '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} - // ('{a}' or '{ia}' delete) + // ('{a}' or '{ia}' delete) ??? '{u}{ch}{y}' // {p}{y}{sh}|{u}{ch}{y} {r}{e}{v}|{u}{ch}{y} '{iu}{ch}{y}' // {s}{ia}|{iu}{ch}{y} {p}{i}{d}{p}{y}{s}{u}|{iu}{ch}{y} '{iu}{ch}{y}{s}{soft}' // {z}{m}{a}{gh}{a}|{iu}{ch}{y}{s}{soft} @@ -100,8 +102,8 @@ backwardmode ( '{l}{ia}{ch}{y}{s}{soft}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{soft} '{l}{ia}{ch}{y}{s}{ia}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{ia} '{ia}{ch}{y}' // {s}{y}{d}|{ia}{ch}{y} {v}{o}{v}{t}{u}{z}|{ia}{ch}{y} - '{ia}{ch}{y}{s}{soft}' // - '{ia}{ch}{y}{s}{ia}' // + '{ia}{ch}{y}{s}{soft}' // ??? + '{ia}{ch}{y}{s}{ia}' // ??? (delete) ) ) @@ -152,49 +154,70 @@ backwardmode ( // '{u}{iu}{shch}' // present active participle // (delete) - '{ia}{ch}{y}{i`}' '{ia}{ch}{o}{gh}{o}' '{ia}{ch}{o}{m}{u}' '{ia}{ch}{y}{m}' '{ia}{ch}{i}{m}' // {s}{y}{d}|{ia}{ch}{y}{i`} {s}{y}{d}|{ia}{ch}{o}{gh}{o} {s}{y}{d}|{ia}{ch}{o}{m}{u} {s}{y}{d}|{ia}{ch}{y}{m} {s}{y}{d}|{ia}{ch}{i}{m} - '{ia}{ch}{a}' '{ia}{ch}{e}' '{ia}{ch}{o}{yi}' '{ia}{ch}{i}{i`}' '{ia}{ch}{u}' '{ia}{ch}{o}{iu}' // {s}{y}{d}|{ia}{ch}{a} {s}{y}{d}|{ia}{ch}{e} {s}{y}{d}|{ia}{ch}{o}{yi} {s}{y}{d}|{ia}{ch}{i}{i`} {s}{y}{d}|{ia}{ch}{u} {s}{y}{d}|{ia}{ch}{o}{iu} - '{ia}{ch}{i}' '{ia}{ch}{y}{kh}' '{ia}{ch}{y}{m}{y}' // {s}{y}{d}|{ia}{ch}{i} {s}{y}{d}|{ia}{ch}{y}{kh} {s}{y}{d}|{ia}{ch}{y}{m}{y} - '{a}{ch}{y}{i`}' '{a}{ch}{o}{gh}{o}' '{a}{ch}{o}{m}{u}' '{a}{ch}{y}{m}' '{a}{ch}{i}{m}' // {d}{r}{y}{zh}|{a}{ch}{y}{i`} {d}{r}{y}{zh}|{a}{ch}{o}{gh}{o} {d}{r}{y}{zh}|{a}{ch}{o}{m}{u} {d}{r}{y}{zh}|{a}{ch}{y}{m} {d}{r}{y}{zh}|{a}{ch}{i}{m} - '{a}{ch}{a}' '{a}{ch}{e}' '{a}{ch}{o}{yi}' '{a}{ch}{i}{i`}' '{a}{ch}{u}' '{a}{ch}{o}{iu}' // {d}{r}{y}{zh}|{a}{ch}{a} {d}{r}{y}{zh}|{a}{ch}{e} {d}{r}{y}{zh}|{a}{ch}{o}{yi} {d}{r}{y}{zh}|{a}{ch}{i}{i`} {d}{r}{y}{zh}|{a}{ch}{u} {d}{r}{y}{zh}|{a}{ch}{o}{iu} - '{a}{ch}{i}' '{a}{ch}{y}{kh}' '{a}{ch}{y}{m}{y}' // {d}{r}{y}{zh}|{a}{ch}{i} {d}{r}{y}{zh}|{a}{ch}{y}{kh} {d}{r}{y}{zh} |{a}{ch}{y}{m}{y} - '{iu}{ch}{y}{i`}' '{iu}{ch}{o}{gh}{o}' '{iu}{ch}{o}{m}{u}' '{iu}{ch}{y}{m}' '{iu}{ch}{i}{m}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{gh}{o} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{o}{m}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m} {d}{a}{l}{e}{n}{i}|{iu}{ch}{i}{m} - '{iu}{ch}{a}' '{iu}{ch}{e}' '{iu}{ch}{o}{yi}' '{iu}{ch}{i}{i`}' '{iu}{ch}{u}' '{iu}{ch}{o}{iu}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{a} {d}{a}{l}{e}{n}{i}|{iu}{ch}{e} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{yi} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{i}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{iu} - '{iu}{ch}{i}' '{iu}{ch}{y}{kh}' '{iu}{ch}{y}{m}{y}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{i} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{kh} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m}{y} - '{u}{ch}{y}{i`}' '{u}{ch}{o}{gh}{o}' '{u}{ch}{o}{m}{u}' '{u}{ch}{y}{m}' '{u}{ch}{i}{m}' // {p}{y}{sh}|{u}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{u}{ch}{o}{gh}{o} {p}{y}{sh}|{u}{ch}{o}{m}{u} {p}{y}{sh}|{u}{ch}{y}{m} {p}{y}{sh}|{u}{ch}{i}{m} - '{u}{ch}{a}' '{u}{ch}{e}' '{u}{ch}{o}{yi}' '{u}{ch}{i}{i`}' '{u}{ch}{u}' '{u}{ch}{o}{iu}' // {p}{y}{sh}|{u}{ch}{a} {p}{y}{sh}|{u}{ch}{e} {p}{y}{sh}|{u}{ch}{o}{yi} {p}{y}{sh}|{u}{ch}{i}{i`} {p}{y}{sh}|{u}{ch}{u} {p}{y}{sh}|{u}{ch}{o}{iu} - '{u}{ch}{i}' '{u}{ch}{y}{kh}' '{u}{ch}{y}{m}{y}' // {p}{y}{sh}|{u}{ch}{i} {p}{y}{sh}|{u}{ch}{y}{kh} {p}{y}{sh}|{u}{ch}{y}{m}{y} - '{e}{n}{y}{i`}' '{e}{n}{o}{gh}{o}' '{e}{n}{o}{m}{u}' '{e}{n}{y}{m}' '{e}{n}{i}{m}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} - '{e}{n}{a}' '{e}{n}{e}' '{e}{n}{o}{yi}' '{e}{n}{i}{i`}' '{e}{n}{u}' '{e}{n}{o}{iu}' // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} - '{e}{n}{i}' '{e}{n}{y}{kh}' '{e}{n}{y}{m}{y}' // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} + '{ia}{ch}' // {s}{y}{d}|{ia}{ch}{y}{i`} {s}{y}{d}|{ia}{ch}{o}{gh}{o} {s}{y}{d}|{ia}{ch}{o}{m}{u} {s}{y}{d}|{ia}{ch}{y}{m} {s}{y}{d}|{ia}{ch}{i}{m} + // {s}{y}{d}|{ia}{ch}{a} {s}{y}{d}|{ia}{ch}{e} {s}{y}{d}|{ia}{ch}{o}{yi} {s}{y}{d}|{ia}{ch}{i}{i`} {s}{y}{d}|{ia}{ch}{u} {s}{y}{d}|{ia}{ch}{o}{iu} + // {s}{y}{d}|{ia}{ch}{i} {s}{y}{d}|{ia}{ch}{y}{kh} {s}{y}{d}|{ia}{ch}{y}{m}{y} + + '{a}{ch}' // {d}{r}{y}{zh}|{a}{ch}{y}{i`} {d}{r}{y}{zh}|{a}{ch}{o}{gh}{o} {d}{r}{y}{zh}|{a}{ch}{o}{m}{u} {d}{r}{y}{zh}|{a}{ch}{y}{m} {d}{r}{y}{zh}|{a}{ch}{i}{m} + // {d}{r}{y}{zh}|{a}{ch}{a} {d}{r}{y}{zh}|{a}{ch}{e} {d}{r}{y}{zh}|{a}{ch}{o}{yi} {d}{r}{y}{zh}|{a}{ch}{i}{i`} {d}{r}{y}{zh}|{a}{ch}{u} {d}{r}{y}{zh}|{a}{ch}{o}{iu} + // {d}{r}{y}{zh}|{a}{ch}{i} {d}{r}{y}{zh}|{a}{ch}{y}{kh} {d}{r}{y}{zh}|{a}{ch}{y}{m}{y} + + '{iu}{ch}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{gh}{o} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{o}{m}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m} {d}{a}{l}{e}{n}{i}|{iu}{ch}{i}{m} + // {d}{a}{l}{e}{n}{i}|{iu}{ch}{a} {d}{a}{l}{e}{n}{i}|{iu}{ch}{e} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{yi} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{i}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{iu} + // {d}{a}{l}{e}{n}{i}|{iu}{ch}{i} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{kh} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m}{y} + '{u}{ch}' // {p}{y}{sh}|{u}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{u}{ch}{o}{gh}{o} {p}{y}{sh}|{u}{ch}{o}{m}{u} {p}{y}{sh}|{u}{ch}{y}{m} {p}{y}{sh}|{u}{ch}{i}{m} + // {p}{y}{sh}|{u}{ch}{a} {p}{y}{sh}|{u}{ch}{e} {p}{y}{sh}|{u}{ch}{o}{yi} {p}{y}{sh}|{u}{ch}{i}{i`} {p}{y}{sh}|{u}{ch}{u} {p}{y}{sh}|{u}{ch}{o}{iu} + // {p}{y}{sh}|{u}{ch}{i} {p}{y}{sh}|{u}{ch}{y}{kh} {p}{y}{sh}|{u}{ch}{y}{m}{y} + + // Need or needn't ? + // '{e}{n}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} + // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} + // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} (delete) ) ) - ) + // define reflexive as ( + // [substring] among ( + // '{t}{y}{s}{ia}' // {b}{y}{t}{y}{s}{ia} + // '{t}{y}{s}{soft}' // {b}{o}{r}|{o}.{t}{y}{s}{soft} + // '{t}{soft}{s}{ia}' // {r}{o}{b}{y}|{t}{soft}{s}{ia} # => {r}{o}{b}|{y}{t}{soft}{s}{ia} !? - {b}{e}{r}{e} {z}{a}{v}{zh}{d}{y} {d}{o}{v}{sh}{y}{i`}, {t}{r}{e}{b}{a} {i}{n}{sh}{e} {s}{l}{o}{v}{o} {p}{i}{d}{i}{b}{r}{a}{t}{y} {a}{b}{o} {v}{y}{d}{a}{l}{y}{t}{y} {ia}{k}{e}{s}{soft} {z} {p}{r}{a}{v}{y}{l} + // '{i}{t}{soft}{s}{ia}' // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} + // '{t}{e}{s}{ia}' // {b}{a}{v}|{t}{e}{s}{ia} + // '{i`}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{s}{ia} + // '{i`}{t}{e}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} + // '{a}{t}{soft}{s}{ia}' // {b}{a}{ch}|{a}{t}{soft}{s}{ia} + // '{v}{s}{ia}' '{l}{a}{s}{ia}' '{l}{o}{s}{ia}' '{l}{y}{s}{ia}' // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} + // '{v}{s}{soft}' '{l}{a}{s}{soft}' '{l}{o}{s}{soft}' '{l}{y}{s}{soft}' // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} + // '{iu}{s}{ia}' '{ye}{sh}{s}{ia}' '{ye}{t}{soft}{s}{ia}' '{ye}{m}{o}{s}{ia}' '{ye}{t}{e}{s}{ia}' '{iu}{t}{soft}{s}{ia}' // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} + // '{u}{s}{ia}' '{e}{sh}{s}{ia}' '{e}{t}{soft}{s}{ia}' '{e}{m}{o}{s}{ia}' '{e}{t}{e}{s}{ia}' '{u}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} + // '{l}{iu}{s}{ia}' '{y}{sh}{s}{ia}' '{y}{t}{soft}{s}{ia}' '{y}{m}{o}{s}{ia}' '{y}{t}{e}{s}{ia}' '{l}{ia}{t}{soft}{s}{ia}'// {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} + // '{yi}{sh}{s}{ia}' '{yi}{t}{soft}{s}{ia}' '{yi}{m}{o}{s}{ia}' '{yi}{t}{e}{s}{ia}' '{ia}{t}{soft}{s}{ia}' // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} + // (delete) + // ) + // ) + define reflexive as ( [substring] among ( - // '{s}{ia}' - // '{s}{'}' - // (delete) - - '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} - '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} - '{t}{y}{s}{ia}' // {b}{y}|{t}{y}{s}{ia} - '{t}{y}{s}{soft}' // {b}{o}{r}{o}|{t}{y}{s}{soft} - // '{t}{soft}{s}{ia}' // {r}{o}{b}{y}|{t}{soft}{s}{ia} ??? - '{i}{t}{soft}{s}{ia}' // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} - '{t}{e}{s}{ia}' // {b}{a}{v}|{t}{e}{s}{ia} - '{i`}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{s}{ia} - '{i`}{t}{e}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} - '{v}{s}{ia}' '{l}{a}{s}{ia}' '{l}{o}{s}{ia}' '{l}{y}{s}{ia}' // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} - '{v}{s}{soft}' '{l}{a}{s}{soft}' '{l}{o}{s}{soft}' '{l}{y}{s}{soft}' // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} - '{iu}{s}{ia}' '{ye}{sh}{s}{ia}' '{ye}{t}{soft}{s}{ia}' '{ye}{m}{o}{s}{ia}' '{ye}{t}{e}{s}{ia}' '{iu}{t}{soft}{s}{ia}' // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} - '{u}{s}{ia}' '{e}{sh}{s}{ia}' '{e}{t}{soft}{s}{ia}' '{e}{m}{o}{s}{ia}' '{e}{t}{e}{s}{ia}' '{u}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} - '{l}{iu}{s}{ia}' '{y}{sh}{s}{ia}' '{y}{t}{soft}{s}{ia}' '{y}{m}{o}{s}{ia}' '{y}{t}{e}{s}{ia}' '{l}{ia}{t}{soft}{s}{ia}'// {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} - '{yi}{sh}{s}{ia}' '{yi}{t}{soft}{s}{ia}' '{yi}{m}{o}{s}{ia}' '{yi}{t}{e}{s}{ia}' '{ia}{t}{soft}{s}{ia}' // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} - '{a}{t}{soft}{s}{ia}' // {b}{a}{ch}|{a}{t}{soft}{s}{ia} + '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} + '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} + // {b}{y}|{t}{y}{s}{ia} + // {b}{o}{r}{o}|{t}{y}{s}{soft} + // {r}{o}{b}{y}|{t}{soft}{s}{ia} ??? + // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} + // {b}{a}{v}|{t}{e}{s}{ia} + // {v}{d}{u}{m}{a}|{i`}{s}{ia} + // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} + // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} + // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} + // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} + // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} + // {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} + // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} + // {b}{a}{ch}|{a}{t}{soft}{s}{ia} + '{ye}{t}{soft}{s}{ia}' // {s}{m}{i}|{ye}{t}{soft}.{s}{ia} + '{e}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{e}{t}{soft}.{s}{ia} (delete) ) ) @@ -304,11 +327,14 @@ define stem as ( // noun perfective_gerund or - ( try reflexive - adjectival or verb or noun + ( + try reflexive + adjectival or verb or noun ) ) - try([ '{i}' ] delete) + + // Need or needn't ? + // try([ '{i}' ] delete) // {a}{k}{a}{d}{e}{m}{i}{iu} => {a}{k}{a}{d}{e}{m} // because noun ending -i{iu} is being treated as verb ending -{iu} // do derivational diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index dbc4a4a7..21daa2be 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -37,7 +37,7 @@ stringdef iu '{U+044E}' stringdef ia '{U+044F}' stringdef apostrophe '{U+0027}' -routines ( mark_regions R2 +routines ( mark_regions R1 R2 perfective_gerund adjective adjectival @@ -50,7 +50,7 @@ routines ( mark_regions R2 externals ( stem ) -integers ( pV p2 ) +integers ( pV p1 p2 ) groupings ( v ) @@ -59,15 +59,17 @@ define v 'аеєиіїоуюя' define mark_regions as ( $pV = limit + $p1 = limit $p2 = limit do ( - gopast v setmark pV gopast non-v + gopast v setmark pV gopast non-v setmark p1 gopast v gopast non-v setmark p2 ) ) backwardmode ( + define R1 as $p1 <= cursor define R2 as $p2 <= cursor define perfective_gerund as ( @@ -152,49 +154,70 @@ backwardmode ( // 'ующ' // present active participle // (delete) - 'ячий' 'ячого' 'ячому' 'ячим' 'ячім' // сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім - 'яча' 'яче' 'ячої' 'ячій' 'ячу' 'ячою' // сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою - 'ячі' 'ячих' 'ячими' // сид|ячі сид|ячих сид|ячими - 'ачий' 'ачого' 'ачому' 'ачим' 'ачім' // дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім - 'ача' 'аче' 'ачої' 'ачій' 'ачу' 'ачою' // дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою - 'ачі' 'ачих' 'ачими' // дриж|ачі дриж|ачих дриж |ачими - 'ючий' 'ючого' 'ючому' 'ючим' 'ючім' // далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім - 'юча' 'юче' 'ючої' 'ючій' 'ючу' 'ючою' // далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою - 'ючі' 'ючих' 'ючими' // далені|ючі далені|ючих далені|ючими - 'учий' 'учого' 'учому' 'учим' 'учім' // пиш|учий далені|учого пиш|учому пиш|учим пиш|учім - 'уча' 'уче' 'учої' 'учій' 'учу' 'учою' // пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою - 'учі' 'учих' 'учими' // пиш|учі пиш|учих пиш|учими - 'ений' 'еного' 'еному' 'еним' 'енім' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім - 'ена' 'ене' 'еної' 'еній' 'ену' 'еною' // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною - 'ені' 'ених' 'еними' // втрач|ені втрач|ених втрач|еними + 'яч' // сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім + // сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою + // сид|ячі сид|ячих сид|ячими + + 'ач' // дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім + // дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою + // дриж|ачі дриж|ачих дриж|ачими + + 'юч' // далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім + // далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою + // далені|ючі далені|ючих далені|ючими + 'уч' // пиш|учий далені|учого пиш|учому пиш|учим пиш|учім + // пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою + // пиш|учі пиш|учих пиш|учими + + // Need or needn't ? + // 'ен' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім + // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною + // втрач|ені втрач|ених втрач|еними (delete) ) ) - ) + // define reflexive as ( + // [substring] among ( + // 'тися' // битися + // 'тись' // бор|о.тись + // 'ться' // роби|ться # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил + // 'іться' // подруж|іться + // 'теся' // бав|теся + // 'йся' // вдума|йся + // 'йтеся' // вдума|йтеся + // 'аться' // бач|аться + // 'вся' 'лася' 'лося' 'лися' // вчи|вся вчи|лася вчи|лося вчи|лися + // 'всь' 'лась' 'лось' 'лись' // вчи|всь вчи|лась вчи|лось вчи|лись + // 'юся' 'єшся' 'ється' 'ємося' 'єтеся' 'ються' // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються + // 'уся' 'ешся' 'еться' 'емося' 'етеся' 'уться' // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться + // 'люся' 'ишся' 'иться' 'имося' 'итеся' 'ляться'// див|люся див|ишся див|иться див|имося див|итеся див|ляться + // 'їшся' 'їться' 'їмося' 'їтеся' 'яться' // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться + // (delete) + // ) + // ) + define reflexive as ( [substring] among ( - // 'ся' - // 'с{'}' - // (delete) - - 'ся' // осік|ся - 'сь' // недонавчи|сь - 'тися' // би|тися - 'тись' // боро|тись - // 'ться' // роби|ться ??? - 'іться' // подруж|іться - 'теся' // бав|теся - 'йся' // вдума|йся - 'йтеся' // вдума|йтеся - 'вся' 'лася' 'лося' 'лися' // вчи|вся вчи|лася вчи|лося вчи|лися - 'всь' 'лась' 'лось' 'лись' // вчи|всь вчи|лась вчи|лось вчи|лись - 'юся' 'єшся' 'ється' 'ємося' 'єтеся' 'ються' // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються - 'уся' 'ешся' 'еться' 'емося' 'етеся' 'уться' // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться - 'люся' 'ишся' 'иться' 'имося' 'итеся' 'ляться'// див|люся див|ишся див|иться див|имося див|итеся див|ляться - 'їшся' 'їться' 'їмося' 'їтеся' 'яться' // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться - 'аться' // бач|аться + 'ся' // осік|ся + 'сь' // недонавчи|сь + // би|тися + // боро|тись + // роби|ться ??? + // подруж|іться + // бав|теся + // вдума|йся + // вдума|йтеся + // вчи|вся вчи|лася вчи|лося вчи|лися + // вчи|всь вчи|лась вчи|лось вчи|лись + // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються + // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться + // див|люся див|ишся див|иться див|имося див|итеся див|ляться + // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться + // бач|аться + 'ється' // смі|єть.ся + 'еться' // спиш|еть.ся (delete) ) ) @@ -304,11 +327,14 @@ define stem as ( // noun perfective_gerund or - ( try reflexive - adjectival or verb or noun + ( + try reflexive + adjectival or verb or noun ) ) - try([ 'і' ] delete) + + // Need or needn't ? + // try([ 'і' ] delete) // академію => академ // because noun ending -iю is being treated as verb ending -ю // do derivational diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb index e9f6b687..01472a47 100644 --- a/tests/algorithms/ukrainian_test.rb +++ b/tests/algorithms/ukrainian_test.rb @@ -53,6 +53,8 @@ 'ячися' => %w[] } +# do we need to add prefix rule 'н*' for adjectives? +# because removes single vowels for verbs like 'вчи|ла.сь' = > 'вчи|л' adjective = { 'ий ого ому им ім' => %w[зелен|ий зелен|ого зелен|ому зелен|им зелен|ім], 'іший ішого ішому ішим ішім' => %w[зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім], @@ -67,41 +69,106 @@ } adjectival = { - # нн => беспреста|нн.о деревя|нн.ыми - 'ячий ячого ячому ячим ячім' => %w[сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім], - 'яча яче ячої ячій ячу ячою' => %w[сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою], - 'ячі ячих ячими' => %w[сид|ячі сид|ячих сид|ячими], - 'ачий ачого ачому ачим ачім' => %w[дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім], - 'ача аче ачої ачій ачу ачою' => %w[дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою], - 'ачі ачих ачими' => %w[дриж|ачі дриж|ачих дриж |ачими], - 'ючий ючого ючому ючим ючім' => %w[далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім], - 'юча юче ючої ючій ючу ючою' => %w[далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою], - 'ючі ючих ючими' => %w[далені|ючі далені|ючих далені|ючими], - 'учий учого учому учим учім' => %w[пиш|учий далені|учого пиш|учому пиш|учим пиш|учім], - 'уча уче учої учій учу учою' => %w[пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою], - 'учі учих учими' => %w[пиш|учі пиш|учих пиш|учими], - 'ений еного еному еним енім' => %w[втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім ], - 'ена ене еної еній ену еною' => %w[втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною], - 'ені ених еними' => %w[втрач|ені втрач|ених втрач|еними], + 'яч' => %w[сид|яч.ий сид|яч.ого сид|яч.ому сид|яч.им сид|яч.ім + сид|яч.а сид|яч.е сид|яч.ої сид|яч.ій сид|яч.у сид|яч.ою + сид|яч.і сид|яч.их сид|яч.ими], + + 'ач' => %w[дриж|ач.ий дриж|ач.ого дриж|ач.ому дриж|ач.им дриж|ач.ім + дриж|ач.а дриж|ач.е дриж|ач.ої дриж|ач.ій дриж|ач.у дриж|ач.ою + дриж|ач.і дриж|ач.их дриж|ач.ими], + + 'юч' => %w[далені|юч.ий далені|юч.ого далені|юч.ому далені|юч.им далені|юч.ім + далені|юч.а далені|юч.е далені|юч.ої далені|юч.ій далені|юч.у далені|юч.ою + далені|юч.і далені|юч.их далені|юч.ими], + + 'уч' => %w[пиш|уч.ий далені|уч.ого пиш|уч.ому пиш|уч.им пиш|уч.ім + пиш|уч.а пиш|уч.е пиш|уч.ої пиш|уч.ій пиш|уч.у пиш|уч.ою + пиш|уч.і пиш|уч.их пиш|уч.ими], + + # Need or needn't ? + # 'ен' => %w[втрач|ен.ий втрач|ен.ого втрач|ен.ому втрач|ен.им втрач|ен.ім + # втрач|ен.а втрач|ен.е втрач|ен.ої втрач|ен.ій втрач|ен.у втрач|ен.ою + # втрач|ен.і втрач|ен.их втрач|ен.ими], } +# https://en.wikipedia.org/wiki/Reflexive_pronoun +# https://en.wikipedia.org/wiki/Reflexive_verb +# https://uk.wikipedia.org/wiki/%D0%A0%D0%B5%D1%84%D0%BB%D0%B5%D0%BA%D1%81%D0%B8%D0%B2%D0%BD%D0%B5_%D0%B4%D1%96%D1%94%D1%81%D0%BB%D0%BE%D0%B2%D0%BE +# reflexive_full = { +# # 'ся' => %w[осік|ся], +# # 'сь' => %w[недонавч|и.сь], # вчи|сь +# 'тися' => %w[би|тися милува|тися], +# 'тись' => %w[боро|тись], +# 'ться' => %w[милується|ться], # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил +# 'іться' => %w[подруж|іться], +# 'теся' => %w[бав|теся], +# 'йся' => %w[вдума|йся], +# 'йтеся' => %w[вдума|йтеся], +# 'аться' => %w[бач|аться], +# 'вся лася лося лися' => %w[вчи|вся вчи|лася вчи|лося вчи|лися], +# 'всь лась лось лись' => %w[вчи|всь вчи|лась вчи|лось вчи|лись], +# 'юся єшся ється ємося єтеся ються' => %w[смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються], +# 'уся ешся еться емося етеся уться' => %w[спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться], +# 'люся ишся иться имося итеся ляться'=> %w[див|люся див|ишся див|иться див|имося див|итеся див|ляться], +# 'їшся їться їмося їтеся яться' => %w[бо|їшся бо|їться бо|їмося бо|їтеся бо|яться], +# } + +# reflexive_short = { +# 'сь' => %w[вчи|сь +# недонавч|и.сь +# боро|ти.сь +# вчи|в.сь вчи|ло.сь вчи|ли.сь], +# # вчи|ла.сь - removes 'а' in adjective ? + +# 'ся' => %w[осік|ся +# би|ти.ся +# роб|иться +# подруж|іться +# бавт|е.ся +# вдума|йся +# вдумайт|еся +# вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся +# смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються +# спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться +# див|люся див|ишся див|иться див|имося див|итеся див|ляться +# бо|їшся бо|їться бо|їмося бо|їтеся бо|яться +# бач|аться], + +# # бавт|е.ся # adj instead of verb бав|те.ся +# # вдумайт|еся # adj instead of verb вдума|йтеся +# } + +# абсорбувати, абсорбувать, абсорбуй, абсорбуймо, абсорбуйте, абсорбую, абсорбуєш, +# абсорбує, абсорбуємо, абсорбуєм, абсорбуєте, абсорбують, абсорбуватиму, абсорбуватимеш, абсорбуватиме, +# абсорбуватимем, абсорбуватимемо, абсорбуватимете, абсорбуватимуть, абсорбував, абсорбувала, абсорбувало, +# абсорбували, абсорбовано + reflexive = { + # *ся 'ся' => %w[осік|ся], - 'сь' => %w[недонавчи|сь], # вчи|сь - 'тися' => %w[би|тися], - 'тись' => %w[боро|тись], - # 'ться' => %w[роби|ться], # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил - 'іться' => %w[подруж|іться], - 'теся' => %w[бав|теся], - 'йся' => %w[вдума|йся], - 'йтеся' => %w[вдума|йтеся], - 'вся лася лося лися' => %w[вчи|вся вчи|лася вчи|лося вчи|лися], - 'всь лась лось лись' => %w[вчи|всь вчи|лась вчи|лось вчи|лись], - 'юся єшся ється ємося єтеся ються' => %w[смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються], - 'уся ешся еться емося етеся уться' => %w[спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться], - 'люся ишся иться имося итеся ляться'=> %w[див|люся див|ишся див|иться див|имося див|итеся див|ляться], - 'їшся їться їмося їтеся яться' => %w[бо|їшся бо|їться бо|їмося бо|їтеся бо|яться], - 'аться' => %w[бач|аться], + + 'ти' => %w[би|ти.ся милува|ти.ся], + # 'ть' => %w[роб|ить.ся], # вже є правило "ить" + 'іть' => %w[подруж|іть.ся], + 'те' => %w[бав|те.ся], + 'й' => %w[вдума|й.ся], + 'йте' => %w[вдума|йте.ся], + 'ать' => %w[бач|ать.ся], + + 'в ла ло ли' => %w[вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся], + 'ю єш ємо єте ють' => %w[смі|ю.ся смі|єш.ся смі|ємо.ся смі|єте.ся смі|ють.ся], + 'у еш емо ете уть' => %w[спиш|у.ся спиш|еш.ся спиш|емо.ся спиш|ете.ся спиш|уть.ся], + 'лю иш ить имо ите лять' => %w[див|лю.ся див|иш.ся див|ить.ся див|имо.ся див|ите.ся див|лять.ся], + 'їш їть їмо їте ять' => %w[бо|їш.ся бо|їть.ся бо|їмо.ся бо|їте.ся бо|ять.ся], + + 'ється' => %w[смі|ється], # незнайшов дієслів + 'еться' => %w[спиш|еться], # незнайшов дієслів + + # *сь + 'сь' => %w[недонавч|и.сь], # вчи|сь + + '2 ти' => %w[боро|ти.сь], + '2 в ла ло ли' => %w[вчи|в.сь вчи|ла.сь вчи|ло.сь вчи|ли.сь], } verb = { @@ -111,20 +178,22 @@ 'те' => %w[відправ|те], 'й' => %w[чита|й], 'йте' => %w[дума|йте], + 'ать' => %w[бач|ать], 'в ла ло ли' => %w[чита|в чита|ла чита|ло чита|ли], 'ю єш є ємо єте ють' => %w[чита|ю чита|єш чита|є чита|ємо чита|єте чита|ють], 'у еш е емо ете уть' => %w[пиш|у пиш|еш пиш|е пиш|емо пиш|ете пиш|уть], 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], 'їш їть їмо їте ять' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять], - 'ать' => %w[бач|ать], + } + noun = { 'а и і у ою о' => %w[вод|а вод|и вод|і вод|у вод|ою вод|о], 'ам ами ах' => %w[вод|ам вод|ами вод|ах], 'я ю ею е' => %w[пісн|я пісн|ю пісн|ею пісн|е], 'ям ями ях' => %w[пісн|ям пісн|ями пісн|ях], - 'ові ом' => %w[батьк|ові батьк|ом], + 'ові ом' => %w[батьк|ові батьк|ом бор|ом], 'ець ем' => %w[олів|ець олівц|ем], # ю олівц|ю - повтор 'ень' => %w[зел|ень], 'ій' => %w[ген|ій], @@ -146,13 +215,14 @@ # 'ь' => %w[свідоміст|ь] # } -# exceptions = { -# # ё => е -# 'угнетённый' => 'угнетен', +exceptions = { + # ё => е + # 'угнетённый' => 'угнетен', -# # -ию => '' -# 'академию' => 'академ' -# } + ## Need or needn't ? + # -ію => '' + # 'академію' => 'академ' +} $all_tests = [] $errors = {} @@ -165,11 +235,19 @@ def check_words_set(words_set, set_name) words_set.each do |_rule, test_cases| test_cases.each do |test_case| stem, ending = test_case.split('|') - word = [stem, ending].join + word = [stem, ending&.delete('.')].join $all_tests << word result_stem = (`echo "#{word}" | ./stemwords -l uk`).strip - + # if result_stem == 'ач' + # puts '>>' + # puts test_case + # puts stem + # puts ending + # puts word + # puts result_stem + # puts '<<' + # end $errors[set_name] ||= [] $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem end @@ -189,11 +267,12 @@ def check_words_set(words_set, set_name) check_words_set(words_set, set_name) end -# exceptions.each do |word, stem| -# $all_tests << word -# result_stem = (`echo "#{word}" | ./stemwords -syntax -l uk `).strip -# $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem -# end +exceptions.each do |word, stem| + $all_tests << word + result_stem = (`echo "#{word}" | ./stemwords -l uk `).strip + $errors['exceptions'] ||= [] + $errors['exceptions'] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem +end if $errors.empty? puts("#{$all_tests.count} test(s) passed successfully!") @@ -205,3 +284,59 @@ def check_words_set(words_set, set_name) puts(errs.join("\n")) end end + +a = %w[ + ий ого ому им ім + іший ішого ішому ішим ішім + іше + ої + іша ішої ішій ішу ішою + их ими + іші іших ішими + ього ьому + ьої ьою + іх іми +] + +v = %w[ + ти + ть + іть + те + йте + ать + ла ло ли + єш ємо єте ють + еш емо ете уть + лю иш ить имо ите лять + їш їть їмо їте ять +] + +n = %w[ + ам ами ах + ею + ям ями ях + ові ом + ець ем + ень + ой + ію ії +] + +adj_verb_noun = %w[ + е а у і я ю + й в ю є у е + а и і у о я ю е й ь + ою ій +] + +puts "a & v" +p (a & v).sort + +puts "v & n" +p (v & n).sort + +puts "n & a" +p (n & a).sort + + From fd30acf179eef95147c2bdf294d236dd0de3d7af Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Sat, 10 Jun 2023 20:54:11 +0300 Subject: [PATCH 08/13] Add Ukrainian stemmer --- algorithms/ukrainian.sbl | 501 ++++++++++++----------------- explanations/ukrainian.sbl.utf | 501 ++++++++++++----------------- tests/algorithms/Readme.md | 4 +- tests/algorithms/ukrainian_test.rb | 263 +++++++++------ 4 files changed, 574 insertions(+), 695 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index 5604bb1a..e848e283 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -35,17 +35,32 @@ stringdef shch '{U+0449}' stringdef soft '{U+044C}' stringdef iu '{U+044E}' stringdef ia '{U+044F}' -stringdef apostrophe '{U+0027}' - -routines ( mark_regions R1 R2 - perfective_gerund - adjective - adjectival - reflexive - verb - noun - // derivational - // tidy_up + +// Apostrophe-like symbols +// stringdef a_apostrophe '{U+0027}' // ' +// stringdef a_grave_accent U+0060 // ` cannot to remove system char in Snowball +stringdef a_ml_prime '{U+02B9}' // {a_ml_prime} +stringdef a_mlt_comma '{U+02BB}' // {a_mlt_comma} +stringdef a_ml_apostrophe '{U+02BC}' // {a_ml_apostrophe} +stringdef a_mlr_comma '{U+02BD}' // {a_mlr_comma} +stringdef a_mlv_line '{U+02C8}' // {a_mlv_line} +stringdef a_lsq_mark '{U+2018}' // {a_lsq_mark} +stringdef a_rsq_mark '{U+2019}' // {a_rsq_mark} +stringdef a_shr9q_mark '{U+201B}' // {a_shr9q_mark} +stringdef a_prime '{U+2032}' // {a_prime} + +routines ( + prelude + mark_regions R1 R2 + perfective_gerund + adjective + adjectival + reflexive + verb + noun + common_avn + derivational + // tidy_up ) externals ( stem ) @@ -56,315 +71,205 @@ groupings ( v ) define v '{a}{e}{ye}{y}{i}{yi}{o}{u}{iu}{ia}' -define mark_regions as ( +define prelude as ( + do repeat ( goto (['{g}']) <- '{gh}' ) + + // Remove any apostrophe-like symbols + do repeat ( goto (['{'}']) delete ) + do repeat ( goto (['{a_ml_prime}']) delete ) + do repeat ( goto (['{a_mlt_comma}']) delete ) + do repeat ( goto (['{a_ml_apostrophe}']) delete ) + do repeat ( goto (['{a_mlr_comma}']) delete ) + do repeat ( goto (['{a_mlv_line}']) delete ) + do repeat ( goto (['{a_lsq_mark}']) delete ) + do repeat ( goto (['{a_rsq_mark}']) delete ) + do repeat ( goto (['{a_shr9q_mark}']) delete ) + do repeat ( goto (['{a_prime}']) delete ) +) - $pV = limit - $p1 = limit - $p2 = limit - do ( - gopast v setmark pV gopast non-v setmark p1 - gopast v gopast non-v setmark p2 - ) +define mark_regions as ( + $pV = limit + $p1 = limit + $p2 = limit + do ( + gopast v setmark pV gopast non-v setmark p1 + gopast v gopast non-v setmark p2 + ) ) backwardmode ( - - define R1 as $p1 <= cursor - define R2 as $p2 <= cursor - - define perfective_gerund as ( - [substring] among ( - // '{v}' - // '{v}{sh}{i}' - // '{v}{sh}{i}{s}{'}' - // ('{a}' or '{ia}' delete) - // '{i}{v}' - // '{i}{v}{sh}{i}' - // '{i}{v}{sh}{i}{s}{'}' - // '{y}{v}' - // '{y}{v}{sh}{i}' - // '{y}{v}{sh}{i}{s}{'}' - // (delete) - - '{v}' // {d}{o}{n}{a}{p}{y}{s}{a}|{v} {d}{o}{r}{o}{b}{y}|{v} {d}{o}{r}{o}{b}{y}|{v} - '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} {z}{r}{o}{b}{y}|{v}{sh}{y} - '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} - '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} - // ('{a}' or '{ia}' delete) ??? - '{u}{ch}{y}' // {p}{y}{sh}|{u}{ch}{y} {r}{e}{v}|{u}{ch}{y} - '{iu}{ch}{y}' // {s}{ia}|{iu}{ch}{y} {p}{i}{d}{p}{y}{s}{u}|{iu}{ch}{y} - '{iu}{ch}{y}{s}{soft}' // {z}{m}{a}{gh}{a}|{iu}{ch}{y}{s}{soft} - '{iu}{ch}{y}{s}{ia}' // {n}{a}{v}{ch}{a}|{iu}{ch}{y}{s}{ia} - '{a}{ch}{y}' // {b}{a}{ch}|{a}{ch}{y} - '{a}{ch}{y}{s}{soft}' // {b}{a}{ch}|{a}{ch}{y}{s}{soft} - '{a}{ch}{y}{s}{ia}' // {b}{a}{ch}|{a}{ch}{y}{s}{ia} - '{l}{ia}{ch}{y}' // {r}{o}{b}|{l}{ia}{ch}{y} {l}{iu}{b}|{l}{ia}{ch}{y} - '{l}{ia}{ch}{y}{s}{soft}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{soft} - '{l}{ia}{ch}{y}{s}{ia}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{ia} - '{ia}{ch}{y}' // {s}{y}{d}|{ia}{ch}{y} {v}{o}{v}{t}{u}{z}|{ia}{ch}{y} - '{ia}{ch}{y}{s}{soft}' // ??? - '{ia}{ch}{y}{s}{ia}' // ??? - (delete) - ) + define R1 as $p1 <= cursor + define R2 as $p2 <= cursor + + define perfective_gerund as ( + [substring] among ( + '{v}' // {d}{o}{n}{a}{p}{y}{s}{a}|{v} {d}{o}{r}{o}{b}{y}|{v} {d}{o}{r}{o}{b}{y}|{v} + '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} {z}{r}{o}{b}{y}|{v}{sh}{y} + '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} + '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} + // ('{a}' or '{ia}' delete) ??? + '{u}{ch}{y}' // {p}{y}{sh}|{u}{ch}{y} {r}{e}{v}|{u}{ch}{y} + '{iu}{ch}{y}' // {s}{ia}|{iu}{ch}{y} {p}{i}{d}{p}{y}{s}{u}|{iu}{ch}{y} + '{iu}{ch}{y}{s}{soft}' // {z}{m}{a}{gh}{a}|{iu}{ch}{y}{s}{soft} + '{iu}{ch}{y}{s}{ia}' // {n}{a}{v}{ch}{a}|{iu}{ch}{y}{s}{ia} + '{a}{ch}{y}' // {b}{a}{ch}|{a}{ch}{y} + '{a}{ch}{y}{s}{soft}' // {b}{a}{ch}|{a}{ch}{y}{s}{soft} + '{a}{ch}{y}{s}{ia}' // {b}{a}{ch}|{a}{ch}{y}{s}{ia} + '{l}{ia}{ch}{y}' // {r}{o}{b}|{l}{ia}{ch}{y} {l}{iu}{b}|{l}{ia}{ch}{y} + '{l}{ia}{ch}{y}{s}{soft}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{soft} + '{l}{ia}{ch}{y}{s}{ia}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{ia} + '{ia}{ch}{y}' // {s}{y}{d}|{ia}{ch}{y} {v}{o}{v}{t}{u}{z}|{ia}{ch}{y} + '{ia}{ch}{y}{s}{soft}' // ??? + '{ia}{ch}{y}{s}{ia}' // ??? + (delete) + ) + ) + + define adjective as ( + [substring] among ( + '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' + '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' '{i}{sh}{e}' + '{o}{yi}' '{i}{i`}' '{o}{iu}' + '{i}{sh}{a}' '{i}{sh}{o}{yi}' '{i}{sh}{i}{i`}' '{i}{sh}{u}' '{i}{sh}{o}{iu}' + '{y}{kh}' '{y}{m}{y}' + '{i}{sh}{i}' '{i}{sh}{y}{kh}' '{i}{sh}{y}{m}{y}' + '{soft}{o}{gh}{o}' '{soft}{o}{m}{u}' + '{soft}{o}{yi}' '{soft}{o}{iu}' + '{i}{kh}' '{i}{m}{y}' + + '{ia}{ch}{a}' '{ia}{ch}{e}' '{ia}{ch}{u}' '{ia}{ch}{i}' + '{a}{ch}{a}' '{a}{ch}{e}' '{a}{ch}{u}' '{a}{ch}{i}' + '{iu}{ch}{a}' '{iu}{ch}{e}' '{iu}{ch}{u}' '{iu}{ch}{i}' + '{u}{ch}{a}' '{u}{ch}{e}' '{u}{ch}{u}' '{u}{ch}{i}' + (delete) ) + ) - define adjective as ( - [substring] among ( - // '{e}{e}' '{i}{e}' '{y}{e}' '{o}{e}' '{i}{m}{i}' '{y}{m}{i}' - // '{e}{i`}' '{o}{i`}' '{e}{m}' - // '{o}{m}' '{e}{g}{o}' '{o}{g}{o}' '{e}{m}{u}' - // '{u}{iu}' '{iu}{iu}' '{a}{ia}' - // '{e}{iu}' // - soft form of {o}{iu} - // (delete) - - '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' // {z}{e}{l}{e}{n}|{y}{i`} {z}{e}{l}{e}{n}|{o}{gh}{o} {z}{e}{l}{e}{n}|{o}{m}{u} {z}{e}{l}{e}{n}|{y}{m} {z}{e}{l}{e}{n}|{i}{m} - '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' // {z}{e}{l}{e}{n}|{i}{sh}{y}{i`} {z}{e}{l}{e}{n}|{i}{sh}{o}{gh}{o} {z}{e}{l}{e}{n}|{i}{sh}{o}{m}{u} {z}{e}{l}{e}{n}|{i}{sh}{y}{m} {z}{e}{l}{e}{n}|{i}{sh}{i}{m} - '{e}' '{i}{sh}{e}' // {z}{e}{l}{e}{n}|{e} {z}{e}{l}{e}{n}|{i}{sh}{e} - '{a}' '{o}{yi}' '{i}{i`}' '{u}' '{o}{iu}' // {z}{e}{l}{e}{n}|{a} {z}{e}{l}{e}{n}|{o}{yi} {z}{e}{l}{e}{n}|{i}{i`} {z}{e}{l}{e}{n}|{u} {z}{e}{l}{e}{n}|{o}{iu} - '{i}{sh}{a}' '{i}{sh}{o}{yi}' '{i}{sh}{i}{i`}' '{i}{sh}{u}' '{i}{sh}{o}{iu}' // {z}{e}{l}{e}{n}|{i}{sh}{a} {z}{e}{l}{e}{n}|{i}{sh}{o}{yi} {z}{e}{l}{e}{n}|{i}{sh}{i}{i`} {z}{e}{l}{e}{n}|{i}{sh}{u} {z}{e}{l}{e}{n}|{i}{sh}{o}{iu} - '{i}' '{y}{kh}' '{y}{m}{y}' // {z}{e}{l}{e}{n}|{i} {z}{e}{l}{e}{n}|{y}{kh} {z}{e}{l}{e}{n}|{y}{m}{y} - '{i}{sh}{i}' '{i}{sh}{y}{kh}' '{i}{sh}{y}{m}{y}' // {z}{e}{l}{e}{n}|{i}{sh}{i} {z}{e}{l}{e}{n}|{i}{sh}{y}{kh} {z}{e}{l}{e}{n}|{i}{sh}{y}{m}{y} - '{soft}{o}{gh}{o}' '{soft}{o}{m}{u}' // {v}{e}{r}{kh}{n}|{soft}{o}{gh}{o} {v}{e}{r}{kh}{n}|{soft}{o}{m}{u} - '{ia}' '{soft}{o}{yi}' '{iu}' '{soft}{o}{iu}' // {v}{e}{r}{kh}{n}|{ia} {v}{e}{r}{kh}{n}|{soft}{o}{yi} {v}{e}{r}{kh}{n}|{iu} {v}{e}{r}{kh}{n}|{soft}{o}{iu} - '{i}{kh}' '{i}{m}{y}' // {v}{e}{r}{kh}{n}|{i}{kh} {v}{e}{r}{kh}{n}|{i}{m}{y} - (delete) - ) - ) + define adjectival as ( + adjective - define adjectival as ( - adjective - - /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. - nn, {iu}shch, shch, u{iu}shch can be removed, with a small proportion of - errors. Removing im, uem, enn creates too many errors. - */ - - try ( - [substring] among ( - // '{e}{m}' // present passive participle - // '{n}{n}' // adjective from past passive participle - // '{v}{sh}' // past active participle - // '{iu}{shch}' '{shch}' // present active participle - // ('{a}' or '{ia}' delete) - - // //but not '{i}{m}' '{u}{e}{m}' // present passive participle - // //or '{e}{n}{n}' // adjective from past passive participle - - // '{i}{v}{sh}' '{y}{v}{sh}'// past active participle - // '{u}{iu}{shch}' // present active participle - // (delete) - - '{ia}{ch}' // {s}{y}{d}|{ia}{ch}{y}{i`} {s}{y}{d}|{ia}{ch}{o}{gh}{o} {s}{y}{d}|{ia}{ch}{o}{m}{u} {s}{y}{d}|{ia}{ch}{y}{m} {s}{y}{d}|{ia}{ch}{i}{m} - // {s}{y}{d}|{ia}{ch}{a} {s}{y}{d}|{ia}{ch}{e} {s}{y}{d}|{ia}{ch}{o}{yi} {s}{y}{d}|{ia}{ch}{i}{i`} {s}{y}{d}|{ia}{ch}{u} {s}{y}{d}|{ia}{ch}{o}{iu} - // {s}{y}{d}|{ia}{ch}{i} {s}{y}{d}|{ia}{ch}{y}{kh} {s}{y}{d}|{ia}{ch}{y}{m}{y} - - '{a}{ch}' // {d}{r}{y}{zh}|{a}{ch}{y}{i`} {d}{r}{y}{zh}|{a}{ch}{o}{gh}{o} {d}{r}{y}{zh}|{a}{ch}{o}{m}{u} {d}{r}{y}{zh}|{a}{ch}{y}{m} {d}{r}{y}{zh}|{a}{ch}{i}{m} - // {d}{r}{y}{zh}|{a}{ch}{a} {d}{r}{y}{zh}|{a}{ch}{e} {d}{r}{y}{zh}|{a}{ch}{o}{yi} {d}{r}{y}{zh}|{a}{ch}{i}{i`} {d}{r}{y}{zh}|{a}{ch}{u} {d}{r}{y}{zh}|{a}{ch}{o}{iu} - // {d}{r}{y}{zh}|{a}{ch}{i} {d}{r}{y}{zh}|{a}{ch}{y}{kh} {d}{r}{y}{zh}|{a}{ch}{y}{m}{y} - - '{iu}{ch}' // {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{gh}{o} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{o}{m}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m} {d}{a}{l}{e}{n}{i}|{iu}{ch}{i}{m} - // {d}{a}{l}{e}{n}{i}|{iu}{ch}{a} {d}{a}{l}{e}{n}{i}|{iu}{ch}{e} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{yi} {d}{a}{l}{e}{n}{i}{iu}|{iu}{ch}{i}{i`} {d}{a}{l}{e}{n}{i}|{iu}{ch}{u} {d}{a}{l}{e}{n}{i}|{iu}{ch}{o}{iu} - // {d}{a}{l}{e}{n}{i}|{iu}{ch}{i} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{kh} {d}{a}{l}{e}{n}{i}|{iu}{ch}{y}{m}{y} - '{u}{ch}' // {p}{y}{sh}|{u}{ch}{y}{i`} {d}{a}{l}{e}{n}{i}|{u}{ch}{o}{gh}{o} {p}{y}{sh}|{u}{ch}{o}{m}{u} {p}{y}{sh}|{u}{ch}{y}{m} {p}{y}{sh}|{u}{ch}{i}{m} - // {p}{y}{sh}|{u}{ch}{a} {p}{y}{sh}|{u}{ch}{e} {p}{y}{sh}|{u}{ch}{o}{yi} {p}{y}{sh}|{u}{ch}{i}{i`} {p}{y}{sh}|{u}{ch}{u} {p}{y}{sh}|{u}{ch}{o}{iu} - // {p}{y}{sh}|{u}{ch}{i} {p}{y}{sh}|{u}{ch}{y}{kh} {p}{y}{sh}|{u}{ch}{y}{m}{y} - - // Need or needn't ? - // '{e}{n}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} - // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} - // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} - (delete) - ) - ) - ) + try ( + [substring] among ( + '{ia}{ch}' + '{a}{ch}' + '{iu}{ch}' + '{u}{ch}' + (delete) - // define reflexive as ( - // [substring] among ( - // '{t}{y}{s}{ia}' // {b}{y}{t}{y}{s}{ia} - // '{t}{y}{s}{soft}' // {b}{o}{r}|{o}.{t}{y}{s}{soft} - // '{t}{soft}{s}{ia}' // {r}{o}{b}{y}|{t}{soft}{s}{ia} # => {r}{o}{b}|{y}{t}{soft}{s}{ia} !? - {b}{e}{r}{e} {z}{a}{v}{zh}{d}{y} {d}{o}{v}{sh}{y}{i`}, {t}{r}{e}{b}{a} {i}{n}{sh}{e} {s}{l}{o}{v}{o} {p}{i}{d}{i}{b}{r}{a}{t}{y} {a}{b}{o} {v}{y}{d}{a}{l}{y}{t}{y} {ia}{k}{e}{s}{soft} {z} {p}{r}{a}{v}{y}{l} - // '{i}{t}{soft}{s}{ia}' // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} - // '{t}{e}{s}{ia}' // {b}{a}{v}|{t}{e}{s}{ia} - // '{i`}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{s}{ia} - // '{i`}{t}{e}{s}{ia}' // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} - // '{a}{t}{soft}{s}{ia}' // {b}{a}{ch}|{a}{t}{soft}{s}{ia} - // '{v}{s}{ia}' '{l}{a}{s}{ia}' '{l}{o}{s}{ia}' '{l}{y}{s}{ia}' // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} - // '{v}{s}{soft}' '{l}{a}{s}{soft}' '{l}{o}{s}{soft}' '{l}{y}{s}{soft}' // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} - // '{iu}{s}{ia}' '{ye}{sh}{s}{ia}' '{ye}{t}{soft}{s}{ia}' '{ye}{m}{o}{s}{ia}' '{ye}{t}{e}{s}{ia}' '{iu}{t}{soft}{s}{ia}' // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} - // '{u}{s}{ia}' '{e}{sh}{s}{ia}' '{e}{t}{soft}{s}{ia}' '{e}{m}{o}{s}{ia}' '{e}{t}{e}{s}{ia}' '{u}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} - // '{l}{iu}{s}{ia}' '{y}{sh}{s}{ia}' '{y}{t}{soft}{s}{ia}' '{y}{m}{o}{s}{ia}' '{y}{t}{e}{s}{ia}' '{l}{ia}{t}{soft}{s}{ia}'// {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} - // '{yi}{sh}{s}{ia}' '{yi}{t}{soft}{s}{ia}' '{yi}{m}{o}{s}{ia}' '{yi}{t}{e}{s}{ia}' '{ia}{t}{soft}{s}{ia}' // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} - // (delete) - // ) - // ) - - define reflexive as ( - [substring] among ( - '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} - '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} - // {b}{y}|{t}{y}{s}{ia} - // {b}{o}{r}{o}|{t}{y}{s}{soft} - // {r}{o}{b}{y}|{t}{soft}{s}{ia} ??? - // {p}{o}{d}{r}{u}{zh}|{i}{t}{soft}{s}{ia} - // {b}{a}{v}|{t}{e}{s}{ia} - // {v}{d}{u}{m}{a}|{i`}{s}{ia} - // {v}{d}{u}{m}{a}|{i`}{t}{e}{s}{ia} - // {v}{ch}{y}|{v}{s}{ia} {v}{ch}{y}|{l}{a}{s}{ia} {v}{ch}{y}|{l}{o}{s}{ia} {v}{ch}{y}|{l}{y}{s}{ia} - // {v}{ch}{y}|{v}{s}{soft} {v}{ch}{y}|{l}{a}{s}{soft} {v}{ch}{y}|{l}{o}{s}{soft} {v}{ch}{y}|{l}{y}{s}{soft} - // {s}{m}{i}|{iu}{s}{ia} {s}{m}{i}|{ye}{sh}{s}{ia} {s}{m}{i}|{ye}{t}{soft}{s}{ia} {s}{m}{i}|{ye}{m}{o}{s}{ia} {s}{m}{i}|{ye}{t}{e}{s}{ia} {s}{m}{i}|{iu}{t}{soft}{s}{ia} - // {s}{p}{y}{sh}|{u}{s}{ia} {s}{p}{y}{sh}|{e}{sh}{s}{ia} {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} {s}{p}{y}{sh}|{e}{m}{o}{s}{ia} {s}{p}{y}{sh}|{e}{t}{e}{s}{ia} {s}{p}{y}{sh}|{u}{t}{soft}{s}{ia} - // {d}{y}{v}|{l}{iu}{s}{ia} {d}{y}{v}|{y}{sh}{s}{ia} {d}{y}{v}|{y}{t}{soft}{s}{ia} {d}{y}{v}|{y}{m}{o}{s}{ia} {d}{y}{v}|{y}{t}{e}{s}{ia} {d}{y}{v}|{l}{ia}{t}{soft}{s}{ia} - // {b}{o}|{yi}{sh}{s}{ia} {b}{o}|{yi}{t}{soft}{s}{ia} {b}{o}|{yi}{m}{o}{s}{ia} {b}{o}|{yi}{t}{e}{s}{ia} {b}{o}|{ia}{t}{soft}{s}{ia} - // {b}{a}{ch}|{a}{t}{soft}{s}{ia} - '{ye}{t}{soft}{s}{ia}' // {s}{m}{i}|{ye}{t}{soft}.{s}{ia} - '{e}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{e}{t}{soft}.{s}{ia} - (delete) - ) + // Need or needn't ? + // '{e}{n}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} + // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} + // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} + ) ) - - define verb as ( - [substring] among ( - // '{n}{a}' '{l}{i}' - // '{l}' '{e}{m}' '{n}' '{n}{o}' '{e}{t}' '{iu}{t}' - // '{n}{y}' '{t}{'}' '{e}{sh}{'}' - - // '{n}{n}{o}' - // ('{a}' or '{ia}' delete) - - // '{i}{l}{a}' '{y}{l}{a}' '{e}{n}{a}' '{e}{i`}{t}{e}' - // '{u}{i`}{t}{e}' '{i}{t}{e}' '{i}{l}{i}' '{y}{l}{i}' '{e}{i`}' - // '{u}{i`}' '{i}{l}' '{y}{l}' '{i}{m}' '{y}{m}' '{e}{n}' - // '{i}{l}{o}' '{y}{l}{o}' '{e}{n}{o}' '{ia}{t}' '{u}{e}{t}' - // '{u}{iu}{t}' '{i}{t}' '{y}{t}' '{e}{n}{y}' '{i}{t}{'}' - // '{y}{t}{'}' '{i}{sh}{'}' '{u}{iu}' - // (delete) - /* note the short passive participle tests: - '{n}{a}' '{n}' '{n}{o}' '{n}{y}' - '{e}{n}{a}' '{e}{n}' '{e}{n}{o}' '{e}{n}{y}' - */ - - '{t}{y}' // {p}{r}{a}{ts}{iu}{v}{a}|{t}{y} - // '{t}{soft}' // {r}{o}{b}{y}|{t}{soft} ??? - '{i}{t}{soft}' // {r}{o}{b}|{i}{t}{soft} - '{t}{e}' // {v}{i}{d}{p}{r}{a}{v}|{t}{e} - '{i`}' // {ch}{y}{t}{a}|{i`} - '{i`}{t}{e}' // {d}{u}{m}{a}|{i`}{t}{e} - '{v}' '{l}{a}' '{l}{o}' '{l}{y}' // {ch}{y}{t}{a}|{v} {ch}{y}{t}{a}|{l}{a} {ch}{y}{t}{a}|{l}{o} {ch}{y}{t}{a}|{l}{y} - '{iu}' '{ye}{sh}' '{ye}' '{ye}{m}{o}' '{ye}{t}{e}' '{iu}{t}{soft}' // {ch}{y}{t}{a}|{iu} {ch}{y}{t}{a}|{ye}{sh} {ch}{y}{t}{a}|{ye} {ch}{y}{t}{a}|{ye}{m}{o} {ch}{y}{t}{a}|{ye}{t}{e} {ch}{y}{t}{a}|{iu}{t}{soft} - '{u}' '{e}{sh}' '{e}' '{e}{m}{o}' '{e}{t}{e}' '{u}{t}{soft}' // {p}{y}{sh}|{u} {p}{y}{sh}|{e}{sh} {p}{y}{sh}|{e} {p}{y}{sh}|{e}{m}{o} {p}{y}{sh}|{e}{t}{e} {p}{y}{sh}|{u}{t}{soft} - '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' // {r}{o}{b}|{l}{iu} {r}{o}{b}|{y}{sh} {r}{o}{b}|{y}{t}{soft} {r}{o}{b}|{y}{m}{o} {r}{o}{b}|{y}{t}{e} {r}{o}{b}|{l}{ia}{t}{soft} - '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' // {s}{t}{o}|{yi}{sh} {s}{t}{o}|{yi}{t}{soft} {s}{t}{o}|{yi}{m}{o} {s}{t}{o}|{yi}{t}{e} {s}{t}{o}|{ia}{t}{soft} - '{a}{t}{soft}' // {b}{a}{ch}|{a}{t}{soft} - (delete) - ) + ) + + define reflexive as ( + [substring] among ( + '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} + '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} + '{ye}{t}{soft}{s}{ia}' // {s}{m}{i}|{ye}{t}{soft}{s}{ia} + '{e}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} + (delete) ) - - define noun as ( - [substring] among ( - // '{a}' '{e}{v}' '{o}{v}' '{i}{e}' '{'}{e}' '{e}' - // '{i}{ia}{m}{i}' '{ia}{m}{i}' '{a}{m}{i}' '{e}{i}' '{i}{i}' - // '{i}' '{i}{e}{i`}' '{e}{i`}' '{o}{i`}' '{i}{i`}' '{i`}' - // '{i}{ia}{m}' '{ia}{m}' '{i}{e}{m}' '{e}{m}' '{a}{m}' '{o}{m}' - // '{o}' '{u}' '{a}{kh}' '{i}{ia}{kh}' '{ia}{kh}' '{y}' '{'}' - // '{i}{iu}' '{'}{iu}' '{iu}' '{i}{ia}' '{'}{ia}' '{ia}' - // (delete) - /* the small class of neuter forms '{e}{n}{i}' '{e}{n}{e}{m}' - '{e}{n}{a}' '{e}{n}' '{e}{n}{a}{m}' '{e}{n}{a}{m}{i}' '{e}{n}{a}{x}' - omitted - they only occur on 12 words. - */ - - '{a}' '{y}' '{i}' '{u}' '{o}{iu}' '{o}' // {v}{o}{d}|{a} {v}{o}{d}|{y} {v}{o}{d}|{i} {v}{o}{d}|{u} {v}{o}{d}|{o}{iu} {v}{o}{d}|{o} - '{a}{m}' '{a}{m}{y}' '{a}{kh}' // {v}{o}{d}|{a}{m} {v}{o}{d}|{a}{m}{y} {v}{o}{d}|{a}{kh} - '{ia}' '{iu}' '{e}{iu}' '{e}' // {p}{i}{s}{n}|{ia} {p}{i}{s}{n}|{iu} {p}{i}{s}{n}|{e}{iu} {p}{i}{s}{n}|{e} - '{ia}{m}' '{ia}{m}{y}' '{ia}{kh}' // {p}{i}{s}{n}|{ia}{m} {p}{i}{s}{n}|{ia}{m}{y} {p}{i}{s}{n}|{ia}{kh} - '{o}{v}{i}' '{o}{m}' // {b}{a}{t}{soft}{k}|{o}{v}{i} {b}{a}{t}{soft}{k}|{o}{m} - '{e}{ts}{soft}' '{e}{m}' // {o}{l}{i}{v}|{e}{ts}{soft} {o}{l}{i}{v}{ts}|{e}{m} - '{e}{n}{soft}' // {z}{e}{l}|{e}{n}{soft} - '{i}{i`}' // {gh}{e}{n}|{i}{i`} - '{i`}' // {s}{a}{r}{a}|{i`} - '{o}{i`}' // {gh}{e}{r}|{o}{i`} - '{soft}' // {s}{o}{v}{i}{s}{t}|{soft} - '{i}{iu}' '{i}{yi}' // {k}{o}{m}{e}{d}|{i}{iu} {k}{o}{m}{e}{d}|{i}{yi} - (delete) - ) + ) + + define verb as ( + [substring] among ( + '{t}{y}' + // '{t}{soft}' // {r}{o}{b}{y}|{t}{soft} ??? + '{i}{t}{soft}' + '{t}{e}' + + '{i`}{t}{e}' + '{l}{a}' '{l}{o}' '{l}{y}' + '{ye}{sh}' '{ye}{m}{o}' '{ye}{t}{e}' '{iu}{t}{soft}' + '{e}{sh}' '{e}{m}{o}' '{e}{t}{e}' '{u}{t}{soft}' + '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' + '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' + '{a}{t}{soft}' + (delete) ) + ) + + define noun as ( + [substring] among ( + '{a}{m}' '{a}{m}{y}' '{a}{kh}' + '{e}{iu}' + '{ia}{m}' '{ia}{m}{y}' '{ia}{kh}' + '{o}{v}{i}' '{o}{m}' + '{e}{ts}{soft}' '{e}{m}' + '{e}{n}{soft}' + '{o}{i`}' + '{i}{iu}' '{i}{yi}' + (delete) + ) + ) - // define derivational as ( - // [substring] R2 among ( - // // '{o}{s}{t}' - // // '{o}{s}{t}{'}' - // // (delete) - // ) - // ) - - // define tidy_up as ( - // [substring] among ( - // // '{e}{i`}{sh}' - // // '{e}{i`}{sh}{e}' // superlative forms - // // (delete - // // ['{n}'] '{n}' delete - // // ) - // // '{n}' - // // ('{n}' delete) // e.g. -nno endings - // // '{'}' - // // (delete) // with some slight false conflations - // ) - // ) -) + define common_avn as ( + [substring] among ( + // adj + // {z}{e}{l}{e}{n}|{a} {z}{e}{l}{e}{n}|{e} {z}{e}{l}{e}{n}|{i} {z}{e}{l}{e}{n}|{u} {v}{e}{r}{kh}{n}|{iu} {v}{e}{r}{kh}{n}|{ia} -define stem as ( + // verb + // {p}{y}{s}{a}|{v} {p}{y}{sh}|{e} {ch}{y}{t}{a}|{ye} {ch}{y}{t}{a}|{i`} {p}{y}{sh}|{u} {ch}{y}{t}{a}|{iu} - // Normalise {e"} to {e}. The documentation has long suggested the user - // should do this before calling the stemmer - we now do it for them. - // do repeat ( goto (['{e"}']) <- '{e}' ) - - do mark_regions - backwards setlimit tomark pV for ( - do ( - // TEST: - // reflexive - // verb - // noun - - perfective_gerund or - ( - try reflexive - adjectival or verb or noun - ) - ) + // noun + // {v}{o}{d}|{a} {p}{i}{s}{n}|{e} {v}{o}{d}|{y} {v}{o}{d}|{i} {s}{a}{r}{a}|{i`} + // {v}{o}{d}|{o} {v}{o}{d}|{u} {s}{o}{v}{i}{s}{t}|{soft} {p}{i}{s}{n}|{iu} {p}{i}{s}{n}|{ia} + // {gh}{e}{n}|{i}{i`} {v}{o}{d}|{o}{iu} - // Need or needn't ? - // try([ '{i}' ] delete) // {a}{k}{a}{d}{e}{m}{i}{iu} => {a}{k}{a}{d}{e}{m} - // because noun ending -i{iu} is being treated as verb ending -{iu} + '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' + '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' + '{i}{i`}' '{o}{iu}' + (delete) + ) + ) - // do derivational - // do tidy_up + define derivational as ( + [substring] R2 among ( + '{i}{s}{t}' // {b}{e}{z}{t}{u}{r}{b}{o}{t}{n}|{i}{s}{t}.{iu} + '{o}{s}{t}' // {b}{e}{z}{t}{u}{r}{b}{o}{t}{n}|{o}{s}{t}.{i} + (delete) ) + ) + + // define tidy_up as ( + // [substring] among ( + // // '{e}{i`}{sh}' + // // '{e}{i`}{sh}{e}' // superlative forms + // // (delete + // // ['{n}'] '{n}' delete + // // ) + // // '{n}' + // // ('{n}' delete) // e.g. -nno endings + // // '{'}' + // // (delete) // with some slight false conflations + // ) + // ) ) +define stem as ( + // Normalise {e"} to {e}. The documentation has long suggested the user + // should do this before calling the stemmer - we now do it for them. + // do repeat ( goto (['{e"}']) <- '{e}' ) -// ToDo: -// 1. Ґ => Г -// do repeat ( goto (['{g}]) <- '{gh}' ) // {u}{gh}{n}{e}{t}ё{n}{n}ы{i`} => {u}{gh}{n}{e}{t}{e}{n} -// 2. В{y}{d}{a}{l}{y}{t}{y} {v}{s}{i} {t}{y}{p}{y} А{p}{o}{s}{t}{r}{o}{f}{i}{v} 'ʼ` - -// 3. Д{o}{d}{a}{t}{k}{o}{v}{o} {p}{e}{r}{e}{v}{i}{r}{y}{t}{y} {s}{l}{o}{v}{a}: -// {b}{r}{a}{t}{y} -// {b}{e}{r}{u}{t}{soft} + do prelude + do mark_regions -// {d}{o}{p}{y}{s}{a}{t}{y} -// {d}{o}{p}{y}{sh}{u}{t}{soft} + backwards setlimit tomark pV for ( + do ( + perfective_gerund or + ( + try reflexive -// {p}{o}{s}{y}{d}{e}{n}{soft}{k}{y} + adjectival or verb or noun or common_avn + ) + ) -// {l}{i}{k}{a}{r} -// {l}{i}{k}{a}{r}{i}{v} + do derivational + // do tidy_up + ) +) -// ----- {p}{r}{y}{s}{l}{i}{v}{n}{y}{k}{y}? - {k}{u}{d}{y} {p}{o}{p}{a}{d}{e}? -// {d}{o}{b}{r}{e} - {d}{o}{b}{r}{o} -// {ch}{a}{s}{t}{o} - {ch}{a}{s}{t}{i}{sh}{y}{i`} -// {d}{o}{v}{gh}{o} - {d}{o}{v}{gh}{y}{i`} -// {ch}{y}{s}{t}{o} - {ch}{y}{s}{t}{i}{sh}{y}{i`} -// {r}{o}{b}{y}{t}{y}{m}{u}{t}{soft} - ? -// {r}{o}{b}{y}{t}{y}{m} diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index 21daa2be..343a5f74 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -35,17 +35,32 @@ stringdef shch '{U+0449}' stringdef soft '{U+044C}' stringdef iu '{U+044E}' stringdef ia '{U+044F}' -stringdef apostrophe '{U+0027}' - -routines ( mark_regions R1 R2 - perfective_gerund - adjective - adjectival - reflexive - verb - noun - // derivational - // tidy_up + +// Apostrophe-like symbols +// stringdef a_apostrophe '{U+0027}' // ' +// stringdef a_grave_accent U+0060 // ` cannot to remove system char in Snowball +stringdef a_ml_prime '{U+02B9}' // ʹ +stringdef a_mlt_comma '{U+02BB}' // ʻ +stringdef a_ml_apostrophe '{U+02BC}' // ʼ +stringdef a_mlr_comma '{U+02BD}' // ʽ +stringdef a_mlv_line '{U+02C8}' // ˈ +stringdef a_lsq_mark '{U+2018}' // ‘ +stringdef a_rsq_mark '{U+2019}' // ’ +stringdef a_shr9q_mark '{U+201B}' // ‛ +stringdef a_prime '{U+2032}' // ′ + +routines ( + prelude + mark_regions R1 R2 + perfective_gerund + adjective + adjectival + reflexive + verb + noun + common_avn + derivational + // tidy_up ) externals ( stem ) @@ -56,315 +71,205 @@ groupings ( v ) define v 'аеєиіїоуюя' -define mark_regions as ( +define prelude as ( + do repeat ( goto (['ґ']) <- 'г' ) + + // Remove any apostrophe-like symbols + do repeat ( goto (['{'}']) delete ) + do repeat ( goto (['ʹ']) delete ) + do repeat ( goto (['ʻ']) delete ) + do repeat ( goto (['ʼ']) delete ) + do repeat ( goto (['ʽ']) delete ) + do repeat ( goto (['ˈ']) delete ) + do repeat ( goto (['‘']) delete ) + do repeat ( goto (['’']) delete ) + do repeat ( goto (['‛']) delete ) + do repeat ( goto (['′']) delete ) +) - $pV = limit - $p1 = limit - $p2 = limit - do ( - gopast v setmark pV gopast non-v setmark p1 - gopast v gopast non-v setmark p2 - ) +define mark_regions as ( + $pV = limit + $p1 = limit + $p2 = limit + do ( + gopast v setmark pV gopast non-v setmark p1 + gopast v gopast non-v setmark p2 + ) ) backwardmode ( - - define R1 as $p1 <= cursor - define R2 as $p2 <= cursor - - define perfective_gerund as ( - [substring] among ( - // 'в' - // 'вші' - // 'вшіс{'}' - // ('а' or 'я' delete) - // 'ів' - // 'івші' - // 'івшіс{'}' - // 'ив' - // 'ивші' - // 'ившіс{'}' - // (delete) - - 'в' // донаписа|в дороби|в дороби|в - 'вши' // написа|вши зроби|вши - 'вшись' // оберіга|вшись спакува|вшись - 'вшися' // оберіга|вшися сподіва|вшися - // ('а' or 'я' delete) ??? - 'учи' // пиш|учи рев|учи - 'ючи' // ся|ючи підпису|ючи - 'ючись' // змага|ючись - 'ючися' // навча|ючися - 'ачи' // бач|ачи - 'ачись' // бач|ачись - 'ачися' // бач|ачися - 'лячи' // роб|лячи люб|лячи - 'лячись' // бав|лячись - 'лячися' // бав|лячися - 'ячи' // сид|ячи вовтуз|ячи - 'ячись' // ??? - 'ячися' // ??? - (delete) - ) + define R1 as $p1 <= cursor + define R2 as $p2 <= cursor + + define perfective_gerund as ( + [substring] among ( + 'в' // донаписа|в дороби|в дороби|в + 'вши' // написа|вши зроби|вши + 'вшись' // оберіга|вшись спакува|вшись + 'вшися' // оберіга|вшися сподіва|вшися + // ('а' or 'я' delete) ??? + 'учи' // пиш|учи рев|учи + 'ючи' // ся|ючи підпису|ючи + 'ючись' // змага|ючись + 'ючися' // навча|ючися + 'ачи' // бач|ачи + 'ачись' // бач|ачись + 'ачися' // бач|ачися + 'лячи' // роб|лячи люб|лячи + 'лячись' // бав|лячись + 'лячися' // бав|лячися + 'ячи' // сид|ячи вовтуз|ячи + 'ячись' // ??? + 'ячися' // ??? + (delete) + ) + ) + + define adjective as ( + [substring] among ( + 'ий' 'ого' 'ому' 'им' 'ім' + 'іший' 'ішого' 'ішому' 'ішим' 'ішім' 'іше' + 'ої' 'ій' 'ою' + 'іша' 'ішої' 'ішій' 'ішу' 'ішою' + 'их' 'ими' + 'іші' 'іших' 'ішими' + 'ього' 'ьому' + 'ьої' 'ьою' + 'іх' 'іми' + + 'яча' 'яче' 'ячу' 'ячі' + 'ача' 'аче' 'ачу' 'ачі' + 'юча' 'юче' 'ючу' 'ючі' + 'уча' 'уче' 'учу' 'учі' + (delete) ) + ) - define adjective as ( - [substring] among ( - // 'ее' 'іе' 'ие' 'ое' 'імі' 'имі' - // 'ей' 'ой' 'ем' - // 'ом' 'еґо' 'оґо' 'ему' - // 'ую' 'юю' 'ая' - // 'ею' // - soft form of ою - // (delete) - - 'ий' 'ого' 'ому' 'им' 'ім' // зелен|ий зелен|ого зелен|ому зелен|им зелен|ім - 'іший' 'ішого' 'ішому' 'ішим' 'ішім' // зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім - 'е' 'іше' // зелен|е зелен|іше - 'а' 'ої' 'ій' 'у' 'ою' // зелен|а зелен|ої зелен|ій зелен|у зелен|ою - 'іша' 'ішої' 'ішій' 'ішу' 'ішою' // зелен|іша зелен|ішої зелен|ішій зелен|ішу зелен|ішою - 'і' 'их' 'ими' // зелен|і зелен|их зелен|ими - 'іші' 'іших' 'ішими' // зелен|іші зелен|іших зелен|ішими - 'ього' 'ьому' // верхн|ього верхн|ьому - 'я' 'ьої' 'ю' 'ьою' // верхн|я верхн|ьої верхн|ю верхн|ьою - 'іх' 'іми' // верхн|іх верхн|іми - (delete) - ) - ) + define adjectival as ( + adjective - define adjectival as ( - adjective - - /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. - nn, юshch, shch, uюshch can be removed, with a small proportion of - errors. Removing im, uem, enn creates too many errors. - */ - - try ( - [substring] among ( - // 'ем' // present passive participle - // 'нн' // adjective from past passive participle - // 'вш' // past active participle - // 'ющ' 'щ' // present active participle - // ('а' or 'я' delete) - - // //but not 'ім' 'уем' // present passive participle - // //or 'енн' // adjective from past passive participle - - // 'івш' 'ивш'// past active participle - // 'ующ' // present active participle - // (delete) - - 'яч' // сид|ячий сид|ячого сид|ячому сид|ячим сид|ячім - // сид|яча сид|яче сид|ячої сид|ячій сид|ячу сид|ячою - // сид|ячі сид|ячих сид|ячими - - 'ач' // дриж|ачий дриж|ачого дриж|ачому дриж|ачим дриж|ачім - // дриж|ача дриж|аче дриж|ачої дриж|ачій дриж|ачу дриж|ачою - // дриж|ачі дриж|ачих дриж|ачими - - 'юч' // далені|ючий далені|ючого даленію|ючому далені|ючим далені|ючім - // далені|юча далені|юче далені|ючої даленію|ючій далені|ючу далені|ючою - // далені|ючі далені|ючих далені|ючими - 'уч' // пиш|учий далені|учого пиш|учому пиш|учим пиш|учім - // пиш|уча пиш|уче пиш|учої пиш|учій пиш|учу пиш|учою - // пиш|учі пиш|учих пиш|учими - - // Need or needn't ? - // 'ен' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім - // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною - // втрач|ені втрач|ених втрач|еними - (delete) - ) - ) - ) + try ( + [substring] among ( + 'яч' + 'ач' + 'юч' + 'уч' + (delete) - // define reflexive as ( - // [substring] among ( - // 'тися' // битися - // 'тись' // бор|о.тись - // 'ться' // роби|ться # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил - // 'іться' // подруж|іться - // 'теся' // бав|теся - // 'йся' // вдума|йся - // 'йтеся' // вдума|йтеся - // 'аться' // бач|аться - // 'вся' 'лася' 'лося' 'лися' // вчи|вся вчи|лася вчи|лося вчи|лися - // 'всь' 'лась' 'лось' 'лись' // вчи|всь вчи|лась вчи|лось вчи|лись - // 'юся' 'єшся' 'ється' 'ємося' 'єтеся' 'ються' // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються - // 'уся' 'ешся' 'еться' 'емося' 'етеся' 'уться' // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться - // 'люся' 'ишся' 'иться' 'имося' 'итеся' 'ляться'// див|люся див|ишся див|иться див|имося див|итеся див|ляться - // 'їшся' 'їться' 'їмося' 'їтеся' 'яться' // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться - // (delete) - // ) - // ) - - define reflexive as ( - [substring] among ( - 'ся' // осік|ся - 'сь' // недонавчи|сь - // би|тися - // боро|тись - // роби|ться ??? - // подруж|іться - // бав|теся - // вдума|йся - // вдума|йтеся - // вчи|вся вчи|лася вчи|лося вчи|лися - // вчи|всь вчи|лась вчи|лось вчи|лись - // смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються - // спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться - // див|люся див|ишся див|иться див|имося див|итеся див|ляться - // бо|їшся бо|їться бо|їмося бо|їтеся бо|яться - // бач|аться - 'ється' // смі|єть.ся - 'еться' // спиш|еть.ся - (delete) - ) + // Need or needn't ? + // 'ен' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім + // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною + // втрач|ені втрач|ених втрач|еними + ) ) - - define verb as ( - [substring] among ( - // 'на' 'лі' - // 'л' 'ем' 'н' 'но' 'ет' 'ют' - // 'ни' 'т{'}' 'еш{'}' - - // 'нно' - // ('а' or 'я' delete) - - // 'іла' 'ила' 'ена' 'ейте' - // 'уйте' 'іте' 'ілі' 'илі' 'ей' - // 'уй' 'іл' 'ил' 'ім' 'им' 'ен' - // 'іло' 'ило' 'ено' 'ят' 'ует' - // 'уют' 'іт' 'ит' 'ени' 'іт{'}' - // 'ит{'}' 'іш{'}' 'ую' - // (delete) - /* note the short passive participle tests: - 'на' 'н' 'но' 'ни' - 'ена' 'ен' 'ено' 'ени' - */ - - 'ти' // працюва|ти - // 'ть' // роби|ть ??? - 'іть' // роб|іть - 'те' // відправ|те - 'й' // чита|й - 'йте' // дума|йте - 'в' 'ла' 'ло' 'ли' // чита|в чита|ла чита|ло чита|ли - 'ю' 'єш' 'є' 'ємо' 'єте' 'ють' // чита|ю чита|єш чита|є чита|ємо чита|єте чита|ють - 'у' 'еш' 'е' 'емо' 'ете' 'уть' // пиш|у пиш|еш пиш|е пиш|емо пиш|ете пиш|уть - 'лю' 'иш' 'ить' 'имо' 'ите' 'лять' // роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять - 'їш' 'їть' 'їмо' 'їте' 'ять' // сто|їш сто|їть сто|їмо сто|їте сто|ять - 'ать' // бач|ать - (delete) - ) + ) + + define reflexive as ( + [substring] among ( + 'ся' // осік|ся + 'сь' // недонавчи|сь + 'ється' // смі|ється + 'еться' // спиш|еться + (delete) ) - - define noun as ( - [substring] among ( - // 'а' 'ев' 'ов' 'іе' '{'}е' 'е' - // 'іямі' 'ямі' 'амі' 'еі' 'іі' - // 'і' 'іей' 'ей' 'ой' 'ій' 'й' - // 'іям' 'ям' 'іем' 'ем' 'ам' 'ом' - // 'о' 'у' 'ах' 'іях' 'ях' 'и' '{'}' - // 'ію' '{'}ю' 'ю' 'ія' '{'}я' 'я' - // (delete) - /* the small class of neuter forms 'ені' 'енем' - 'ена' 'ен' 'енам' 'енамі' 'ена{x}' - omitted - they only occur on 12 words. - */ - - 'а' 'и' 'і' 'у' 'ою' 'о' // вод|а вод|и вод|і вод|у вод|ою вод|о - 'ам' 'ами' 'ах' // вод|ам вод|ами вод|ах - 'я' 'ю' 'ею' 'е' // пісн|я пісн|ю пісн|ею пісн|е - 'ям' 'ями' 'ях' // пісн|ям пісн|ями пісн|ях - 'ові' 'ом' // батьк|ові батьк|ом - 'ець' 'ем' // олів|ець олівц|ем - 'ень' // зел|ень - 'ій' // ген|ій - 'й' // сара|й - 'ой' // гер|ой - 'ь' // совіст|ь - 'ію' 'ії' // комед|ію комед|ії - (delete) - ) + ) + + define verb as ( + [substring] among ( + 'ти' + // 'ть' // роби|ть ??? + 'іть' + 'те' + + 'йте' + 'ла' 'ло' 'ли' + 'єш' 'ємо' 'єте' 'ють' + 'еш' 'емо' 'ете' 'уть' + 'лю' 'иш' 'ить' 'имо' 'ите' 'лять' + 'їш' 'їть' 'їмо' 'їте' 'ять' + 'ать' + (delete) ) + ) + + define noun as ( + [substring] among ( + 'ам' 'ами' 'ах' + 'ею' + 'ям' 'ями' 'ях' + 'ові' 'ом' + 'ець' 'ем' + 'ень' + 'ой' + 'ію' 'ії' + (delete) + ) + ) - // define derivational as ( - // [substring] R2 among ( - // // 'ост' - // // 'ост{'}' - // // (delete) - // ) - // ) - - // define tidy_up as ( - // [substring] among ( - // // 'ейш' - // // 'ейше' // superlative forms - // // (delete - // // ['н'] 'н' delete - // // ) - // // 'н' - // // ('н' delete) // e.g. -nno endings - // // '{'}' - // // (delete) // with some slight false conflations - // ) - // ) -) + define common_avn as ( + [substring] among ( + // adj + // зелен|а зелен|е зелен|і зелен|у верхн|ю верхн|я -define stem as ( + // verb + // писа|в пиш|е чита|є чита|й пиш|у чита|ю - // Normalise {e"} to е. The documentation has long suggested the user - // should do this before calling the stemmer - we now do it for them. - // do repeat ( goto (['{e"}']) <- 'е' ) - - do mark_regions - backwards setlimit tomark pV for ( - do ( - // TEST: - // reflexive - // verb - // noun - - perfective_gerund or - ( - try reflexive - adjectival or verb or noun - ) - ) + // noun + // вод|а пісн|е вод|и вод|і сара|й + // вод|о вод|у совіст|ь пісн|ю пісн|я + // ген|ій вод|ою - // Need or needn't ? - // try([ 'і' ] delete) // академію => академ - // because noun ending -iю is being treated as verb ending -ю + 'а' 'в' 'е' 'є' 'и' 'і' + 'й' 'о' 'у' 'ь' 'ю' 'я' + 'ій' 'ою' + (delete) + ) + ) - // do derivational - // do tidy_up + define derivational as ( + [substring] R2 among ( + 'іст' // безтурботн|іст.ю + 'ост' // безтурботн|ост.і + (delete) ) + ) + + // define tidy_up as ( + // [substring] among ( + // // 'ейш' + // // 'ейше' // superlative forms + // // (delete + // // ['н'] 'н' delete + // // ) + // // 'н' + // // ('н' delete) // e.g. -nno endings + // // '{'}' + // // (delete) // with some slight false conflations + // ) + // ) ) +define stem as ( + // Normalise {e"} to е. The documentation has long suggested the user + // should do this before calling the stemmer - we now do it for them. + // do repeat ( goto (['{e"}']) <- 'е' ) -// ToDo: -// 1. Ґ => Г -// do repeat ( goto (['ґ]) <- 'г' ) // угнетённый => угнетен -// 2. Видалити всі типи Апострофів 'ʼ` - -// 3. Додатково перевірити слова: -// брати -// беруть + do prelude + do mark_regions -// дописати -// допишуть + backwards setlimit tomark pV for ( + do ( + perfective_gerund or + ( + try reflexive -// посиденьки + adjectival or verb or noun or common_avn + ) + ) -// лікар -// лікарів + do derivational + // do tidy_up + ) +) -// ----- прислівники? - куди попаде? -// добре - добро -// часто - частіший -// довго - довгий -// чисто - чистіший -// робитимуть - ? -// робитим diff --git a/tests/algorithms/Readme.md b/tests/algorithms/Readme.md index de7e6535..656fb9d5 100644 --- a/tests/algorithms/Readme.md +++ b/tests/algorithms/Readme.md @@ -2,5 +2,7 @@ For checking the correctness of the stemmer you can run some language test cases, for example: ```sh -ruby ./tests/algorithms/russian_test.rb +bin/utf_to_sbl ./explanations/ukrainian.sbl.utf > algorithms/ukrainian.sbl && make + +ruby ./tests/algorithms/ukrainian_test.rb ``` diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb index 01472a47..92594795 100644 --- a/tests/algorithms/ukrainian_test.rb +++ b/tests/algorithms/ukrainian_test.rb @@ -33,7 +33,7 @@ perfective_gerund = { - 'в' => %w[донаписа|в дороби|в дороби|в], + 'в' => %w[донаписа|в дороби|в дороби|в], # ?? very common 'вши' => %w[написа|вши зроби|вши], 'вшись' => %w[оберіга|вшись спакува|вшись], 'вшися' => %w[оберіга|вшися сподіва|вшися], @@ -49,8 +49,8 @@ 'лячись' => %w[бав|лячись], 'лячися' => %w[бав|лячися], 'ячи' => %w[сид|ячи вовтуз|ячи], - 'ячись' => %w[], - 'ячися' => %w[] + 'ячись' => %w[], #? + 'ячися' => %w[], #? } # do we need to add prefix rule 'н*' for adjectives? @@ -58,32 +58,33 @@ adjective = { 'ий ого ому им ім' => %w[зелен|ий зелен|ого зелен|ому зелен|им зелен|ім], 'іший ішого ішому ішим ішім' => %w[зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім], - 'е іше' => %w[зелен|е зелен|іше], - 'а ої ій у ою' => %w[зелен|а зелен|ої зелен|ій зелен|у зелен|ою], + 'іше' => %w[зелен|іше], + 'ої ій ою' => %w[зелен|ої зелен|ій зелен|ою], 'іша ішої ішій ішу ішою' => %w[зелен|іша зелен|ішої зелен|ішій зелен|ішу зелен|ішою], - 'і их ими' => %w[зелен|і зелен|их зелен|ими], + 'их ими' => %w[зелен|их зелен|ими], 'іші іших ішими' => %w[зелен|іші зелен|іших зелен|ішими], 'ього ьому' => %w[верхн|ього верхн|ьому], - 'я ьої ю ьою' => %w[верхн|я верхн|ьої верхн|ю верхн|ьою], + 'ьої ьою' => %w[верхн|ьої верхн|ьою], 'іх іми' => %w[верхн|іх верхн|іми], + + 'яча яче ячу ячі' => %w[сид|яча сид|яче сид|ячу сид|ячі], + 'ача аче ачу ачі' => %w[дриж|ача дриж|аче дриж|ачу дриж|ачі], + 'юча юче ючу ючі' => %w[далені|юча далені|юче далені|ючу далені|ючі], + 'уча уче учу учі' => %w[пиш|уча пиш|уче пиш|учу пиш|учі], } adjectival = { 'яч' => %w[сид|яч.ий сид|яч.ого сид|яч.ому сид|яч.им сид|яч.ім - сид|яч.а сид|яч.е сид|яч.ої сид|яч.ій сид|яч.у сид|яч.ою - сид|яч.і сид|яч.их сид|яч.ими], + сид|яч.ої сид|яч.ій сид|яч.ою сид|яч.их сид|яч.ими], 'ач' => %w[дриж|ач.ий дриж|ач.ого дриж|ач.ому дриж|ач.им дриж|ач.ім - дриж|ач.а дриж|ач.е дриж|ач.ої дриж|ач.ій дриж|ач.у дриж|ач.ою - дриж|ач.і дриж|ач.их дриж|ач.ими], + дриж|ач.ої дриж|ач.ій дриж|ач.ою дриж|ач.их дриж|ач.ими], - 'юч' => %w[далені|юч.ий далені|юч.ого далені|юч.ому далені|юч.им далені|юч.ім - далені|юч.а далені|юч.е далені|юч.ої далені|юч.ій далені|юч.у далені|юч.ою - далені|юч.і далені|юч.их далені|юч.ими], + 'юч' => %w[далені|юч.ий далені|юч.ого далені|юч.ому далені|юч.им далені|юч.ім + далені|юч.ої далені|юч.ій далені|юч.ою далені|юч.их далені|юч.ими], 'уч' => %w[пиш|уч.ий далені|уч.ого пиш|уч.ому пиш|уч.им пиш|уч.ім - пиш|уч.а пиш|уч.е пиш|уч.ої пиш|уч.ій пиш|уч.у пиш|уч.ою - пиш|уч.і пиш|уч.их пиш|уч.ими], + пиш|уч.ої пиш|уч.ій пиш|уч.ою пиш|уч.их пиш|уч.ими], # Need or needn't ? # 'ен' => %w[втрач|ен.ий втрач|ен.ого втрач|ен.ому втрач|ен.им втрач|ен.ім @@ -144,9 +145,13 @@ # абсорбували, абсорбовано reflexive = { + 'ється' => %w[смі|ється], # незнайшов дієслів + 'еться' => %w[спиш|еться], # незнайшов дієслів + # *ся 'ся' => %w[осік|ся], + # rules from verb: 'ти' => %w[би|ти.ся милува|ти.ся], # 'ть' => %w[роб|ить.ся], # вже є правило "ить" 'іть' => %w[подруж|іть.ся], @@ -161,12 +166,11 @@ 'лю иш ить имо ите лять' => %w[див|лю.ся див|иш.ся див|ить.ся див|имо.ся див|ите.ся див|лять.ся], 'їш їть їмо їте ять' => %w[бо|їш.ся бо|їть.ся бо|їмо.ся бо|їте.ся бо|ять.ся], - 'ється' => %w[смі|ється], # незнайшов дієслів - 'еться' => %w[спиш|еться], # незнайшов дієслів # *сь 'сь' => %w[недонавч|и.сь], # вчи|сь + # rules from verb: '2 ти' => %w[боро|ти.сь], '2 в ла ло ли' => %w[вчи|в.сь вчи|ла.сь вчи|ло.сь вчи|ли.сь], } @@ -176,37 +180,43 @@ # 'ть' => %w[роби|ть], # => роб|ить !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил 'іть' => %w[роб|іть], 'те' => %w[відправ|те], - 'й' => %w[чита|й], 'йте' => %w[дума|йте], 'ать' => %w[бач|ать], - 'в ла ло ли' => %w[чита|в чита|ла чита|ло чита|ли], - 'ю єш є ємо єте ють' => %w[чита|ю чита|єш чита|є чита|ємо чита|єте чита|ють], - 'у еш е емо ете уть' => %w[пиш|у пиш|еш пиш|е пиш|емо пиш|ете пиш|уть], - 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], - 'їш їть їмо їте ять' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять], - + 'ла ло ли' => %w[чита|ла чита|ло чита|ли], + 'єш ємо єте ють' => %w[чита|єш чита|ємо чита|єте чита|ють], + 'еш емо ете уть' => %w[пиш|еш пиш|емо пиш|ете пиш|уть], + 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], + 'їш їть їмо їте ять' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять], } - noun = { - 'а и і у ою о' => %w[вод|а вод|и вод|і вод|у вод|ою вод|о], 'ам ами ах' => %w[вод|ам вод|ами вод|ах], - 'я ю ею е' => %w[пісн|я пісн|ю пісн|ею пісн|е], + 'ею' => %w[пісн|ею], 'ям ями ях' => %w[пісн|ям пісн|ями пісн|ях], 'ові ом' => %w[батьк|ові батьк|ом бор|ом], - 'ець ем' => %w[олів|ець олівц|ем], # ю олівц|ю - повтор + 'ець ем' => %w[олів|ець олівц|ем], 'ень' => %w[зел|ень], - 'ій' => %w[ген|ій], - 'й' => %w[сара|й], 'ой' => %w[гер|ой], - 'ь' => %w[совіст|ь], 'ію ії' => %w[комед|ію комед|ії], } -# derivational = { -# 'остей' => %w[люб'язн|остей], -# 'ість' => %w[люб'язн|ість] -# } +adj_verb_noun = { + # adj + 'а е і у ю я' => %w[зелен|а зелен|е зелен|і зелен|у верхн|ю верхн|я], + # verb + 'в е є й у ю' => %w[писа|в пиш|е чита|є чита|й пиш|у чита|ю], + # noun + 'а е и і й ' => %w[вод|а пісн|е вод|и вод|і сара|й], + 'о у ь ю я' => %w[вод|о вод|у совіст|ь пісн|ю пісн|я], + 'ій ою' => %w[ген|ій вод|ою], +} + +derivational = { + 'іст' => %w[безтурботн|іст.ь безтурботн|іст.ю], + + 'ост' => %w[безтурботн|ост.і безтурботн|ост.ям безтурботн|ост|ями безтурботн|ост.ях + безтурботн|ост.и безтурботн|ост.е безтурботн|ост.ей], # ??? ти/те/й +} # tidy_up = { # 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], @@ -216,12 +226,57 @@ # } exceptions = { - # ё => е - # 'угнетённый' => 'угнетен', - - ## Need or needn't ? - # -ію => '' - # 'академію' => 'академ' + # ґ => г + 'аванґард' => 'авангард', + 'аванґарду' => 'авангард|у', + 'аванґардові' => 'авангард|ові', + 'аванґардом' => 'авангард|ом', + 'аванґарді' => 'авангард|і', + 'аванґарди' => 'авангард|и', + 'аванґарде' => 'авангард|е', + 'аванґардів' => 'авангард|ів', # ?? в + 'аванґардам' => 'авангард|ам', + 'аванґардами' => 'авангард|ами', + 'аванґардах' => 'авангард|ах', + + # remove any apostrophe: ' ʹ ʻ ʼ ʽ ˈ ‘ ’ ‛ ′ + # "сім`я" => "сім", # cannot to remove Grave Accent + "сім'я" => "сім", + "сімʹя" => "сім", + "сімʻя" => "сім", + "сімʼя" => "сім", + "сімʽя" => "сім", + "сімˈя" => "сім", + "сім‘я" => "сім", + "сім’я" => "сім", + "сім‛я" => "сім", + "сім′я" => "сім", + + # Додатково перевірити слова: + "брати" => "бра|ти", + "беруть" => "бер|уть", + + "дописати" => "дописа|ти", + "допишуть" => "допиш|уть", + + "посиденьки" => "посиденьк|и", + + "лікар" => "лікар", + "лікарів" => "лікар|ів", # ??? в + + # прислівники: + "добре" => "добр|е", + "добро" => "добр|о", + "часто" => "част|о", + "частіший" => "част|іший", + "довго" => "довг|о", + "довгий" => "довг|ий", + "чисто" => "чист|о", + "чистіший" => "чист|іший", + + "робитимуть" => "робитим|уть", + + 'академію' => 'академ', } $all_tests = [] @@ -261,20 +316,22 @@ def check_words_set(words_set, set_name) [reflexive, 'reflexive'], [verb, 'verb'], [noun, 'noun'], - # [derivational, 'derivational'], + [adj_verb_noun, 'adj_verb_noun'], + [derivational, 'derivational'], # [tidy_up, 'tidy_up'] ].each do |words_set, set_name| check_words_set(words_set, set_name) end -exceptions.each do |word, stem| +exceptions.each do |word, test_case| + stem, ending = test_case.split('|') $all_tests << word result_stem = (`echo "#{word}" | ./stemwords -l uk `).strip $errors['exceptions'] ||= [] $errors['exceptions'] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem end -if $errors.empty? +if $errors.values.all?(&:empty?) puts("#{$all_tests.count} test(s) passed successfully!") else $errors.each do |set_name, errs| @@ -285,58 +342,68 @@ def check_words_set(words_set, set_name) end end -a = %w[ - ий ого ому им ім - іший ішого ішому ішим ішім - іше - ої - іша ішої ішій ішу ішою - их ими - іші іших ішими - ього ьому - ьої ьою - іх іми -] - -v = %w[ - ти - ть - іть - те - йте - ать - ла ло ли - єш ємо єте ють - еш емо ете уть - лю иш ить имо ите лять - їш їть їмо їте ять -] - -n = %w[ - ам ами ах - ею - ям ями ях - ові ом - ець ем - ень - ой - ію ії -] - -adj_verb_noun = %w[ - е а у і я ю - й в ю є у е - а и і у о я ю е й ь - ою ій -] - -puts "a & v" -p (a & v).sort - -puts "v & n" -p (v & n).sort - -puts "n & a" -p (n & a).sort +# a = %w[ +# ий ого ому им ім +# іший ішого ішому ішим ішім +# іше +# ої +# іша ішої ішій ішу ішою +# их ими +# іші іших ішими +# ього ьому +# ьої ьою +# іх іми +# ] + +# v = %w[ +# ти +# ть +# іть +# те +# йте +# ать +# ла ло ли +# єш ємо єте ють +# еш емо ете уть +# лю иш ить имо ите лять +# їш їть їмо їте ять +# ] + +# n = %w[ +# ам ами ах +# ею +# ям ями ях +# ові ом +# ець ем +# ень +# ой +# ію ії +# ] + +# adj_verb_noun = %w[ +# е а у і я ю +# й в ю є у е +# а и і у о я ю е й ь +# ою ій +# ] + +# puts "a & v" +# p (a & v).sort + +# puts "v & n" +# p (v & n).sort + +# puts "n & a" +# p (n & a).sort + +# ToDo: + +# +1. Ґ => Г +# do repeat ( goto (['ґ]) <- 'г' ) // угнетённый => угнетен + +# +2. Видалити всі типи Апострофів 'ʼ` + +# +3. Додатково перевірити слова: + From f6b4a80ca760b8f20bb460441340320cb24e49a7 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Tue, 13 Jun 2023 21:20:25 +0300 Subject: [PATCH 09/13] Add Ukrainian stemmer --- algorithms/ukrainian.sbl | 59 ++++++++++++---------------------- explanations/ukrainian.sbl.utf | 59 ++++++++++++---------------------- 2 files changed, 40 insertions(+), 78 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index e848e283..05b2db62 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -51,7 +51,7 @@ stringdef a_prime '{U+2032}' // {a_prime} routines ( prelude - mark_regions R1 R2 + mark_regions R2 perfective_gerund adjective adjectival @@ -65,7 +65,7 @@ routines ( externals ( stem ) -integers ( pV p1 p2 ) +integers ( pV p2 ) groupings ( v ) @@ -89,16 +89,14 @@ define prelude as ( define mark_regions as ( $pV = limit - $p1 = limit $p2 = limit do ( - gopast v setmark pV gopast non-v setmark p1 + gopast v setmark pV gopast non-v gopast v gopast non-v setmark p2 ) ) backwardmode ( - define R1 as $p1 <= cursor define R2 as $p2 <= cursor define perfective_gerund as ( @@ -108,17 +106,17 @@ backwardmode ( '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} // ('{a}' or '{ia}' delete) ??? - '{u}{ch}{y}' // {p}{y}{sh}|{u}{ch}{y} {r}{e}{v}|{u}{ch}{y} - '{iu}{ch}{y}' // {s}{ia}|{iu}{ch}{y} {p}{i}{d}{p}{y}{s}{u}|{iu}{ch}{y} - '{iu}{ch}{y}{s}{soft}' // {z}{m}{a}{gh}{a}|{iu}{ch}{y}{s}{soft} - '{iu}{ch}{y}{s}{ia}' // {n}{a}{v}{ch}{a}|{iu}{ch}{y}{s}{ia} - '{a}{ch}{y}' // {b}{a}{ch}|{a}{ch}{y} - '{a}{ch}{y}{s}{soft}' // {b}{a}{ch}|{a}{ch}{y}{s}{soft} - '{a}{ch}{y}{s}{ia}' // {b}{a}{ch}|{a}{ch}{y}{s}{ia} - '{l}{ia}{ch}{y}' // {r}{o}{b}|{l}{ia}{ch}{y} {l}{iu}{b}|{l}{ia}{ch}{y} - '{l}{ia}{ch}{y}{s}{soft}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{soft} - '{l}{ia}{ch}{y}{s}{ia}' // {b}{a}{v}|{l}{ia}{ch}{y}{s}{ia} - '{ia}{ch}{y}' // {s}{y}{d}|{ia}{ch}{y} {v}{o}{v}{t}{u}{z}|{ia}{ch}{y} + '{u}{ch}{y}' + '{iu}{ch}{y}' + '{iu}{ch}{y}{s}{soft}' + '{iu}{ch}{y}{s}{ia}' + '{a}{ch}{y}' + '{a}{ch}{y}{s}{soft}' + '{a}{ch}{y}{s}{ia}' + '{l}{ia}{ch}{y}' + '{l}{ia}{ch}{y}{s}{soft}' + '{l}{ia}{ch}{y}{s}{ia}' + '{ia}{ch}{y}' '{ia}{ch}{y}{s}{soft}' // ??? '{ia}{ch}{y}{s}{ia}' // ??? (delete) @@ -166,10 +164,10 @@ backwardmode ( define reflexive as ( [substring] among ( - '{s}{ia}' // {o}{s}{i}{k}|{s}{ia} - '{s}{soft}' // {n}{e}{d}{o}{n}{a}{v}{ch}{y}|{s}{soft} - '{ye}{t}{soft}{s}{ia}' // {s}{m}{i}|{ye}{t}{soft}{s}{ia} - '{e}{t}{soft}{s}{ia}' // {s}{p}{y}{sh}|{e}{t}{soft}{s}{ia} + '{s}{ia}' + '{s}{soft}' + '{ye}{t}{soft}{s}{ia}' + '{e}{t}{soft}{s}{ia}' (delete) ) ) @@ -208,17 +206,6 @@ backwardmode ( define common_avn as ( [substring] among ( - // adj - // {z}{e}{l}{e}{n}|{a} {z}{e}{l}{e}{n}|{e} {z}{e}{l}{e}{n}|{i} {z}{e}{l}{e}{n}|{u} {v}{e}{r}{kh}{n}|{iu} {v}{e}{r}{kh}{n}|{ia} - - // verb - // {p}{y}{s}{a}|{v} {p}{y}{sh}|{e} {ch}{y}{t}{a}|{ye} {ch}{y}{t}{a}|{i`} {p}{y}{sh}|{u} {ch}{y}{t}{a}|{iu} - - // noun - // {v}{o}{d}|{a} {p}{i}{s}{n}|{e} {v}{o}{d}|{y} {v}{o}{d}|{i} {s}{a}{r}{a}|{i`} - // {v}{o}{d}|{o} {v}{o}{d}|{u} {s}{o}{v}{i}{s}{t}|{soft} {p}{i}{s}{n}|{iu} {p}{i}{s}{n}|{ia} - // {gh}{e}{n}|{i}{i`} {v}{o}{d}|{o}{iu} - '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' '{i}{i`}' '{o}{iu}' @@ -228,8 +215,8 @@ backwardmode ( define derivational as ( [substring] R2 among ( - '{i}{s}{t}' // {b}{e}{z}{t}{u}{r}{b}{o}{t}{n}|{i}{s}{t}.{iu} - '{o}{s}{t}' // {b}{e}{z}{t}{u}{r}{b}{o}{t}{n}|{o}{s}{t}.{i} + '{i}{s}{t}' + '{o}{s}{t}' (delete) ) ) @@ -250,10 +237,6 @@ backwardmode ( ) define stem as ( - // Normalise {e"} to {e}. The documentation has long suggested the user - // should do this before calling the stemmer - we now do it for them. - // do repeat ( goto (['{e"}']) <- '{e}' ) - do prelude do mark_regions @@ -271,5 +254,3 @@ define stem as ( // do tidy_up ) ) - - diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index 343a5f74..a9928f59 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -51,7 +51,7 @@ stringdef a_prime '{U+2032}' // ′ routines ( prelude - mark_regions R1 R2 + mark_regions R2 perfective_gerund adjective adjectival @@ -65,7 +65,7 @@ routines ( externals ( stem ) -integers ( pV p1 p2 ) +integers ( pV p2 ) groupings ( v ) @@ -89,16 +89,14 @@ define prelude as ( define mark_regions as ( $pV = limit - $p1 = limit $p2 = limit do ( - gopast v setmark pV gopast non-v setmark p1 + gopast v setmark pV gopast non-v gopast v gopast non-v setmark p2 ) ) backwardmode ( - define R1 as $p1 <= cursor define R2 as $p2 <= cursor define perfective_gerund as ( @@ -108,17 +106,17 @@ backwardmode ( 'вшись' // оберіга|вшись спакува|вшись 'вшися' // оберіга|вшися сподіва|вшися // ('а' or 'я' delete) ??? - 'учи' // пиш|учи рев|учи - 'ючи' // ся|ючи підпису|ючи - 'ючись' // змага|ючись - 'ючися' // навча|ючися - 'ачи' // бач|ачи - 'ачись' // бач|ачись - 'ачися' // бач|ачися - 'лячи' // роб|лячи люб|лячи - 'лячись' // бав|лячись - 'лячися' // бав|лячися - 'ячи' // сид|ячи вовтуз|ячи + 'учи' + 'ючи' + 'ючись' + 'ючися' + 'ачи' + 'ачись' + 'ачися' + 'лячи' + 'лячись' + 'лячися' + 'ячи' 'ячись' // ??? 'ячися' // ??? (delete) @@ -166,10 +164,10 @@ backwardmode ( define reflexive as ( [substring] among ( - 'ся' // осік|ся - 'сь' // недонавчи|сь - 'ється' // смі|ється - 'еться' // спиш|еться + 'ся' + 'сь' + 'ється' + 'еться' (delete) ) ) @@ -208,17 +206,6 @@ backwardmode ( define common_avn as ( [substring] among ( - // adj - // зелен|а зелен|е зелен|і зелен|у верхн|ю верхн|я - - // verb - // писа|в пиш|е чита|є чита|й пиш|у чита|ю - - // noun - // вод|а пісн|е вод|и вод|і сара|й - // вод|о вод|у совіст|ь пісн|ю пісн|я - // ген|ій вод|ою - 'а' 'в' 'е' 'є' 'и' 'і' 'й' 'о' 'у' 'ь' 'ю' 'я' 'ій' 'ою' @@ -228,8 +215,8 @@ backwardmode ( define derivational as ( [substring] R2 among ( - 'іст' // безтурботн|іст.ю - 'ост' // безтурботн|ост.і + 'іст' + 'ост' (delete) ) ) @@ -250,10 +237,6 @@ backwardmode ( ) define stem as ( - // Normalise {e"} to е. The documentation has long suggested the user - // should do this before calling the stemmer - we now do it for them. - // do repeat ( goto (['{e"}']) <- 'е' ) - do prelude do mark_regions @@ -271,5 +254,3 @@ define stem as ( // do tidy_up ) ) - - From 40800bb682b1ab9dac5bb2435fa507abe3e62808 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Tue, 19 Sep 2023 17:44:19 +0300 Subject: [PATCH 10/13] Add Ukrainian stemmer: extra rules --- algorithms/ukrainian.sbl | 112 ++++++----- explanations/ukrainian.sbl.utf | 112 ++++++----- tests/algorithms/ukrainian_test.rb | 296 ++++++++++++++++++++--------- 3 files changed, 316 insertions(+), 204 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index 05b2db62..85cbe47c 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -58,9 +58,9 @@ routines ( reflexive verb noun - common_avn + all_vowels derivational - // tidy_up + tidy_up ) externals ( stem ) @@ -101,11 +101,9 @@ backwardmode ( define perfective_gerund as ( [substring] among ( - '{v}' // {d}{o}{n}{a}{p}{y}{s}{a}|{v} {d}{o}{r}{o}{b}{y}|{v} {d}{o}{r}{o}{b}{y}|{v} - '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} {z}{r}{o}{b}{y}|{v}{sh}{y} - '{v}{sh}{y}{s}{soft}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{soft} {s}{p}{a}{k}{u}{v}{a}|{v}{sh}{y}{s}{soft} - '{v}{sh}{y}{s}{ia}' // {o}{b}{e}{r}{i}{gh}{a}|{v}{sh}{y}{s}{ia} {s}{p}{o}{d}{i}{v}{a}|{v}{sh}{y}{s}{ia} - // ('{a}' or '{ia}' delete) ??? + '{v}{sh}{y}' // {n}{a}{p}{y}{s}{a}|{v}{sh}{y} + '{v}{sh}{y}{s}{soft}' + '{v}{sh}{y}{s}{ia}' '{u}{ch}{y}' '{iu}{ch}{y}' '{iu}{ch}{y}{s}{soft}' @@ -117,15 +115,25 @@ backwardmode ( '{l}{ia}{ch}{y}{s}{soft}' '{l}{ia}{ch}{y}{s}{ia}' '{ia}{ch}{y}' - '{ia}{ch}{y}{s}{soft}' // ??? - '{ia}{ch}{y}{s}{ia}' // ??? + '{ia}{ch}{y}{s}{soft}' + '{ia}{ch}{y}{s}{ia}' (delete) ) ) + define reflexive as ( + [substring] among ( + '{ye}{t}{soft}{s}{ia}' // {s}{m}{i}|{ye}{t}{soft}{s}{ia} + '{e}{t}{soft}{s}{ia}' + '{s}{ia}' + '{s}{soft}' + (delete) + ) + ) + define adjective as ( [substring] among ( - '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' + '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' // {z}{e}{l}|{e}{n}.{y}{i`} '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' '{i}{sh}{e}' '{o}{yi}' '{i}{i`}' '{o}{iu}' '{i}{sh}{a}' '{i}{sh}{o}{yi}' '{i}{sh}{i}{i`}' '{i}{sh}{u}' '{i}{sh}{o}{iu}' @@ -134,7 +142,11 @@ backwardmode ( '{soft}{o}{gh}{o}' '{soft}{o}{m}{u}' '{soft}{o}{yi}' '{soft}{o}{iu}' '{i}{kh}' '{i}{m}{y}' - + '{o}{v}{a}' '{o}{v}{e}' + '{yi}{i`}' '{y}{yi}{i`}' + '{i`}{o}{m}{u}' '{y}{i`}{o}{m}{u}' + '{ye}{ye}' '{e}{ye}' + '{e}{n}{a}' '{e}{n}{i}' '{e}{n}{e}' '{e}{n}{u}' '{ia}{ch}{a}' '{ia}{ch}{e}' '{ia}{ch}{u}' '{ia}{ch}{i}' '{a}{ch}{a}' '{a}{ch}{e}' '{a}{ch}{u}' '{a}{ch}{i}' '{iu}{ch}{a}' '{iu}{ch}{e}' '{iu}{ch}{u}' '{iu}{ch}{i}' @@ -148,51 +160,30 @@ backwardmode ( try ( [substring] among ( - '{ia}{ch}' - '{a}{ch}' - '{iu}{ch}' - '{u}{ch}' - (delete) - - // Need or needn't ? - // '{e}{n}' // {v}{t}{r}{a}{ch}|{e}{n}{y}{i`} {v}{t}{r}{a}{ch}|{e}{n}{o}{gh}{o} {v}{t}{r}{a}{ch}|{e}{n}{o}{m}{u} {v}{t}{r}{a}{ch}|{e}{n}{y}{m} {v}{t}{r}{a}{ch}|{e}{n}{i}{m} - // {v}{t}{r}{a}{ch}|{e}{n}{a} {v}{t}{r}{a}{ch}|{e}{n}{e} {v}{t}{r}{a}{ch}|{e}{n}{o}{yi} {v}{t}{r}{a}{ch}|{e}{n}{i}{i`} {v}{t}{r}{a}{ch}|{e}{n}{u} {v}{t}{r}{a}{ch}|{e}{n}{o}{iu} - // {v}{t}{r}{a}{ch}|{e}{n}{i} {v}{t}{r}{a}{ch}|{e}{n}{y}{kh} {v}{t}{r}{a}{ch}|{e}{n}{y}{m}{y} + '{e}{n}' '{ia}{ch}' '{a}{ch}' '{iu}{ch}' '{u}{ch}' (delete) // {z}{e}{l}|{e}{n}.{y}{i`} ) ) ) - define reflexive as ( - [substring] among ( - '{s}{ia}' - '{s}{soft}' - '{ye}{t}{soft}{s}{ia}' - '{e}{t}{soft}{s}{ia}' - (delete) - ) - ) - define verb as ( [substring] among ( - '{t}{y}' - // '{t}{soft}' // {r}{o}{b}{y}|{t}{soft} ??? + '{a}{v}' '{a}{l}{y}' '{a}{l}{o}' '{a}{l}{a}' '{a}{t}{soft}' '{a}{t}{y}' // {p}{i}{z}{n}{a}{v}|{a}{v} + '{m}{e}' '{i}{t}{soft}' - '{t}{e}' - '{i`}{t}{e}' '{l}{a}' '{l}{o}' '{l}{y}' + '{t}{y}' '{t}{soft}' '{t}{e}' '{ye}{sh}' '{ye}{m}{o}' '{ye}{t}{e}' '{iu}{t}{soft}' '{e}{sh}' '{e}{m}{o}' '{e}{t}{e}' '{u}{t}{soft}' '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' - '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' - '{a}{t}{soft}' + '{l}{ia}{t}{y}' + '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' '{ia}{t}{y}' (delete) ) ) - define noun as ( [substring] among ( - '{a}{m}' '{a}{m}{y}' '{a}{kh}' + '{a}{m}' '{a}{m}{y}' '{a}{kh}' // {v}{o}{d}|{a}{m} '{e}{iu}' '{ia}{m}' '{ia}{m}{y}' '{ia}{kh}' '{o}{v}{i}' '{o}{m}' @@ -200,40 +191,45 @@ backwardmode ( '{e}{n}{soft}' '{o}{i`}' '{i}{iu}' '{i}{yi}' + '{i}{v}' + '{e}{v}' '{o}{v}' '{e}{i`}' '{y}{ia}{m}' '{y}{ia}{kh}' '{y}{iu}' + '{i}{ia}{m}' '{i}{ia}{kh}' + '{y}{ia}' '{ye}{iu}' '{e}{v}{i}' '{ye}{m}' '{yi}{v}' + '{i}{ye}{iu}' '{y}{ye}{iu}' '{e}{ye}{iu}' + '{soft}{yi}' '{soft}{ye}' '{soft}{ye}{iu}' '{soft}{iu}' '{soft}{ia}' (delete) ) ) - define common_avn as ( + define all_vowels as ( [substring] among ( - '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' + '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' // {v}{o}{d}|{a} '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' - '{i}{i`}' '{o}{iu}' (delete) ) ) + // HERE!!!! define derivational as ( [substring] R2 among ( - '{i}{s}{t}' + '{i}{s}{t}' // {n}{e}{z}{a}{l}{e}{zh}{n}|{i}{s}{t}.{t}{iu} '{o}{s}{t}' + '{e}{n}{soft}{k}' (delete) ) ) - // define tidy_up as ( - // [substring] among ( - // // '{e}{i`}{sh}' - // // '{e}{i`}{sh}{e}' // superlative forms - // // (delete - // // ['{n}'] '{n}' delete - // // ) - // // '{n}' - // // ('{n}' delete) // e.g. -nno endings - // // '{'}' - // // (delete) // with some slight false conflations - // ) - // ) + define tidy_up as ( + [substring] among ( + '{d}' ('{d}' delete) // {u}{s}{e}{v}{l}{a}{d}|{d}.{ia}{m} + '{zh}' ('{zh}' delete) + '{l}' ('{l}' delete) + '{n}' ('{n}' delete) + '{s}' ('{s}' delete) + '{t}' ('{t}' delete) + '{ch}' ('{ch}' delete) + ) + ) ) define stem as ( @@ -246,11 +242,11 @@ define stem as ( ( try reflexive - adjectival or verb or noun or common_avn + adjectival or verb or noun or all_vowels ) ) do derivational - // do tidy_up + do tidy_up ) ) diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index a9928f59..3f321ef6 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -58,9 +58,9 @@ routines ( reflexive verb noun - common_avn + all_vowels derivational - // tidy_up + tidy_up ) externals ( stem ) @@ -101,11 +101,9 @@ backwardmode ( define perfective_gerund as ( [substring] among ( - 'в' // донаписа|в дороби|в дороби|в - 'вши' // написа|вши зроби|вши - 'вшись' // оберіга|вшись спакува|вшись - 'вшися' // оберіга|вшися сподіва|вшися - // ('а' or 'я' delete) ??? + 'вши' // написа|вши + 'вшись' + 'вшися' 'учи' 'ючи' 'ючись' @@ -117,15 +115,25 @@ backwardmode ( 'лячись' 'лячися' 'ячи' - 'ячись' // ??? - 'ячися' // ??? + 'ячись' + 'ячися' (delete) ) ) + define reflexive as ( + [substring] among ( + 'ється' // смі|ється + 'еться' + 'ся' + 'сь' + (delete) + ) + ) + define adjective as ( [substring] among ( - 'ий' 'ого' 'ому' 'им' 'ім' + 'ий' 'ого' 'ому' 'им' 'ім' // зел|ен.ий 'іший' 'ішого' 'ішому' 'ішим' 'ішім' 'іше' 'ої' 'ій' 'ою' 'іша' 'ішої' 'ішій' 'ішу' 'ішою' @@ -134,7 +142,11 @@ backwardmode ( 'ього' 'ьому' 'ьої' 'ьою' 'іх' 'іми' - + 'ова' 'ове' + 'їй' 'иїй' + 'йому' 'ийому' + 'єє' 'еє' + 'ена' 'ені' 'ене' 'ену' 'яча' 'яче' 'ячу' 'ячі' 'ача' 'аче' 'ачу' 'ачі' 'юча' 'юче' 'ючу' 'ючі' @@ -148,51 +160,30 @@ backwardmode ( try ( [substring] among ( - 'яч' - 'ач' - 'юч' - 'уч' - (delete) - - // Need or needn't ? - // 'ен' // втрач|ений втрач|еного втрач|еному втрач|еним втрач|енім - // втрач|ена втрач|ене втрач|еної втрач|еній втрач|ену втрач|еною - // втрач|ені втрач|ених втрач|еними + 'ен' 'яч' 'ач' 'юч' 'уч' (delete) // зел|ен.ий ) ) ) - define reflexive as ( - [substring] among ( - 'ся' - 'сь' - 'ється' - 'еться' - (delete) - ) - ) - define verb as ( [substring] among ( - 'ти' - // 'ть' // роби|ть ??? + 'ав' 'али' 'ало' 'ала' 'ать' 'ати' // пізнав|ав + 'ме' 'іть' - 'те' - 'йте' 'ла' 'ло' 'ли' + 'ти' 'ть' 'те' 'єш' 'ємо' 'єте' 'ють' 'еш' 'емо' 'ете' 'уть' 'лю' 'иш' 'ить' 'имо' 'ите' 'лять' - 'їш' 'їть' 'їмо' 'їте' 'ять' - 'ать' + 'ляти' + 'їш' 'їть' 'їмо' 'їте' 'ять' 'яти' (delete) ) ) - define noun as ( [substring] among ( - 'ам' 'ами' 'ах' + 'ам' 'ами' 'ах' // вод|ам 'ею' 'ям' 'ями' 'ях' 'ові' 'ом' @@ -200,40 +191,45 @@ backwardmode ( 'ень' 'ой' 'ію' 'ії' + 'ів' + 'ев' 'ов' 'ей' 'иям' 'иях' 'ию' + 'іям' 'іях' + 'ия' 'єю' 'еві' 'єм' 'їв' + 'ією' 'иєю' 'еєю' + 'ьї' 'ьє' 'ьєю' 'ью' 'ья' (delete) ) ) - define common_avn as ( + define all_vowels as ( [substring] among ( - 'а' 'в' 'е' 'є' 'и' 'і' + 'а' 'в' 'е' 'є' 'и' 'і' // вод|а 'й' 'о' 'у' 'ь' 'ю' 'я' - 'ій' 'ою' (delete) ) ) + // HERE!!!! define derivational as ( [substring] R2 among ( - 'іст' + 'іст' // незалежн|іст.тю 'ост' + 'еньк' (delete) ) ) - // define tidy_up as ( - // [substring] among ( - // // 'ейш' - // // 'ейше' // superlative forms - // // (delete - // // ['н'] 'н' delete - // // ) - // // 'н' - // // ('н' delete) // e.g. -nno endings - // // '{'}' - // // (delete) // with some slight false conflations - // ) - // ) + define tidy_up as ( + [substring] among ( + 'д' ('д' delete) // усевлад|д.ям + 'ж' ('ж' delete) + 'л' ('л' delete) + 'н' ('н' delete) + 'с' ('с' delete) + 'т' ('т' delete) + 'ч' ('ч' delete) + ) + ) ) define stem as ( @@ -246,11 +242,11 @@ define stem as ( ( try reflexive - adjectival or verb or noun or common_avn + adjectival or verb or noun or all_vowels ) ) do derivational - // do tidy_up + do tidy_up ) ) diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb index 92594795..44dc7d08 100644 --- a/tests/algorithms/ukrainian_test.rb +++ b/tests/algorithms/ukrainian_test.rb @@ -33,7 +33,6 @@ perfective_gerund = { - 'в' => %w[донаписа|в дороби|в дороби|в], # ?? very common 'вши' => %w[написа|вши зроби|вши], 'вшись' => %w[оберіга|вшись спакува|вшись], 'вшися' => %w[оберіга|вшися сподіва|вшися], @@ -49,24 +48,58 @@ 'лячись' => %w[бав|лячись], 'лячися' => %w[бав|лячися], 'ячи' => %w[сид|ячи вовтуз|ячи], - 'ячись' => %w[], #? - 'ячися' => %w[], #? + 'ячись' => %w[вовтуз|ячись] +} + +reflexive = { + 'ється' => %w[смі|ється], # незнайшов дієслів + 'еться' => %w[спиш|еться], # незнайшов дієслів + + # *ся + 'ся' => %w[осік|ся], + + # rules from verb: + 'ти' => %w[би|ти.ся вовтузи|ти.ся], + # 'ть' => %w[роб|ить.ся], # вже є правило "ить" + 'іть' => %w[подруж|іть.ся], + 'те' => %w[бав|те.ся], + 'й' => %w[вдума|й.ся], + 'йте' => %w[вдума|йте.ся], + 'ать' => %w[бач|ать.ся], + + 'в ла ло ли' => %w[вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся], + 'ю єш ємо єте ють' => %w[смі|ю.ся смі|єш.ся смі|ємо.ся смі|єте.ся смі|ють.ся], + 'у еш емо ете уть' => %w[спиш|у.ся спиш|еш.ся спиш|емо.ся спиш|ете.ся спиш|уть.ся], + 'лю иш ить имо ите лять' => %w[див|лю.ся див|иш.ся див|ить.ся див|имо.ся див|ите.ся див|лять.ся], + 'їш їть їмо їте ять' => %w[бо|їш.ся бо|їть.ся бо|їмо.ся бо|їте.ся бо|ять.ся], + + + # *сь + 'сь' => %w[недонавч|и.сь змага|ю.сь], # вчи|сь + + # rules from verb: + '2 ти' => %w[боро|ти.сь], + '2 в ла ло ли' => %w[вчи|в.сь вчи|ла.сь вчи|ло.сь вчи|ли.сь], } # do we need to add prefix rule 'н*' for adjectives? # because removes single vowels for verbs like 'вчи|ла.сь' = > 'вчи|л' adjective = { - 'ий ого ому им ім' => %w[зелен|ий зелен|ого зелен|ому зелен|им зелен|ім], - 'іший ішого ішому ішим ішім' => %w[зелен|іший зелен|ішого зелен|ішому зелен|ішим зелен|ішім], - 'іше' => %w[зелен|іше], - 'ої ій ою' => %w[зелен|ої зелен|ій зелен|ою], - 'іша ішої ішій ішу ішою' => %w[зелен|іша зелен|ішої зелен|ішій зелен|ішу зелен|ішою], - 'их ими' => %w[зелен|их зелен|ими], - 'іші іших ішими' => %w[зелен|іші зелен|іших зелен|ішими], + 'ий ого ому им ім' => %w[зел|ен.ий зел|ен.ого зел|ен.ому зел|ен.им зел|ен.ім], + 'іший ішого ішому ішим ішім' => %w[зел|ен.іший зел|ен.ішого зел|ен.ішому зел|ен.ішим зел|ен.ішім], + 'іше' => %w[зел|ен.іше], + 'ої ій ою' => %w[зел|ен.ої зел|ен.ій зел|ен.ою], + 'іша ішої ішій ішу ішою' => %w[зел|ен.іша зел|ен.ішої зел|ен.ішій зел|ен.ішу зел|ен.ішою], + 'их ими' => %w[зел|ен.их зел|ен.ими], + 'іші іших ішими' => %w[зел|ен.іші зел|ен.іших зел|ен.ішими], 'ього ьому' => %w[верхн|ього верхн|ьому], 'ьої ьою' => %w[верхн|ьої верхн|ьою], 'іх іми' => %w[верхн|іх верхн|іми], - + 'ова ове' => %w[ацетон|ова ацетон|ове], + 'їй иїй' => %w[довгові|їй голош|иїй], + 'йому ийому' => %w[незна|йому товстош|ийому], + 'єє еє' => %w[трет|єє турецьк|еє], + 'ена ені ене ену' => %w[втрач|ені втрач|ена втрач|ене втрач|ену], 'яча яче ячу ячі' => %w[сид|яча сид|яче сид|ячу сид|ячі], 'ача аче ачу ачі' => %w[дриж|ача дриж|аче дриж|ачу дриж|ачі], 'юча юче ючу ючі' => %w[далені|юча далені|юче далені|ючу далені|ючі], @@ -86,10 +119,9 @@ 'уч' => %w[пиш|уч.ий далені|уч.ого пиш|уч.ому пиш|уч.им пиш|уч.ім пиш|уч.ої пиш|уч.ій пиш|уч.ою пиш|уч.их пиш|уч.ими], - # Need or needn't ? - # 'ен' => %w[втрач|ен.ий втрач|ен.ого втрач|ен.ому втрач|ен.им втрач|ен.ім - # втрач|ен.а втрач|ен.е втрач|ен.ої втрач|ен.ій втрач|ен.у втрач|ен.ою - # втрач|ен.і втрач|ен.их втрач|ен.ими], + 'ен' => %w[втрач|ен.ий втрач|ен.ого втрач|ен.ому втрач|ен.им втрач|ен.ім + втрач|ен.ої втрач|ен.ій втрач|ен.ою втрач|ен.их втрач|ен.ими + клен| ], } # https://en.wikipedia.org/wiki/Reflexive_pronoun @@ -139,54 +171,28 @@ # # вдумайт|еся # adj instead of verb вдума|йтеся # } -# абсорбувати, абсорбувать, абсорбуй, абсорбуймо, абсорбуйте, абсорбую, абсорбуєш, -# абсорбує, абсорбуємо, абсорбуєм, абсорбуєте, абсорбують, абсорбуватиму, абсорбуватимеш, абсорбуватиме, -# абсорбуватимем, абсорбуватимемо, абсорбуватимете, абсорбуватимуть, абсорбував, абсорбувала, абсорбувало, -# абсорбували, абсорбовано - -reflexive = { - 'ється' => %w[смі|ється], # незнайшов дієслів - 'еться' => %w[спиш|еться], # незнайшов дієслів - - # *ся - 'ся' => %w[осік|ся], - - # rules from verb: - 'ти' => %w[би|ти.ся милува|ти.ся], - # 'ть' => %w[роб|ить.ся], # вже є правило "ить" - 'іть' => %w[подруж|іть.ся], - 'те' => %w[бав|те.ся], - 'й' => %w[вдума|й.ся], - 'йте' => %w[вдума|йте.ся], - 'ать' => %w[бач|ать.ся], - - 'в ла ло ли' => %w[вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся], - 'ю єш ємо єте ють' => %w[смі|ю.ся смі|єш.ся смі|ємо.ся смі|єте.ся смі|ють.ся], - 'у еш емо ете уть' => %w[спиш|у.ся спиш|еш.ся спиш|емо.ся спиш|ете.ся спиш|уть.ся], - 'лю иш ить имо ите лять' => %w[див|лю.ся див|иш.ся див|ить.ся див|имо.ся див|ите.ся див|лять.ся], - 'їш їть їмо їте ять' => %w[бо|їш.ся бо|їть.ся бо|їмо.ся бо|їте.ся бо|ять.ся], - - - # *сь - 'сь' => %w[недонавч|и.сь], # вчи|сь - - # rules from verb: - '2 ти' => %w[боро|ти.сь], - '2 в ла ло ли' => %w[вчи|в.сь вчи|ла.сь вчи|ло.сь вчи|ли.сь], -} +# абсорбу|ватиму +# абсорбу|ватимеш +# абсорбу|ватиме +# абсорбу|ватимем +# абсорбу|ватимемо +# абсорбу|ватимете +# абсорбу|ватимуть +# абсорбу|вали +# абсорбо|вано verb = { - 'ти' => %w[працюва|ти], - # 'ть' => %w[роби|ть], # => роб|ить !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил - 'іть' => %w[роб|іть], - 'те' => %w[відправ|те], - 'йте' => %w[дума|йте], - 'ать' => %w[бач|ать], - 'ла ло ли' => %w[чита|ла чита|ло чита|ли], - 'єш ємо єте ють' => %w[чита|єш чита|ємо чита|єте чита|ють], - 'еш емо ете уть' => %w[пиш|еш пиш|емо пиш|ете пиш|уть], - 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], - 'їш їть їмо їте ять' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять], + 'ав али ало ала ать ати' => %w[пізнав|ав пізнав|али пізнав|ало пізнав|ала пізнав|ать пізнав|ати], + 'іть' => %w[роб|іть], + 'йте' => %w[дума|йте], + 'ме' => %w[пізнавати|ме], + 'ла ло ли' => %w[повез|ла повез|ло повез|ли], + 'ти ть те' => %w[обігну|ти поборо|ть обжені|те], + 'єш ємо єте ють' => %w[чита|єш чита|ємо чита|єте чита|ють], + 'еш емо ете уть' => %w[пиш|еш пиш|емо пиш|ете пиш|уть], + 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], + 'ляти' => %w[вироб|ляти], + 'їш їть їмо їте ять яти' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять сто|яти], } noun = { @@ -198,32 +204,69 @@ 'ень' => %w[зел|ень], 'ой' => %w[гер|ой], 'ію ії' => %w[комед|ію комед|ії], + 'ів' => %w[вовчик|ів], + 'ев ов ей иям иях ию' => %w[дер|ев електрол|ов солов|ей кривош|иям кривош|иях кривош|ию], + 'іям іях' => %w[промоакц|іям промоакц|іях], + 'ия єю еві єм їв' => %w[кривош|ия медіазбро|єю праотц|еві праотц|ем промете|їв], + 'ією иєю еєю' => %w[хім|ією кривош|иєю левз|еєю], + 'ьї ьє ьєю ью ья' => %w[лазан|ьї лазан|ьє лазан|ьєю лазан|ью лазан|ья], } adj_verb_noun = { # adj - 'а е і у ю я' => %w[зелен|а зелен|е зелен|і зелен|у верхн|ю верхн|я], + 'а е і у ю я' => %w[зел|ен.а зел|ен.е зел|ен.і зел|ен.у верхн|ю верхн|я], # verb - 'в е є й у ю' => %w[писа|в пиш|е чита|є чита|й пиш|у чита|ю], + 'в е є й у ю' => %w[нагляну|в пиш|е чита|є чита|й пиш|у чита|ю], # noun - 'а е и і й ' => %w[вод|а пісн|е вод|и вод|і сара|й], - 'о у ь ю я' => %w[вод|о вод|у совіст|ь пісн|ю пісн|я], - 'ій ою' => %w[ген|ій вод|ою], + 'а е и і й ' => %w[вод|а пісн|е вод|и вод|і сара|й], + 'о у ь ю я' => %w[вод|о вод|у ваган|ь пісн|ю пісн|я] } derivational = { - 'іст' => %w[безтурботн|іст.ь безтурботн|іст.ю], + 'іст' => %w[безтурботн|іст.ю незалежн|іст.ю], - 'ост' => %w[безтурботн|ост.і безтурботн|ост.ям безтурботн|ост|ями безтурботн|ост.ях - безтурботн|ост.и безтурботн|ост.е безтурботн|ост.ей], # ??? ти/те/й + 'ост' => %w[безтурботн|ост.і безтурботн|ост.ям безтурботн|ост|ями + безтурботн|ост.ях безтурботн|ост.ей незалежн|ост.ями їмост|ями ], # ??? ти/те/й + + 'еньк' => %w[посид|еньк.и холодн|еньк.ий] } -# tidy_up = { -# 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], -# 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], -# 'н[н]' => %w[смирен|но смирн|о], -# 'ь' => %w[свідоміст|ь] -# } +need_to_approve = { + # noun + 'ві' => %w[район|о.ві], #? *ві + 'го' => %w[раду|го], + 'ка кою ку' => %w[єзуїт|ка єзуїт|кою єзуїт|ку + сака сакою саку], # more then 2 syllables + 'очки очці очку очкою очка' => %w[маків|очки маків|очці маків|очку маків|очкою маків|очка], + 'очко очок очкам очками очках' => %w[маків|очко маків|очок маків|очкам маків|очками маків|очках], + + # verb + 'ала ало ась' => %w[поруб|ала поруб|ало докр|ась], + 'вав вавсь вався вала' => %w[району|вав району|вавсь району|вався району|вала], + 'валася вали вались валися вало' => %w[району|валася району|вали району|валися району|вало], + 'валось валося ватись ватися' => %w[району|валось району|валося району|ватись району|ватися], + 'валась всь вся вати' => %w[району|валась зруши|всь зруши|вся району|вати], + 'есь еся' => %w[європеїзуйт|есь європеїзуйт|еся], + 'ила или ило илося ити ись ися' => %w[жар|ила жар|или жар|ило жар|илося жар|ити жарит|ись жарит|ися], + 'ім імо' => %w[жаріюч|ім жаріюч|імо], + 'ймо ймось ймося йсь йся' => %w[жарту|ймо жеврі|ймось жеврі|ймося єдна|йсь єдна|йся], + 'лась лася лись лися лось лося' => %w[єдна|лась єдна|лася єдна|лись єдна|лися єдна|лось єдна|лося], + 'мо мось мося' => %w[жали|мо жали|мось жали|мося], + 'овував овувала овувати ' => %w[забальзам|овував забальзам|овувала забальзам|овувати], + 'ось осте ості' => %w[пилос|ось лукав|осте лукав|ості лушпин|очка], + 'сті сть стю' => %w[маневрено|сті маневрені|сть маневрені|стю], + 'ував увала увати' => %w[маневр|ував маневр|увала маневр|увати], +} + +tidy_up = { + 'дд' => %w[усевлад|д.ям], + 'жж' => %w[лівобереж|ж.ями], + 'лл' => %w[весіл|л.ями], + 'нн' => %w[осін|н.ій], + 'сс' => %w[прус|с.ів], + 'тт' => %w[століт|т.ями], + 'чч' => %w[клоч|ч.я] +} exceptions = { # ґ => г @@ -256,11 +299,9 @@ "брати" => "бра|ти", "беруть" => "бер|уть", - "дописати" => "дописа|ти", + "дописати" => "допис|ати", "допишуть" => "допиш|уть", - "посиденьки" => "посиденьк|и", - "лікар" => "лікар", "лікарів" => "лікар|ів", # ??? в @@ -279,11 +320,83 @@ 'академію' => 'академ', } + +need_to_approve_2 = { + # заміна + 'завойовував' => 'завойов', # завойов|ував + 'завойовувала' => 'завойов', + 'завойовувати' => 'завойов', + + 'надкльовував' => 'надкльов', # надкльов|ував + 'надкльовувала' => 'надкльов', + 'надкльовувати' => 'надкльов', + + 'витанцьовував' => 'витанцьов', # витанцьов|ував + 'витанцьовувала' => 'витанцьов', + 'витанцьовувати' => 'витанцьов', +} + +need_to_approve_3 = { + # для слів менше/рівне 3-м літерам не змінювати нічого + 'а' => 'а', + 'і' => 'і', + 'у' => 'у', + 'в' => 'в', + 'на' => 'на', + 'по' => 'по', + 'до' => 'до', + 'ні' => 'ні', + 'але' => 'але', + 'був' => 'був', + 'рік' => 'рік', + 'кіт' => 'кіт', + 'ніж' => 'ніж', + 'так' => 'так', + + # слова із 4-х літер - вдсікати останню літеру 'а в е є и і й о у ь ю я' + 'бува' => 'був', + 'віче' => 'віч', + 'наче' => 'нач', + 'паче' => 'пач', + # року, + # році, + # роче, + # роки, + # ріка + # ріка, ріки, ріці, ріку, , ріці, ріко, ріки, , ріки, , , ріки + + # для слів більше 4х літер усі правила + # рокові, + # роком, + # років, рокам, роками, роках, + # рікою рікам ріками ріках + # річка, річку, річкою, річці, річко, річки, річок, річкам, річками, річках + # рікша + # відер + # відра + + + 'неначе' => 'неначе', + 'одначе' => 'одначе', + + 'пірʼя' => 'пір' +} + $all_tests = [] $errors = {} +require 'yaml' + +def yml_h_tests(file) + YAML.load_file(file) +end + def incorrect_stem_msg(result_stem, word, stem) - "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" + # "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" + # "--------------------------------\n" + "Word: #{word}\n" + + "should be: #{stem}\n" + + "but it is: #{result_stem}\n" end def check_words_set(words_set, set_name) @@ -293,7 +406,7 @@ def check_words_set(words_set, set_name) word = [stem, ending&.delete('.')].join $all_tests << word - result_stem = (`echo "#{word}" | ./stemwords -l uk`).strip + result_stem = (`echo "#{word}" | ../stemwords -l uk`).strip # if result_stem == 'ач' # puts '>>' # puts test_case @@ -318,17 +431,22 @@ def check_words_set(words_set, set_name) [noun, 'noun'], [adj_verb_noun, 'adj_verb_noun'], [derivational, 'derivational'], - # [tidy_up, 'tidy_up'] + [tidy_up, 'tidy_up'] ].each do |words_set, set_name| check_words_set(words_set, set_name) end -exceptions.each do |word, test_case| - stem, ending = test_case.split('|') - $all_tests << word - result_stem = (`echo "#{word}" | ./stemwords -l uk `).strip - $errors['exceptions'] ||= [] - $errors['exceptions'] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem +[ + [exceptions, 'exceptions'] + # [yml_h_tests('./algorithms/uk_test_pairs_N1.yml'), 'uk_test_pairs_N1.yml'] +].each do |words_set, set_name| + words_set.each do |word, test_case| + stem, ending = test_case.to_s.split('|') + $all_tests << word + result_stem = (`echo "#{word}" | ../stemwords -l uk `).strip + $errors[set_name] ||= [] + $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem + end end if $errors.values.all?(&:empty?) @@ -337,7 +455,7 @@ def check_words_set(words_set, set_name) $errors.each do |set_name, errs| next if errs.empty? - puts "=== #{set_name}:" + puts "\n=== #{set_name}:\n\n" puts(errs.join("\n")) end end @@ -407,3 +525,5 @@ def check_words_set(words_set, set_name) +# Add yml tests +# https://github.com/Tapkomet/UAStemming/blob/master/Results.txt From a3546d6f5a61a38dad57263e3cb885f8dd8ef5fd Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Wed, 20 Sep 2023 18:59:18 +0300 Subject: [PATCH 11/13] Add Ukrainian stemmer: added word length restriction --- algorithms/ukrainian.sbl | 43 ++-- explanations/ukrainian.sbl.utf | 43 ++-- .../uk_test_01_one_two_three_size.txt | 54 +++++ tests/algorithms/uk_test_02_four_size.txt | 18 ++ tests/algorithms/uk_test_03_test_victory.txt | 22 +++ tests/algorithms/uk_test_04_test_popular.txt | 185 ++++++++++++++++++ tests/algorithms/ukrainian_test.rb | 72 +++---- 7 files changed, 363 insertions(+), 74 deletions(-) create mode 100644 tests/algorithms/uk_test_01_one_two_three_size.txt create mode 100644 tests/algorithms/uk_test_02_four_size.txt create mode 100644 tests/algorithms/uk_test_03_test_victory.txt create mode 100644 tests/algorithms/uk_test_04_test_popular.txt diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index 85cbe47c..6b3cc847 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -52,13 +52,16 @@ stringdef a_prime '{U+2032}' // {a_prime} routines ( prelude mark_regions R2 + min_len + short_word + long_word perfective_gerund adjective adjectival reflexive verb noun - all_vowels + remove_last_letter derivational tidy_up ) @@ -91,8 +94,8 @@ define mark_regions as ( $pV = limit $p2 = limit do ( - gopast v setmark pV gopast non-v - gopast v gopast non-v setmark p2 + gopast v setmark pV gopast non-v + gopast v gopast non-v setmark p2 ) ) @@ -201,9 +204,9 @@ backwardmode ( ) ) - define all_vowels as ( + define remove_last_letter as ( [substring] among ( - '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' // {v}{o}{d}|{a} + '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' // NOUN: {v}{o}{d}|{a}, VERB: {v}{ch}{y}|{v} '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' (delete) ) @@ -230,23 +233,37 @@ backwardmode ( '{ch}' ('{ch}' delete) ) ) -) -define stem as ( - do prelude - do mark_regions + define min_len as ( + $(len >= 4) + ) - backwards setlimit tomark pV for ( + define short_word as ( + $(len == 4) and remove_last_letter + ) + + define long_word as ( do ( - perfective_gerund or - ( + perfective_gerund or ( try reflexive - adjectival or verb or noun or all_vowels + adjectival or verb or noun or remove_last_letter ) ) do derivational + ) +) + +define stem as ( + do prelude + do mark_regions + + backwards setlimit tomark pV for ( + min_len + + short_word or long_word + do tidy_up ) ) diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf index 3f321ef6..9ff1b342 100755 --- a/explanations/ukrainian.sbl.utf +++ b/explanations/ukrainian.sbl.utf @@ -52,13 +52,16 @@ stringdef a_prime '{U+2032}' // ′ routines ( prelude mark_regions R2 + min_len + short_word + long_word perfective_gerund adjective adjectival reflexive verb noun - all_vowels + remove_last_letter derivational tidy_up ) @@ -91,8 +94,8 @@ define mark_regions as ( $pV = limit $p2 = limit do ( - gopast v setmark pV gopast non-v - gopast v gopast non-v setmark p2 + gopast v setmark pV gopast non-v + gopast v gopast non-v setmark p2 ) ) @@ -201,9 +204,9 @@ backwardmode ( ) ) - define all_vowels as ( + define remove_last_letter as ( [substring] among ( - 'а' 'в' 'е' 'є' 'и' 'і' // вод|а + 'а' 'в' 'е' 'є' 'и' 'і' // NOUN: вод|а, VERB: вчи|в 'й' 'о' 'у' 'ь' 'ю' 'я' (delete) ) @@ -230,23 +233,37 @@ backwardmode ( 'ч' ('ч' delete) ) ) -) -define stem as ( - do prelude - do mark_regions + define min_len as ( + $(len >= 4) + ) - backwards setlimit tomark pV for ( + define short_word as ( + $(len == 4) and remove_last_letter + ) + + define long_word as ( do ( - perfective_gerund or - ( + perfective_gerund or ( try reflexive - adjectival or verb or noun or all_vowels + adjectival or verb or noun or remove_last_letter ) ) do derivational + ) +) + +define stem as ( + do prelude + do mark_regions + + backwards setlimit tomark pV for ( + min_len + + short_word or long_word + do tidy_up ) ) diff --git a/tests/algorithms/uk_test_01_one_two_three_size.txt b/tests/algorithms/uk_test_01_one_two_three_size.txt new file mode 100644 index 00000000..370824b4 --- /dev/null +++ b/tests/algorithms/uk_test_01_one_two_three_size.txt @@ -0,0 +1,54 @@ +а +в +є +ж +з +з +і +й +о +у +я +ай +ба +до +же +її +їм +ку +ні +ну +ой +та +фу +це +ще +як +вау +вії +вій +він +вія +вус +гід +дай +дім +дія +лай +най +паж +піт +пуд +рік +рок +рук +ряд +син +так +фух +хай +хоч +хто +чом +шик +шия diff --git a/tests/algorithms/uk_test_02_four_size.txt b/tests/algorithms/uk_test_02_four_size.txt new file mode 100644 index 00000000..bc90ee6c --- /dev/null +++ b/tests/algorithms/uk_test_02_four_size.txt @@ -0,0 +1,18 @@ +хат|а +лап|а +лат|и +літ|о +луп|а +тус|я +люс|я +лял|я +люд|а +сін|о +сел|о +сар|а +дід|о +дул|о +дяд|я +мам|а +тат|о +син|у diff --git a/tests/algorithms/uk_test_03_test_victory.txt b/tests/algorithms/uk_test_03_test_victory.txt new file mode 100644 index 00000000..e71dcbf0 --- /dev/null +++ b/tests/algorithms/uk_test_03_test_victory.txt @@ -0,0 +1,22 @@ +перемог +перемог|а +перемог|ам +перемоз|і +перемаг|ав +перемага|вши +перемага|й +перемага|єш +перемог|ла +перемог|ли +перемож|е +перемож|емо +перемож|ете +переміг +перемігш|и +переможн|о +перемож|ець +переможц|еві +переможц|ем +переможн|а +переможн|е +переможн|ий diff --git a/tests/algorithms/uk_test_04_test_popular.txt b/tests/algorithms/uk_test_04_test_popular.txt new file mode 100644 index 00000000..7ce23e94 --- /dev/null +++ b/tests/algorithms/uk_test_04_test_popular.txt @@ -0,0 +1,185 @@ +популяризатор +популяризатор|а +популяризатор|ові +популяризатор|у +популяризатор|ом +популяризатор|і +популяризатор|е +популяризатор|и +популяризатор|ів +популяризатор|ам +популяризатор|ами +популяризатор|ах +популяризаторк|а +популяризаторк|и +популяризаторц|і +популяризаторк|у +популяризаторк|ою +популяризаторк|о +популяризаторок +популяризаторк|ам +популяризаторк|ами +популяризаторк|ах +популяризаторськ|ий +популяризаторськ|ого +популяризаторськ|ому +популяризаторськ|им +популяризаторськ|ім +популяризаторськ|а +популяризаторськ|ої +популяризаторськ|ій +популяризаторськ|у +популяризаторськ|ою +популяризаторськ|е +популяризаторськ|і +популяризаторськ|их +популяризаторськ|ими +популяризаційн|ий +популяризаційн|ого +популяризаційн|ому +популяризаційн|им +популяризаційн|ім +популяризаційн|а +популяризаційн|ої +популяризаційн|ій +популяризаційн|у +популяризаційн|ою +популяризаційн|е +популяризаційн|і +популяризаційн|их +популяризаційн|ими +популяризаці|я +популяризац|ії +популяризац|ію +популяризац|ією +популяризаці|є +популяризован|ий +популяризован|ого +популяризован|ому +популяризован|им +популяризован|ім +популяризован|а +популяризован|ої +популяризован|ій +популяризован|у +популяризован|ою +популяризован|е +популяризован|і +популяризован|их +популяризован|ими +популяризува|вши +популяризува|вшись +популяризува|вшися +популяризуван|ня +популяризуван|ню +популяризуван|ням +популяризуван|ні +популяризув|ати +популяризув|ать +популяризу|й +популяризуйм|о +популяризу|йте +популяризу|ю +популяризу|єш +популяризу|є +популяризу|ємо +популяризу|єм +популяризу|єте +популяризу|ють +популяризуватим|у +популяризуватим|еш +популяризувати|ме +популяризуватим|ем +популяризуватим|емо +популяризуватим|ете +популяризуватим|уть +популяризув|ав +популяризув|ала +популяризув|ало +популяризув|али +популяризован|о +популяризув|атися +популяризув|атись +популяризув|аться +популяризу|йсь +популяризу|йся +популяризуйм|ось +популяризуйм|ося +популяризу|йтесь +популяризу|йтеся +популяризу|юсь +популяризу|юся +популяризу|єшся +популяриз|ується +популяризу|ємось +популяризу|ємося +популяризу|ємся +популяризу|єтесь +популяризу|єтеся +популяризу|ються +популяризуватим|усь +популяризуватим|уся +популяризуватим|ешся +популяризуват|иметься +популяризуватим|емось +популяризуватим|емося +популяризуватим|емся +популяризуватим|етесь +популяризуватим|етеся +популяризуватим|уться +популяризув|авсь +популяризув|ався +популяризув|алась +популяризув|алася +популяризув|алось +популяризув|алося +популяризув|ались +популяризув|алися +популяризу|ючи +популяризу|ючись +популяризу|ючися +популяристик|а +популяристик|и +популяристиц|і +популяристик|у +популяристик|ою +популяристик|о +популярн|ий +популярн|ого +популярн|ому +популярн|им +популярн|ім +популярн|а +популярн|ої +популярн|ій +популярн|у +популярн|ою +популярн|е +популярн|і +популярн|их +популярн|ими +популярніс|ть +популярн|ості +популярнос|ти +популярн|істю +популярнос|те +популярн|остей +популярн|остям +популярн|остями +популярн|остях +популярн|іше +популярніш +популярн|іший +популярн|ішого +популярн|ішому +популярн|ішим +популярн|ішім +популярн|іша +популярн|ішої +популярн|ішій +популярн|ішу +популярн|ішою +популярн|іші +популярн|іших +популярн|ішими +популярн|о diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb index 44dc7d08..dcb56f6f 100644 --- a/tests/algorithms/ukrainian_test.rb +++ b/tests/algorithms/ukrainian_test.rb @@ -212,7 +212,7 @@ 'ьї ьє ьєю ью ья' => %w[лазан|ьї лазан|ьє лазан|ьєю лазан|ью лазан|ья], } -adj_verb_noun = { +adj_verb_noun = { # remove_last_letter # adj 'а е і у ю я' => %w[зел|ен.а зел|ен.е зел|ен.і зел|ен.у верхн|ю верхн|я], # verb @@ -336,52 +336,6 @@ 'витанцьовувати' => 'витанцьов', } -need_to_approve_3 = { - # для слів менше/рівне 3-м літерам не змінювати нічого - 'а' => 'а', - 'і' => 'і', - 'у' => 'у', - 'в' => 'в', - 'на' => 'на', - 'по' => 'по', - 'до' => 'до', - 'ні' => 'ні', - 'але' => 'але', - 'був' => 'був', - 'рік' => 'рік', - 'кіт' => 'кіт', - 'ніж' => 'ніж', - 'так' => 'так', - - # слова із 4-х літер - вдсікати останню літеру 'а в е є и і й о у ь ю я' - 'бува' => 'був', - 'віче' => 'віч', - 'наче' => 'нач', - 'паче' => 'пач', - # року, - # році, - # роче, - # роки, - # ріка - # ріка, ріки, ріці, ріку, , ріці, ріко, ріки, , ріки, , , ріки - - # для слів більше 4х літер усі правила - # рокові, - # роком, - # років, рокам, роками, роках, - # рікою рікам ріками ріках - # річка, річку, річкою, річці, річко, річки, річок, річкам, річками, річках - # рікша - # відер - # відра - - - 'неначе' => 'неначе', - 'одначе' => 'одначе', - - 'пірʼя' => 'пір' -} - $all_tests = [] $errors = {} @@ -391,6 +345,10 @@ def yml_h_tests(file) YAML.load_file(file) end +def txt_tests(file) + IO.read(file).split +end + def incorrect_stem_msg(result_stem, word, stem) # "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" # "--------------------------------\n" @@ -437,7 +395,7 @@ def check_words_set(words_set, set_name) end [ - [exceptions, 'exceptions'] + [exceptions, 'exceptions'], # [yml_h_tests('./algorithms/uk_test_pairs_N1.yml'), 'uk_test_pairs_N1.yml'] ].each do |words_set, set_name| words_set.each do |word, test_case| @@ -449,6 +407,24 @@ def check_words_set(words_set, set_name) end end +[ + [txt_tests('./algorithms/uk_test_01_one_two_three_size.txt'), '01_one_two_three_size'], + [txt_tests('./algorithms/uk_test_02_four_size.txt'), '02_four_size'], + [txt_tests('./algorithms/uk_test_03_test_victory.txt'), '03_test_victory'], # check and fix + [txt_tests('./algorithms/uk_test_04_test_popular.txt'), '04_popular'], # check and fix +].each do |test_words, set_name| + test_words.each do |test_word| + stem, ending = test_word.to_s.split('|') + word =[stem, ending].join('') + $all_tests << word + result_stem = (`echo "#{word}" | ../stemwords -l uk `).strip + $errors[set_name] ||= [] + $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem + end +end + + + if $errors.values.all?(&:empty?) puts("#{$all_tests.count} test(s) passed successfully!") else From 7545589155db64a69836ff728282dfbd2a797e22 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Sun, 24 Sep 2023 22:11:28 +0300 Subject: [PATCH 12/13] Add Ukrainian stemmer --- bin/readable_sbl | 57 -- bin/utf_to_sbl | 56 -- explanations/russian.sbl.explanation | 261 --------- explanations/ukrainian.sbl.utf | 269 ---------- tests/algorithms/Readme.md | 8 - tests/algorithms/russian_test.rb | 128 ----- .../uk_test_01_one_two_three_size.txt | 54 -- tests/algorithms/uk_test_02_four_size.txt | 18 - tests/algorithms/uk_test_03_test_victory.txt | 22 - tests/algorithms/uk_test_04_test_popular.txt | 185 ------- tests/algorithms/ukrainian_test.rb | 505 ------------------ 11 files changed, 1563 deletions(-) delete mode 100755 bin/readable_sbl delete mode 100755 bin/utf_to_sbl delete mode 100644 explanations/russian.sbl.explanation delete mode 100755 explanations/ukrainian.sbl.utf delete mode 100644 tests/algorithms/Readme.md delete mode 100644 tests/algorithms/russian_test.rb delete mode 100644 tests/algorithms/uk_test_01_one_two_three_size.txt delete mode 100644 tests/algorithms/uk_test_02_four_size.txt delete mode 100644 tests/algorithms/uk_test_03_test_victory.txt delete mode 100644 tests/algorithms/uk_test_04_test_popular.txt delete mode 100644 tests/algorithms/ukrainian_test.rb diff --git a/bin/readable_sbl b/bin/readable_sbl deleted file mode 100755 index ac0163b9..00000000 --- a/bin/readable_sbl +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env ruby - -# Replaces UTF chars and prints SBL files in a more readable way: -# $ bin/readable_sbl ./algorithms/russian.sbl - -# Converts Latin chars into Unicode letters: -# -# define perfective_gerund as ( -# [substring] among ( -# '{v}' -# '{v}{sh}{i}' -# '{v}{sh}{i}{s}{'}' -# ... -# => -# define perfective_gerund as ( -# [substring] among ( -# 'в' -# 'вши' -# 'вшись' -# ... - -def build_chars_map(sbl_file) - chars_hash = {} - exceptions = ["'"] # apostrophe - - File.readlines(sbl_file).each do |line| - char = line.match(/stringdef\s+(\S+)\s+'\{U\+(\S+)\}'/) # E.g.: stringdef zh '{U+0436}' - next if char.nil? - - latin = char[1] - utf = '' << char[2].to_i(16) - next unless exceptions.index(utf).nil? - - chars_hash[latin] = utf # extracts { 'zh': '0436' } => { 'zh': 'ж' } - end - - chars_hash -end - -def readable_sbl_file(sbl_file, chars_map) - File.readlines(sbl_file).map do |line| - readable_line = line - chars_map.each do |latin_letter, real_letter| - readable_line = readable_line.gsub("{#{latin_letter}}", real_letter) - end - readable_line - end.join -end - -sbl_file = ARGV.first.to_s - -puts("Run script with sbl file, e.g.: 'bin/readable_sbl ./algorithms/russian.sbl'") and exit if sbl_file.empty? - -puts("File '#{sbl_file}' doesn't exist") and exit unless File.exist?(sbl_file) - -chars_map = build_chars_map(sbl_file) -puts readable_sbl_file(sbl_file, chars_map) diff --git a/bin/utf_to_sbl b/bin/utf_to_sbl deleted file mode 100755 index f43cf717..00000000 --- a/bin/utf_to_sbl +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env ruby - -# Replaces Latin chars and prints SBL file: -# $ bin/utf_to_sbl ./explanations/ukrainian.sbl.utf - -# Converts Unicode chars into Latin letters: -# -# define perfective_gerund as ( -# [substring] among ( -# 'вши' -# 'вшись' -# ... -# => -# define perfective_gerund as ( -# [substring] among ( -# '{v}{sh}{i}' -# '{v}{sh}{i}{s}{'}' -# ... - - -def build_chars_map(utf_file) - chars_hash = {} - exceptions = ["'"] # apostrophe - - File.readlines(utf_file).each do |line| - char = line.match(/stringdef\s+(\S+)\s+'\{U\+(\S+)\}'/) # E.g.: stringdef zh '{U+0436}' - next if char.nil? - - latin = char[1] - utf = '' << char[2].to_i(16) - next unless exceptions.index(utf).nil? - - chars_hash[utf] = latin # extracts { 'zh': '0436' } => { 'ж': 'zh' } - end - - chars_hash -end - -def readable_sbl_file(utf_file, chars_map) - File.readlines(utf_file).map do |line| - readable_line = line - chars_map.each do |real_letter, latin_letter| - readable_line = readable_line.gsub(real_letter, "{#{latin_letter}}") - end - readable_line - end.join -end - -utf_file = ARGV.first.to_s - -puts("Run script with 'utf' file, e.g.: 'bin/utf_to_sbl ./explanations/ukrainian.sbl.utf'") and exit if utf_file.empty? - -puts("File '#{utf_file}' doesn't exist") and exit unless File.exist?(utf_file) - -chars_map = build_chars_map(utf_file) -puts readable_sbl_file(utf_file, chars_map) diff --git a/explanations/russian.sbl.explanation b/explanations/russian.sbl.explanation deleted file mode 100644 index e59bdacd..00000000 --- a/explanations/russian.sbl.explanation +++ /dev/null @@ -1,261 +0,0 @@ -stringescapes {} - -/* the 33 Cyrillic letters represented in ASCII characters following the - * conventions of the standard Library of Congress transliteration: */ - -stringdef a '{U+0430}' -stringdef b '{U+0431}' -stringdef v '{U+0432}' -stringdef g '{U+0433}' -stringdef d '{U+0434}' -stringdef e '{U+0435}' -stringdef e" '{U+0451}' -stringdef zh '{U+0436}' -stringdef z '{U+0437}' -stringdef i '{U+0438}' -stringdef i` '{U+0439}' -stringdef k '{U+043A}' -stringdef l '{U+043B}' -stringdef m '{U+043C}' -stringdef n '{U+043D}' -stringdef o '{U+043E}' -stringdef p '{U+043F}' -stringdef r '{U+0440}' -stringdef s '{U+0441}' -stringdef t '{U+0442}' -stringdef u '{U+0443}' -stringdef f '{U+0444}' -stringdef kh '{U+0445}' -stringdef ts '{U+0446}' -stringdef ch '{U+0447}' -stringdef sh '{U+0448}' -stringdef shch '{U+0449}' -stringdef " '{U+044A}' -stringdef y '{U+044B}' -stringdef ' '{U+044C}' -stringdef e` '{U+044D}' -stringdef iu '{U+044E}' -stringdef ia '{U+044F}' - -routines ( mark_regions R2 - perfective_gerund - adjective - adjectival - reflexive - verb - noun - derivational - tidy_up -) - -externals ( stem ) - -integers ( pV p2 ) - -groupings ( v ) - -define v 'аеиоуыэюя' - -define mark_regions as ( - - $pV = limit - $p2 = limit - do ( - gopast v setmark pV gopast non-v - gopast v gopast non-v setmark p2 - ) -) - -backwardmode ( - - define R2 as $p2 <= cursor - - define perfective_gerund as ( - [substring] among ( - 'в' // написа|в проковыля|в - 'вши' // написа|вши заслоня|вши - 'вшись' // написа|вшись обня|вшись - ('а' or 'я' delete) // REGEXP /(.*[ая])вшись|вши|в/ - 'ив' // насыт|ив - 'ивши' // насыт|ивши - 'ившись' // насыт|ившись - 'ыв' // приб|ыв - 'ывши' // приб|ывши - 'ывшись' // приб|ывшись - (delete) // REGEXP /(.*)ывшись|ывши|ыв|ившись|ивши|ив/ - ) - ) - - define adjective as ( - [substring] among ( - 'ее' 'ие' 'ые' 'ое' 'ими' 'ыми' // зелен|ее висевш|ие ароматн|ые испорчен|ое иссохш|ими атласн|ыми - 'ей' 'ий' 'ый' 'ой' 'ем' 'им' // зелен|ей баран|ий аккуратн|ый активн|ой высохш|ем глубок|им - 'ым' 'ом' 'его' 'ого' 'ему' // главн|ым главн|ом бегущ|его главн|ого бывш|ему - 'ому' 'их' 'ых' 'ую' 'юю' 'ая' // богат|ому больш|их бурн|ых бронзов|ую верхн|юю весел|ая - 'яя' // внешн|яя - // and - - 'ою' // - which is somewhat archaic // верн|ою - 'ею' // - soft form of ою // верхн|ею - (delete) - ) - ) - - define adjectival as ( - adjective // cut firstly adjective ending - - /* of the participle forms, em, vsh, ivsh, yvsh are readily removable. - nn, юshch, shch, uюshch can be removed, with a small proportion of - errors. Removing im, uem, enn creates too many errors. - */ - - try ( - [substring] among ( - 'ем' // present passive participle // задава|емые изменя|ем - 'нн' // adjective from past passive participle // беспреста|нно деревя|нными - 'вш' // past active participle // отказа|вшись отделя|вший - 'ющ' 'щ' // present active participle // сталкива|ющихся умоля|ющими спеша|щих блестя|щему - ('а' or 'я' delete) - - // but not 'им' 'уем' // present passive participle - // or 'енн' // adjective from past passive participle - - 'ивш' 'ывш' // past active participle // брод|ивших несб|ывш(ее(ся)) - 'ующ' // present active participle // несуществ|ующий - (delete) - ) - ) - - ) - - define reflexive as ( - [substring] among ( - 'ся' // осек|ся несбывшее|ся - 'сь' // ввы|сь - (delete) - ) - ) - - define verb as ( - [substring] among ( - 'ла' 'на' 'ете' 'йте' 'ли' 'й' // сдела|ла приня|ла воспита|на потеря|на сдела|ете причиня|ете - // сдела|йте причиня|йте сдела|ли причиня|ли сдела|й причиня|й - 'л' 'ем' 'н' 'ло' 'но' 'ет' 'ют' // сдела|л приня|л воспита|ем потеря|ем сдела|н растеря|н - // сдела|ло причиня|ло сдела|но настоя|но сдела|ет объясня|ет - // сдела|ют объясня|ют - 'ны' 'ть' 'ешь' // сдела|ны потеря|ны сдела|ть потеря|ть сдела|ешь потеря|ешь - - 'нно' // пута|нно постоя|нно - ('а' or 'я' delete) - - 'ила' 'ыла' 'ена' 'ейте' // беспоко|ила прикр|ыла выруч|ена пожал|ейте - 'уйте' 'ите' 'или' 'ыли' 'ей' // пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей - 'уй' 'ил' 'ыл' 'им' 'ым' 'ен' // протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен - 'ило' 'ыло' 'ено' 'ят' 'ует' // став|ило неун|ыло обознач|ено обрат|ят повеств|ует - 'уют' 'ит' 'ыт' 'ены' 'ить' // преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить - 'ыть' 'ишь' 'ую' 'ю' // откр|ыть отправ|ишь отперт|ую отрица|ю - (delete) - /* note the short passive participle tests: - 'на' 'н' 'но' 'ны' - 'ена' 'ен' 'ено' 'ены' - */ - ) - ) - - define noun as ( - [substring] among ( - 'а' 'ев' 'ов' 'ие' 'ье' 'е' // вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е - 'иями' 'ями' 'ами' 'еи' 'ии' // волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии - 'и' 'ией' 'ей' 'ой' 'ий' 'й' // потер|и гармон|ией галере|ей гер|ой ген|ий сара|й - 'иям' 'ям' 'ием' 'ем' 'ам' 'ом' // губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом - 'о' 'у' 'ах' 'иях' 'ях' 'ы' 'ь' // брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь - 'ию' 'ью' 'ю' 'ия' 'ья' 'я' // комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я - (delete) - /* the small class of neuter forms 'ени' 'енем' - 'ена' 'ен' 'енам' 'енами' 'ена{x}' - omitted - they only occur on 12 words. - */ - ) - ) - - define derivational as ( - [substring] R2 among ( - 'ост' // любезностей - 'ость' // любезностью - (delete) - ) - ) - - define tidy_up as ( - [substring] among ( - - 'ейш' // наиполезн|ейший смирен|нейший - 'ейше' // superlative forms // многочислен|нейшее сильн|ейшее - (delete - ['н'] 'н' delete // REGEXP /(.*н)н(ейше|ейш|).*/ - ) - 'н' // смирен|но смирн|о - ('н' delete) // e.g. -nno endings // REGEXP /(.*н)н.*/ - 'ь' // совест|ь - (delete) // with some slight false conflations - ) - ) -) - -define stem as ( - - // Normalise ё to е. The documentation has long suggested the user - // should do this before calling the stemmer - we now do it for them. - do repeat ( goto (['ё']) <- 'е' ) // угнетённый => угнетен - - do mark_regions - backwards setlimit tomark pV for ( - do ( - perfective_gerund or - ( try reflexive - adjectival or verb or noun - ) - ) - try([ 'и' ] delete) // академию => академ - // because noun ending -ию is being treated as verb ending -ю - - do derivational - do tidy_up - ) -) - - - - - - -/* -Russian stemming algorithm: --------------------------- - -[Step 1] -remove(perfective_gerund) # всплыла ? -> No -OR - remove!(reflexive) # всплыла ? -> No - remove([adjective, adjectival]) # всплыла ? -> No - OR - remove(verb) # вспл|ыла ? -> Yes -> вспл !!But Snowball skips it!! Why?! - OR - remove(noun) - -[Step 2] -remove('и') - -[Step 3] -remove(derivational) - -[Step 4] -remove(tidy_up) - --------------------------- - -echo "всплыла" | ./stemwords -l ru -=> -всплыл - -Why?! -*/ diff --git a/explanations/ukrainian.sbl.utf b/explanations/ukrainian.sbl.utf deleted file mode 100755 index 9ff1b342..00000000 --- a/explanations/ukrainian.sbl.utf +++ /dev/null @@ -1,269 +0,0 @@ -stringescapes {} - -/* the 33 Ukrainian letters and apostrophe represented by single quote */ - -stringdef a '{U+0430}' -stringdef b '{U+0431}' -stringdef v '{U+0432}' -stringdef gh '{U+0433}' -stringdef g '{U+0491}' -stringdef d '{U+0434}' -stringdef e '{U+0435}' -stringdef ye '{U+0454}' -stringdef zh '{U+0436}' -stringdef z '{U+0437}' -stringdef y '{U+0438}' -stringdef i '{U+0456}' -stringdef yi '{U+0457}' -stringdef i` '{U+0439}' -stringdef k '{U+043A}' -stringdef l '{U+043B}' -stringdef m '{U+043C}' -stringdef n '{U+043D}' -stringdef o '{U+043E}' -stringdef p '{U+043F}' -stringdef r '{U+0440}' -stringdef s '{U+0441}' -stringdef t '{U+0442}' -stringdef u '{U+0443}' -stringdef f '{U+0444}' -stringdef kh '{U+0445}' -stringdef ts '{U+0446}' -stringdef ch '{U+0447}' -stringdef sh '{U+0448}' -stringdef shch '{U+0449}' -stringdef soft '{U+044C}' -stringdef iu '{U+044E}' -stringdef ia '{U+044F}' - -// Apostrophe-like symbols -// stringdef a_apostrophe '{U+0027}' // ' -// stringdef a_grave_accent U+0060 // ` cannot to remove system char in Snowball -stringdef a_ml_prime '{U+02B9}' // ʹ -stringdef a_mlt_comma '{U+02BB}' // ʻ -stringdef a_ml_apostrophe '{U+02BC}' // ʼ -stringdef a_mlr_comma '{U+02BD}' // ʽ -stringdef a_mlv_line '{U+02C8}' // ˈ -stringdef a_lsq_mark '{U+2018}' // ‘ -stringdef a_rsq_mark '{U+2019}' // ’ -stringdef a_shr9q_mark '{U+201B}' // ‛ -stringdef a_prime '{U+2032}' // ′ - -routines ( - prelude - mark_regions R2 - min_len - short_word - long_word - perfective_gerund - adjective - adjectival - reflexive - verb - noun - remove_last_letter - derivational - tidy_up -) - -externals ( stem ) - -integers ( pV p2 ) - -groupings ( v ) - -define v 'аеєиіїоуюя' - -define prelude as ( - do repeat ( goto (['ґ']) <- 'г' ) - - // Remove any apostrophe-like symbols - do repeat ( goto (['{'}']) delete ) - do repeat ( goto (['ʹ']) delete ) - do repeat ( goto (['ʻ']) delete ) - do repeat ( goto (['ʼ']) delete ) - do repeat ( goto (['ʽ']) delete ) - do repeat ( goto (['ˈ']) delete ) - do repeat ( goto (['‘']) delete ) - do repeat ( goto (['’']) delete ) - do repeat ( goto (['‛']) delete ) - do repeat ( goto (['′']) delete ) -) - -define mark_regions as ( - $pV = limit - $p2 = limit - do ( - gopast v setmark pV gopast non-v - gopast v gopast non-v setmark p2 - ) -) - -backwardmode ( - define R2 as $p2 <= cursor - - define perfective_gerund as ( - [substring] among ( - 'вши' // написа|вши - 'вшись' - 'вшися' - 'учи' - 'ючи' - 'ючись' - 'ючися' - 'ачи' - 'ачись' - 'ачися' - 'лячи' - 'лячись' - 'лячися' - 'ячи' - 'ячись' - 'ячися' - (delete) - ) - ) - - define reflexive as ( - [substring] among ( - 'ється' // смі|ється - 'еться' - 'ся' - 'сь' - (delete) - ) - ) - - define adjective as ( - [substring] among ( - 'ий' 'ого' 'ому' 'им' 'ім' // зел|ен.ий - 'іший' 'ішого' 'ішому' 'ішим' 'ішім' 'іше' - 'ої' 'ій' 'ою' - 'іша' 'ішої' 'ішій' 'ішу' 'ішою' - 'их' 'ими' - 'іші' 'іших' 'ішими' - 'ього' 'ьому' - 'ьої' 'ьою' - 'іх' 'іми' - 'ова' 'ове' - 'їй' 'иїй' - 'йому' 'ийому' - 'єє' 'еє' - 'ена' 'ені' 'ене' 'ену' - 'яча' 'яче' 'ячу' 'ячі' - 'ача' 'аче' 'ачу' 'ачі' - 'юча' 'юче' 'ючу' 'ючі' - 'уча' 'уче' 'учу' 'учі' - (delete) - ) - ) - - define adjectival as ( - adjective - - try ( - [substring] among ( - 'ен' 'яч' 'ач' 'юч' 'уч' (delete) // зел|ен.ий - ) - ) - ) - - define verb as ( - [substring] among ( - 'ав' 'али' 'ало' 'ала' 'ать' 'ати' // пізнав|ав - 'ме' - 'іть' - 'йте' - 'ла' 'ло' 'ли' - 'ти' 'ть' 'те' - 'єш' 'ємо' 'єте' 'ють' - 'еш' 'емо' 'ете' 'уть' - 'лю' 'иш' 'ить' 'имо' 'ите' 'лять' - 'ляти' - 'їш' 'їть' 'їмо' 'їте' 'ять' 'яти' - (delete) - ) - ) - define noun as ( - [substring] among ( - 'ам' 'ами' 'ах' // вод|ам - 'ею' - 'ям' 'ями' 'ях' - 'ові' 'ом' - 'ець' 'ем' - 'ень' - 'ой' - 'ію' 'ії' - 'ів' - 'ев' 'ов' 'ей' 'иям' 'иях' 'ию' - 'іям' 'іях' - 'ия' 'єю' 'еві' 'єм' 'їв' - 'ією' 'иєю' 'еєю' - 'ьї' 'ьє' 'ьєю' 'ью' 'ья' - (delete) - ) - ) - - define remove_last_letter as ( - [substring] among ( - 'а' 'в' 'е' 'є' 'и' 'і' // NOUN: вод|а, VERB: вчи|в - 'й' 'о' 'у' 'ь' 'ю' 'я' - (delete) - ) - ) - - // HERE!!!! - define derivational as ( - [substring] R2 among ( - 'іст' // незалежн|іст.тю - 'ост' - 'еньк' - (delete) - ) - ) - - define tidy_up as ( - [substring] among ( - 'д' ('д' delete) // усевлад|д.ям - 'ж' ('ж' delete) - 'л' ('л' delete) - 'н' ('н' delete) - 'с' ('с' delete) - 'т' ('т' delete) - 'ч' ('ч' delete) - ) - ) - - define min_len as ( - $(len >= 4) - ) - - define short_word as ( - $(len == 4) and remove_last_letter - ) - - define long_word as ( - do ( - perfective_gerund or ( - try reflexive - - adjectival or verb or noun or remove_last_letter - ) - ) - - do derivational - ) -) - -define stem as ( - do prelude - do mark_regions - - backwards setlimit tomark pV for ( - min_len - - short_word or long_word - - do tidy_up - ) -) diff --git a/tests/algorithms/Readme.md b/tests/algorithms/Readme.md deleted file mode 100644 index 656fb9d5..00000000 --- a/tests/algorithms/Readme.md +++ /dev/null @@ -1,8 +0,0 @@ -# Stemmers testing - -For checking the correctness of the stemmer you can run some language test cases, for example: -```sh -bin/utf_to_sbl ./explanations/ukrainian.sbl.utf > algorithms/ukrainian.sbl && make - -ruby ./tests/algorithms/ukrainian_test.rb -``` diff --git a/tests/algorithms/russian_test.rb b/tests/algorithms/russian_test.rb deleted file mode 100644 index 86806ce0..00000000 --- a/tests/algorithms/russian_test.rb +++ /dev/null @@ -1,128 +0,0 @@ -# Words test set -# https://raw.githubusercontent.com/snowballstem/snowball-data/master/russian/voc.txt - -perfective_gerund = { - 'в' => %w[написа|в проковыля|в], - 'вши' => %w[написа|вши заслоня|вши], - 'вшись' => %w[оберега|вшись обня|вшись], - - 'ив' => %w[насыт|ив], - 'ивши' => %w[насыт|ивши], - 'ившись' => %w[насыт|ившись], - 'ыв' => %w[приб|ыв], - 'ывши' => %w[приб|ывши], - 'ывшись' => %w[незб|ывшись ] -} - -adjective = { - 'ее ие ые ое ими ыми' => %w[зелен|ее висевш|ие ароматн|ые испорчен|ое иссохш|ими атласн|ыми], - 'ей ий ый ой ем им' => %w[зелен|ей баран|ий аккуратн|ый активн|ой высохш|ем глубок|им], - 'ым ом его ого ему' => %w[главн|ым главн|ом бегущ|его главн|ого бывш|ему], - 'ому их ых ую юю ая' => %w[богат|ому больш|их бурн|ых бронзов|ую верхн|юю весел|ая], - 'яя' => %w[внешн|яя], - 'ою' => %w[верн|ою ], - 'ею' => %w[верхн|ею], -} - -adjectival = { - 'ем' => %w[задава|емые изменя|ем], - 'нн' => %w[беспреста|нно деревя|нными], - 'вш' => %w[отказа|вшись отделя|вший], - 'ющ щ' => %w[сталкива|ющихся спеша|щих - умоля|ющими блестя|щему], - - 'ивш ывш' => %w[брод|ивших несб|ывшееся], # несб|ывш(ее(ся)) - 'ующ' => %w[несуществ|ующий] -} - -reflexive = { - 'ся' => %w[осек|ся], - 'сь' => %w[ввы|сь] -} - -verb = { - 'ла на ете йте ли й' => %w[сдела|ла воспита|на сдела|ете сдела|йте сдела|ли сдела|й - приня|ла потеря|на причиня|ете причиня|йте причиня|ли причиня|й], - - 'л ем н ло но ет ют' => %w[сдела|л воспита|ем сдела|н сдела|ло сдела|но сдела|ет сдела|ют - приня|л потеря|ем растеря|н причиня|ло настоя|но объясня|ет объясня|ют], - - 'ны ть ешь' => %w[сдела|ны сдела|ть сдела|ешь - потеря|ны потеря|ть потеря|ешь], - - 'нно' => %w[пута|нно постоя|нно], - - 'ила ыла ена ейте' => %w[беспоко|ила прикр|ыла выруч|ена пожал|ейте вспл|ыла], # вспл|ыла? - 'уйте ите или ыли ей' => %w[пожал|уйте позвол|ите полюб|или приб|ыли приникш|ей], - 'уй ил ыл им ым ен' => %w[протест|уй проход|ил раскр|ыл редк|им решительн|ым свобод|ен], - 'ило ыло ено ят ует' => %w[став|ило неун|ыло обознач|ено обрат|ят повеств|ует], - 'уют ит ыт ены ить' => %w[преслед|уют прибеж|ит закр|ыт зауч|ены затуш|ить], - 'ыть ишь ую ю' => %w[откр|ыть отправ|ишь отперт|ую отрица|ю] -} - -noun = { - 'а ев ов ие ье е' => %w[вод|а нап|ев вопрос|ов здрав|ие здоров|ье вопрос|е], - 'иями ями ами еи ии' => %w[волнен|иями вопл|ями вопрос|ами галер|еи гармон|ии], - 'и ией ей ой ий й' => %w[потер|и гармон|ией галере|ей гер|ой ген|ий сара|й], - 'иям ям ием ем ам ом' => %w[губерн|иям двер|ям биен|ием братц|ем бумаг|ам букет|ом], - 'о у ах иях ях ы ь' => %w[брюх|о брюх|у бумаг|ах здан|иях камн|ях казн|ы камен|ь], - 'ию ью ю ия ья я' => %w[комед|ию кров|ью кровл|ю лечен|ия лист|ья локт|я] -} - -derivational = { - 'ост' => %w[любезн|остей], - 'ость' => %w[любезн|остью] -} - -tidy_up = { - 'н[н]ейш' => %w[наиполезн|ейший смирен|нейший], - 'н[н]ейше' => %w[многочислен|нейшее сильн|ейшее], - 'н[н]' => %w[смирен|но смирн|о], - 'ь' => %w[совест|ь] -} - -exceptions = { - # ё => е - 'угнетённый' => 'угнетен', - - # -ию => '' - 'академию' => 'академ' -} - -$all_tests = [] -$errors = [] - -def incorrect_stem_msg(result_stem, word, stem) - "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" -end - -def check_words_set(words_set) - words_set.each do |_rule, test_cases| - test_cases.each do |test_case| - stem, ending = test_case.split('|') - word = [stem, ending].join - $all_tests << word - result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip - $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem - end - end -end - -[ - perfective_gerund, - adjective, - adjectival, - reflexive, - verb, - noun, - derivational, - tidy_up -].each {|words_set| check_words_set(words_set) } - -exceptions.each do |word, stem| - $all_tests << word - result_stem = (`echo "#{word}" | ./stemwords -l ru`).strip - $errors << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem -end - -$errors.empty? ? puts("#{$all_tests.count} test(s) passed successfully!") : puts($errors.join("\n")) diff --git a/tests/algorithms/uk_test_01_one_two_three_size.txt b/tests/algorithms/uk_test_01_one_two_three_size.txt deleted file mode 100644 index 370824b4..00000000 --- a/tests/algorithms/uk_test_01_one_two_three_size.txt +++ /dev/null @@ -1,54 +0,0 @@ -а -в -є -ж -з -з -і -й -о -у -я -ай -ба -до -же -її -їм -ку -ні -ну -ой -та -фу -це -ще -як -вау -вії -вій -він -вія -вус -гід -дай -дім -дія -лай -най -паж -піт -пуд -рік -рок -рук -ряд -син -так -фух -хай -хоч -хто -чом -шик -шия diff --git a/tests/algorithms/uk_test_02_four_size.txt b/tests/algorithms/uk_test_02_four_size.txt deleted file mode 100644 index bc90ee6c..00000000 --- a/tests/algorithms/uk_test_02_four_size.txt +++ /dev/null @@ -1,18 +0,0 @@ -хат|а -лап|а -лат|и -літ|о -луп|а -тус|я -люс|я -лял|я -люд|а -сін|о -сел|о -сар|а -дід|о -дул|о -дяд|я -мам|а -тат|о -син|у diff --git a/tests/algorithms/uk_test_03_test_victory.txt b/tests/algorithms/uk_test_03_test_victory.txt deleted file mode 100644 index e71dcbf0..00000000 --- a/tests/algorithms/uk_test_03_test_victory.txt +++ /dev/null @@ -1,22 +0,0 @@ -перемог -перемог|а -перемог|ам -перемоз|і -перемаг|ав -перемага|вши -перемага|й -перемага|єш -перемог|ла -перемог|ли -перемож|е -перемож|емо -перемож|ете -переміг -перемігш|и -переможн|о -перемож|ець -переможц|еві -переможц|ем -переможн|а -переможн|е -переможн|ий diff --git a/tests/algorithms/uk_test_04_test_popular.txt b/tests/algorithms/uk_test_04_test_popular.txt deleted file mode 100644 index 7ce23e94..00000000 --- a/tests/algorithms/uk_test_04_test_popular.txt +++ /dev/null @@ -1,185 +0,0 @@ -популяризатор -популяризатор|а -популяризатор|ові -популяризатор|у -популяризатор|ом -популяризатор|і -популяризатор|е -популяризатор|и -популяризатор|ів -популяризатор|ам -популяризатор|ами -популяризатор|ах -популяризаторк|а -популяризаторк|и -популяризаторц|і -популяризаторк|у -популяризаторк|ою -популяризаторк|о -популяризаторок -популяризаторк|ам -популяризаторк|ами -популяризаторк|ах -популяризаторськ|ий -популяризаторськ|ого -популяризаторськ|ому -популяризаторськ|им -популяризаторськ|ім -популяризаторськ|а -популяризаторськ|ої -популяризаторськ|ій -популяризаторськ|у -популяризаторськ|ою -популяризаторськ|е -популяризаторськ|і -популяризаторськ|их -популяризаторськ|ими -популяризаційн|ий -популяризаційн|ого -популяризаційн|ому -популяризаційн|им -популяризаційн|ім -популяризаційн|а -популяризаційн|ої -популяризаційн|ій -популяризаційн|у -популяризаційн|ою -популяризаційн|е -популяризаційн|і -популяризаційн|их -популяризаційн|ими -популяризаці|я -популяризац|ії -популяризац|ію -популяризац|ією -популяризаці|є -популяризован|ий -популяризован|ого -популяризован|ому -популяризован|им -популяризован|ім -популяризован|а -популяризован|ої -популяризован|ій -популяризован|у -популяризован|ою -популяризован|е -популяризован|і -популяризован|их -популяризован|ими -популяризува|вши -популяризува|вшись -популяризува|вшися -популяризуван|ня -популяризуван|ню -популяризуван|ням -популяризуван|ні -популяризув|ати -популяризув|ать -популяризу|й -популяризуйм|о -популяризу|йте -популяризу|ю -популяризу|єш -популяризу|є -популяризу|ємо -популяризу|єм -популяризу|єте -популяризу|ють -популяризуватим|у -популяризуватим|еш -популяризувати|ме -популяризуватим|ем -популяризуватим|емо -популяризуватим|ете -популяризуватим|уть -популяризув|ав -популяризув|ала -популяризув|ало -популяризув|али -популяризован|о -популяризув|атися -популяризув|атись -популяризув|аться -популяризу|йсь -популяризу|йся -популяризуйм|ось -популяризуйм|ося -популяризу|йтесь -популяризу|йтеся -популяризу|юсь -популяризу|юся -популяризу|єшся -популяриз|ується -популяризу|ємось -популяризу|ємося -популяризу|ємся -популяризу|єтесь -популяризу|єтеся -популяризу|ються -популяризуватим|усь -популяризуватим|уся -популяризуватим|ешся -популяризуват|иметься -популяризуватим|емось -популяризуватим|емося -популяризуватим|емся -популяризуватим|етесь -популяризуватим|етеся -популяризуватим|уться -популяризув|авсь -популяризув|ався -популяризув|алась -популяризув|алася -популяризув|алось -популяризув|алося -популяризув|ались -популяризув|алися -популяризу|ючи -популяризу|ючись -популяризу|ючися -популяристик|а -популяристик|и -популяристиц|і -популяристик|у -популяристик|ою -популяристик|о -популярн|ий -популярн|ого -популярн|ому -популярн|им -популярн|ім -популярн|а -популярн|ої -популярн|ій -популярн|у -популярн|ою -популярн|е -популярн|і -популярн|их -популярн|ими -популярніс|ть -популярн|ості -популярнос|ти -популярн|істю -популярнос|те -популярн|остей -популярн|остям -популярн|остями -популярн|остях -популярн|іше -популярніш -популярн|іший -популярн|ішого -популярн|ішому -популярн|ішим -популярн|ішім -популярн|іша -популярн|ішої -популярн|ішій -популярн|ішу -популярн|ішою -популярн|іші -популярн|іших -популярн|ішими -популярн|о diff --git a/tests/algorithms/ukrainian_test.rb b/tests/algorithms/ukrainian_test.rb deleted file mode 100644 index dcb56f6f..00000000 --- a/tests/algorithms/ukrainian_test.rb +++ /dev/null @@ -1,505 +0,0 @@ -# Words test set -# https://raw.githubusercontent.com/snowballstem/snowball-data/master/russian/voc.txt - -# Граматика української мови -# https://uk.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0_%D1%83%D0%BA%D1%80%D0%B0%D1%97%D0%BD%D1%81%D1%8C%D0%BA%D0%BE%D1%97_%D0%BC%D0%BE%D0%B2%D0%B8 - - -# 1 -# runtime/utilities.c -# comment out 'debug' function: - #if 1 - # fprintf(stderr, "faulty slice operation:\n"); - # debug(z, -1, 0); - - #if 1 - #extern void debug(struct SN_env * z, int number, int line_count) { - -# insert 'debug' where debugging is needed: -# src_c/stem_UTF_8_ukrainian.c -# static int r_perfective_gerund(struct SN_env * z) { - # printf("R1: "); - # printf("R2: "); - # debug(z, -1, 0); - -# 2 -# bin/utf_to_sbl ./explanations/ukrainian.sbl.utf > algorithms/ukrainian.sbl && make - - -# 4 -# ruby tests/algorithms/ukrainian_test.rb -# ./snowball algorithms/ukrainian_test.sbl -syntax -# ./snowball algorithms/english.sbl -syntax - - -perfective_gerund = { - 'вши' => %w[написа|вши зроби|вши], - 'вшись' => %w[оберіга|вшись спакува|вшись], - 'вшися' => %w[оберіга|вшися сподіва|вшися], - # (а и ) - 'учи' => %w[пиш|учи рев|учи], - 'ючи' => %w[ся|ючи підпису|ючи], - 'ючись' => %w[змага|ючись], - 'ючися' => %w[навча|ючися], - 'ачи' => %w[бач|ачи], - 'ачись' => %w[бач|ачись], - 'ачися' => %w[бач|ачися], - 'лячи' => %w[роб|лячи люб|лячи], - 'лячись' => %w[бав|лячись], - 'лячися' => %w[бав|лячися], - 'ячи' => %w[сид|ячи вовтуз|ячи], - 'ячись' => %w[вовтуз|ячись] -} - -reflexive = { - 'ється' => %w[смі|ється], # незнайшов дієслів - 'еться' => %w[спиш|еться], # незнайшов дієслів - - # *ся - 'ся' => %w[осік|ся], - - # rules from verb: - 'ти' => %w[би|ти.ся вовтузи|ти.ся], - # 'ть' => %w[роб|ить.ся], # вже є правило "ить" - 'іть' => %w[подруж|іть.ся], - 'те' => %w[бав|те.ся], - 'й' => %w[вдума|й.ся], - 'йте' => %w[вдума|йте.ся], - 'ать' => %w[бач|ать.ся], - - 'в ла ло ли' => %w[вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся], - 'ю єш ємо єте ють' => %w[смі|ю.ся смі|єш.ся смі|ємо.ся смі|єте.ся смі|ють.ся], - 'у еш емо ете уть' => %w[спиш|у.ся спиш|еш.ся спиш|емо.ся спиш|ете.ся спиш|уть.ся], - 'лю иш ить имо ите лять' => %w[див|лю.ся див|иш.ся див|ить.ся див|имо.ся див|ите.ся див|лять.ся], - 'їш їть їмо їте ять' => %w[бо|їш.ся бо|їть.ся бо|їмо.ся бо|їте.ся бо|ять.ся], - - - # *сь - 'сь' => %w[недонавч|и.сь змага|ю.сь], # вчи|сь - - # rules from verb: - '2 ти' => %w[боро|ти.сь], - '2 в ла ло ли' => %w[вчи|в.сь вчи|ла.сь вчи|ло.сь вчи|ли.сь], -} - -# do we need to add prefix rule 'н*' for adjectives? -# because removes single vowels for verbs like 'вчи|ла.сь' = > 'вчи|л' -adjective = { - 'ий ого ому им ім' => %w[зел|ен.ий зел|ен.ого зел|ен.ому зел|ен.им зел|ен.ім], - 'іший ішого ішому ішим ішім' => %w[зел|ен.іший зел|ен.ішого зел|ен.ішому зел|ен.ішим зел|ен.ішім], - 'іше' => %w[зел|ен.іше], - 'ої ій ою' => %w[зел|ен.ої зел|ен.ій зел|ен.ою], - 'іша ішої ішій ішу ішою' => %w[зел|ен.іша зел|ен.ішої зел|ен.ішій зел|ен.ішу зел|ен.ішою], - 'их ими' => %w[зел|ен.их зел|ен.ими], - 'іші іших ішими' => %w[зел|ен.іші зел|ен.іших зел|ен.ішими], - 'ього ьому' => %w[верхн|ього верхн|ьому], - 'ьої ьою' => %w[верхн|ьої верхн|ьою], - 'іх іми' => %w[верхн|іх верхн|іми], - 'ова ове' => %w[ацетон|ова ацетон|ове], - 'їй иїй' => %w[довгові|їй голош|иїй], - 'йому ийому' => %w[незна|йому товстош|ийому], - 'єє еє' => %w[трет|єє турецьк|еє], - 'ена ені ене ену' => %w[втрач|ені втрач|ена втрач|ене втрач|ену], - 'яча яче ячу ячі' => %w[сид|яча сид|яче сид|ячу сид|ячі], - 'ача аче ачу ачі' => %w[дриж|ача дриж|аче дриж|ачу дриж|ачі], - 'юча юче ючу ючі' => %w[далені|юча далені|юче далені|ючу далені|ючі], - 'уча уче учу учі' => %w[пиш|уча пиш|уче пиш|учу пиш|учі], -} - -adjectival = { - 'яч' => %w[сид|яч.ий сид|яч.ого сид|яч.ому сид|яч.им сид|яч.ім - сид|яч.ої сид|яч.ій сид|яч.ою сид|яч.их сид|яч.ими], - - 'ач' => %w[дриж|ач.ий дриж|ач.ого дриж|ач.ому дриж|ач.им дриж|ач.ім - дриж|ач.ої дриж|ач.ій дриж|ач.ою дриж|ач.их дриж|ач.ими], - - 'юч' => %w[далені|юч.ий далені|юч.ого далені|юч.ому далені|юч.им далені|юч.ім - далені|юч.ої далені|юч.ій далені|юч.ою далені|юч.их далені|юч.ими], - - 'уч' => %w[пиш|уч.ий далені|уч.ого пиш|уч.ому пиш|уч.им пиш|уч.ім - пиш|уч.ої пиш|уч.ій пиш|уч.ою пиш|уч.их пиш|уч.ими], - - 'ен' => %w[втрач|ен.ий втрач|ен.ого втрач|ен.ому втрач|ен.им втрач|ен.ім - втрач|ен.ої втрач|ен.ій втрач|ен.ою втрач|ен.их втрач|ен.ими - клен| ], -} - -# https://en.wikipedia.org/wiki/Reflexive_pronoun -# https://en.wikipedia.org/wiki/Reflexive_verb -# https://uk.wikipedia.org/wiki/%D0%A0%D0%B5%D1%84%D0%BB%D0%B5%D0%BA%D1%81%D0%B8%D0%B2%D0%BD%D0%B5_%D0%B4%D1%96%D1%94%D1%81%D0%BB%D0%BE%D0%B2%D0%BE -# reflexive_full = { -# # 'ся' => %w[осік|ся], -# # 'сь' => %w[недонавч|и.сь], # вчи|сь -# 'тися' => %w[би|тися милува|тися], -# 'тись' => %w[боро|тись], -# 'ться' => %w[милується|ться], # => роб|иться !? - бере завжди довший, треба інше слово підібрати або видалити якесь з правил -# 'іться' => %w[подруж|іться], -# 'теся' => %w[бав|теся], -# 'йся' => %w[вдума|йся], -# 'йтеся' => %w[вдума|йтеся], -# 'аться' => %w[бач|аться], -# 'вся лася лося лися' => %w[вчи|вся вчи|лася вчи|лося вчи|лися], -# 'всь лась лось лись' => %w[вчи|всь вчи|лась вчи|лось вчи|лись], -# 'юся єшся ється ємося єтеся ються' => %w[смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються], -# 'уся ешся еться емося етеся уться' => %w[спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться], -# 'люся ишся иться имося итеся ляться'=> %w[див|люся див|ишся див|иться див|имося див|итеся див|ляться], -# 'їшся їться їмося їтеся яться' => %w[бо|їшся бо|їться бо|їмося бо|їтеся бо|яться], -# } - -# reflexive_short = { -# 'сь' => %w[вчи|сь -# недонавч|и.сь -# боро|ти.сь -# вчи|в.сь вчи|ло.сь вчи|ли.сь], -# # вчи|ла.сь - removes 'а' in adjective ? - -# 'ся' => %w[осік|ся -# би|ти.ся -# роб|иться -# подруж|іться -# бавт|е.ся -# вдума|йся -# вдумайт|еся -# вчи|в.ся вчи|ла.ся вчи|ло.ся вчи|ли.ся -# смі|юся смі|єшся смі|ється смі|ємося смі|єтеся смі|ються -# спиш|уся спиш|ешся спиш|еться спиш|емося спиш|етеся спиш|уться -# див|люся див|ишся див|иться див|имося див|итеся див|ляться -# бо|їшся бо|їться бо|їмося бо|їтеся бо|яться -# бач|аться], - -# # бавт|е.ся # adj instead of verb бав|те.ся -# # вдумайт|еся # adj instead of verb вдума|йтеся -# } - -# абсорбу|ватиму -# абсорбу|ватимеш -# абсорбу|ватиме -# абсорбу|ватимем -# абсорбу|ватимемо -# абсорбу|ватимете -# абсорбу|ватимуть -# абсорбу|вали -# абсорбо|вано - -verb = { - 'ав али ало ала ать ати' => %w[пізнав|ав пізнав|али пізнав|ало пізнав|ала пізнав|ать пізнав|ати], - 'іть' => %w[роб|іть], - 'йте' => %w[дума|йте], - 'ме' => %w[пізнавати|ме], - 'ла ло ли' => %w[повез|ла повез|ло повез|ли], - 'ти ть те' => %w[обігну|ти поборо|ть обжені|те], - 'єш ємо єте ють' => %w[чита|єш чита|ємо чита|єте чита|ють], - 'еш емо ете уть' => %w[пиш|еш пиш|емо пиш|ете пиш|уть], - 'лю иш ить имо ите лять' => %w[роб|лю роб|иш роб|ить роб|имо роб|ите роб|лять], - 'ляти' => %w[вироб|ляти], - 'їш їть їмо їте ять яти' => %w[сто|їш сто|їть сто|їмо сто|їте сто|ять сто|яти], -} - -noun = { - 'ам ами ах' => %w[вод|ам вод|ами вод|ах], - 'ею' => %w[пісн|ею], - 'ям ями ях' => %w[пісн|ям пісн|ями пісн|ях], - 'ові ом' => %w[батьк|ові батьк|ом бор|ом], - 'ець ем' => %w[олів|ець олівц|ем], - 'ень' => %w[зел|ень], - 'ой' => %w[гер|ой], - 'ію ії' => %w[комед|ію комед|ії], - 'ів' => %w[вовчик|ів], - 'ев ов ей иям иях ию' => %w[дер|ев електрол|ов солов|ей кривош|иям кривош|иях кривош|ию], - 'іям іях' => %w[промоакц|іям промоакц|іях], - 'ия єю еві єм їв' => %w[кривош|ия медіазбро|єю праотц|еві праотц|ем промете|їв], - 'ією иєю еєю' => %w[хім|ією кривош|иєю левз|еєю], - 'ьї ьє ьєю ью ья' => %w[лазан|ьї лазан|ьє лазан|ьєю лазан|ью лазан|ья], -} - -adj_verb_noun = { # remove_last_letter - # adj - 'а е і у ю я' => %w[зел|ен.а зел|ен.е зел|ен.і зел|ен.у верхн|ю верхн|я], - # verb - 'в е є й у ю' => %w[нагляну|в пиш|е чита|є чита|й пиш|у чита|ю], - # noun - 'а е и і й ' => %w[вод|а пісн|е вод|и вод|і сара|й], - 'о у ь ю я' => %w[вод|о вод|у ваган|ь пісн|ю пісн|я] -} - -derivational = { - 'іст' => %w[безтурботн|іст.ю незалежн|іст.ю], - - 'ост' => %w[безтурботн|ост.і безтурботн|ост.ям безтурботн|ост|ями - безтурботн|ост.ях безтурботн|ост.ей незалежн|ост.ями їмост|ями ], # ??? ти/те/й - - 'еньк' => %w[посид|еньк.и холодн|еньк.ий] -} - -need_to_approve = { - # noun - 'ві' => %w[район|о.ві], #? *ві - 'го' => %w[раду|го], - 'ка кою ку' => %w[єзуїт|ка єзуїт|кою єзуїт|ку - сака сакою саку], # more then 2 syllables - 'очки очці очку очкою очка' => %w[маків|очки маків|очці маків|очку маків|очкою маків|очка], - 'очко очок очкам очками очках' => %w[маків|очко маків|очок маків|очкам маків|очками маків|очках], - - # verb - 'ала ало ась' => %w[поруб|ала поруб|ало докр|ась], - 'вав вавсь вався вала' => %w[району|вав району|вавсь району|вався району|вала], - 'валася вали вались валися вало' => %w[району|валася району|вали району|валися району|вало], - 'валось валося ватись ватися' => %w[району|валось району|валося району|ватись району|ватися], - 'валась всь вся вати' => %w[району|валась зруши|всь зруши|вся району|вати], - 'есь еся' => %w[європеїзуйт|есь європеїзуйт|еся], - 'ила или ило илося ити ись ися' => %w[жар|ила жар|или жар|ило жар|илося жар|ити жарит|ись жарит|ися], - 'ім імо' => %w[жаріюч|ім жаріюч|імо], - 'ймо ймось ймося йсь йся' => %w[жарту|ймо жеврі|ймось жеврі|ймося єдна|йсь єдна|йся], - 'лась лася лись лися лось лося' => %w[єдна|лась єдна|лася єдна|лись єдна|лися єдна|лось єдна|лося], - 'мо мось мося' => %w[жали|мо жали|мось жали|мося], - 'овував овувала овувати ' => %w[забальзам|овував забальзам|овувала забальзам|овувати], - 'ось осте ості' => %w[пилос|ось лукав|осте лукав|ості лушпин|очка], - 'сті сть стю' => %w[маневрено|сті маневрені|сть маневрені|стю], - 'ував увала увати' => %w[маневр|ував маневр|увала маневр|увати], -} - -tidy_up = { - 'дд' => %w[усевлад|д.ям], - 'жж' => %w[лівобереж|ж.ями], - 'лл' => %w[весіл|л.ями], - 'нн' => %w[осін|н.ій], - 'сс' => %w[прус|с.ів], - 'тт' => %w[століт|т.ями], - 'чч' => %w[клоч|ч.я] -} - -exceptions = { - # ґ => г - 'аванґард' => 'авангард', - 'аванґарду' => 'авангард|у', - 'аванґардові' => 'авангард|ові', - 'аванґардом' => 'авангард|ом', - 'аванґарді' => 'авангард|і', - 'аванґарди' => 'авангард|и', - 'аванґарде' => 'авангард|е', - 'аванґардів' => 'авангард|ів', # ?? в - 'аванґардам' => 'авангард|ам', - 'аванґардами' => 'авангард|ами', - 'аванґардах' => 'авангард|ах', - - # remove any apostrophe: ' ʹ ʻ ʼ ʽ ˈ ‘ ’ ‛ ′ - # "сім`я" => "сім", # cannot to remove Grave Accent - "сім'я" => "сім", - "сімʹя" => "сім", - "сімʻя" => "сім", - "сімʼя" => "сім", - "сімʽя" => "сім", - "сімˈя" => "сім", - "сім‘я" => "сім", - "сім’я" => "сім", - "сім‛я" => "сім", - "сім′я" => "сім", - - # Додатково перевірити слова: - "брати" => "бра|ти", - "беруть" => "бер|уть", - - "дописати" => "допис|ати", - "допишуть" => "допиш|уть", - - "лікар" => "лікар", - "лікарів" => "лікар|ів", # ??? в - - # прислівники: - "добре" => "добр|е", - "добро" => "добр|о", - "часто" => "част|о", - "частіший" => "част|іший", - "довго" => "довг|о", - "довгий" => "довг|ий", - "чисто" => "чист|о", - "чистіший" => "чист|іший", - - "робитимуть" => "робитим|уть", - - 'академію' => 'академ', -} - - -need_to_approve_2 = { - # заміна - 'завойовував' => 'завойов', # завойов|ував - 'завойовувала' => 'завойов', - 'завойовувати' => 'завойов', - - 'надкльовував' => 'надкльов', # надкльов|ував - 'надкльовувала' => 'надкльов', - 'надкльовувати' => 'надкльов', - - 'витанцьовував' => 'витанцьов', # витанцьов|ував - 'витанцьовувала' => 'витанцьов', - 'витанцьовувати' => 'витанцьов', -} - -$all_tests = [] -$errors = {} - -require 'yaml' - -def yml_h_tests(file) - YAML.load_file(file) -end - -def txt_tests(file) - IO.read(file).split -end - -def incorrect_stem_msg(result_stem, word, stem) - # "Incorrect stemming '#{result_stem}' for word '#{word}', should be '#{stem}'" - # "--------------------------------\n" - "Word: #{word}\n" + - "should be: #{stem}\n" + - "but it is: #{result_stem}\n" -end - -def check_words_set(words_set, set_name) - words_set.each do |_rule, test_cases| - test_cases.each do |test_case| - stem, ending = test_case.split('|') - word = [stem, ending&.delete('.')].join - $all_tests << word - - result_stem = (`echo "#{word}" | ../stemwords -l uk`).strip - # if result_stem == 'ач' - # puts '>>' - # puts test_case - # puts stem - # puts ending - # puts word - # puts result_stem - # puts '<<' - # end - $errors[set_name] ||= [] - $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem - end - end -end - -[ - [perfective_gerund, 'perfective_gerund'], - [adjective, 'adjective'], - [adjectival, 'adjectival'], - [reflexive, 'reflexive'], - [verb, 'verb'], - [noun, 'noun'], - [adj_verb_noun, 'adj_verb_noun'], - [derivational, 'derivational'], - [tidy_up, 'tidy_up'] -].each do |words_set, set_name| - check_words_set(words_set, set_name) -end - -[ - [exceptions, 'exceptions'], - # [yml_h_tests('./algorithms/uk_test_pairs_N1.yml'), 'uk_test_pairs_N1.yml'] -].each do |words_set, set_name| - words_set.each do |word, test_case| - stem, ending = test_case.to_s.split('|') - $all_tests << word - result_stem = (`echo "#{word}" | ../stemwords -l uk `).strip - $errors[set_name] ||= [] - $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem - end -end - -[ - [txt_tests('./algorithms/uk_test_01_one_two_three_size.txt'), '01_one_two_three_size'], - [txt_tests('./algorithms/uk_test_02_four_size.txt'), '02_four_size'], - [txt_tests('./algorithms/uk_test_03_test_victory.txt'), '03_test_victory'], # check and fix - [txt_tests('./algorithms/uk_test_04_test_popular.txt'), '04_popular'], # check and fix -].each do |test_words, set_name| - test_words.each do |test_word| - stem, ending = test_word.to_s.split('|') - word =[stem, ending].join('') - $all_tests << word - result_stem = (`echo "#{word}" | ../stemwords -l uk `).strip - $errors[set_name] ||= [] - $errors[set_name] << incorrect_stem_msg(result_stem, word, stem) if result_stem != stem - end -end - - - -if $errors.values.all?(&:empty?) - puts("#{$all_tests.count} test(s) passed successfully!") -else - $errors.each do |set_name, errs| - next if errs.empty? - - puts "\n=== #{set_name}:\n\n" - puts(errs.join("\n")) - end -end - -# a = %w[ -# ий ого ому им ім -# іший ішого ішому ішим ішім -# іше -# ої -# іша ішої ішій ішу ішою -# их ими -# іші іших ішими -# ього ьому -# ьої ьою -# іх іми -# ] - -# v = %w[ -# ти -# ть -# іть -# те -# йте -# ать -# ла ло ли -# єш ємо єте ють -# еш емо ете уть -# лю иш ить имо ите лять -# їш їть їмо їте ять -# ] - -# n = %w[ -# ам ами ах -# ею -# ям ями ях -# ові ом -# ець ем -# ень -# ой -# ію ії -# ] - -# adj_verb_noun = %w[ -# е а у і я ю -# й в ю є у е -# а и і у о я ю е й ь -# ою ій -# ] - -# puts "a & v" -# p (a & v).sort - -# puts "v & n" -# p (v & n).sort - -# puts "n & a" -# p (n & a).sort - -# ToDo: - -# +1. Ґ => Г -# do repeat ( goto (['ґ]) <- 'г' ) // угнетённый => угнетен - -# +2. Видалити всі типи Апострофів 'ʼ` - -# +3. Додатково перевірити слова: - - - -# Add yml tests -# https://github.com/Tapkomet/UAStemming/blob/master/Results.txt From 2e638b9ce7aa9a667e3ffb780760ad619f173165 Mon Sep 17 00:00:00 2001 From: Oleksandr Bratashov Date: Tue, 12 Dec 2023 23:06:08 +0200 Subject: [PATCH 13/13] Add Ukrainian stemmer: extra rules --- algorithms/ukrainian.sbl | 152 ++++++++++++++++++++++++++++++++------- runtime/utilities.c | 4 +- 2 files changed, 129 insertions(+), 27 deletions(-) diff --git a/algorithms/ukrainian.sbl b/algorithms/ukrainian.sbl index 6b3cc847..310544ea 100644 --- a/algorithms/ukrainian.sbl +++ b/algorithms/ukrainian.sbl @@ -53,15 +53,21 @@ routines ( prelude mark_regions R2 min_len - short_word + short_word_4l + short_word_5l long_word perfective_gerund + reflexive + long_endings adjective adjectival - reflexive verb noun remove_last_letter + remove_last_2_letters + remove_last_2_vowels + remove_vowel_before_vowel + remove_last_vowel derivational tidy_up ) @@ -134,22 +140,43 @@ backwardmode ( ) ) + define long_endings as ( + [substring] among ( + // nouns + '{i}{s}{t}{soft}' '{i}{s}{t}{iu}' '{i}{s}{t}{y}' '{i}{s}{t}{e}' '{i}{s}{t}{s}{soft}{k}{o}{gh}{o}' + '{e}{n}{a}{m}{y}' + '{o}{ch}{k}{y}' '{o}{ch}{ts}{i}' '{o}{ch}{k}{u}' '{o}{ch}{k}{o}{iu}' '{o}{ch}{k}{a}' + '{o}{ch}{k}{o}' '{o}{ch}{o}{k}' '{o}{ch}{k}{a}{m}' '{o}{ch}{k}{a}{m}{y}' '{o}{ch}{k}{a}{kh}' + '{o}{s}{t}{i}' '{o}{s}{t}{y}' '{o}{s}{t}{e}' '{o}{s}{t}{e}{i`}' '{o}{s}{t}{ia}{m}' '{o}{s}{t}{ia}{m}{y}' '{o}{s}{t}{ia}{kh}' + '{n}{y}{k}{o}{m}' '{n}{y}{k}{o}{v}{i}' '{n}{y}{k}{u}' '{n}{y}{k}{i}{v}' '{n}{y}{k}{a}' '{n}{y}{k}{a}{m}' '{n}{y}{k}{a}{m}{y}' '{n}{y}{k}{a}{kh}' '{n}{y}{k}{y}' // need to remove ? + // '{n}{i}{k}{o}{m}' '{n}{i}{k}{o}{v}{i}' '{n}{i}{k}{u}' '{n}{i}{k}{i}{v}' '{n}{i}{k}{a}' '{n}{i}{k}{a}{m}' '{n}{i}{k}{a}{m}{y}' '{n}{i}{k}{a}{kh}' '{n}{i}{k}{y}' // need to remove ? + '{ts}{i}{v}' '{ts}{ia}{m}{y}' + '{k}{i}{v}' + + // female gender + '{k}{o}{iu}' '{k}{a}{m}' '{k}{a}{m}{y}' '{k}{a}{kh}' + '{s}{soft}{k}{o}{iu}' '{s}{soft}{k}{a}' '{s}{soft}{k}{u}' '{s}{soft}{k}{o}' + (delete) + ) + ) + define adjective as ( [substring] among ( '{y}{i`}' '{o}{gh}{o}' '{o}{m}{u}' '{y}{m}' '{i}{m}' // {z}{e}{l}|{e}{n}.{y}{i`} - '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' '{i}{sh}{e}' + '{i}{sh}{y}{i`}' '{i}{sh}{o}{gh}{o}' '{i}{sh}{o}{m}{u}' '{i}{sh}{y}{m}' '{i}{sh}{i}{m}' '{i}{sh}{e}' '{i}{sh}' '{o}{yi}' '{i}{i`}' '{o}{iu}' '{i}{sh}{a}' '{i}{sh}{o}{yi}' '{i}{sh}{i}{i`}' '{i}{sh}{u}' '{i}{sh}{o}{iu}' '{y}{kh}' '{y}{m}{y}' + '{n}{y}{i`}' '{n}{a}' '{n}{e}' '{n}{y}{m}' '{n}{i}{m}' '{n}{o}{yi}' '{n}{u}' '{n}{o}{iu}' '{n}{i}{i`}' '{n}{y}{kh}' '{n}{i}' '{n}{y}{k}' '{n}{o}' '{n}{o}{gh}{o}' '{n}{y}{m}{y}' '{n}{o}{m}{u}' '{i}{sh}{i}' '{i}{sh}{y}{kh}' '{i}{sh}{y}{m}{y}' '{soft}{o}{gh}{o}' '{soft}{o}{m}{u}' '{soft}{o}{yi}' '{soft}{o}{iu}' '{i}{kh}' '{i}{m}{y}' - '{o}{v}{a}' '{o}{v}{e}' + '{o}{v}{a}' '{o}{v}{e}' '{v}{o}' '{yi}{i`}' '{y}{yi}{i`}' '{i`}{o}{m}{u}' '{y}{i`}{o}{m}{u}' '{ye}{ye}' '{e}{ye}' - '{e}{n}{a}' '{e}{n}{i}' '{e}{n}{e}' '{e}{n}{u}' + '{e}{n}' '{e}{n}{a}' '{e}{n}{i}' '{e}{n}{e}' '{e}{n}{u}' '{e}{n}{a}{m}' '{e}{n}{y}' '{e}{n}{i}{v}' '{e}{n}{o}{m}' '{ia}{ch}{a}' '{ia}{ch}{e}' '{ia}{ch}{u}' '{ia}{ch}{i}' '{a}{ch}{a}' '{a}{ch}{e}' '{a}{ch}{u}' '{a}{ch}{i}' '{iu}{ch}{a}' '{iu}{ch}{e}' '{iu}{ch}{u}' '{iu}{ch}{i}' @@ -163,7 +190,13 @@ backwardmode ( try ( [substring] among ( - '{e}{n}' '{ia}{ch}' '{a}{ch}' '{iu}{ch}' '{u}{ch}' (delete) // {z}{e}{l}|{e}{n}.{y}{i`} + '{e}{n}' // {z}{e}{l}|{e}{n}.{y}{i`} + '{o}{v}' // {a}{b}{e}{t}{k}|{o}{v}.{o}{gh}{o} + '{ia}{ch}' + '{a}{ch}' + '{iu}{ch}' + '{u}{ch}' + (delete) ) ) ) @@ -171,22 +204,25 @@ backwardmode ( define verb as ( [substring] among ( '{a}{v}' '{a}{l}{y}' '{a}{l}{o}' '{a}{l}{a}' '{a}{t}{soft}' '{a}{t}{y}' // {p}{i}{z}{n}{a}{v}|{a}{v} - '{m}{e}' '{i}{t}{soft}' - '{i`}{t}{e}' - '{l}{a}' '{l}{o}' '{l}{y}' - '{t}{y}' '{t}{soft}' '{t}{e}' + '{i`}{t}{e}' '{i`}{m}{o}' + '{m}{e}' + '{l}{a}' '{l}{o}' '{l}{y}' '{l}{u}' + '{n}{o}' + //'{t}{y}' '{t}{soft}' '{t}{e}' // need to remove ? '{ye}{sh}' '{ye}{m}{o}' '{ye}{t}{e}' '{iu}{t}{soft}' '{e}{sh}' '{e}{m}{o}' '{e}{t}{e}' '{u}{t}{soft}' - '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' + '{l}{iu}' '{y}{sh}' '{y}{t}{soft}' '{y}{m}{o}' '{y}{t}{e}' '{l}{ia}{t}{soft}' '{sh}{y}' '{l}{ia}{t}{y}' '{yi}{sh}' '{yi}{t}{soft}' '{yi}{m}{o}' '{yi}{t}{e}' '{ia}{t}{soft}' '{ia}{t}{y}' (delete) ) ) + define noun as ( [substring] among ( '{a}{m}' '{a}{m}{y}' '{a}{kh}' // {v}{o}{d}|{a}{m} + '{a}{r}' '{a}{r}{e}{m}' '{a}{r}{ia}' '{e}{iu}' '{ia}{m}' '{ia}{m}{y}' '{ia}{kh}' '{o}{v}{i}' '{o}{m}' @@ -196,9 +232,10 @@ backwardmode ( '{i}{iu}' '{i}{yi}' '{i}{v}' '{e}{v}' '{o}{v}' '{e}{i`}' '{y}{ia}{m}' '{y}{ia}{kh}' '{y}{iu}' - '{i}{ia}{m}' '{i}{ia}{kh}' - '{y}{ia}' '{ye}{iu}' '{e}{v}{i}' '{ye}{m}' '{yi}{v}' + '{i}{ia}{m}' '{i}{ia}{kh}' '{i}{ia}' + '{y}{ia}' '{ye}{iu}' '{e}{v}{i}' '{ye}{m}' '{e}{yi}{v}' '{yi}{v}' '{i}{ye}{iu}' '{y}{ye}{iu}' '{e}{ye}{iu}' + '{k}{a}' '{k}{y}' '{ts}{i}' '{k}{u}' '{k}{o}' '{o}{k}' // female gender '{soft}{yi}' '{soft}{ye}' '{soft}{ye}{iu}' '{soft}{iu}' '{soft}{ia}' (delete) ) @@ -206,31 +243,83 @@ backwardmode ( define remove_last_letter as ( [substring] among ( - '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' // NOUN: {v}{o}{d}|{a}, VERB: {v}{ch}{y}|{v} + '{a}' '{v}' '{e}' '{ye}' '{y}' '{i}' '{yi}' // NOUN: {v}{o}{d}|{a}, VERB: {v}{ch}{y}|{v} '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' (delete) ) ) - // HERE!!!! + define remove_last_2_letters as ( // 2-letters from the all previous sets + [substring] among ( + '{a}{v}' '{a}{m}' '{a}{r}' '{a}{kh}' '{a}{ch}' + '{e}{v}' '{e}{ye}' '{e}{i`}' '{e}{m}' '{e}{n}' '{e}{sh}' '{e}{iu}' + '{ye}{ye}' '{ye}{m}' '{ye}{sh}' '{ye}{iu}' + '{y}{i`}' '{y}{m}' '{y}{kh}' '{y}{sh}' '{y}{iu}' '{y}{ia}' + '{i}{v}' '{yi}{v}' '{i}{yi}' '{i}{i`}' '{yi}{i`}' '{i}{m}' '{i}{kh}' '{i}{iu}' + '{yi}{sh}' + '{l}{a}' '{l}{y}' '{l}{o}' '{l}{iu}' // {a}{k}{u}|{l}{i} ? + '{m}{e}' // {d}{i}{ia}|{m}{y} ? + '{o}{v}' '{o}{yi}' '{o}{i`}' '{o}{m}' '{o}{iu}' '{s}{soft}' '{s}{ia}' + //'{t}{y}' '{t}{e}' '{t}{soft}' // need to remove ? + '{u}{ch}' + '{soft}{ye}' '{soft}{yi}' '{soft}{iu}' '{soft}{ia}' + '{iu}{ch}' + '{ia}{m}' '{ia}{kh}' '{ia}{ch}' + (delete) + ) + ) + + define remove_last_vowel as ( + [substring] among ( + '{a}' '{e}' '{ye}' '{y}' '{i}' '{yi}' + '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' + (delete) + ) + ) + + define remove_last_2_vowels as ( + remove_vowel_before_vowel + and remove_last_vowel + ) + + define remove_vowel_before_vowel as ( + [substring] among ( + '{a}' '{e}' '{ye}' '{y}' '{i}' '{yi}' '{i`}' '{o}' '{u}' '{soft}' '{iu}' '{ia}' + ('{a}' or '{e}' or '{ye}' or '{y}' or '{i}' or '{yi}' or '{i`}' or '{o}' or '{u}' or '{soft}' or '{iu}' or '{ia}' delete ) + ) + ) + define derivational as ( [substring] R2 among ( '{i}{s}{t}' // {n}{e}{z}{a}{l}{e}{zh}{n}|{i}{s}{t}.{t}{iu} '{o}{s}{t}' - '{e}{n}{soft}{k}' + '{e}{n}{soft}' '{e}{n}{soft}{k}' + '{s}{soft}{k}' + '{i}{z}{m}' (delete) ) ) define tidy_up as ( [substring] among ( + '{b}' ('{b}' delete) // {kh}{o}{b}|{b}.{i} + '{v}' ('{v}' delete) + '{gh}' ('{gh}' delete) '{d}' ('{d}' delete) // {u}{s}{e}{v}{l}{a}{d}|{d}.{ia}{m} '{zh}' ('{zh}' delete) + '{z}' ('{z}' delete) + '{k}' ('{k}' delete) '{l}' ('{l}' delete) + '{m}' ('{m}' delete) '{n}' ('{n}' delete) + '{p}' ('{p}' delete) + '{r}' ('{r}' delete) '{s}' ('{s}' delete) '{t}' ('{t}' delete) + '{f}' ('{f}' delete) + '{ts}' ('{ts}' delete) '{ch}' ('{ch}' delete) + '{sh}' ('{sh}' delete) ) ) @@ -238,20 +327,33 @@ backwardmode ( $(len >= 4) ) - define short_word as ( - $(len == 4) and remove_last_letter + define short_word_4l as ( + $(len == 4) and (remove_last_2_vowels or remove_last_vowel) + ) + + define short_word_5l as ( + $(len == 5) and ( + remove_last_2_vowels + or remove_last_vowel + or remove_last_2_letters + ) or + $(len == 5) and do remove_last_vowel ) define long_word as ( - do ( - perfective_gerund or ( - try reflexive + $(len > 5) and do ( + do ( + perfective_gerund or ( + try reflexive - adjectival or verb or noun or remove_last_letter + long_endings or adjectival or verb or noun or remove_last_letter + ) ) - ) - do derivational + do derivational + do remove_last_2_vowels + do remove_last_vowel + ) ) ) @@ -262,7 +364,7 @@ define stem as ( backwards setlimit tomark pV for ( min_len - short_word or long_word + short_word_4l or short_word_5l or long_word do tidy_up ) diff --git a/runtime/utilities.c b/runtime/utilities.c index 20f1ce55..d7dd218d 100644 --- a/runtime/utilities.c +++ b/runtime/utilities.c @@ -415,7 +415,7 @@ static int slice_check(struct SN_env * z) { z->p == NULL || z->l > SIZE(z->p)) /* this line could be removed */ { -#if 1 +#if 0 fprintf(stderr, "faulty slice operation:\n"); debug(z, -1, 0); #endif @@ -490,7 +490,7 @@ extern int len_utf8(const symbol * p) { return len; } -#if 1 +#if 0 extern void debug(struct SN_env * z, int number, int line_count) { int i; int limit = SIZE(z->p);