Skip to content

Commit

Permalink
Fix #56, #53 and #55
Browse files Browse the repository at this point in the history
  • Loading branch information
wapmorgan committed Jul 9, 2019
1 parent fdb727a commit 0387e69
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 50 deletions.
51 changes: 48 additions & 3 deletions src/Russian/GeographicalNamesInflection.php
Expand Up @@ -31,12 +31,19 @@ class GeographicalNamesInflection extends \morphos\BaseInflection implements Cas
'санкт',
'йошкар',
'улан',
'ханты',
'буда',
];

protected static $runawayVowelsExceptions = [
'торжо*к',
'волоче*к',
'орё*л',
'египе*т',
'лунине*ц',
'городо*к',
'новогрудо*к',
'острове*ц',
];

protected static $misspellings = [
Expand Down Expand Up @@ -91,7 +98,8 @@ public static function isMutable($name)
}

// ends with 'е' or 'о', but not with 'ово/ёво/ево/ино/ыно'
if (in_array(S::slice($name, -1), ['е', 'о'], true) && !in_array(S::slice($name, -3, -1), ['ов', 'ёв', 'ев', 'ин', 'ын'], true)) {
if (in_array(S::slice($name, -1), ['е', 'о'], true)
&& !in_array(S::slice($name, -3, -1), ['ов', 'ёв', 'ев', 'ин', 'ын'], true)) {
return false;
}
return true;
Expand Down Expand Up @@ -135,7 +143,7 @@ public static function getCases($name)
}
}

// Сложное название через пробел, '-' или '-на-'
// Сложное название с разделителем
foreach (static::$delimiters as $delimiter) {
if (strpos($name, $delimiter) !== false) {
$parts = explode($delimiter, $name);
Expand Down Expand Up @@ -241,10 +249,18 @@ public static function getCases($name)

// Березники, Ессентуки
case 'ки':
// Старые Дороги
case 'ги':
// Ушачи, Ивацевичи
case 'чи':
$prefix = S::name(S::slice($name, 0, -1));
return [
static::IMENIT => $prefix . 'и',
static::RODIT => $name == 'луки' ? $prefix : $prefix . 'ов',
static::RODIT => ($name === 'луки'
? $prefix
: (S::slice($name, -2) === 'чи'
? $prefix . 'ей'
: $prefix . 'ов')),
static::DAT => $prefix . 'ам',
static::VINIT => $prefix . 'и',
static::TVORIT => $prefix . 'ами',
Expand Down Expand Up @@ -289,6 +305,10 @@ public static function getCases($name)

// Челны
case 'ны':
// Мосты
case 'ты':
// Столбцы
case 'цы':
$prefix = S::name(S::slice($name, 0, -1));
return [
static::IMENIT => $prefix . 'ы',
Expand Down Expand Up @@ -322,6 +342,31 @@ public static function getCases($name)
static::TVORIT => $prefix.'ью',
static::PREDLOJ => $prefix.'и',
];

//
case 'чи':
$prefix = S::name(S::slice($name, 0, -1));
return [
static::IMENIT => $prefix.'и',
static::RODIT => $prefix.'ей',
static::DAT => $prefix.'ам',
static::VINIT => $prefix.'и',
static::TVORIT => $prefix.'ами',
static::PREDLOJ => $prefix.'ах',
];

// Глубокое
case 'ое':
$prefix = S::name(S::slice($name, 0, -2));
return [
static::IMENIT => $prefix.'ое',
static::RODIT => $prefix.'ого',
static::DAT => $prefix.'ому',
static::VINIT => $prefix.'ое',
static::TVORIT => $prefix.'им',
static::PREDLOJ => $prefix.'ом',
];

}

switch (S::slice($name, -1)) {
Expand Down
68 changes: 41 additions & 27 deletions src/Russian/NounDeclension.php
Expand Up @@ -16,6 +16,26 @@ class NounDeclension extends BaseInflection implements Cases, Gender
const SECOND_DECLENSION = 2;
const THIRD_DECLENSION = 3;

public static $immutableWords = [
// валюты
'евро', 'пенни', 'песо', 'сентаво',

// на а
'боа', 'бра', 'фейхоа', 'амплуа', 'буржуа',
// на о
'манго', 'какао', 'кино', 'трюмо', 'пальто', 'бюро', 'танго', 'вето', 'бунгало', 'сабо', 'авокадо', 'депо',
// на у
'зебу', 'кенгуру', 'рагу', 'какаду', 'шоу',
// на е
'шимпанзе', 'конферансье', 'атташе', 'колье', 'резюме', 'пенсне', 'кашне', 'протеже', 'коммюнике', 'драже', 'суфле', 'пюре', 'купе', 'фойе', 'шоссе', 'крупье',
// на и
'такси', 'жалюзи', 'шасси', 'алиби', 'киви', 'иваси', 'регби', 'конфетти', 'колибри', 'жюри', 'пенальти', 'рефери', 'кольраби',
// на э
'каноэ', 'алоэ',
// на ю
'меню', 'парвеню', 'авеню', 'дежавю', 'инженю', 'барбекю', 'интервью',
];

/**
* These words has 2 declension type.
*/
Expand Down Expand Up @@ -58,6 +78,14 @@ class NounDeclension extends BaseInflection implements Cases, Gender
'председатель',
'руководитель',
'заместитель',
'библиотекарь',
'делопроизводитель',
'преподаватель',
'представитель',
'производитель',
'слесарь',
'строитель',
'учитель',
];

protected static $masculineWithSoftAndRunAwayVowels = [
Expand All @@ -69,26 +97,6 @@ class NounDeclension extends BaseInflection implements Cases, Gender
'трутень',
];

protected static $immutableWords = [
// валюты
'евро', 'пенни', 'песо', 'сентаво',

// на а
'боа', 'бра', 'фейхоа', 'амплуа', 'буржуа',
// на о
'манго', 'какао', 'кино', 'трюмо', 'пальто', 'бюро', 'танго', 'вето', 'бунгало', 'сабо', 'авокадо', 'депо',
// на у
'зебу', 'кенгуру', 'рагу', 'какаду', 'шоу',
// на е
'шимпанзе', 'конферансье', 'атташе', 'колье', 'резюме', 'пенсне', 'кашне', 'протеже', 'коммюнике', 'драже', 'суфле', 'пюре', 'купе', 'фойе', 'шоссе',
// на и
'такси', 'жалюзи', 'шасси', 'алиби', 'киви', 'иваси', 'регби', 'конфетти', 'колибри', 'жюри', 'пенальти', 'рефери', 'кольраби',
// на э
'каноэ', 'алоэ',
// на ю
'меню', 'парвеню', 'авеню', 'дежавю', 'инженю', 'барбекю', 'интервью',
];

/**
* Проверка, изменяемое ли слово.
* @param string $word Слово для проверки
Expand Down Expand Up @@ -220,10 +228,10 @@ public static function declinateFirstDeclension($word)
$forms[Cases::DAT] = static::getPredCaseOf12Declensions($word, $last, $prefix);

// VINIT
$forms[Cases::VINIT] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) != 'ч', $prefix.'ю', $prefix.'у');
$forms[Cases::VINIT] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) !== 'ч', $prefix.'ю', $prefix.'у');

// TVORIT
if ($last == 'ь') {
if ($last === 'ь') {
$forms[Cases::TVORIT] = $prefix.'ой';
} else {
$forms[Cases::TVORIT] = static::chooseVowelAfterConsonant($last, $soft_last, $prefix.'ей', $prefix.'ой');
Expand All @@ -249,10 +257,10 @@ public static function declinateSecondDeclension($word, $animateness = false)
{
$word = S::lower($word);
$last = S::slice($word, -1);
$soft_last = $last == 'й' || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true)
$soft_last = $last === 'й' || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true)
&& ((
static::isConsonant(S::slice($word, -2, -1)) && !static::isHissingConsonant(S::slice($word, -2, -1)))
|| S::slice($word, -2, -1) == 'и'));
|| S::slice($word, -2, -1) === 'и'));
$prefix = static::getPrefixOfSecondDeclension($word, $last);
$forms = [
Cases::IMENIT => $word,
Expand All @@ -278,7 +286,9 @@ public static function declinateSecondDeclension($word, $animateness = false)
// $forms[Cases::TVORIT] = $prefix.'ем';
// else
// $forms[Cases::TVORIT] = $prefix.'ом'; # http://morpher.ru/Russian/Spelling.aspx#sibilant
if (static::isHissingConsonant($last) || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true) && static::isHissingConsonant(S::slice($word, -2, -1))) || $last == 'ц') {
if (static::isHissingConsonant($last)
|| (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true) && static::isHissingConsonant(S::slice($word, -2, -1)))
|| ($last === 'ц' && S::slice($word, -2) !== 'ец')) {
$forms[Cases::TVORIT] = $prefix.'ем';
} elseif (in_array($last, ['й'/*, 'ч', 'щ'*/], true) || $soft_last) {
$forms[Cases::TVORIT] = $prefix.'ем';
Expand Down Expand Up @@ -401,8 +411,12 @@ public static function getPrefixOfSecondDeclension($word, $last)
$prefix = S::slice($word, 0, -1);
}
// уменьшительные формы слов (котенок) и слова с суффиксом ок
elseif (S::slice($word, -2) == 'ок' && S::length($word) > 3) {
$prefix = S::slice($word, 0, -2).'к';
elseif (S::slice($word, -2) === 'ок' && S::length($word) > 3) {
$prefix = S::slice($word, 0, -2) . 'к';
}
// слова с суффиксом бец
elseif (S::slice($word, -3) === 'бец' && S::length($word) > 4) {
$prefix = S::slice($word, 0, -3).'бц';
} else {
$prefix = $word;
}
Expand Down
10 changes: 3 additions & 7 deletions src/Russian/NounPluralization.php
Expand Up @@ -35,11 +35,6 @@ class NounPluralization extends \morphos\BasePluralization implements Cases
'год' => 'лет',
];

protected static $immutableWords = [
'евро',
'пенни',
];

protected static $runawayVowelsExceptions = [
'писе*ц',
'песе*ц',
Expand Down Expand Up @@ -151,7 +146,7 @@ public static function getCases($word, $animateness = false)
{
$word = S::lower($word);

if (in_array($word, static::$immutableWords, true)) {
if (in_array($word, NounDeclension::$immutableWords, true)) {
return [
static::IMENIT => $word,
static::RODIT => $word,
Expand Down Expand Up @@ -209,7 +204,8 @@ protected static function declinateSubstative($word, $animateness)

$forms = [];

if (in_array($last, ['ч', 'г'], false) || in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь'], true)
if (in_array($last, ['ч', 'г'], true)
|| in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь', 'рь'], true)
|| (static::isVowel($last) && in_array(S::slice($word, -2, -1), ['ч', 'к'], true))) { // before ч, чь, сь, ч+vowel, к+vowel
$forms[Cases::IMENIT] = $prefix.'и';
} elseif (in_array($last, ['н', 'ц', 'р', 'т'], true)) {
Expand Down
2 changes: 1 addition & 1 deletion tests/CasesHelperTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test;
namespace morphos\test;

use morphos\CasesHelper;
use morphos\Cases;
Expand Down
2 changes: 1 addition & 1 deletion tests/CurrenciesHelperTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test;
namespace morphos\test;

use morphos\CurrenciesHelper;
use morphos\Currency;
Expand Down
2 changes: 1 addition & 1 deletion tests/English/CardinalNumeralTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\English;
namespace morphos\test\English;

use morphos\English\CardinalNumeralGenerator;

Expand Down
2 changes: 1 addition & 1 deletion tests/English/NounPluralizationTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\English;
namespace morphos\test\English;

use morphos\English\NounPluralization;

Expand Down
2 changes: 1 addition & 1 deletion tests/English/OrdinalNumeralTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\English;
namespace morphos\test\English;

use morphos\English\OrdinalNumeralGenerator;

Expand Down
2 changes: 1 addition & 1 deletion tests/Russian/AdjectiveDeclensionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Gender;
use morphos\Russian\AdjectiveDeclension;
Expand Down
2 changes: 1 addition & 1 deletion tests/Russian/AdjectivePluralizationTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Gender;
use morphos\Russian\AdjectiveDeclension;
Expand Down
2 changes: 1 addition & 1 deletion tests/Russian/FirstNamesInflecionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Gender;
use morphos\NamesInflection;
Expand Down
7 changes: 6 additions & 1 deletion tests/Russian/GeographicalNamesInflectionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Russian\Cases;
use morphos\Russian\GeographicalNamesInflection;
Expand Down Expand Up @@ -48,6 +48,11 @@ public function wordsProvider()
['Анадырь', 'Анадыря', 'Анадырю', 'Анадырь', 'Анадырем', 'Анадыре'],
['Россошь', 'Россоши', 'Россоши', 'Россошь', 'Россошью', 'Россоши'],
['Чебоксары', 'Чебоксар', 'Чебоксарам', 'Чебоксары', 'Чебоксарами', 'Чебоксарах'],
['Ивацевичи', 'Ивацевичей', 'Ивацевичам', 'Ивацевичи', 'Ивацевичами', 'Ивацевичах'],
['Глубокое', 'Глубокого', 'Глубокому', 'Глубокое', 'Глубоким', 'Глубоком'],
['Египет', 'Египта', 'Египту', 'Египет', 'Египтом', 'Египте'],
['Столбцы', 'Столбцов', 'Столбцам', 'Столбцы', 'Столбцами', 'Столбцах'],
['Ханты-Мансийск', 'Ханты-Мансийска', 'Ханты-Мансийску', 'Ханты-Мансийск', 'Ханты-Мансийском', 'Ханты-Мансийске'],

// с беглой гласной
['Торжок', 'Торжка', 'Торжку', 'Торжок', 'Торжком', 'Торжке'],
Expand Down
2 changes: 1 addition & 1 deletion tests/Russian/LastNamesInflectionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Russian\Cases;
use morphos\Russian\LastNamesInflection;
Expand Down
2 changes: 1 addition & 1 deletion tests/Russian/MiddleNamesInflectionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Russian\Cases;
use morphos\Russian\MiddleNamesInflection;
Expand Down
4 changes: 3 additions & 1 deletion tests/Russian/NounDeclensionTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Gender;
use morphos\Russian\NounDeclension;
Expand Down Expand Up @@ -63,10 +63,12 @@ public function wordsProvider()
['путь', false, 2, ['путь', 'пути', 'пути', 'путь', 'путем', 'пути']],
['поселок', false, 2, ['поселок', 'поселка', 'поселку', 'поселок', 'поселком', 'поселке']],
['пирсинг', false, 2, ['пирсинг', 'пирсинга', 'пирсингу', 'пирсинг', 'пирсингом', 'пирсинге']],
['столбец', false, 2, ['столбец', 'столбца', 'столбцу', 'столбец', 'столбцом', 'столбце']],
['гений', true, 2, ['гений', 'гения', 'гению', 'гения', 'гением', 'гении']],
['ястреб', true, 2, ['ястреб', 'ястреба', 'ястребу', 'ястреба', 'ястребом', 'ястребе']],
['руководитель', true, 2, ['руководитель', 'руководителя', 'руководителю', 'руководителя', 'руководителем', 'руководителе']],
['председатель', true, 2, ['председатель', 'председателя', 'председателю', 'председателя', 'председателем', 'председателе']],
['библиотекарь', true, 2, ['библиотекарь', 'библиотекаря', 'библиотекарю', 'библиотекаря', 'библиотекарем', 'библиотекаре']],
// сущ мужского рода с мягким окончанием
['гвоздь', false, 2, ['гвоздь', 'гвоздя', 'гвоздю', 'гвоздь', 'гвоздем', 'гвозде']],
['день', false, 2, ['день', 'дня', 'дню', 'день', 'днем', 'дне']],
Expand Down
3 changes: 2 additions & 1 deletion tests/Russian/NounPluralizationTest.php
@@ -1,5 +1,5 @@
<?php
namespace morhos\test\Russian;
namespace morphos\test\Russian;

use morphos\Russian\Cases;
use morphos\Russian\NounPluralization;
Expand Down Expand Up @@ -127,6 +127,7 @@ public function pluralWordsProvider()
['пирсинг', false, ['пирсинги', 'пирсингов', 'пирсингам', 'пирсинги', 'пирсингами', 'пирсингах']],
['фабрика', false, ['фабрики', 'фабрик', 'фабрикам', 'фабрики', 'фабриками', 'фабриках']],
['гений', true, ['гения', 'гениев', 'гениям', 'гениев', 'гениями', 'гениях']],
['библиотекарь', true, ['библиотекари', 'библиотекарей', 'библиотекарям', 'библиотекарей', 'библиотекарями', 'библиотекарях']],

['копейка', false, ['копейки', 'копеек', 'копейкам', 'копейки', 'копейками', 'копейках']],
['батарейка', false, ['батарейки', 'батареек', 'батарейкам', 'батарейки', 'батарейками', 'батарейках']],
Expand Down

0 comments on commit 0387e69

Please sign in to comment.