Module:sla-noun/data

local declensions = {}

local com = require("Module:sla-common") local m_table_tools = require("Module:table tools") local lang = require("Module:languages").getByCode("sla-pro")

local u = mw.ustring.char local rfind = mw.ustring.find local rsubn = mw.ustring.gsub local rmatch = mw.ustring.match local rsplit = mw.text.split local ulower = mw.ustring.lower local uupper = mw.ustring.upper local usub = mw.ustring.sub local ulen = mw.ustring.len local ugmatch = mw.ustring.gmatch

local GRAVE = u(0x0300) -- grave = ̀ local TILDE = u(0x0303) -- tilde = ̃ local INVBREVE = u(0x0311) -- inverse breve = ̑ local MACRON = u(0x0304) -- macron = ̄ local UNK = "-" -- unknown accent (placeholder; existing accents removed) local LEAVE = nil -- leave the accent alone

local contract_across_j_note = "The second form occurs in languages that contract early across /j/ (e.g. Czech), while the first form occurs in languages that do not (e.g. Russian)." local a_stem_loc_pl_note = "-asъ is the expected Balto-Slavic form but is found only in some Old Czech documents; -axъ is found everywhere else and is formed by analogy with other locative plurals in -xъ." local hard_o_stem_ins_sg_note = "-ъmь in North Slavic, -omь in South Slavic." local soft_o_stem_ins_sg_note = "-ьmь in North Slavic, -emь in South Slavic." local cons_stem_alt_pl_note = "-ьmъ/etc. are the original consonant-stem endings, while -amъ/etc. are later Common Slavic endings formed by analogy with a-stems."

local function combine_stem_ending(stem, endinfo) if endinfo.override then return endinfo.override end local accent = endinfo[1] local ending = endinfo[2] if endinfo.pal1 then stem = com.first_palatalization(stem) elseif endinfo.pal2 then stem = com.second_palatalization(stem) elseif endinfo.iotate then stem = com.iotate(stem) end if accent then stem = com.set_accent(stem, accent) end return stem .. ending end

local next_notesym_table = { ["*"]="**",	["**"]="***",	["***"]="†",	["†"]="††",	["††"]="†††",	["†††"]="‡",	["‡"]="‡‡",	["‡‡"]="‡‡",	["‡‡‡"]="1" }

local function get_next_notesym(sym) return next_notesym_table[sym] or sym + 1 end -- Value is either a single string (substitute that exact string), -- an "ending table" or a list of ending tables. An ending table is -- a table of one item (a string, substitute that exact string) or -- two items (the accent to apply to the stem, and the ending). -- Either form can have optional named values attached. In both -- forms, 'footnote' can be used to specify a footnote; in the -- two-item form, 'pal1', 'pal2', and 'iotate' can additionally be -- given to cause the appropriate modification to the end of the -- stem. local function add_form(data, stem, endinfo) if type(endinfo) ~= "table" then endinfo = {endinfo} end if type(endinfo[1]) ~= "table" then endinfo = {endinfo} end local retval = {} for _, endi in ipairs(endinfo) do		local form if endi[2] then form = combine_stem_ending(stem, endi) else form = endi[1] end if endi.footnote then local notesym = data.footnote_to_sym[endi.footnote] if not notesym then notesym = data.next_notesym data.next_notesym = get_next_notesym(notesym) data.footnote_to_sym[endi.footnote] = notesym table.insert(data.footnotes, m_table_tools.superscript_notes(notesym) .. " " .. endi.footnote) end table.insert(retval, {form, notesym=notesym}) else table.insert(retval, form) end end return retval end -- Add a full set of forms to the forms in FORMS for a given stem and the -- ending specs for all endings. The value of SG, DU and PL is a table of -- ending specs, containing entries for individual cases (n=nominative, -- a=accusative, g=genitive, l=locative, d=dative, i=instrumental, v=vocative). -- All seven values should be provided for the singular; all but vocative -- should be provided for the plural (vocative plural is always the same as -- nominative plural); for the dual, only nominative, genitive and dative -- should be provided (accusative and vocative are the same as nominative, -- locative is the same as genitive, and instrumental is the same as dative). -- -- Each ending spec is either a string (use that exact string for the entire -- case form) or a table SPEC indicating how to construct the case form, or -- a list of such table SPECS if there are multiple possibilities. SPEC should -- be either a list containing a single string (use that exact string for the -- entire case form), or a list containing two strings and optional additional -- flags. In the latter case, where SPEC[1] is the accent to place on the -- stem (or an empty string to remove any stressed accent but leave macrons, -- or the value UNK [for "unknown"] to remove all accents, or the value -- LEAVE to leave any existing accents), SPEC[2] is the ending to add to the -- stem, optional SPEC.pal1 causes the stem to have the first palatalization -- applied, optional SPEC.pal2 causes the stem to have the second palatalization -- applied, optional SPEC.iotate causes the stem to have iotation applied. local function add_forms(data, forms, stem, sg, du, pl) forms.nom = { s = add_form(data, stem, sg.n), d = add_form(data, stem, du.n), p = add_form(data, stem, pl.n), }	forms.acc = { s = add_form(data, stem, sg.a), d = forms.nom.d,		p = add_form(data, stem, pl.a), }	forms.gen = { s = add_form(data, stem, sg.g), d = add_form(data, stem, du.g), p = add_form(data, stem, pl.g), }	forms.loc = { s = add_form(data, stem, sg.l), d = forms.gen.d,		p = add_form(data, stem, pl.l), }	forms.dat = { s = add_form(data, stem, sg.d), d = add_form(data, stem, du.d), p = add_form(data, stem, pl.d), }	forms.ins = { s = add_form(data, stem, sg.i), d = forms.dat.d,		p = add_form(data, stem, pl.i), }	forms.voc = { s = add_form(data, stem, sg.v), d = forms.nom.d,		p = forms.nom.p,	} end

-- All consonant stems (ū, r, masc/neut n, s, nt) behave very similarly so -- we merge their functionality. All such stems have an infix composed of -- a vowel (V) + a consonant (C), which occurs between the stem and ending in -- all cases but the nominative/vocative (and accusative singular of neuters). -- DOPAL should be true if the stem should be first-palatalized before the -- infix, and ALTFEMPL is true if alternative endings in -am* should be given -- as well (used for v-stems). local function handle_consonant_stem(data, v, c, g, dopal, altfempl) local forms = {} local palstem = dopal and com.first_palatalization(data.stem) or data.stem local nonsyll = com.is_nonsyllabic(palstem) local ap = data.ap -- FIXME! Don't know the actual accents of *dьnь (pattern c), -- so treat as if unknown. if nonsyll and g == "m" then ap = nil end if ap == "a" or ap == "b" then add_forms(data, forms, palstem .. v .. (data.ap == "b" and GRAVE or "") .. c,			-- FIXME! Need to check voc, need accents for dual			-- FIXME! Formerly had ьmi for inst pl of all genders			{n=data.nom_sg, a=g == "n" and data.nom_sg or {GRAVE, "ь"}, g={GRAVE, "e"}, l={GRAVE, "e"}, d={GRAVE, "i"}, i=g == "f" and {{GRAVE, "ьjǫ"}, {GRAVE, "ǭ", iotate=true, footnote=contract_across_j_note}} or {GRAVE, "ьmь"}, v=data.nom_sg},			{n={GRAVE, "i"}, g={GRAVE, "u"},				d=altfempl and {{GRAVE, "ьma"}, {GRAVE, "ama", footnote=cons_stem_alt_pl_note}} or {GRAVE, "ьma"}},			{n={GRAVE, g == "m" and "e" or g == "f" and "i" or "ā"}, a={GRAVE, g == "n" and "ā" or "i"}, g={GRAVE, "ъ"},				l=altfempl and {{GRAVE, "ьxъ"}, {GRAVE, "axъ", footnote=cons_stem_alt_pl_note}} or {GRAVE, "ьxъ"},				d=altfempl and {{GRAVE, "ьmъ"}, {GRAVE, "amъ", footnote=cons_stem_alt_pl_note}} or {GRAVE, "ьmъ"},				i=altfempl and {{GRAVE, "ьmī"}, {GRAVE, "amī", footnote=cons_stem_alt_pl_note}} or {GRAVE, g == "n" and "ȳ" or "ьmī"} }		)	elseif ap == "c" then		local ldac = nonsyll and INVBREVE or TILDE		add_forms(data, forms, palstem .. v .. c, -- FIXME! Need to check voc -- FIXME! Formerly had ьmi for inst pl of all genders {n=data.nom_sg, a=g == "n" and data.nom_sg or {INVBREVE, "ь"}, g={INVBREVE, "e"}, l={INVBREVE, "e"}, d={INVBREVE, "i"}, i=g == "f" and {"", "ьjǫ́"} or {INVBREVE, "ьmь"}, v=data.nom_sg}, {n={INVBREVE, "i"}, g={"", "ù"}, d=altfempl and {{"", "ьmà"}, {"", "àma", footnote=cons_stem_alt_pl_note}} or {"", "ьmà"}}, {n=g == "n" and {"", "à"} or g == "m" and {INVBREVE, "e"} or {INVBREVE, "i"}, a=g == "n" and {"", "à"} or {INVBREVE, "i"}, g={TILDE, "ъ"}, l=altfempl and {{ldac, "ьxъ"}, {ldac, "axъ", footnote=cons_stem_alt_pl_note}} or {ldac, "ьxъ"}, d=altfempl and {{ldac, "ьmъ"}, {ldac, "amъ", footnote=cons_stem_alt_pl_note}} or {ldac, "ьmъ"}, i=altfempl and {{"", "ьmì"}, {"", "amì", footnote=cons_stem_alt_pl_note}} or {"", g == "n" and "ý" or "ьmì"} }		)	else		add_forms(data, forms, palstem .. v .. c, -- FIXME! Need to check voc, need accents for dual -- FIXME! Formerly had ьmi for inst pl of all genders {n=data.nom_sg, a=g == "n" and data.nom_sg or {UNK, "ь"}, g={UNK, "e"}, l={UNK, "e"}, d={UNK, "i"}, i=g == "f" and {{UNK, "ьjǫ"}, {UNK, "ǫ", iotate=true, footnote=contract_across_j_note}} or {UNK, "ьmь"}, v=nonsyll and g == "m" and {UNK, "y"} or data.nom_sg}, {n={UNK, "i"}, g={UNK, "u"}, d=altfempl and {{UNK, "ьma"}, {UNK, "ama", footnote=cons_stem_alt_pl_note}} or {UNK, "ьma"}}, {n={UNK, g == "m" and "e" or g == "f" and "i" or "a"}, a={UNK, g == "n" and "a" or "i"}, g={UNK, "ъ"}, l=altfempl and {{UNK, "ьxъ"}, {UNK, "axъ", footnote=cons_stem_alt_pl_note}} or {UNK, "ьxъ"}, d=altfempl and {{UNK, "ьmъ"}, {UNK, "amъ", footnote=cons_stem_alt_pl_note}} or {UNK, "ьmъ"}, i=altfempl and {{UNK, "ьmi"}, {UNK, "ami", footnote=cons_stem_alt_pl_note}} or {UNK, g == "n" and "y" or "ьmi"} }		)	end	return forms end

declensions["v-stem"] = function(data) local forms

local y_type = data.desinence == "y" local i_type = data.desinence == "i"

if not(y_type or i_type) then error("v-stem nouns must end in -y or -i") end if i_type then forms = handle_consonant_stem(data, "ь", "v", "f", false, "altfempl") else forms = handle_consonant_stem(data, "ъ", "v", "f", false, "altfempl") end if i_type then return forms, "soft v-stem" else return forms, "hard v-stem" end end

declensions["s-stem"] = function(data) if data.desinence ~= "e" and data.desinence ~= "o" then error("s-stem nouns must end in -e or -o") end

return handle_consonant_stem(data, "e", "s", "n", "palatalize"), "s-stem" end

declensions["r-stem"] = function(data) if (data.unom_sg ~= "mati") and (data.unom_sg ~= "dъťi") then error("Must be used only for nouns *mati and *dъťi") end

return handle_consonant_stem(data, "e", "r", "f", "palatalize"), "r-stem" end

declensions["nt-stem"] = function(data) if data.desinence ~= "ę" then error("nt-stem nouns must end in -ę") end

return handle_consonant_stem(data, "ę", "t", "n", "palatalize"), "nt-stem" end

declensions["n-stem"] = function(data) local forms

-- masculine nouns have desinence end in -nь or -y, neuters in -ę local y_type = data.desinence == "y" local ni_type = data.desinence == "ь" local e_type = data.desinence == "ę"

if not(y_type or ni_type or e_type) then error("Wrong ending for an n-stem noun") end

if ni_type then if data.ustem ~= "dьn" then error("n-stem noun ending in -ь must be *dьnь") end data.stem = "d" data.ustem = "d" forms = handle_consonant_stem(data, "", "", "m", "palatalize") else forms = handle_consonant_stem(data, "e", "n", y_type and "m" or "n", "palatalize") end

return forms, "n-stem", e_type and {"neuter n-stem nouns"} or {"masculine n-stem nouns"} end

-- Masculine and feminine i-stems differ only in the instrumental singular and -- nominative plural so handle them together. local function handle_i_stem(data, masc) local forms = {}

if data.ap == "a" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc, dual			{n=data.nom_sg, a=data.nom_sg, g={GRAVE, "ī"}, l={GRAVE, "ī"}, d={GRAVE, "i"}, i=masc and {GRAVE, "ьmь"} or {{GRAVE, "ьjǫ"}, {GRAVE, "ǭ", iotate=true, footnote=contract_across_j_note}}, v={UNK, "i"}},			{n={GRAVE, "i"}, g={{GRAVE, "ьju"}, {GRAVE, "u", iotate=true, footnote=contract_across_j_note}}, d={GRAVE, "ьma"}},			{n=masc and {{GRAVE, "ьjē"}, {GRAVE, "ē", iotate=true, footnote=contract_across_j_note}} or {GRAVE, "i"}, a={GRAVE, "i"}, g={{GRAVE, "ьjь"}, {GRAVE, "ī", footnote=contract_across_j_note}}, l={GRAVE, "ьxъ"}, d={GRAVE, "ьmъ"}, i={GRAVE, "ьmī"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc, dual			{n={TILDE, "ь"}, a={TILDE, "ь"}, g={TILDE, "i"}, l={TILDE, "i"}, d={MACRON, "ì"}, i=masc and {MACRON, "ь̀mь"} or {{TILDE, "ьjǫ"}, {TILDE, "ǫ", iotate=true, footnote=contract_across_j_note}}, v={UNK, "i"}},			{n={MACRON, "ì"}, g={{TILDE, "ьju"}, {UNK, "u", iotate=true, footnote=contract_across_j_note}}, d={TILDE, "ьma"}},			{n=masc and {{TILDE, "ьjē"}, {TILDE, "ē", iotate=true, footnote=contract_across_j_note}} or {MACRON, "ì"}, a={MACRON, "ì"}, g={{MACRON, "ь̀jь"}, {TILDE, "i", footnote=contract_across_j_note}}, l={MACRON, "ь̀xъ"}, d={MACRON, "ь̀mъ"}, i={TILDE, "ьmī"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={INVBREVE, "ь"}, a={INVBREVE, "ь"}, g={"", "í"}, l={"", "í"}, d={INVBREVE, "i"}, i=masc and {INVBREVE, "ьmь"} or {"", "ьjǫ́"}, v={UNK, "i"}},			{n={INVBREVE, "i"}, g={{"", "ьjù"}, {UNK, "u", iotate=true, footnote=contract_across_j_note}}, d={"", "ьmà"}},			{n=masc and {{INVBREVE, "ьjē"}, {INVBREVE, "ē", iotate=true, footnote=contract_across_j_note}} or {INVBREVE, "i"}, a={INVBREVE, "i"}, g={"", "ь̀jь"}, l={INVBREVE, "ьxъ"}, d={INVBREVE, "ьmъ"}, i={"", "ьmì"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "i"}, l={UNK, "i"}, d={UNK, "i"}, i=masc and {UNK, "ьmь"} or {{UNK, "ьjǫ"}, {UNK, "ǫ", iotate=true, footnote=contract_across_j_note}}, v={UNK, "i"}},			{n={UNK, "i"}, g={{UNK, "ьju"}, {UNK, "u", iotate=true, footnote=contract_across_j_note}}, d={UNK, "ьma"}},			{n=masc and {{UNK, "ьje"}, {UNK, "e", iotate=true, footnote=contract_across_j_note}} or {UNK, "i"}, a={UNK, "i"}, g={{UNK, "ьjь"}, {UNK, "i", footnote=contract_across_j_note}}, l={UNK, "ьxъ"}, d={UNK, "ьmъ"}, i={UNK, "ьmi"}}		) end

return forms, "i-stem", masc and {"masculine i-stem nouns"} or {"feminine i-stem nouns"} end

declensions["feminine i-stem"] = function(data) return handle_i_stem(data, false) end

declensions["masculine i-stem"] = function(data) return handle_i_stem(data, "masc") end

declensions["u-stem"] = function(data) local forms = {}

if data.desinence ~= "ъ" then error("u-stem nouns must end in -ъ") end if data.ap == "a" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc, dual			{n=data.nom_sg, a=data.nom_sg, g={GRAVE, "u"}, l={GRAVE, "ū"}, d={GRAVE, "ovi"}, i={GRAVE, "ъmь"}, v={GRAVE, "u"}},			{n={GRAVE, "y"}, g={GRAVE, "ovu"}, d={GRAVE, "ъma"}},			{n={GRAVE, "ove"}, a={GRAVE, "y"}, g={GRAVE, "ovъ"}, l={GRAVE, "ъxъ"}, d={GRAVE, "ъmъ"}, i={GRAVE, "ъmī"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={TILDE, "ъ"}, a={TILDE, "ъ"}, g={MACRON, "ù"}, l={TILDE, "u"}, d={MACRON, "òvi"}, i={MACRON, "ъ̀mь"}, v={UNK, "u"}},			{n={MACRON, "ỳ"}, g={MACRON, "òvu"}, d={TILDE, "ъma"}},			{n={MACRON, "òve"}, a={MACRON, "ỳ"}, g={MACRON, "òvъ"}, l={MACRON, "ъ̀xъ"}, d={MACRON, "ъ̀mъ"}, i={TILDE, "ъmī"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={INVBREVE, "ъ"}, a={INVBREVE, "ъ"}, g={INVBREVE, "u"}, l={"", "ú"}, d={INVBREVE, "ovi"}, i={INVBREVE, "ъmь"}, v={UNK, "u"}},			{n={INVBREVE, "y"}, g={"", "ovù"}, d={"", "ъmà"}},			{n={INVBREVE, "ove"}, a={INVBREVE, "y"}, g={"", "òvъ"}, l={INVBREVE, "ъxъ"}, d={INVBREVE, "ъmъ"}, i={"", "ъmì"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "u"}, l={UNK, "u"}, d={UNK, "ovi"}, i={UNK, "ъmь"}, v={UNK, "u"}},			{n={UNK, "y"}, g={UNK, "ovu"}, d={UNK, "ъma"}},			{n={UNK, "ove"}, a={UNK, "y"}, g={UNK, "ovъ"}, l={UNK, "ъxъ"}, d={UNK, "ъmъ"}, i={UNK, "ъmi"}}		) end

return forms, "u-stem" end

declensions["hard a-stem"] = function(data) local forms = {}

if data.ap == "a" then add_forms(data, forms, data.stem,			{n=data.nom_sg, a={GRAVE, "ǫ"}, g={GRAVE, "y"}, l={GRAVE, "ě", pal2=true}, d={GRAVE, "ě", pal2=true}, i={{GRAVE, "ojǫ"}, {GRAVE, "ǭ", footnote=contract_across_j_note}}, v={GRAVE, "o"}},			{n={GRAVE, "ě", pal2=true}, g={GRAVE, "u"}, d={GRAVE, "ama"}},			{n={GRAVE, "y"}, a={GRAVE, "y"}, g={GRAVE, "ъ"}, l={{GRAVE, "asъ"}, {GRAVE, "axъ", footnote=a_stem_loc_pl_note}}, d={GRAVE, "amъ"}, i={GRAVE, "amī"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={MACRON, "à"}, a={MACRON, "ǫ̀"}, g={MACRON, "ỳ"}, l={MACRON, "ě̀", pal2=true}, d={MACRON, "ě̀", pal2=true}, i={{MACRON, "òjǫ"}, {TILDE, "ǫ", footnote=contract_across_j_note}}, v={UNK, "o"}},			{n={TILDE, "ě", pal2=true}, g={MACRON, "ù"}, d={MACRON, "àma"}},			{n={MACRON, "ỳ"}, a={MACRON, "ỳ"}, g={TILDE, "ъ"}, l={{MACRON, "àsъ"}, {MACRON, "àxъ", footnote=a_stem_loc_pl_note}}, d={MACRON, "àmъ"}, i={MACRON, "àmī"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={"", "à"}, a={INVBREVE, "ǫ"}, g={"", "ý"}, l={INVBREVE, "ě", pal2=true}, d={"", "ě̀", pal2=true}, i={"", "ojǫ́"}, v={UNK, "o"}},			{n={INVBREVE, "ě", pal2=true}, g={"", "ù"}, d={"", "àma"}},			{n={INVBREVE, "y"}, a={INVBREVE, "y"}, g={TILDE, "ъ"}, l={{"", "àsъ"}, {"", "àxъ", footnote=a_stem_loc_pl_note}}, d={"", "àmъ"}, i={"", "àmi"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a={UNK, "ǫ"}, g={UNK, "y"}, l={UNK, "ě", pal2=true}, d={UNK, "ě", pal2=true}, i={{UNK, "ojǫ"}, {UNK, "ǫ", footnote=contract_across_j_note}}, v={LEAVE, "o"}},			{n={UNK, "ě", pal2=true}, g={UNK, "u"}, d={UNK, "ama"}},			{n={UNK, "y"}, a={UNK, "y"}, g={UNK, "ъ"}, l={{UNK, "asъ"}, {UNK, "axъ", footnote=a_stem_loc_pl_note}}, d={UNK, "amъ"}, i={UNK, "ami"}}		) end

return forms, "hard a-stem" end

declensions["soft a-stem"] = function(data) local forms = {} local stem = data.ustem local title -- ī-stems share the same endings as soft a-stems in all cases except for the nominative singular, so they are handled as a	-- special case of them. -- for genuine ī-stems that are not preceded by a soft, palatal consonant (e.g. olni) we add "j" everywhere except in nom_sg if data.desinence == "i" then title = "ī-stem" stem = com.iotate(stem) else if not rfind(stem, "[cčďjľňřšťž]$") and not rfind(stem, "dz$") then error("Soft a-stem must end in a soft consonant (given: " .. stem .. ")")		end title = "soft a-stem" end if data.ap == "a" then add_forms(data, forms, data.stem,			{n=data.nom_sg, a={GRAVE, "ǫ"}, g={GRAVE, "ę̇"}, l={GRAVE, "ī"}, d={GRAVE, "ī"}, i={{GRAVE, "ējǫ"}, {GRAVE, "ǭ", footnote=contract_across_j_note}}, v={GRAVE, "e"}},			{n={GRAVE, "i"}, g={GRAVE, "u"}, d={GRAVE, "ama"}},			{n={GRAVE, "ę̇"}, a={GRAVE, "ę̇"}, g={GRAVE, "ь"}, l={GRAVE, "āsъ"}, d={GRAVE, "āmъ"}, i={GRAVE, "āmī"}}		) elseif data.ap == "b" then -- Some accent-b ja-stem nouns behave more like a-stem nouns (e.g.		-- *svě̄ťà), while others take the standard form with neoacute accent -- (vòlja). Remember that data.nom_sg and data.stem are decomposed. if rfind(data.nom_sg, "a" .. GRAVE .. "$") then add_forms(data, forms, data.stem,				-- FIXME! Need accents for voc				{n={MACRON, "à"}, a={MACRON, "ǫ̀"}, g={MACRON, "ę̇̀"}, l={MACRON, "ì"}, d={MACRON, "ì"}, i={{MACRON, "èjǫ"}, {TILDE, "ǫ", footnote=contract_across_j_note}}, v={UNK, "e"}},				{n={TILDE, "i"}, g={MACRON, "ù"}, d={MACRON, "àma"}},				{n={MACRON, "ę̇̀"}, a={MACRON, "ę̇̀"}, g={TILDE, "ь"}, l={{MACRON, "àsъ"}, {MACRON, "àxъ", footnote=a_stem_loc_pl_note}}, d={MACRON, "àmъ"}, i={MACRON, "àmī"}}			) else add_forms(data, forms, data.stem,				-- FIXME! Need accents for voc				{n={TILDE, "a"}, a={TILDE, "ǫ"}, g={TILDE, "ę̇"}, l={TILDE, "i"}, d={TILDE, "i"}, i={{TILDE, "ejǫ"}, {TILDE, "ǫ", footnote=contract_across_j_note}}, v={UNK, "e"}},				{n={TILDE, "i"}, g={TILDE, "u"}, d={TILDE, "ama"}},				{n={TILDE, "ę̇"}, a={TILDE, "ę̇"}, g={TILDE, "ь"}, l={{TILDE, "asъ"}, {TILDE, "axъ", footnote=a_stem_loc_pl_note}}, d={TILDE, "amъ"}, i={TILDE, "amī"}}			) end elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for voc			{n={"", "à"}, a={INVBREVE, "ǫ"}, g={"", "ę̇́"}, l={INVBREVE, "ī"}, d={"", "ì"}, i={"", "ejǫ́"}, v={UNK, "e"}},			{n={INVBREVE, "i"}, g={"", "ù"}, d={"", "àma"}},			{n={INVBREVE, "ę̇"}, a={INVBREVE, "ę̇"}, g={TILDE, "ь"}, l={{"", "àsъ"}, {"", "àxъ", footnote=a_stem_loc_pl_note}}, d={"", "àmъ"}, i={"", "àmi"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a={UNK, "ǫ"}, g={UNK, "ę̇"}, l={UNK, "i"}, d={UNK, "i"}, i={{UNK, "ejǫ"}, {UNK, "ǫ", footnote=contract_across_j_note}}, v={LEAVE, "e"}},			{n={UNK, "i"}, g={UNK, "u"}, d={UNK, "ama"}},			{n={UNK, "ę̇"}, a={UNK, "ę̇"}, g={UNK, "ь"}, l={{UNK, "asъ"}, {UNK, "axъ", footnote=a_stem_loc_pl_note}}, d={UNK, "amъ"}, i={UNK, "ami"}}		) end

return forms, title end

declensions["soft neuter o-stem"] = function(data) local forms = {}

-- FIXME! No forms given for ap=a in Verweij if data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for dual			{n={MACRON, "è"}, a={MACRON, "è"}, g={MACRON, "à"}, l={MACRON, "ì"}, d={MACRON, "ù"}, i={{MACRON, "ь̀mь"}, {MACRON, "èmь", footnote=soft_o_stem_ins_sg_note}}, v={MACRON, "è"}},			{n={TILDE, "i"}, g={UNK, "u"}, d={UNK, "ema"}}, -- The plural has neoacute throughout. Does the dual have this also?			{n={TILDE, "a"}, a={TILDE, "a"}, g={TILDE, "ь"}, l={TILDE, "ixъ"}, d={TILDE, "emъ"}, i={TILDE, "i"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			{n={INVBREVE, "e"}, a={INVBREVE, "e"}, g={INVBREVE, "a"}, l={INVBREVE, "i"}, d={INVBREVE, "u"}, i={{INVBREVE, "ьmь"}, {INVBREVE, "emь", footnote=soft_o_stem_ins_sg_note}}, v={INVBREVE, "e"}},			{n={INVBREVE, "i"}, g={"", "ù"}, d={"", "emà"}},			{n={"", "à"}, a={"", "à"}, g={TILDE, "ь"}, l={"", "íxъ"}, d={"", "émъ"}, i={"", "í"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "a"}, l={UNK, "i"}, d={UNK, "u"}, i={{UNK, "ьmь"}, {UNK, "emь", footnote=soft_o_stem_ins_sg_note}}, v=data.nom_sg},			{n={UNK, "i"}, g={UNK, "u"}, d={UNK, "ema"}},			{n={UNK, "a"}, a={UNK, "a"}, g={UNK, "ь"}, l={UNK, "ixъ"}, d={UNK, "emъ"}, i={UNK, "i"}}		) end

return forms, "soft o-stem", {"soft neuter o-stem nouns"} end

declensions["hard neuter o-stem"] = function(data) local forms = {}

if data.ap == "a" then add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={GRAVE, "a"}, l={GRAVE, "ě", pal2=true}, d={GRAVE, "u"}, i={{GRAVE, "ъmь"}, {GRAVE, "omь", footnote=hard_o_stem_ins_sg_note}}, v=data.nom_sg},			{n={GRAVE, "ě", pal2=true}, g={GRAVE, "u"}, d={GRAVE, "oma"}},			{n={GRAVE, "a"}, a={GRAVE, "a"}, g={GRAVE, "ъ"}, l={GRAVE, "ě̄xъ", pal2=true}, d={GRAVE, "omъ"}, i={GRAVE, "ȳ"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			{n={MACRON, "ò"}, a={MACRON, "ò"}, g={MACRON, "à"}, l={MACRON, "ě̀", pal2=true}, d={MACRON, "ù"}, i={{MACRON, "ъ̀mь"}, {MACRON, "òmь", footnote=hard_o_stem_ins_sg_note}}, v={MACRON, "ò"}},			{n={TILDE, "ě", pal2=true}, g={MACRON, "ù"}, d={MACRON, "òma"}},			{n={MACRON, "à"}, a={MACRON, "à"}, g={TILDE, "ъ"}, l={TILDE, "ěxъ", pal2=true}, d={MACRON, "òmъ"}, i={TILDE, "y"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			{n={INVBREVE, "o"}, a={INVBREVE, "o"}, g={INVBREVE, "a"}, l={INVBREVE, "ě", pal2=true}, d={INVBREVE, "u"}, i={{INVBREVE, "ъmь"}, {INVBREVE, "omь", footnote=hard_o_stem_ins_sg_note}}, v=data.nom_sg},			{n={INVBREVE, "ě", pal2=true}, g={"", "ù"}, d={"", "omà"}},			{n={"", "à"}, a={"", "à"}, g={TILDE, "ъ"}, l={"", "ě̃xъ", pal2=true}, d={"", "òmъ"}, i={"", "ý"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "a"}, l={UNK, "ě", pal2=true}, d={UNK, "u"}, i={{UNK, "ъmь"}, {UNK, "omь", footnote=hard_o_stem_ins_sg_note}}, v=data.nom_sg},			{n={UNK, "ě", pal2=true}, g={UNK, "u"}, d={UNK, "oma"}},			{n={UNK, "a"}, a={UNK, "a"}, g={UNK, "ъ"}, l={UNK, "ěxъ", pal2=true}, d={UNK, "omъ"}, i={UNK, "y"}}		) end

return forms, "hard o-stem", {"hard neuter o-stem nouns"} end

declensions["hard masculine o-stem"] = function(data) local forms = {}

if data.ap == "a" then add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={GRAVE, "a"}, l={GRAVE, "ě", pal2=true}, d={GRAVE, "u"}, i={{GRAVE, "ъmь"}, {GRAVE, "omь", footnote=hard_o_stem_ins_sg_note}}, v={GRAVE, "e", pal1=true}},			{n={GRAVE, "a"}, g={GRAVE, "u"}, d={GRAVE, "oma"}},			{n={GRAVE, "i", pal2=true}, a={GRAVE, "y"}, g={GRAVE, "ъ"}, l={GRAVE, "ě̄xъ", pal2=true}, d={GRAVE, "omъ"}, i={GRAVE, "ȳ"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for vocative sg			{n={TILDE, "ъ"}, a={TILDE, "ъ"}, g={MACRON, "à"}, l={MACRON, "ě̀", pal2=true}, d={MACRON, "ù"}, i={{MACRON, "ъ̀mь"}, {MACRON, "òmь", footnote=hard_o_stem_ins_sg_note}}, v={UNK, "e", pal1=true}},			{n={MACRON, "à"}, g={MACRON, "ù"}, d={MACRON, "òma"}},			{n={MACRON, "ì", pal2=true}, a={MACRON, "ỳ"}, g={TILDE, "ъ"}, l={TILDE, "ěxъ", pal2=true}, d={MACRON, "òmъ"}, i={TILDE, "y"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for vocative sg			{n={INVBREVE, "ъ"}, a={INVBREVE, "ъ"}, g={INVBREVE, "a"}, l={INVBREVE, "ě", pal2=true}, d={INVBREVE, "u"}, i={{INVBREVE, "ъmь"}, {INVBREVE, "omь", footnote=hard_o_stem_ins_sg_note}}, v={UNK, "e", pal1=true}},			{n={INVBREVE, "a"}, g={"", "ù"}, d={"", "omà"}},			{n={INVBREVE, "i", pal2=true}, a={INVBREVE, "y"}, g={TILDE, "ъ"}, l={"", "ě̃xъ", pal2=true}, d={"", "òmъ"}, i={"", "ý"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "a"}, l={UNK, "ě", pal2=true}, d={UNK, "u"}, i={{UNK, "ъmь"}, {UNK, "omь", footnote=hard_o_stem_ins_sg_note}}, v={UNK, "e", pal1=true}},			{n={UNK, "a"}, g={UNK, "u"}, d={UNK, "oma"}},			{n={UNK, "i", pal2=true}, a={UNK, "y"}, g={UNK, "ъ"}, l={UNK, "ěxъ", pal2=true}, d={UNK, "omъ"}, i={UNK, "y"}}		) end

return forms, "hard o-stem", {"hard masculine o-stem nouns"} end

declensions["soft masculine o-stem"] = function(data) local forms = {}

local voc_e = rfind(data.stem, "c$") or rfind(data.stem, "dz$") or		rfind(data.stem, "sc$") or rfind(data.stem, "zdz$")

if data.ap == "a" then add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={GRAVE, "a"}, l={GRAVE, "i"}, d={GRAVE, "u"}, i={{GRAVE, "ьmь"}, {GRAVE, "emь", footnote=soft_o_stem_ins_sg_note}}, v={GRAVE, voc_e and "e" or "u", pal1=true}},			{n={GRAVE, "a"}, g={GRAVE, "u"}, d={GRAVE, "ema"}},			{n={GRAVE, "i"}, a={GRAVE, "ę̇"}, g={GRAVE, "ь"}, l={GRAVE, "īxъ"}, d={GRAVE, "ēmъ"}, i={GRAVE, "ī"}}		) elseif data.ap == "b" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for vocative sg			{n={TILDE, "ь"}, a={TILDE, "ь"}, g={MACRON, "à"}, l={MACRON, "ì"}, d={MACRON, "ù"}, i={{MACRON, "ь̀mь"}, {MACRON, "èmь", footnote=soft_o_stem_ins_sg_note}}, v={UNK, voc_e and "e" or "u", pal1=true}},			{n={MACRON, "à"}, g={MACRON, "ù"}, d={MACRON, "èma"}},			{n={MACRON, "ì"}, a={MACRON, "ę̇̀"}, g={TILDE, "ь"}, l={TILDE, "ixъ"}, d={TILDE, "emъ"}, i={TILDE, "i"}}		) elseif data.ap == "c" then add_forms(data, forms, data.stem,			-- FIXME! Need accents for vocative sg			{n={INVBREVE, "ь"}, a={INVBREVE, "ь"}, g={INVBREVE, "a"}, l={INVBREVE, "i"}, d={INVBREVE, "u"}, i={{INVBREVE, "ьmь"}, {INVBREVE, "emь", footnote=soft_o_stem_ins_sg_note}}, v={UNK, voc_e and "e" or "u", pal1=true}},			{n={INVBREVE, "a"}, g={"", "ù"}, d={"", "emà"}},			{n={INVBREVE, "i"}, a={INVBREVE, "ę̇"}, g={TILDE, "ь"}, l={"", "ĩxъ"}, d={"", "èmъ"}, i={"", "í"}}		) else add_forms(data, forms, data.stem,			{n=data.nom_sg, a=data.nom_sg, g={UNK, "a"}, l={UNK, "i"}, d={UNK, "u"}, i={{UNK, "ьmь"}, {UNK, "emь", footnote=soft_o_stem_ins_sg_note}}, v={UNK, voc_e and "e" or "u", pal1=true}},			{n={UNK, "a"}, g={UNK, "u"}, d={UNK, "ema"}},			{n={UNK, "i"}, a={UNK, "ę̇"}, g={UNK, "ь"}, l={UNK, "ixъ"}, d={UNK, "emъ"}, i={UNK, "i"}}		) end

return forms, "soft o-stem", {"soft masculine o-stem nouns"} end

return declensions