Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Склонение русских имён и фамилий
- *
- * var rn = new RussianName('Паниковский Михаил Самуэльевич');
- * rn.fullName(rn.gcaseRod); // Паниковского Михаила Самуэльевича
- *
- * Список констант по падежам см. ниже в коде.
- *
- * Пожалуйста, присылайте свои уточнения мне на почту. Спасибо.
- *
- * @version 0.1.4
- * @author Johnny Woo <agalkin@agalkin.ru>
- */
- var RussianNameProcessor = {
- sexM: 'm',
- sexF: 'f',
- gcaseIm: 'nominative', gcaseNom: 'nominative', // именительный
- gcaseRod: 'genitive', gcaseGen: 'genitive', // родительный
- gcaseDat: 'dative', // дательный
- gcaseVin: 'accusative', gcaseAcc: 'accusative', // винительный
- gcaseTvor: 'instrumentative', gcaseIns: 'instrumentative', // творительный
- gcasePred: 'prepositional', gcasePos: 'prepositional', // предложный
- rules: {
- lastName: {
- exceptions: [
- ' дюма,тома,дега,люка,ферма,гамарра,петипа,шандра . . . . .',
- ' гусь,ремень,камень,онук,богода,нечипас,долгопалец,маненок,рева,кива . . . . .',
- ' вий,сой,цой,хой -я -ю -я -ем -е'
- ],
- suffixes: [
- 'f б,в,г,д,ж,з,й,к,л,м,н,п,р,с,т,ф,х,ц,ч,ш,щ,ъ,ь . . . . .',
- 'f ска,цка -ой -ой -ую -ой -ой',
- 'f ая --ой --ой --ую --ой --ой',
- ' ская --ой --ой --ую --ой --ой',
- 'f на -ой -ой -у -ой -ой',
- ' иной -я -ю -я -ем -е',
- ' уй -я -ю -я -ем -е',
- ' ца -ы -е -у -ей -е',
- ' рих а у а ом е',
- ' ия . . . . .',
- ' иа,аа,оа,уа,ыа,еа,юа,эа . . . . .',
- ' их,ых . . . . .',
- ' о,е,э,и,ы,у,ю . . . . .',
- ' ова,ева -ой -ой -у -ой -ой',
- ' га,ка,ха,ча,ща,жа -и -е -у -ой -е',
- ' ца -и -е -у -ей -е',
- ' а -ы -е -у -ой -е',
- ' ь -я -ю -я -ем -е',
- ' ия -и -и -ю -ей -и',
- ' я -и -е -ю -ей -е',
- ' ей -я -ю -я -ем -е',
- ' ян,ан,йн а у а ом е',
- ' ынец,обец --ца --цу --ца --цем --це',
- ' онец,овец --ца --цу --ца --цом --це',
- ' ц,ч,ш,щ а у а ем е',
- ' ай -я -ю -я -ем -е',
- ' гой,кой -го -му -го --им -м',
- ' ой -го -му -го --ым -м',
- ' ах,ив а у а ом е',
- ' ший,щий,жий,ний --его --ему --его -м --ем',
- ' кий,ый --ого --ому --ого -м --ом',
- ' ий -я -ю -я -ем -и',
- ' ок --ка --ку --ка --ком --ке',
- ' ец --ца --цу --ца --цом --це',
- ' в,н а у а ым е',
- ' б,г,д,ж,з,к,л,м,п,р,с,т,ф,х а у а ом е'
- ]
- },
- firstName: {
- exceptions: [
- ' лев --ьва --ьву --ьва --ьвом --ьве',
- ' павел --ла --лу --ла --лом --ле',
- 'm шота . . . . .',
- 'f рашель,нинель,николь,габриэль,даниэль . . . . .'
- ],
- suffixes: [
- ' е,ё,и,о,у,ы,э,ю . . . . .',
- 'f б,в,г,д,ж,з,й,к,л,м,н,п,р,с,т,ф,х,ц,ч,ш,щ,ъ . . . . .',
- 'f ь -и -и . ю -и',
- 'm ь -я -ю -я -ем -е',
- ' га,ка,ха,ча,ща,жа -и -е -у -ой -е',
- ' а -ы -е -у -ой -е',
- ' ия -и -и -ю -ей -и',
- ' я -и -е -ю -ей -е',
- ' ей -я -ю -я -ем -е',
- ' ий -я -ю -я -ем -и',
- ' й -я -ю -я -ем -е',
- ' б,в,г,д,ж,з,к,л,м,н,п,р,с,т,ф,х,ц,ч а у а ом е'
- ]
- },
- middleName: {
- suffixes: [
- ' ич а у а ем е',
- ' на -ы -е -у -ой -е'
- ]
- }
- },
- initialized: false,
- init: function() {
- if(this.initialized) return;
- this.prepareRules();
- this.initialized = true;
- },
- prepareRules: function() {
- for(var type in this.rules) {
- for(var key in this.rules[type]) {
- for(var i = 0, n = this.rules[type][key].length; i < n; i++) {
- this.rules[type][key][i] = this.rule(this.rules[type][key][i]);
- }
- }
- }
- },
- rule: function(rule) {
- var m = rule.match(/^\s*([fm]?)\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/);
- if(m) return {
- sex: m[1],
- test: m[2].split(','),
- mods: [m[3], m[4], m[5], m[6], m[7]]
- }
- return false;
- },
- // склоняем слово по указанному набору правил и исключений
- word: function(word, sex, wordType, gcase) {
- // исходное слово находится в именительном падеже
- if(gcase == this.gcaseNom) return word;
- // составные слова
- if(word.match(/[-]/)) {
- var list = word.split('-');
- for(var i = 0, n = list.length; i < n; i++) {
- list[i] = this.word(list[i], sex, wordType, gcase);
- }
- return list.join('-');
- }
- // Иванов И. И.
- if(word.match(/^[А-ЯЁ]\.?$/i)) return word;
- this.init();
- var rules = this.rules[wordType];
- if(rules.exceptions) {
- var pick = this.pick(word, sex, gcase, rules.exceptions, true);
- if(pick) return pick;
- }
- var pick = this.pick(word, sex, gcase, rules.suffixes, false);
- return pick || word;
- },
- // выбираем из списка правил первое подходящее и применяем
- pick: function(word, sex, gcase, rules, matchWholeWord) {
- wordLower = word.toLowerCase();
- for(var i = 0, n = rules.length; i < n; i++) {
- if(this.ruleMatch(wordLower, sex, rules[i], matchWholeWord)) {
- return this.applyMod(word, gcase, rules[i]);
- }
- }
- return false;
- },
- // проверяем, подходит ли правило к слову
- ruleMatch: function(word, sex, rule, matchWholeWord) {
- if(rule.sex == this.sexM && sex == this.sexF) return false; // male by default
- if(rule.sex == this.sexF && sex != this.sexF) return false;
- for(var i = 0, n = rule.test.length; i < n; i++) {
- var test = matchWholeWord ? word : word.substr(Math.max(word.length - rule.test[i].length, 0));
- if(test == rule.test[i]) return true;
- }
- return false;
- },
- // склоняем слово (правим окончание)
- applyMod: function(word, gcase, rule) {
- switch(gcase) {
- case this.gcaseNom: var mod = '.'; break;
- case this.gcaseGen: var mod = rule.mods[0]; break;
- case this.gcaseDat: var mod = rule.mods[1]; break;
- case this.gcaseAcc: var mod = rule.mods[2]; break;
- case this.gcaseIns: var mod = rule.mods[3]; break;
- case this.gcasePos: var mod = rule.mods[4]; break;
- default: throw "Unknown grammatic case: "+gcase;
- }
- for(var i = 0, n = mod.length; i < n; i++) {
- var c = mod.substr(i, 1);
- switch(c) {
- case '.': break;
- case '-': word = word.substr(0, word.length - 1); break;
- default: word += c;
- }
- }
- return word;
- }
- }
- // new RussianName('Козлов Евгений Павлович') // годится обычная форма
- // new RussianName('Евгений Павлович Козлов') // в таком виде тоже
- // new RussianName('Козлов', 'Евгений') // можно явно указать составляющие
- // new RussianName('Кунтидия', 'Убиреко', '', 'f') // можно явно указать пол ('m' или 'f')
- var RussianName = function(lastName, firstName, middleName, sex) {
- if(typeof firstName == 'undefined') {
- var m = lastName.match(/^\s*(\S+)(\s+(\S+)(\s+(\S+))?)?\s*$/);
- if(!m) throw "Cannot parse supplied name";
- if(m[5] && m[3].match(/(ич|на)$/) && !m[5].match(/(ич|на)$/)) {
- // Иван Петрович Сидоров
- lastName = m[5];
- firstName = m[1];
- middleName = m[3];
- this.fullNameSurnameLast = true;
- } else {
- // Сидоров Иван Петрович
- lastName = m[1];
- firstName = m[3];
- middleName = m[5];
- }
- }
- this.ln = lastName;
- this.fn = firstName || '';
- this.mn = middleName || '';
- this.sex = sex || this.getSex();
- }
- RussianName.prototype = {
- // constants
- sexM: RussianNameProcessor.sexM,
- sexF: RussianNameProcessor.sexF,
- gcaseIm: RussianNameProcessor.gcaseIm, gcaseNom: RussianNameProcessor.gcaseNom, // именительный
- gcaseRod: RussianNameProcessor.gcaseRod, gcaseGen: RussianNameProcessor.gcaseGen, // родительный
- gcaseDat: RussianNameProcessor.gcaseDat, // дательный
- gcaseVin: RussianNameProcessor.gcaseVin, gcaseAcc: RussianNameProcessor.gcaseAcc, // винительный
- gcaseTvor: RussianNameProcessor.gcaseTvor, gcaseIns: RussianNameProcessor.gcaseIns, // творительный
- gcasePred: RussianNameProcessor.gcasePred, gcasePos: RussianNameProcessor.gcasePos, // предложный
- fullNameSurnameLast: false,
- ln: '', fn: '', mn: '', sex: '',
- // если пол явно не указан, его можно легко узнать по отчеству
- getSex: function() {
- if(this.mn.length > 2) {
- switch(this.mn.substr(this.mn.length - 2)) {
- case 'ич': return this.sexM;
- case 'на': return this.sexF;
- }
- }
- return '';
- },
- fullName: function(gcase) {
- return (
- (this.fullNameSurnameLast ? '' : this.lastName(gcase) + ' ')
- + this.firstName(gcase) + ' ' + this.middleName(gcase) +
- (this.fullNameSurnameLast ? ' ' + this.lastName(gcase) : '')
- ).replace(/^ +| +$/g, '');
- },
- lastName: function(gcase) {
- return RussianNameProcessor.word(this.ln, this.sex, 'lastName', gcase);
- },
- firstName: function(gcase) {
- return RussianNameProcessor.word(this.fn, this.sex, 'firstName', gcase);
- },
- middleName: function(gcase) {
- return RussianNameProcessor.word(this.mn, this.sex, 'middleName', gcase);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement