Module:tr-harmony

From Wiktionary, the free dictionary
Jump to navigation Jump to search
This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

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