Module:syl-common

local export = {}

--[=[

Authorship: Ben Wing

]=]

local m_links = require("Module:links") local iut = require("Module:inflection utilities")

local lang = require("Module:languages").getByCode("syl")

local current_title = mw.title.getCurrentTitle local PAGENAME = current_title.text

local u = mw.ustring.char local rsplit = mw.text.split local rfind = mw.ustring.find local rmatch = mw.ustring.match local rsubn = mw.ustring.gsub local usub = mw.ustring.sub

-- version of rsubn that discards all but the first return value local function rsub(term, foo, bar) local retval = rsubn(term, foo, bar) return retval end

-- vowel diacritics; don't display nicely on their own local A = u(0xA823) local I = u(0xA824) local U = u(0xA825) local E = u(0xA826) local O = u(0xA827)

export.diacritic_to_independent = { [A] = "ꠀ", [I] = "ꠁ", [U] = "ꠃ", [E] = "ꠄ", [O] = "ꠅ", }

local diacritic_list = {} local independent_list = {} for dia, ind in pairs(export.diacritic_to_independent) do	table.insert(independent_list, ind) table.insert(diacritic_list, dia) end

export.diacritics = table.concat(diacritic_list) export.independents = table.concat(independent_list) .. "ꠅ" export.vowels = export.diacritics .. export.independents

-- variant codes export.VAR1 = u(0xFFF0) export.VAR2 = u(0xFFF1) export.VAR3 = u(0xFFF2) export.VAR4 = u(0xFFF3) export.VAR5 = u(0xFFF4) export.VAR6 = u(0xFFF5) export.var_code_c = "[" .. export.VAR1 .. export.VAR2 .. export.VAR3 .. export.VAR4 .. export.VAR5 .. export.VAR6 .. "]" export.not_var_code_c = "[^" .. export.VAR1 .. export.VAR2 .. export.VAR3 .. export.VAR4 .. export.VAR5 .. export.VAR6 .. "]"

export.index_to_variant_code = { [1] = export.VAR1, [2] = export.VAR2, [3] = export.VAR3, [4] = export.VAR4, [5] = export.VAR5, [6] = export.VAR6, }

function export.split_term_respelling(term) if rfind(term, "//") then local split = rsplit(term, "//") if #split ~= 2 then error("Term with respelling should have only one // in it: " .. term) end return unpack(split) else return term, nil end end

function export.transliterate_respelling(phon) if not phon then return nil end local Sylheti_range = "[ꠀ-ˍ꠫*]" -- 0xA800 to 0xA82C; include *, which is a translit signal if rfind(phon, "^%-?" .. Sylheti_range) then return rsub((lang:transliterate(phon)), "%.", "") end return phon -- already transliterated end

function export.add_form(base, stem, translit_stem, slot, ending, footnotes, link_words, double_word) if not ending then return end

local function combine_stem_ending(stem, ending) local result if ending == "" then result = stem else if stem == "" or rfind(stem, "[" .. export.vowels .. "]$") then -- A diacritic at the beginning of the ending should be converted to its independent form -- if the stem does not end in a consonant. if rfind(ending, "^[" .. export.diacritics .. "]") then local ending_first = usub(ending, 1, 1) ending = (export.diacritic_to_independent[ending_first] or ending_first) .. usub(ending, 2) -- Diacritic e goes above the line and requires anusvara, but independent e does not -- go above the line and prefers chandrabindu in endings. ending = rsub(ending, "ꠄꠋ", "ꠄꠋ") end end -- Don't convert independent letters to diacritics after consonants because of cases like ꠝꠁ -- where the independent letter belongs after the consonant. result = stem .. ending end if link_words then -- Add links around the words. result = "" .. rsub(result, " ", " ") .. "" end if double_word then -- hack to support the progressive form of verbs, which is e.g. ꠇꠞꠔꠦ-ꠇꠞꠔꠦ return result .. "-" .. result else return result end end

local function combine_stem_ending_tr(stem, ending) local result if not ending or ending == "" then result = stem else -- When adding a non-null ending, remove final '-a' from the stem, but only -- if the transliterated lemma also ended in '-a'. This way, a noun like -- ꠙꠥꠘꠡ꠆ꠌ transliterated 'punaśca' "postscript" gets oblique plural transliterated -- 'punaścõ' with dropped '-a', but ꠝꠁ transliterated 'maī' "May" with -- transliterated stem 'ma' and ending singular ending '-ī' doesn't get the -- '-a' dropped. A third case we need to handle correctly is ꠁꠋꠐꠞꠛ꠆ꠎꠥ "interview"; -- if we truncate the final ꠥ '-ū' and then transliterate, we get 'iṇṭarvya' -- with extra '-a' that may appear in the transliteration if we're not careful. --			-- HACK! Handle ꠙ꠆ꠞꠣꠔꠢ꠆ correctly by checking specially for lemma_translit ending -- in -a or -aḥ and ending starting with a vowel. The proper way to do this -- correctly that handles all of the above cases requires access to the original -- (Syloti Nagri) ending, and checks to see if the stem ends in '-a' and the ending -- begins with a Syloti Nagri diacritic; in this case, it's correct to elide the '-a' result = stem .. ending end if double_word then -- hack to support the progressive form of verbs, which is e.g. ꠇꠞꠔꠦ-ꠇꠞꠔꠦ return result .. "-" .. result else return result end end

footnotes = iut.combine_footnotes(base.footnotes, footnotes) local ending_obj = iut.combine_form_and_footnotes(ending, footnotes) if translit_stem then stem = {form = stem, translit = translit_stem} end iut.add_forms(base.forms, slot, stem, ending_obj, combine_stem_ending, lang,		combine_stem_ending_tr) end

function export.strip_ending_from_stem(stem, translit_stem, ending) local new_stem = rmatch(stem, "^(.*)" .. ending .. "$") if not new_stem then error("Internal error: Lemma or stem " .. stem .. " should end in " .. ending) end local new_translit_stem if translit_stem then local ending_translit = (lang:transliterate(ending)) new_translit_stem = rmatch(translit_stem, "^(.*)" .. ending_translit .. "$") if not new_translit_stem then error("Unable to strip ending " .. ending .. " (transliterated " .. ending_translit .. ") from transliteration " .. translit_stem) end end return new_stem, new_translit_stem end

function export.strip_ending(base, ending) return export.strip_ending_from_stem(base.lemma, base.lemma_translit, ending) end

-- Normalize all lemmas, splitting out phonetic respellings and substituting -- the pagename for blank lemmas. Set `lemma_translit` to the transliteration of the -- respelling, or (if `always_transliterate` is given) to the transliteration of the -- lemma. `always_transliterate` should be specified for nouns and adjectives, where the -- lemma transliteration should be carried over to all remaining forms (hence since ꠅꠋꠇꠟ -- is transliterated 'aṅkal', the oblique plural ꠅꠋꠇꠟꠧꠋ should be 'aṅkalõ' not #'aṅklõ', -- the default transliteration). But it should not be specified for verbs, where this -- carry-over doesn't apply: even though ꠃꠉꠣꠟꠘꠣ has transliteration 'ugalnā', the -- perfective participle ꠃꠉꠟꠣ has default transliteration 'uglā' not the carry-over -- transliteration #'ugalā'. function export.normalize_all_lemmas(alternant_multiword_spec, always_transliterate) iut.map_word_specs(alternant_multiword_spec, function(base)		base.lemma, base.phon_lemma = export.split_term_respelling(base.lemma)		if base.lemma == "" then			base.lemma = PAGENAME		end		base.orig_lemma = base.lemma		base.orig_lemma_no_links = m_links.remove_links(base.lemma)		base.lemma = base.orig_lemma_no_links		if base.phon_lemma then			base.lemma_translit = export.transliterate_respelling(base.phon_lemma)		elseif always_transliterate then			base.lemma_translit = (lang:transliterate(base.lemma))		end	end) end

--[=[ Remove redundant translit. We need to do all declension of nouns and adjectives using manual translit because declined forms of nouns like ꠅꠌꠇꠘ "jacket" and ꠇꠣꠟꠣꠗꠘ "black money" may need manual translit, even though the base form itself doesn't need manual translit. For example, ꠅꠌꠇꠘ has default translit ackan, which is correct, but the oblique plural ꠅꠌꠇꠘꠧꠋ has default translit acaknõ, which is incorrect (correct is ackanõ, with stem translit as in the base). In general, such words need manual translit that forces the stem of the inflected form to have the same translit as the stem of the base form. We want to remove redundant manual translit so that accelerator-generated entries don't have unnecessary manual translit in them. Finally, we need to remove redundant manual translit at the very end, not as we decline each part of a multiword expression (which we used to do), because of cases like ꠇꠣꠟꠣꠗꠘ, which declines as if written ꠇꠣꠟꠣ ꠗꠘ. Hence it has oblique plural ꠇꠣꠟꠦꠗꠘꠧꠋ, which has incorrect default translit kaledhnõ instead of correct kaledhanõ, even though the individual parts ꠇꠣꠟꠦ and ꠗꠘꠧꠋ both have correct default translits. ]=] function export.remove_redundant_translit(alternant_multiword_spec) for slot, forms in pairs(alternant_multiword_spec.forms) do		alternant_multiword_spec.forms[slot] = iut.map_forms(forms, function(form, translit)			if translit and (lang:transliterate(m_links.remove_links(form))) == translit then				return form, nil			else				return form, translit			end		end) end end

function export.get_variants(form) return rsub(form, export.not_var_code_c, "") end

function export.remove_variant_codes(form) return rsub(form, export.var_code_c, "") end

-- Add variant codes to all slots with more than one form. The intention of variant -- codes is to prevent there being N^2 slot variants in a verb like ꠢꠤꠟꠘꠣ-ꠒꠥꠟꠘꠣ in -- slots that normally have N variants. Rather than combining all variants of ꠢꠤꠟꠘꠣ -- with all variants of ꠒꠥꠟꠘꠣ for the given slot, we only want to combine parallel -- variants. We implement this by tagging each variant with a "variant code" character -- and rejecting combinations with mismatching variant code characters. function export.add_variant_codes(base) for slot, forms in pairs(base.forms) do		if #forms > 1 then local index = 0 base.forms[slot] = iut.map_forms(forms, function(form, translit)				index = index + 1				local varcode = export.index_to_variant_code[index]				if not varcode then					error("Internal error: Encountered too many variants (" .. #forms .. "), no more variant codes available")				end				return form .. varcode, translit			end) end end end

return export