Jump to content

Module:akk-common

From Wiktionary, the free dictionary


local export = {}

local cuneiforms = mw.loadData("Module:akk-common/data")

function export.assimilate(pattern)
	local replace = {
		["nt"] = "tt",
		["dt"] = "dd",
		["ṭt"] = "ṭṭ",
		["zt"] = "zz",
		["st"] = "ss",
		["ṣt"] = "ṣṣ"
	}
	return replace[pattern] or pattern
end

local to_OB = {
	["pi"] = "pi₂",
	["pe"] = "pe₂",
	["qu"] = "qu₂",
	["qa"] = "qa₂",
	["qi"] = "qi₂",
	["ṭu"] = "ṭu₂"
}
function export.to_long(vowel)
	local table = {
		["a"] = "ā",
		["e"] = "ē",
		["i"] = "ī",
		["u"] = "ū",
	}
	return table[vowel] or vowel
end

function export.to_double_long(vowel)
	local table = {
		["a"] = "â",
		["e"] = "ê",
		["i"] = "î",
		["u"] = "û",
	}
	return table[vowel] or vowel
end

function export.to_short(vowel)
	local table = {
		["ā"] = "a",
		["ē"] = "e",
		["ī"] = "i",
		["ū"] = "u",
		["â"] = "a",
		["ê"] = "e",
		["î"] = "i",
		["û"] = "u",
	}
	return table[vowel] or vowel
end

local function is_vowel(char)
	local table = {
		["ā"] = true,
		["ē"] = true,
		["ī"] = true,
		["ū"] = true,
		["â"] = true,
		["ê"] = true,
		["î"] = true,
		["û"] = true,
		["a"] = true,
		["e"] = true,
		["i"] = true,
		["u"] = true,
	}
	return table[char] ~= nil
end
local Stream = {}

function Stream:new(word)
	local object = setmetatable({}, { __index = self })
	object.index = 0
	object.word = word
	return object
end

function Stream:peek(step)
	return mw.ustring.sub(self.word, self.index + (step or 0), self.index + (step or 0))
end

function Stream:next()
	self.index = self.index + 1
	return self:peek()
end

function Stream:is_vowel(offset)
	return is_vowel(self:peek(offset))
end

function Stream:is_geminate()
	-- VCC or VC$
	local v1 = self:peek(1) == self:peek(2)
	-- CVCC or CVC$
	local v2 = self:peek(2) == self:peek(3)
	if self:is_vowel() then
		return v1 and self:peek(2) ~= ""
	else
		return v2 and self:peek(2) ~= ""
	end
end

function Stream:is_closed()
	local v = {
		self:is_vowel(),
		self:is_vowel(1),
		self:is_vowel(2),
		self:is_vowel(3),
	}
	local e = {
		self:peek() == "",
		self:peek(1) == "",
		self:peek(2) == "",
		self:peek(3) == "",
	}
	-- VCC or VC$
	local v1 = v[1] and not v[2] and (not v[3] or e[3])
	local e1 = not e[1] and not e[2]
	-- CVCC or CVC$
	local v2 = not v[1] and v[2] and not v[3] and (not v[4] or e[4])
	local e2 = not e[1] and not e[2] and not e[3]
	return (v1 and e1) or (v2 and e2)
end

function Stream:syll_phonetic()
	local syll = {}
	local i = #syll
	while self:next() ~= "" do
		i = #syll + 1
		if self:is_closed() then
			syll[i] = self:peek() .. self:next()
			if self:is_vowel() then
				syll[i] = syll[i] .. self:next()
			end
		elseif self:is_vowel() then
			syll[i] = self:peek()
		else
			syll[i] = self:peek() .. self:next()
		end
	end
	return syll
end

-- this function will syllabify an Akkadian word
-- phonetically. It is intended to be used for
-- inflection table modules that will occationally need
-- to do this kind of work. E.G
--		"parasum" => "pa" - "ra" - "sum"
--		"abriqqu" => "ab" - "riq" - "qum"
function export.syllabify_phonetic(word)
	local stream = Stream:new(word)
	return stream:syll_phonetic()
end

function Stream:syll()
	local syll = {}
	local i = #syll
	while self:next() ~= "" do
		i = #syll + 1
		local p = self:peek()
		if i == 1 and (p == "a" or p == "e") and self:is_closed() then
			syll[i] = p
			i = #syll + 1
		end
		if self:is_closed() then
			syll[i] = self:peek() .. self:next()
			if self:is_vowel() then
				syll[i + 1] = self:peek() .. self:next()
			end
		elseif self:is_vowel() then
			syll[i] = self:peek()
		else
			syll[i] = self:peek() .. self:next()
		end
	end
	return syll
end

function export.syllable_is_closed(syll)
	return not export.is_vowel(mw.ustring.sub(syll, #syll))
end

local function syllabify(word)
	if word == "–" or word == "" then
		return { "–" }
	end
	local normalized = ""
	for char in mw.ustring.gmatch(word, ".") do
		normalized = normalized .. export.to_short(char)
	end
	local stream = Stream:new(normalized)
	return stream:syll()
end
-- this function returns a naive transliteration
-- for the word based of the broad transcription.
function export.naive_transliteration(word)
	local translit = nil
	for _, sign in ipairs(syllabify(word)) do
		if translit then
			translit = translit .. "-" .. (to_OB[sign] or sign)
		else
			translit = to_OB[sign] or sign
		end
	end
	translit = mw.ustring.gsub(translit, "tu[-]um", "tum")
	translit = mw.ustring.gsub(translit, "lu[-]um", "lum")
	translit = mw.ustring.gsub(translit, "li[-]im", "lim")
	translit = mw.ustring.gsub(translit, "la[-]am", "lam")
	translit = mw.ustring.gsub(translit, "ti[-]im", "tim")
	translit = mw.ustring.gsub(translit, "ta[-]am", "tam")
	return translit
end

-- This will transform a transcription into cuneiform
function export.from_transliteration(trans)
	local cuneiform = ""
	for sign in mw.ustring.gmatch(trans, "([^-\\. ]+)[-\\.]?") do
		if not cuneiforms[sign] and sign ~= "–" then
			error("no cuneiform sign for " .. sign)
		end
		cuneiform = cuneiform .. (cuneiforms[sign] or sign)
	end
	return cuneiform
end

function export.from_transcription(word)
	if word == "–" then return word end
	local trans = export.naive_transliteration(word)
	return export.from_transliteration(trans)
end

export.is_vowel = is_vowel

return export