Module:sandbox/sa-pronunc

Hello, you have come here looking for the meaning of the word Module:sandbox/sa-pronunc. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:sandbox/sa-pronunc, but we will also tell you about its etymology, its characteristics and you will know how to say Module:sandbox/sa-pronunc in singular and plural. Everything you need to know about the word Module:sandbox/sa-pronunc you have here. The definition of the word Module:sandbox/sa-pronunc will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:sandbox/sa-pronunc, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.

This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local export = {}

local u = mw.ustring.char
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local find = mw.ustring.find

local ACUTE     = u(0x0301)
local COARTIC   = u(0x0361)
local DENTAL    = u(0x032A)
local FLAP      = u(0x0306)
local NORELEASE = u(0x031A)
local SYLLABIC  = u(0x0329)
local NASAL     = u(0x0303)

local udatta = "/"
local anudatta = "_"
local anudattara = "="
local lis = "\\" --long independent svarita
local sis = "|" --short independent svarita
local ds = "`" --dependent svarita
local long_kampa = "^"
local short_kampa = "\*"

local accent_list = udatta .. anudatta .. anudattara .. lis .. sis .. ds .. long_kampa .. short_kampa
local accent = ""

local m_IPA = require("Module:IPA")
local lang = require("Module:languages").getByCode("sa")
local m_a = require("Module:accent qualifier")
local m_sa_translit = require("Module:sa-utilities/translit")
local m_str = require("Module:string")

local consonants = {
	 = "k",  = "ɡ",  = "kʰ",  = "ɡʱ",  = "ŋ",
	 = "t͡ɕ",  = "d͡ʑ",  = "t͡ɕʰ",  = "d͡ʑʱ",  = "ɲ",
	 = "t̪",  = "d̪",  = "t̪ʰ",  = "d̪ʱ",  = "n̪",
	 = "ʈ",  = "ɖ",  = "ʈʰ",  = "ɖʱ",  = "ɳ",
	 = "p",  = "b",  = "pʰ",  = "bʱ",  = "m",
	 = "j",  = "ɽ",  = "l̪",  = "ʋ",  = "ɭ̆",  = "ɭ̆ʱ",
	 = "ɕ",  = "ʂ",  = "s̪",  = "ɦ",
}

local diacritics = {
	 = "ɑː",  = "i",  = "iː",  = "u",  = "uː",  = "r̩",  = "r̩ː",
	 = "l̩",  = "l̩ː",  = "ɐj",  = "ɑːj",  = "ɐw",  = "ɑːw",  = "",
}

local vowel_list = {
	 = true,  = true,  = true,  = true,  = true,  = true,  = true,  = true,
	 = true,  = true,  = true,  = true,  = true,  = true,
}

local stop_list = {
	 = true,  = true,  = true,  = true,
	 = true,  = true,  = true,  = true,
	 = true,  = true,  = true,  = true,
	 = true,  = true,  = true,  = true,
	 = true,  = true,  = true,  = true,
}

local consonant_sonority = {
	-- voiceless stops and affricates
	 = 1,  = 1,
	 = 1,  = 1,
	 = 1,  = 1,
	 = 1,  = 1,
	 = 1,  = 1,
	-- voiceless fricatives
	 = 2,  = 2,  = 2,  = 2,  = 2,  = 2,
	-- voiced stops and affricates
	 = 3,  = 3,
	 = 3,  = 3,
	 = 3,  = 3,
	 = 3,  = 3,
	 = 3,  = 3,
	-- voiced fricatives
	 = 4,
	-- nasals
	 = 5,  = 5,  = 5,  = 5,  = 5,  = 5,  = 5,
	-- flaps
	 = 6,
	-- laterals
	 = 7,  = 7,  = 7,
	-- glides
	 = 8,  = 8,
}

local tt = {
	-- vowels
	 = "ɐ",  = "ɑː",  = "i",  = "iː",  = "u",  = "uː",  = "r̩",  = "r̩ː",
	 = "l̩",  = "l̩ː",  = "ɐj",  = "ɑːj",  = "ɐw",  = "ɑːw",
	-- visarga
	 = "h",
	-- chandrabindu
	 = "m̐",
	-- anusvara
	 = "ṃ",
	-- avagraha
	 = "",
	--Vedic extensions
	 = "x",  = "ɸ",
}

local accent_vowel = {
	 = "ɐ́",  = "ɑ́ː",  = "í",  = "íː",  = "ú",  = "úː",  = "ŕ̩",  = "ŕ̩ː",
	 = "ĺ̩",  = "ĺ̩ː",  = "ɐ́j",  = "ɑ́ːj",  = "ɐ́w",  = "ɑ́ːw",
}

local function shift_to_codas(syllables)
	-- shift codas to previous syllable using the Weerasinghe-Wasala-Gamage method
	local to_move = 0
	for i, syll in ipairs(syllables) do
		if i == 1 then
			-- no need to shift to coda if in the first syllable
		elseif #syll < 3 then
			-- coda movement only needed for onset clusters of 2 or more
		elseif #syll == 3 then
			-- V.CCV => VC.CV
			to_move = 1
		elseif #syll == 4 then
			if syll == "ɽ" or syll == "j" or (stop_list] and stop_list]) then
				-- V.CCrV or V.CCyV => VC.CrV or VC.CyV
				-- if the first two consonants are stops, VC.CCV
				to_move = 1
			else
				-- V.CCCV => VCC.CV
				to_move = 2
			end
		else
			-- 4 consonants or more
			if syll == "ɽ" or syll == "j" then
				to_move = #syll - 3
			else
				-- find index of consonant of least sonority
				to_move = #syll - 1
				local min_son = consonant_sonority]
				for i = (#syll - 1), 1, -1 do
					if consonant_sonority] < min_son then
						to_move = i
						min_son = consonant_sonority]
					end
				end
			end
		end
		
		while to_move > 0 do
			table.insert(syllables, table.remove(syllables, 1))
			to_move = to_move - 1
		end
	end
	return syllables
end

local function syllabify(remainder, accent)
	local syllables = {}
	local syll = {}
	
	while #remainder > 0 do
		local phoneme = table.remove(remainder, 1)
		
		if vowel_list then
			table.insert(syll, phoneme)
			table.insert(syllables, syll)
			syll = {}
		else
			table.insert(syll, phoneme)
		end
	end
	-- store whatever consonants remain
	local final_cons = syll
	
	-- Vedic pitch accent
	if accent ~= nil and accent <= #syllables then
		syll = syllables
		syllables = accent_vowel]
	end
	
	syllables = shift_to_codas(syllables)
	
	local short_vowel_patt = "^" .. SYLLABIC .. "?" .. ACUTE .. "?$"
	
	-- Classic stress accent
	local num_sylls = #syllables
	if num_sylls == 2 then
		table.insert(syllables, 1, 'ˈ')
	elseif num_sylls == 3 then
		-- if the final segment of the second syllable is not a short vowel, stress the second syllable
		if mw.ustring.match(syllables], short_vowel_patt) == nil then
			table.insert(syllables, 1, 'ˈ')
			-- else stress the third
		else
			table.insert(syllables, 1, 'ˈ')
		end
	elseif num_sylls >= 4 then
		if mw.ustring.match(syllables], short_vowel_patt) == nil then
			table.insert(syllables, 1, 'ˈ')
		elseif mw.ustring.match(syllables], short_vowel_patt) == nil then
			table.insert(syllables, 1, 'ˈ')
		else
			table.insert(syllables, 1, 'ˈ')
		end
	end
	
	-- If there are phonemes left, then the word ends in a consonant
	-- Add them to the last syllable
	for _, phoneme in ipairs(final_cons) do
		table.insert(syllables, phoneme)
	end
	
	for i, _ in ipairs(syllables) do
		syllables = table.concat(syllables, "")
	end
	
	return table.concat(syllables, ".")
end

local anu_to_nasals = {
	 = "ŋ",  = "ŋ",
	 = "ɲ",  = "ɲ",
	 = "n̪",  = "n̪",
	 = "ɳ",  = "ɳ",
	 = "m",  = "m",
}

local function anusvara(text)
	text = gsub(text, "ṃ$", "m")
	text = gsub(
		text,
		"ṃ(?)()(?)(?)",
		function(div, cons, mark, fric)
			return anu_to_nasals .. div .. cons .. mark .. fric
		end
	)
	text = gsub(
		text,
		"()(" .. SYLLABIC .. "?)(" .. ACUTE .. "?)(ː?)(?)ṃ",
		"%1%2" .. NASAL .. "%3%4%5"
	)
	return text
end

local function convert_word(word, accent)
	local chars = {}
	local t = {}
	
	gsub(word, ".", function(c) table.insert(chars, c) end)
	
	for i, c in ipairs(chars) do
		if consonants then
			table.insert(t, consonants)
			if not diacritics] then
				table.insert(t, "ɐ")
			end
		elseif c == "्" then
			-- do nothing
		elseif diacritics then
			table.insert(t, diacritics)
		elseif tt then
			table.insert(t, tt)
		end
	end
	
	word = syllabify(t, accent)
	
	word = gsub(word, "%.ˈ", "ˈ")
	
	-- chandrabindu
	word = gsub(
		word,
		"()(" .. SYLLABIC .. "?)(" .. ACUTE .. "?)(ː?)(?)m̐",
		"%1%2" .. NASAL .. "%3%4%5"
	)
	return word
end

local function convert_words(words, accents)
	local result = {}
	
	local word_num = 1
	for word in mw.text.gsplit(words, " ") do
		table.insert(result, convert_word(word, accents))
		word_num = word_num + 1
	end
	
	text = table.concat(result, " ")
	
	return text
end

local function phon_procs(text)
	-- Anusvāra
	text = anusvara(text)
	
	return text
end

local function abhinidhana_phonemic(text)
	--de-aspirate and de-affricate before stops
	text = gsub(
		text,
		"()(" .. DENTAL .. "?)?(?)()",
		"%1%2%3%4"
	)
	text = gsub(
		text,
		"()" .. COARTIC .. "?(?)()",
		"%1%2%3"
	)
	return text
end

local function abhinidhana_phonetic(text)
	text = gsub(
		text,
		"()(" .. DENTAL .. "?)(?)()",
		"%1%2" .. NORELEASE .. "%3%4"
	)
	return text
end

local superscript = {
	 = "ᵄ",
	 = "ᵅ",
	 = "ᵉ",
	 = "ᵒ",
	 = "ⁱ",
	 = "ᵘ",
}

local function make_dialects(text)
	local dialects = {}
	
	text = abhinidhana_phonemic(text)
	
	-- Rigvedic Sanskrit
	local rig_phnm = text
	rig_phnm = gsub(rig_phnm, "^ˈ", "")
	rig_phnm = gsub(rig_phnm, "ˈ", ".")
	rig_phnm = gsub(rig_phnm, " %.", " ")
	
	local rig_phnt = abhinidhana_phonetic(rig_phnm)
	-- visarga alternation
	rig_phnt = gsub(rig_phnt, "h(?)()", "ɸ%1%2")
	rig_phnt = gsub(rig_phnt, "h(?)()", "x%1%2")
	-- nasalized semivowels
	rig_phnt = gsub(
		rig_phnt,
		"()(" .. DENTAL .. "?)(?)()(?)(ʱ?)",
		"%4%5" .. NASAL .. "%3%4%5%6"
	)
	
	dialects = {
		label = "Vedic",
		phonemic = rig_phnm,
		phonetic = rig_phnt,
	}
	
	-- Classical Sanskrit
	local cla_phnm = text
	cla_phnm = gsub(cla_phnm, "", { = "e",  = "o",  = "i",  = "u",  = "",  = "r"})
	cla_phnm = gsub(cla_phnm, "ɐ(" .. NASAL .. "?)j", "e%1ː")
	cla_phnm = gsub(cla_phnm, "ɐ(" .. NASAL .. "?)w", "o%1ː")
	cla_phnm = gsub(cla_phnm, "ɑ(" .. NASAL .. "?)ː()", "ɑ%1%2")
	
	local cla_phnt = abhinidhana_phonetic(cla_phnm)
	-- cla_pron = gsub(cla_pron, "r̩(" .. NASAL .. "?)(" .. ACUTE .. "?)(ː?)", "ɽi%1%2%3")
	-- cla_pron = gsub(cla_pron, "l̩(" .. NASAL .. "?)(" .. ACUTE .. "?)(ː?)", "l̪i%1%2%3")
	
	cla_phnt = gsub(
		cla_phnt,
		"()(" .. NASAL .. "?)(ː?)(?)h$",
		function (vow, nas, length, glide)
			return vow .. nas .. length .. glide .. "h" .. superscript
		end
	)
	cla_phnt = gsub(
		cla_phnt,
		"()(" .. NASAL .. "?)(ː?)(?)h ",
		function (vow, nas, length, glide)
			return vow .. nas .. length .. glide .. "h" .. superscript .. " "
		end
	)
	
	dialects = {
		label = "Classical Sanskrit",
		phonemic = cla_phnm,
		phonetic = cla_phnt,
	}
	
	return dialects
end

local function make_table(dialects, novedic)
	local dial_types = {'rig', 'cla'}
	
	if novedic then
		table.remove(dial_types, 1)
	end
	
	if #dial_types == 1 then
		local dial = dial_types
		local IPA_args = {{pron = '/' .. dialects.phonemic .. '/'}}
		if dialects.phonemic ~= dialects.phonetic then
			table.insert(IPA_args, {pron = '.phonetic .. ']'})
		end
		return table.concat{
			'\n* ',
			m_a.format_qualifiers(lang, {dialects.label}),
			' ',
			m_IPA.format_IPA_full { lang = lang, items = IPA_args },
		}
	else
		
		local inline_args = {{pron = '/' .. dialects.cla.phonemic .. '/'}}
		
		if dialects.cla.phonemic ~= dialects.cla.phonetic then
			table.insert(inline_args, {pron = ''})
		end
		
		local inline = table.concat{
			'<div class="vsShow" style="display:none">',
			'\n* ',
			m_IPA.format_IPA_full { lang = lang, items = inline_args },
			'</div>',
		}
		
		local full = {}
		for _, dial in ipairs(dial_types) do
			local full_args = {{pron = '/' .. dialects.phonemic .. '/'}}
			if dialects.phonemic ~= dialects.phonetic then
				table.insert(full_args, {pron = '.phonetic ..']'})
			end
			table.insert(full, table.concat{
				'\n* ',
				m_a.format_qualifiers(lang, {dialects.label}),
				' ',
				m_IPA.format_IPA_full { lang = lang, items = full_args },
			})
		end
		
		return table.concat{
			inline,
			table.concat(full, ""),
		}
	end
end


local consonant_list = "kKgGNcCjJYwWqQRtTdDnpPbBmyrlLvSzshMHZV'"
local consonant = ""
local vowel_list = "aAiIuUfFxXeEoO"
local vowel = ""
local not_vowel = ""

local short_vowel_cat = ""
local long_vowel_cat = ""

local function mark_accent(SLP)
	local i, syls = 1, {}

	for c, v, a in gmatch(SLP, "(" .. consonant .. "*)(" .. vowel .. ")(" .. accent .. "?)") do
		table.insert(syls, {c, v, a})
		i = i + 1
	end
	if match(SLP, consonant .. "+$") then
		table.insert(syls, {match(SLP, consonant .. "+$")})
	end
	
--	SLP = gsub(SLP, "(" .. short_vowel_cat .. ")" .. lis, "%1" .. sis) -- long to short independent svarita
--	SLP = gsub(SLP, "(" .. vowel .. ")(" .. vowel .. udatta .. ")", "%1" .. anudatta .. "%2")
--	SLP = gsub(
--		SLP,
--		"(" .. vowel .. udatta .. not_vowel .. "*" .. vowel .. ")%f",
--		"%1" .. ds
--	) -- dependent svarita
--	return SLP
	
	local out ={}
	for i, ret in ipairs(syls) do
		local foo = {}
		if ret then
			table.insert(foo, ret)
		end
		if ret then
			table.insert(foo, ret)
		end
		if ret then
			table.insert(foo, ret)
		end
		table.insert(out, i .. ": " .. table.concat(foo, ","))
	end
	return table.concat(out, "<br/>")
end

function export.show(frame)
	local params = {
		 = {default = mw.title.getCurrentTitle().text},
		novedic = {type = 'boolean'}
	}
	local args = require("Module:parameters").process(frame:getParent().args, params)
	local SLP = m_sa_translit.detect_to_SLP(args)
	local accented = match(SLP, "") and true or false
	if accented then
		SLP = mark_accent(SLP)
	end
	return SLP
end

function export.show1(frame)
	local params = {
		 = {alias_of = 'w'},
		w = {default = mw.title.getCurrentTitle().text},
		a = {list = true, allow_holes = true, type = 'number'},
		novedic = {type = 'boolean'}
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local text = convert_words(args.w, args.a)
	
	text = phon_procs(text)
	
	local dialects = make_dialects(text)
	
	return make_table(dialects, args.novedic)
end

return export