shevchenko
Version:
JavaScript library for declension of Ukrainian anthroponyms
60 lines (57 loc) • 2.13 kB
JavaScript
/**
* @file JavaScript library for declension of Ukrainian anthroponyms
* @module shevchenko
* @version 3.2.2
* @author Oleksandr Tolochko <shevchenko-js@tooleks.com>
* @license MIT
* @copyright 2017-2026 Oleksandr Tolochko <shevchenko-js@tooleks.com>
* @see {@link git+https://github.com/tooleks/shevchenko-js.git}
*/
import '../language/alphabet.js';
import '../language/word-class.js';
import '../language/grammatical-case.js';
import '../language/grammatical-gender.js';
import { copyLetterCase } from '../language/letter-case.js';
import { CommandRunnerFactory } from './command-runner-factory.js';
/**
* Counts a number of groups in a given regular expression.
*/
function countGroups(src) {
const pattern = new RegExp(`${src.toString()}|`);
const matches = pattern.exec('');
if (matches == null) {
return 0;
}
return matches.length - 1;
}
class DeclensionRuleInflector {
constructor(rule) {
this.rule = rule;
this.commandRunnerFactory = new CommandRunnerFactory();
}
/**
* Inflects the given word in the given grammatical case using the rule.
*/
inflect(word, grammaticalCase) {
const [commands] = this.rule.grammaticalCases[grammaticalCase];
if (commands) {
const searchValue = new RegExp(this.rule.pattern.modify, 'gi');
const inflectedWord = word.replace(searchValue, (match, ...groups) => {
let replacer = '';
const groupCount = countGroups(this.rule.pattern.modify);
for (let groupIndex = 0; groupIndex < groupCount; groupIndex += 1) {
let value = groups[groupIndex];
const command = commands[groupIndex];
if (command != null) {
value = this.commandRunnerFactory.make(command).exec(value);
}
replacer += value;
}
return replacer;
});
return copyLetterCase(word, inflectedWord);
}
return word;
}
}
export { DeclensionRuleInflector, countGroups };