Module:tr-harmony

local m_str_utils = require("Module:string utilities")

local codepoint = m_str_utils.codepoint local find = m_str_utils.find local gcodepoint = m_str_utils.gcodepoint local gsub = m_str_utils.gsub local len = m_str_utils.len local match = m_str_utils.match local sub = m_str_utils.sub local u = m_str_utils.char local upper = m_str_utils.upper

local export = {}

export.vowels_back_unrounded = "aâı" export.vowels_back_rounded = "ouû" export.vowels_front_unrounded = "eiî" export.vowels_front_rounded = "öü"

export.vowels_back = export.vowels_back_unrounded .. export.vowels_back_rounded export.vowels_front = export.vowels_front_unrounded .. export.vowels_front_rounded

export.vowels = export.vowels_back .. export.vowels_front

export.voiceless_consonants = "çfhkptsş" export.voiced_consonants = "bcdgğjlmnrvyz"

export.consonants = export.voiceless_consonants .. export.voiced_consonants

function is_in(c, str) if len(c) ~= 1 then error("argument with bad length: " .. tostring(len(c)) .. " ~= 1") end return find(str, c) ~= nil end

function export.is_vowel(c) return is_in(c, export.vowels) end

function export.is_voiceless_consonant(c) return is_in(c, export.voiceless_consonants) end

function export.is_voiced_consonant(c) return is_in(c, export.voiced_consonants) end

function export.get_last_vowel(str) return match(str, "([" .. export.vowels .. "])[^" .. export.vowels .. "]*$") end

function export.starts_with_vowel(str) if match(str, "^[" .. export.vowels .. "]") then return true else return false end end

function export.starts_with_consonant(str) return not starts_with_vowel(str) end function export.ends_with_vowel(str) if match(str, "[" .. export.vowels .. "]$") then return true else return false end end

function export.ends_with_consonant(str) return not ends_with_vowel(str) end function export.ends_with_voiceless_consonant(str) if match(str, "[" .. export.voiceless_consonants .. "]$") then return true else return false end end

function export.soften(str) str = gsub(str, "ç$", "c") str = gsub(str, "p$", "b") str = gsub(str, "t$", "d") str = gsub(str, "k$", "ğ") return str end

function export.get_2_way_harmony(vowel) if match(vowel, "^[" .. export.vowels_back .. "]$") then return "a" elseif match(vowel, "^[" .. export.vowels_front .. "]$") then return "e" else error("'" .. export.vowel .. "' is not a vowel") end end

function export.get_4_way_harmony(vowel) if match(vowel, "^[" .. export.vowels_back_unrounded .. "]$") then return "ı" elseif match(vowel, "^[" .. export.vowels_back_rounded .. "]$") then return "u" elseif match(vowel, "^[" .. export.vowels_front_unrounded .. "]$") then return "i" elseif match(vowel, "^[" .. export.vowels_front_rounded .. "]$") then return "ü" else error("'" .. export.vowel .. "' is not a vowel") end end

function export.get_ki_harmony(vowel) if match(str, "^[" .. export.vowels_back_unrounded .. export.vowels_back_rounded .. export.vowels_front_unrounded .. "]$") then return "i" elseif match(str, "^[" .. export.vowels_front_rounded .. "]$") then return "ü" else error("'" .. export.vowel .. "' is not a vowel") end end

function export.attach_suffixes(base, suffixes, base_vowel, generate_2_way_aorist, generate_4_way_aorist) local result = base local previous_char = u(codepoint(base, -1)) local previous_vowel = base_vowel or export.get_last_vowel(base) or "i" -- yemek -> yiyor local remaining_suffixes = suffixes for c in gcodepoint(suffixes) do		c = u(c) remaining_suffixes = sub(remaining_suffixes, 2) if c == "R" then -- aorist R			if export.is_vowel(previous_char) then c = "r" else if generate_2_way_aorist and generate_4_way_aorist then ar = export.attach_suffixes(result, "Ar" .. remaining_suffixes, nil, generate_2_way_aorist, generate_4_way_aorist) ir = export.attach_suffixes(result, "Ir" .. remaining_suffixes, nil, generate_2_way_aorist, generate_4_way_aorist) for _, v in ipairs(ir) do						ar[#ar + 1] = v					end return ar				elseif generate_2_way_aorist or generate_4_way_aorist then previous_char = (generate_2_way_aorist and export.get_2_way_harmony or export.get_4_way_harmony)(previous_vowel) previous_vowel = previous_char result = result .. previous_char c = "r" else error("suffixes contain an aorist placeholder after a consonant but no harmony is specified") end end elseif c == "Y" then -- intervocalic Y			c = export.is_vowel(previous_char) and "y" or nil elseif c == "N" then -- intervocalic N			c = export.is_vowel(previous_char) and "n" or nil elseif c == "S" then -- intervocalic S			c = export.is_vowel(previous_char) and "s" or nil elseif c == "J" then -- interconsonantal I			c = export.is_vowel(previous_char) and nil or export.get_4_way_harmony(previous_vowel) elseif c == "D" then -- d/t c = export.is_voiceless_consonant(previous_char) and "t" or "d" elseif c == "A" then -- 2-way c = export.get_2_way_harmony(previous_vowel) elseif c == "I" then -- 4-way c = export.get_4_way_harmony(previous_vowel) end if c ~= nil then if c == upper(c) then error("unrecognized placeholder '" .. c .. "'") end result = result .. c			previous_char = c			if export.is_vowel(c) then previous_vowel = c			end end end return { result } end return export