Module:User:Vitalik/inflection/units/ru-noun

Hello, you have come here looking for the meaning of the word Module:User:Vitalik/inflection/units/ru-noun. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:User:Vitalik/inflection/units/ru-noun, but we will also tell you about its etymology, its characteristics and you will know how to say Module:User:Vitalik/inflection/units/ru-noun in singular and plural. Everything you need to know about the word Module:User:Vitalik/inflection/units/ru-noun you have here. The definition of the word Module:User:Vitalik/inflection/units/ru-noun will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:User:Vitalik/inflection/units/ru-noun, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.

Template:inflection/nav

Zaliznyak's algorithm

Zaliznyak's notation

Gender and animacy

  Zaliznyak     Our template   Description
м m-in   masculine inanimate  
мо m-an masculine animate
ж f-in feminine inanimate
жо f-an feminine animate
с n-in neuter inanimate
со n-an neuter animate

Standard endings

Hard stem type (#1) {2.1}

singular plural
  masculine     neuter     feminine     masculine     neuter     feminine  
nominative -о -а -ы -а -ы
genitive -а -ы -ов
dative -у -е -ам
 accusative   inanimate  = nominative  = nominative  -у = nominative
animate = genitive = genitive
instrumental -ом -ой,-ою -ами
  prepositional   -е -ах

Soft stem type (#2) {2.2}

singular plural
  masculine     neuter     feminine     masculine     neuter     feminine  
nominative -ь -е (unstressed)
-ё (stressed)
-я -и -я -и
genitive -я -и -ей  -ь (unstressed)
-ей (stressed)
dative -ю -е -ям
 accusative   inanimate  = nominative  = nominative  -ю = nominative
animate = genitive = genitive
instrumental -ем (unstressed)
-ём (stressed)
  -ей,-ею (unstressed)  
-ёй,-ёю (stressed)
-ями
  prepositional   -е -ях

Other stem types (#3-#7) {2.3}

type stem ends with  endings like  changes
in endings
changes in genitive plural other changes in endings
velar (#3) к, г, х hard (#1) ыи
 sibilant (#4)  ш, ж, ч, щ ыи
unstressed oе
masculine: -ей

 feminine and neuter:  ∅ (unstressed)
-ей (stressed)
 

letter-ц (#5) ц  unstressed oе 
vowel (#6)  vowels (except и) or й  soft (#2) ьй masculine: -ев (unstressed)
-ёв (stressed)

feminine and neuter: -й

letter-и (#7) и feminine dative singular and prepositional (all genders):

-и (unstressed)
-е (stressed)

Reducables {3}

Case A

applies to:

  • masculine (all types)
  • feminine (type #8 only)

description:

  • reducable is in nominative singular
 reducable  the rule when applies examples
о о → ∅ always любовь → любви
сон → сна
{3.A.1}
е/ё е/ёй if letter before e/ё is vowel боец → бойца
паёк → пайка
{3.A.2}
е/ёь if stem type is vowel (#6) улей → улья {3.A.3.1}
if stem type is velar (#3)
 and letter before е/ё is consonant 
(except ш, ж, ч, щ, ц)
зверёк → зверька {3.A.3.2}
if letter before e/ё is л лёд → льда
палец → пальца
{3.A.3.3}
 е/ё → ∅  in all other cases орёл → орла
кашель → кашля
{3.A.4}

Case B

applies to:

  • feminine (except type #8)
  • neuter (all types)

description:

  • reducable is not in nominative singular
 reducable  the rule when applies examples
TODO description

Stress types {4}

Form Stress type
a b b' c d d' e f f' f''
singular nominative stém-ending stem-énding like b stém-ending stem-énding like d stém-ending stem-énding like f like f
genitive stém-ending stem-énding stém-ending stem-énding stém-ending stem-énding
dative stém-ending stem-énding stém-ending stem-énding stém-ending stem-énding
accusative stém-ending stem-énding stém-ending stem-énding stém-ending stém-ending stem-énding stém-ending
instrumental stém-ending stem-énding stém-ending stém-ending stem-énding like d stém-ending stem-énding like f stém-ending
prepositional stém-ending stem-énding like b stém-ending stem-énding stém-ending stem-énding like f
plural nominative stém-ending stem-énding like b stem-énding stém-ending like d stém-ending stém-ending like f like f
genitive stém-ending stem-énding stem-énding stém-ending stem-énding stem-énding
dative stém-ending stem-énding stem-énding stém-ending stem-énding stem-énding
instrumental stém-ending stem-énding stem-énding stém-ending stem-énding stem-énding
prepositional stém-ending stem-énding stem-énding stém-ending stem-énding stem-énding

-- Inflection unit for Russian nouns
-- Version 2.0.38
-- Date: 2015-08-25

local dev_prefix = ''
dev_prefix = 'User:Vitalik/'  -- comment this on active version

local export = {}
local _ = require('Module:' .. dev_prefix .. 'inflection-tools')
-- local lang = require("Module:languages").getByCode("ru")
-- local m_links = require("Module:links")
-- local strutils = require("Module:string utilities")

-- constants:
local unstressed = 1
local stressed = 2

function export.template(base, args)
	return dev_prefix .. 'ru-decl-noun-table-z'
end

local function get_standard_endings()
	return {
		m = {  -- masculine endings
			hard = {
				nom_sg = '',
				gen_sg = 'а',
				dat_sg = 'у',
				ins_sg = 'ом',
				nom_pl = 'ы',
				gen_pl = {'ов', 'ов'},  -- possibly we can join them together again (m_hard_gen_pl stressed and unstressed)
			},
			soft = {
				nom_sg = 'ь',
				gen_sg = 'я',
				dat_sg = 'ю',
				ins_sg = {'ем', 'ём'},
				nom_pl = 'и',
				gen_pl = {'ей', 'ей'},
			},
		},
		f = {  -- feminine endings
			hard = {
				nom_sg = 'а',
				gen_sg = 'ы',
				dat_sg = 'е',
				acc_sg = 'у',
				ins_sg = 'ой',
				nom_pl = 'ы',
				gen_pl = {'', ''},
			},
			soft = {
				nom_sg = 'я',
				gen_sg = 'и',
				dat_sg = {'е', 'е'},
				acc_sg = 'ю',
				ins_sg = {'ей', 'ёй'},
				nom_pl = 'и',
				gen_pl = {'ь', 'ей'},
			},
		},
		n = {  -- neuter endings
			hard = {
				nom_sg = 'о',
				gen_sg = 'а',
				dat_sg = 'у',
				ins_sg = 'ом',
				nom_pl = 'а',
				gen_pl = {'', ''},
			},
			soft = {
				nom_sg = 'е',  -- was: {'е', 'ё'}
				gen_sg = 'я',
				dat_sg = 'ю',
				ins_sg = {'ем', 'ём'},
				nom_pl = 'я',
				gen_pl = {'ь', 'ей'},
			},
		},
		common = {  -- common endings
			hard = {
				prp_sg = {'е', 'е'},
				dat_pl = 'ам',
				ins_pl = 'ами',
				prp_pl = 'ах',
			},
			soft = {
				prp_sg = {'е', 'е'},
				dat_pl = 'ям',
				ins_pl = 'ями',
				prp_pl = 'ях',
			},
		}
	}
end

local function get_stress_flags(stress_type)
	return {
		stem = {
			sg     = _.equals(stress_type, {"a", "c", "e"})                          and stressed or unstressed,
			acc_sg = _.equals(stress_type, {"a", "c", "e", "d'", "f'"})              and stressed or unstressed,
			ins_sg = _.equals(stress_type, {"a", "c", "e", "b'", "f''"})             and stressed or unstressed,
			pl     = _.equals(stress_type, {"a", "d", "d'"})                         and stressed or unstressed,
			nom_pl = _.equals(stress_type, {"a", "d", "d'", "e", "f", "f'", "f''"})  and stressed or unstressed,
		},
		ending = {
			sg     = _.equals(stress_type, {"b", "b'", "d", "d'", "f", "f'", "f''"}) and stressed or unstressed,
			acc_sg = _.equals(stress_type, {"b", "b'", "d", "f", "f''"})             and stressed or unstressed,
			ins_sg = _.equals(stress_type, {"b", "d", "d'", "f", "f'"})              and stressed or unstressed,
			pl     = _.equals(stress_type, {"b", "b'", "c", "e", "f", "f'", "f''"})  and stressed or unstressed,
			nom_pl = _.equals(stress_type, {"b", "b'", "c"})                         and stressed or unstressed,
		}
	}
end

local function get_stem_type(z)
	if _.endswith(z.stem, '') then
		z.stem_type = 'velar'
	elseif _.endswith(z.stem, '') then
		z.stem_type = 'sibilant'
	elseif _.endswith(z.stem, 'ц') then
		z.stem_type = 'letter-ц'
	elseif _.endswith(z.stem, {'', ''}) then
		z.stem_type = 'vowel'
	elseif _.endswith(z.stem, 'и') then
		z.stem_type = 'letter-и'
	else
		if z.gender == 'm' then
			if z.stem == z.word or _.endswith(z.word, 'ы') then
				z.stem_type = 'hard'
			elseif _.endswith(z.word, 'путь') then
				z.stem_type = 'm-3rd'
			elseif _.endswith(z.word, 'ь') or _.endswith(z.word, 'и') then
				z.stem_type = 'soft'
			elseif _.endswith(z.word, 'а') then
				z.gender = 'f'
				z.stem_type = 'hard'
			elseif _.endswith(z.word, 'я') then
				z.gender = 'f'
				z.stem_type = 'soft'
			end
		elseif z.gender == 'f' then
			if _.endswith(z.word, 'а') or _.endswith(z.word, 'ы') then
				z.stem_type = 'hard'
			elseif _.endswith(z.word, 'я') or _.endswith(z.word, 'и') then
				z.stem_type = 'soft'
			elseif _.endswith(z.word, 'ь') then  -- conflict in pl
				z.stem_type = 'f-3rd'
			end
		elseif z.gender == 'n' then
			if _.endswith(z.word, 'о') or _.endswith(z.word, 'а') then
				z.stem_type = 'hard'
			elseif _.endswith(z.word, 'е') or _.endswith(z.word, 'я') then
				z.stem_type = 'soft'
			elseif _.endswith(z.word, 'мя')  or _.endswith(z.word, 'мена') then
				z.stem_type = 'n-3rd'
			end
		end
	end
	
	if z.gender == 'm' then
		if _.endswith(z.word, {'а', 'я'}) then
			z.gender = 'f'
		end
	end

	if z.gender == 'f' and z.stem_type == 'sibilant' and _.endswith(z.word, 'ь') then
		z.stem_type = 'f-3rd-sibilant'
	end
	if z.stem_type == '' then
		z.stem_type = 'hard'
	end
end

local function change_endings_for_other_stem_types(z)
	if _.equals(z.stem_type, {'velar', 'sibilant'}) then
		-- Replace "ы" to "и"
		z.e = 'и'
		z.e = 'и'
		z.e = 'и'
	end

	if _.equals(z.stem_type, {'sibilant', 'letter-ц'}) then
		-- Replace unstressed "о" to "е"
		if z.stress_flags == unstressed then
			z.e = 'е'
		end
		if z.stress_flags == unstressed then
			z.e = 'ем'
			z.e = 'ем'
			z.e = 'ей'
		end
		if z.stress_flags == unstressed then
			z.e = {'ев', 'ев'}  -- TODO: should we change stressed value here?
		end
	end

	if _.equals(z.stem_type, 'sibilant') then
		-- Replace "ов", "ев", "ёв" and null to "ей"
		z.e = {'ей', 'ей'}
		z.e = 'ей'
		-- z.e_unstressed = ''  this is just don't changed
		z.e = 'ей'
		-- z.e_unstressed = ''  this is just don't changed
	end

	if _.equals(z.stem_type, {'vowel', 'letter-и'}) then
		-- Replace "ь" to "й"
		z.e = 'й'
		z.e = 'й'
		z.e = 'й'
	end

	if _.equals(z.stem_type, {'vowel', 'letter-и'}) then
		-- Replace "ей" to "ев/ёв", and "ь,ей" to "й"
		z.e = {'ев', 'ёв'}
		z.e = {'й', 'й'}
		z.e = {'й', 'й'}
	end

	if _.equals(z.stem_type, 'letter-и') then
		z.e = 'и'
		z.e = 'и'
	end

	if _.equals(z.stem_type, 'm-3rd') then
		z.e = 'и'
		z.e = 'и'
		z.e = {'и', 'и'}
	end

	if _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then
		z.e = 'ь'
		z.e = {'и', 'и'}
		z.e = 'ь'
		z.e = {'ью', 'ью'}
		z.e = {'и', 'и'}
		z.e = {'ей', 'ей'}
	end

	if _.equals(z.stem_type, 'f-3rd-sibilant') then
		z.e = 'ам'
		z.e = 'ами'
		z.e = 'ах'
	end
end

local function apply_specific_1_2(z)
-- If we have specific (1) or (2)
	if _.contains(z.specific, '%(1%)') then
		z.e = 'а'
		z.e = 'я'
		z.e = 'ы'
		z.e = 'и'
		if _.equals(z.stem_type, {'velar', 'sibilant'}) then
			-- Replace "ы" to "и"
			z.e = 'и'
		end
	end
	if _.contains(z.specific, '%(2%)') then
		z.e = {'', ''}
		z.e = {'ь', 'ь'}
		z.e = {'ов', 'ов'}
		z.e = {'ев', 'ёв'}
		z.e = {'ей', 'ей'}
		z.e = {'ей', 'ей'}
		if _.equals(z.stem_type, {'sibilant', 'letter-ц'}) then
			-- Replace unstressed "о" to "е"
			z.e = 'ев'
		end
	--[=[ Possibly we don't need this:
			-- Replace "ов", "ев", "ёв" and null to "ей"
			if z.stem_type = {'sibilant'}}
				z.e = {'ей', 'ей'}
				z.e = 'ей'
			end
			-- Replace "ь" to "й"
			if z.stem_type = {'vowel', 'letter-и'}}
				z.e = {'й', 'й'}
			end
			-- Replace "ей" to "ев/ёв", and "ь,ей" to "й"
			if z.stem_type = {'vowel', 'letter-и'}}
				z.e = {'ев', 'ёв'}
				z.e = {'й', 'й'}
			end
	]=]--
	end
end

local function choose(endings, case, type)
	endings = endings
end

local function choose_stress_for_endings(z)
	local s
	s = z.stress_flags
	choose(z.e, 'dat_sg', s)
	choose(z.e, 'prp_sg', s)
	choose(z.e, 'prp_sg', s)

	s = z.stress_flags
	choose(z.e, 'ins_sg', s)
	choose(z.e, 'ins_sg', s)
	choose(z.e, 'ins_sg', s)

	s = z.stress_flags
	choose(z.e, 'gen_pl', s)
	choose(z.e, 'gen_pl', s)
	choose(z.e, 'gen_pl', s)
	choose(z.e, 'gen_pl', s)
	choose(z.e, 'gen_pl', s)
	choose(z.e, 'gen_pl', s)
end

local function choose_endings_by_stem_type(z)
	local base_stem_type
	if _.equals(z.stem_type, {'hard', 'soft'}) then
		base_stem_type = z.stem_type
	elseif _.equals(z.stem_type, {'velar', 'sibilant', 'letter-ц'}) then
		base_stem_type = 'hard'
	elseif _.equals(z.stem_type, {'vowel', 'letter-и', 'm-3rd', 'f-3rd', 'f-3rd-sibilant'}) then
		base_stem_type = 'soft'
	else
		return {error_msg = 'Unexpected internal error: Unknown stem type'}
	end
	for key, value in pairs(z.e) do
		z.e = value
	end
	z.endings = z.e
end

local function add_stress(endings, case)
	endings = _.replace(endings, '^({vowel})', '%1́ ')
end

local function apply_stress_type(z)
	if z.stress_flags == stressed then
		z.stems = z.stem_stressed
	else
		z.stems = z.stem
		add_stress(z.endings, 'nom_sg')
		add_stress(z.endings, 'gen_sg')
		add_stress(z.endings, 'dat_sg')
		add_stress(z.endings, 'prp_sg')
	end

	if z.stress_flags == stressed then
		z.stems = z.stem_stressed
	else
		z.stems = z.stem
		add_stress(z.endings, 'ins_sg')
	end

	if z.gender == 'f' then
		if z.stress_flags == stressed then
			z.stems = z.stem_stressed
		else
			z.stems = z.stem
			add_stress(z.endings, 'acc_sg')
		end
	end

	if z.stress_flags == stressed then
		z.stems = z.stem_stressed
	else
		z.stems = z.stem
		add_stress(z.endings, 'nom_pl')
	end

	if z.stress_flags == stressed then
		z.stems = z.stem_stressed
	else
		z.stems = z.stem
		add_stress(z.endings, 'gen_pl')
		add_stress(z.endings, 'dat_pl')
		add_stress(z.endings, 'ins_pl')
		add_stress(z.endings, 'prp_pl')
	end
end

local function apply_specific_degree(z)
	-- If degree sign °
	if _.endswith(z.word, 'нин') and z.animacy == 'an' and z.word ~= 'семьянин' then
		z.stems = _.replace(z.stems, '()ни́ н$', '%1́ н')
		z.stems = _.replace(z.stems, '(́ ?н)ин$', '%1')
		z.stems = _.replace(z.stems, '()ни́ н$', '%1́ н')
		z.stems = _.replace(z.stems, '(́ ?н)ин$', '%1')
		z.endings = 'е'
		z.endings = ''
		z.specific = z.specific .. '°'
	end
	if _.endswith(z.word, {'ёнок', 'онок', 'ёночек', 'оночек'}) then
		if _.endswith(z.word, 'ёнок') then
			z.stems = _.replace(z.stems, 'ёнок$', 'я́т')
			z.stems = _.replace(z.stems, 'ёнок$', 'я́т')
		end
		if _.endswith(z.word, 'онок') then
			z.stems = _.replace(z.stems, 'о́нок$', 'а́т')
			z.stems = _.replace(z.stems, 'о́нок$', 'а́т')
		end
		if _.endswith(z.word, 'ёночек') then
			z.stems = _.replace(z.stems, 'ёночек$', 'я́тк')
			z.stems = _.replace(z.stems, 'ёночек$', 'я́тк')
		end
		if _.endswith(z.word, 'оночек') then
			z.stems = _.replace(z.stems, 'о́ночек$', 'а́тк')
			z.stems = _.replace(z.stems, 'о́ночек$', 'а́тк')
		end
		z.endings = z.e
		z.endings = z.e
		z.specific = z.specific .. '*'
		z.specific = z.specific .. '°'
	end
end

local function apply_specific_reducable(z)
	if _.contains(z.specific, '%*') then
		if z.gender == 'm' then
			reduced = 'A'
		elseif z.gender == 'n' then
			reduced = 'B'
		elseif z.gender == 'f' then
			if _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then 
				reduced = 'A'
			else
				reduced = 'B'
			end
		end
	
		if reduced == 'A' then
			reduced_letter = _.extract(z.word, '({vowel+ё}){consonant}+$')
			if reduced_letter == 'о' then
				z.stems = _.replace(z.stems, 'о́ ?(+)$', '%1')
				if not _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then
					z.stems = _.replace(z.stems, 'о́ ?(+)$', '%1')
				end
				z.stems = _.replace(z.stems, 'о́ ?(+)$', '%1')
				z.stems = _.replace(z.stems, 'о́ ?(+)$', '%1')
			elseif _.equals(reduced_letter, {'е', 'ё'}) then
				prev = _.extract(z.word, '(.)+$')
				if _.contains(prev, '{vowel+ё}') then                                     -- 1).
					z.stems = _.replace(z.stems, '́ ?(+)$', 'й%1')
					if not _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then  
						z.stems = _.replace(z.stems, '́ ?(+)$', 'й%1')
					end
					z.stems = _.replace(z.stems, '́ ?(+)$', 'й%1')
					z.stems = _.replace(z.stems, '́ ?(+)$', 'й%1')
				elseif z.stem_type == 'vowel'                                                  -- 2) а).
						or z.stem_type == 'velar' and _.contains(prev, '')   -- 2) б).
						or not _.equals(z.stem_type, {'vowel', 'velar'}) and prev == 'л' then  -- 2) в).
					z.stems = _.replace(z.stems, '́ ?(*)$', 'ь%1')
					if not _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then  
						z.stems = _.replace(z.stems, '́ ?(*)$', 'ь%1')
					end
					z.stems = _.replace(z.stems, '́ ?(*)$', 'ь%1')
					z.stems = _.replace(z.stems, '́ ?(*)$', 'ь%1')
				else                                                                         -- 3).
					z.stems = _.replace(z.stems, '́ ?(*)$', '%1')
					if not _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then  
						z.stems = _.replace(z.stems, '́ ?(*)$', '%1')
					end
					z.stems = _.replace(z.stems, '́ ?(*)$', '%1')
					z.stems = _.replace(z.stems, '́ ?(*)$', '%1')
				end
			end
		end  -- reduced A
	
		-- TODO: pcerhaps this line is redundant?
		z.stems = z.stems  -- apply changes in stems for stems
	
		if reduced == 'B' and 
			not (z.stem_type == 'soft' and _.equals(z.stress_type, {'b', 'f'}) -- we should ignore asterix for 2*b and 2*f (so to process it just like 2b or 2f)
				 or _.contains(z.specific, '(2)') and _.equals(z.stem_type, {'velar', 'letter-ц', 'vowel'}))  -- and also the same for (2)-specific and 3,5,6 stem-types
		then 
			if z.stem_type == 'vowel' then  -- 1).
				if _.equals(z.stress_type, {'b', 'c', 'e', 'f', "f'", "b'" }) then  -- gen_pl ending stressed  -- TODO: special vars for that
					z.stems = _.replace(z.stems, 'ь$', 'е́')
				else
					z.stems = _.replace(z.stems, 'ь$', 'и')
				end
			elseif _.contains(z.stem, '{consonant}$') then  -- 2).
				if z.stem_type == 'letter-ц' or _.equals(z.stress_type, {'a', 'd', "d'"}) then  -- gen_pl ending unstressed  -- TODO: special vars for that
					z.stems = _.replace(z.stems, '({consonant})$', 'е%1')
				else
					z.stems = _.replace(z.stems, '({consonant})$', 'ё%1')
				end
			else  -- 3).
				prev = _.extract(z.stem, '(.){consonant}$')
				if z.stem_type == 'velar' and _.contains(prev, '')  -- 3). а).
						or _.contains(prev, '') then                -- 3). б).
					z.stems = _.replace(z.stems, '(.)({consonant})$', '%1о%2')
				else  -- 3). в).
					if z.stem_type == 'letter-ц' then
						z.stems = _.replace(z.stems, '(.)({consonant})$', '%1е%2')
					else 
						if _.equals(z.stress_type, {'b', 'c', 'e', 'f', "f'", "b'" }) then  -- gen_pl ending stressed  -- TODO: special vars for that
							if _.contains(prev, '') then
								z.stems = _.replace(z.stems, '(.)({consonant})$', '%1о́%2')
							else
								z.stems = _.replace(z.stems, '(.)({consonant})$', '%1ё%2')
							end
						else 
							z.stems = _.replace(z.stems, '(.)({consonant})$', '%1е%2')
						end
					end
				end
			end
			if z.stem_type == 'soft' and _.endswith(z.word, 'ня') and z.stress_type == 'a' then
				z.endings = ''
			end
		end  -- reduced B
	end  -- specific *
end

local function choose_accusative_forms(z, forms)
	forms = ''
	forms = ''
	forms = ''
	forms = ''
	
	if z.gender == 'n' then
		forms = forms
	elseif z.gender == 'm' then
		if z.animacy == 'in' then
			forms = forms
		elseif z.animacy == 'an' then
			forms = forms
		else
			forms = forms
			forms = forms
		end
	elseif z.gender == 'f' then
		if _.equals(z.stem_type, {'f-3rd', 'f-3rd-sibilant'}) then
			forms = forms
		else
			forms = z.stems .. z.endings
		end
	end

	if z.animacy == 'in' then
		forms = forms
	elseif z.animacy == 'an' then
		forms = forms
	else
		forms = forms
		forms = forms
	end
end

function get_zaliznyak_index(z)
	local stem_types = {
		 = '1',
		 = '2',
		 = '3',
		 = '4',
		 = '5',
		 = '6',
		 = '7',
		 = '8',
		 = '8',
		 = '8',
		 = '8',
	}
	local index = z.gender_animacy .. ' ' .. stem_types
	if _.contains(z.specific, '°') then
		index = index .. '°'
	elseif _.contains(z.specific, '%*') then
		index = index .. '*'
	end
	index = index .. _.replace(z.stress_type, "'", "'")
	if _.contains(z.specific, '%(1%)') then
		index = index .. '①'
	end
	if _.contains(z.specific, '%(2%)') then
		index = index .. '②'
	end
	if _.contains(z.specific, '%(3%)') then
		index = index .. '③'
	end
	if _.contains(z.specific, 'ё') then
		index = index .. ', ё'
	end
	return index
end

function export.forms(base, args)
	_.clear_stash()
	_.add_stash('{vowel}', '')
	_.add_stash('{vowel+ё}', '')
	_.add_stash('{consonant}', '')

	local z = {}
	z.e = get_standard_endings()

	z.word_stressed = args
	if _.contains_several(z.word_stressed, '{vowel+ё}') and not _.contains(z.word_stressed, '') then
		return {error_msg = 'Error in template {{ru-decl-noun-z}}: You should add stress mark for the argument "word_stressed"'}
	end
	z.word = _.replace(z.word_stressed, '́ ', '')

	-- Parse "gender_animacy" argument and get values for "gender" and "animacy"'
	z.gender_animacy = args
	z.gender = _.extract(z.gender_animacy, '()%-+')
	z.animacy = _.extract(z.gender_animacy, '%-(+)')
	
	z.stress_type = args
	if not _.equals(z.stress_type, {'a', 'b', "b'", 'c', 'd', "d'", 'e', 'f', "f'", "f''"}) then
		return {error_msg = 'Error in template {{ru-decl-noun-z}}: Wrong value for the argument "stress_type"'}
	end
	z.stress_flags = get_stress_flags(z.stress_type)

	z.specific = args

	-- Remove ending (-а, -е, -ё, -о, -я, -й, -ь) to get stem
	z.stem = _.replace(z.word, '$', '')
	z.stem_stressed = _.replace(z.word_stressed, '́ ?$', '')

	-- Add stress to stem_stressed if stress is absent (i.e. there is only one syllable or stress was on the ending)
	if not _.contains(z.stem_stressed, '') then
		if _.equals(z.stress_type, {"f", "f'"}) then
			z.stem_stressed = _.replace(z.stem_stressed, '^({consonant}*)({vowel})', '%1%2́ ')
		else
		-- if _.equals(stress_type, {'a', "b'", 'b', 'c', 'd', "d'", 'e'}) then
			z.stem_stressed = _.replace(z.stem_stressed, '({vowel})({consonant}*)$', '%1́ %2')
		end
		-- TODO: process cases with * (stress on penultimate syllable)
	end

	-- Determination of stem type
	get_stem_type(z)

	-- Special changes in endings for velar, sibilant, vowel etc. stem types
	change_endings_for_other_stem_types(z)

	-- apply special cases (1) or (2) in specific
	apply_specific_1_2(z)

	-- Resolve stressed/unstressed cases of endings
	choose_stress_for_endings(z)

	if z.gender == 'n' and _.endswith(z.word, 'ё') then
		z.e = 'ё'
	end

	-- Choose endings by stem type and gender (either 'hard' or 'soft' key from changed "z.e")
	choose_endings_by_stem_type(z)

	-- If we have "ё" specific
	if _.contains(z.specific, 'ё') then
		z.stem_stressed = _.replace(z.stem_stressed, 'е́?(*)$', 'ё%1')
	end

	z.stems = {}
	apply_stress_type(z)

	apply_specific_degree(z)

	-- Changes for reduceable cases
	z.stems = z.stems  -- *save* unchanged stem value for nominative singular
	z.stems = z.stems  -- set default stem value for genitive plural	
	apply_specific_reducable(z)

	-- If we have "ё" specific
	if _.contains(z.specific, 'ё') and not _.contains(z.endings, '{vowel+ё}') and not _.contains(z.stems, 'ё') then
		z.stems = _.replace(z.stems, 'е́?(*)$', 'ё%1')
		z.specific = z.specific .. 'ё'
	end

	-- Generate forms
	local forms = {
		nom_sg = z.stems .. z.endings,
		gen_sg = z.stems .. z.endings,
		dat_sg = z.stems .. z.endings,
		acc_sg = '',
		ins_sg = z.stems .. z.endings,
		prp_sg = z.stems .. z.endings,
		nom_pl = z.stems .. z.endings,
		gen_pl = z.stems .. z.endings,
		dat_pl = z.stems .. z.endings,
		acc_pl = '',
		ins_pl = z.stems .. z.endings,
		prp_pl = z.stems .. z.endings,
	}

	-- Add stress if there is no one
	if _.contains_several(forms, '{vowel}') and not _.contains(forms, '') then
		-- perhaps this is redundant for nom_sg?
		forms = _.replace(forms, '({vowel})({consonant}*)$', '%1́ %2')
	end
	if _.contains_several(forms, '{vowel+ё}') and not _.contains(forms, '') then
		forms = _.replace(forms, '({vowel})({consonant}*)$', '%1́ %2')
	end

	for key, value in pairs(forms) do
		-- Remove stress if there is only one syllable
		if _.contains_once(value, '{vowel+ё}') then
			forms = _.replace(value, '́ ', '')
		end
		-- Replace 'ё' with 'е' when unstressed
		if _.contains_once(value, 'ё') and _.contains(value, '́ ') then
			forms = _.replace(value, 'ё', 'е')
		end
	end

	choose_accusative_forms(z, forms)

	-- partitive case
	if args and args ~= '' then
		forms = forms
	end

	-- locative case
	if args and args ~= '' then
		loc = forms
		loc = _.replace(loc, '́ ', '')
		loc = _.replace(loc, 'ё', 'е')
		loc = _.replace(loc, '({vowel})({consonant}*)$', '%1́ %2')
		forms = loc
		if args == 'в' or args == 'на' then
			forms = '(' .. args .. ')'
		else
			forms = '(в, на) '
		end
	end

	forms = z.stem_type  -- for testcases
	forms = z.stress_type  -- for categories
	forms = get_zaliznyak_index(z)
	forms = dev_prefix

	local keys = {
		'nom_sg', 'gen_sg', 'dat_sg', 'acc_sg', 'ins_sg', 'prp_sg', 
		'nom_pl', 'gen_pl', 'dat_pl', 'acc_pl', 'ins_pl', 'prp_pl', 
		'voc', 'n', 'note',
	}
	for i, key in pairs(keys) do
		if args and args ~= '' then
			forms = args
		end
		--[=[ -- I think we don't need this here, let's do it in template
		if form_key == 'nom_sg' then
			if forms and forms ~= '' then
				value = forms
				transliterated = lang:transliterate(m_links.remove_links(value))
				link = m_links.full_link(value, nil, lang, nil, nil, nil, {tr = "-"}, false)
				forms = strutils.format("{link}<br/><span style='color: #888'>{transliterated}</span>", {link=link, transliterated=transliterated})
			else
				forms = '&mdash;'
			end
		end
		]=]--
	end
	
	return forms
end

return export