aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Kiryukhin <alexander@kiryukhin.su>2017-11-07 15:35:34 +0300
committerGitHub <noreply@github.com>2017-11-07 15:35:34 +0300
commitf18b94cf00426e57261deabe6cfd977d434bd228 (patch)
treebf288db2713490eb493a6d4834330eace1f0d2f5 /src
parentfb502e2f603cc5a7d0268d281643e37ba8f80196 (diff)
parent5f5c5b124b2c8c7056aac01426d2c249d3f35aff (diff)
Merge pull request #7 from acelot/master
All methods are now static
Diffstat (limited to 'src')
-rw-r--r--src/NXP/Stemmer.php178
1 files changed, 99 insertions, 79 deletions
diff --git a/src/NXP/Stemmer.php b/src/NXP/Stemmer.php
index 76d494b..0232ecb 100644
--- a/src/NXP/Stemmer.php
+++ b/src/NXP/Stemmer.php
@@ -12,126 +12,146 @@ namespace NXP;
class Stemmer
{
- private $vowel = "аеёиоуыэюя";
- private $regexPerfectiveGerunds = array(
- "(в|вши|вшись)$",
- "(ив|ивши|ившись|ыв|ывши|ывшись)$"
- );
- private $regexAdjective = "(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$";
- private $regexParticiple = array(
- "(ем|нн|вш|ющ|щ)",
- "(ивш|ывш|ующ)"
- );
- private $regexReflexives = "(ся|сь)$";
- private $regexVerb = array(
- "(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)$",
- "(ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)$"
- );
- private $regexNoun = "(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$";
- private $regexSuperlative = "(ейш|ейше)$";
- private $regexDerivational = "(ост|ость)$";
- private $regexI = "и$";
- private $regexNN = "нн$";
- private $regexSoftSign = "ь$";
-
- private $word = '';
- private $RV = 0;
- private $R2 = 0;
-
- public function getWordBase($word)
+ const VOWEL = 'аеёиоуыэюя';
+ const REGEX_PERFECTIVE_GERUNDS1 = '(в|вши|вшись)$';
+ const REGEX_PERFECTIVE_GERUNDS2 = '(ив|ивши|ившись|ыв|ывши|ывшись)$';
+ const REGEX_ADJECTIVE = '(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$';
+ const REGEX_PARTICIPLE1 = '(ем|нн|вш|ющ|щ)';
+ const REGEX_PARTICIPLE2 = '(ивш|ывш|ующ)';
+ const REGEX_REFLEXIVES = '(ся|сь)$';
+ const REGEX_VERB1 = '(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)$';
+ const REGEX_VERB2 = '(ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)$';
+ const REGEX_NOUN = '(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$';
+ const REGEX_SUPERLATIVE = '(ейш|ейше)$';
+ const REGEX_DERIVATIONAL = '(ост|ость)$';
+ const REGEX_I = 'и$';
+ const REGEX_NN = 'нн$';
+ const REGEX_SOFT_SIGN = 'ь$';
+
+ /**
+ * @param string $word
+ *
+ * @return string
+ */
+ public static function getWordBase($word)
{
+ $originalInternalEncoding = mb_internal_encoding();
mb_internal_encoding('UTF-8');
- $this->word = $word;
- $this->findRegions();
- //Шаг 1
- //Найти окончание PERFECTIVE GERUND. Если оно существует – удалить его и завершить этот шаг.
- if (!$this->removeEndings($this->regexPerfectiveGerunds, $this->RV)) {
- //Иначе, удаляем окончание REFLEXIVE (если оно существует).
- $this->removeEndings($this->regexReflexives, $this->RV);
- //Затем в следующем порядке пробуем удалить окончания: ADJECTIVAL, VERB, NOUN. Как только одно из них найдено – шаг завершается.
- if (!($this->removeEndings(
+
+ list($rv, $r2) = self::findRegions($word);
+
+ // Шаг 1: Найти окончание PERFECTIVE GERUND. Если оно существует – удалить его и завершить этот шаг.
+ if (!self::removeEndings($word, array(self::REGEX_PERFECTIVE_GERUNDS1, self::REGEX_PERFECTIVE_GERUNDS2), $rv)) {
+ // Иначе, удаляем окончание REFLEXIVE (если оно существует).
+ self::removeEndings($word, self::REGEX_REFLEXIVES, $rv);
+
+ // Затем в следующем порядке пробуем удалить окончания: ADJECTIVAL, VERB, NOUN. Как только одно из них найдено – шаг завершается.
+ if (!(self::removeEndings(
+ $word,
array(
- $this->regexParticiple[0] . $this->regexAdjective,
- $this->regexParticiple[1] . $this->regexAdjective
+ self::REGEX_PARTICIPLE1 . self::REGEX_ADJECTIVE,
+ self::REGEX_PARTICIPLE2 . self::REGEX_ADJECTIVE
),
- $this->RV
- ) || $this->removeEndings($this->regexAdjective, $this->RV))
+ $rv
+ ) || self::removeEndings($word, self::REGEX_ADJECTIVE, $rv))
) {
- if (!$this->removeEndings($this->regexVerb, $this->RV)) {
- $this->removeEndings($this->regexNoun, $this->RV);
+ if (!self::removeEndings($word, array(self::REGEX_VERB1, self::REGEX_VERB2), $rv)) {
+ self::removeEndings($word, self::REGEX_NOUN, $rv);
}
}
}
- //Шаг 2
- //Если слово оканчивается на и – удаляем и.
- $this->removeEndings($this->regexI, $this->RV);
- //Шаг 3
- //Если в R2 найдется окончание DERIVATIONAL – удаляем его.
- $this->removeEndings($this->regexDerivational, $this->R2);
- //Шаг 4
- //Возможен один из трех вариантов:
- //Если слово оканчивается на нн – удаляем последнюю букву.
- if ($this->removeEndings($this->regexNN, $this->RV)) {
- $this->word .= 'н';
+
+ // Шаг 2: Если слово оканчивается на и – удаляем и.
+ self::removeEndings($word, self::REGEX_I, $rv);
+
+ // Шаг 3: Если в R2 найдется окончание DERIVATIONAL – удаляем его.
+ self::removeEndings($word, self::REGEX_DERIVATIONAL, $r2);
+
+ // Шаг 4: Возможен один из трех вариантов:
+ // 1. Если слово оканчивается на нн – удаляем последнюю букву.
+ if (self::removeEndings($word, self::REGEX_NN, $rv)) {
+ $word .= 'н';
}
- //Если слово оканчивается на SUPERLATIVE – удаляем его и снова удаляем последнюю букву, если слово оканчивается на нн.
- $this->removeEndings($this->regexSuperlative, $this->RV);
- //Если слово оканчивается на ь – удаляем его.
- $this->removeEndings($this->regexSoftSign, $this->RV);
- return $this->word;
+ // 2. Если слово оканчивается на SUPERLATIVE – удаляем его и снова удаляем последнюю букву, если слово оканчивается на нн.
+ self::removeEndings($word, self::REGEX_SUPERLATIVE, $rv);
+
+ // 3. Если слово оканчивается на ь – удаляем его.
+ self::removeEndings($word, self::REGEX_SOFT_SIGN, $rv);
+
+ mb_internal_encoding($originalInternalEncoding);
+ return $word;
}
- public function removeEndings($regex, $region)
+ /**
+ * @param string $word
+ * @param string|string[] $regex
+ * @param int $region
+ *
+ * @return bool
+ */
+ public static function removeEndings(&$word, $regex, $region)
{
- $prefix = mb_substr($this->word, 0, $region, 'utf8');
- $word = substr($this->word,strlen($prefix));
+ $prefix = mb_substr($word, 0, $region, 'utf8');
+ $ending = substr($word, strlen($prefix));
if (is_array($regex)) {
- if (preg_match('/.+[а|я]' . $regex[0] . '/u', $word)) {
- $this->word = $prefix . preg_replace('/' . $regex[0] . '/u', '', $word);
+ if (preg_match('/.+[а|я]' . $regex[0] . '/u', $ending)) {
+ $word = $prefix . preg_replace('/' . $regex[0] . '/u', '', $ending);
return true;
}
$regex = $regex[1];
}
- if (preg_match('/.+' . $regex . '/u', $word)) {
- $this->word = $prefix . preg_replace('/' . $regex . '/u', '', $word);
+ if (preg_match('/.+' . $regex . '/u', $ending)) {
+ $word = $prefix . preg_replace('/' . $regex . '/u', '', $ending);
return true;
}
return false;
}
- private function findRegions()
+ /**
+ * @param string $word
+ *
+ * @return int[]
+ */
+ private static function findRegions($word)
{
+ $rv = 0;
$state = 0;
- $wordLength = mb_strlen($this->word, 'utf8');
+ $wordLength = mb_strlen($word, 'utf8');
for ($i = 1; $i < $wordLength; $i++) {
- $prevChar = mb_substr($this->word, $i - 1, 1, 'utf8');
- $char = mb_substr($this->word, $i, 1, 'utf8');
+ $prevChar = mb_substr($word, $i - 1, 1, 'utf8');
+ $char = mb_substr($word, $i, 1, 'utf8');
switch ($state) {
case 0:
- if ($this->isVowel($char)) {
- $this->RV = $i + 1;
- $state = 1;
+ if (self::isVowel($char)) {
+ $rv = $i + 1;
+ $state = 1;
}
break;
case 1:
- if ($this->isVowel($prevChar) && !$this->isVowel($char)) {
- $state = 2;
+ if (self::isVowel($prevChar) && !self::isVowel($char)) {
+ $state = 2;
}
break;
case 2:
- if ($this->isVowel($prevChar) && !$this->isVowel($char)) {
- $this->R2 = $i + 1;
- return;
+ if (self::isVowel($prevChar) && !self::isVowel($char)) {
+ return [$rv, $i + 1];
}
break;
}
}
+
+ return [$rv, 0];
}
- private function isVowel($char)
+ /**
+ * @param string $char
+ *
+ * @return bool
+ */
+ private static function isVowel($char)
{
- return (strpos($this->vowel, $char) !== false);
+ return strpos(self::VOWEL, $char) !== false;
}
}