Module:rad-IPA: Difference between revisions

Added phonetic option
(Added stress prediction)
(Added phonetic option)
Line 130: Line 130:
}
}


-- ALL PHONES --
local valid_phone = {
local valid_phone = {
["a"] = true, ["aː"] = true, ["aːː"] = true, ["æː"] = true, ["ai"] = true,
["a"] = true, ["aː"] = true, ["aːː"] = true, ["æː"] = true, ["ai"] = true,
Line 144: Line 143:
["uːː"] = true, ["uːo"] = true, ["ua"] = true, ["uo"] = true, ["v"] = true,
["uːː"] = true, ["uːo"] = true, ["ua"] = true, ["uo"] = true, ["v"] = true,
["w"] = true, ["y"] = true, ["z"] = true, ["ʒ"] = true, ["θ"] = true,  
["w"] = true, ["y"] = true, ["z"] = true, ["ʒ"] = true, ["θ"] = true,  
-- allophones --
["x"] = true, ["ʝ"] = true,
}
}
local valid_phone_temp = {"iːj", "uːj", "yːj", "ù", "ū", "ĵ"}
local valid_phone_temp = {"iːj", "uːj", "yːj", "ù", "ū", "ĵ"}
Line 159: Line 162:
["t"] = true, ["ts"] = true, ["tʃ"] = true, ["v"] = true, ["w"] = true,
["t"] = true, ["ts"] = true, ["tʃ"] = true, ["v"] = true, ["w"] = true,
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
-- allophones --
["x"] = true, ["ʝ"] = true,
}
}
local consonant_temp = {"ĵ"}
local consonant_temp = {"ĵ"}
Line 171: Line 178:
["t"] = true, ["ts"] = true, ["tʃ"] = true, ["v"] = true,
["t"] = true, ["ts"] = true, ["tʃ"] = true, ["v"] = true,
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
-- allophones --
["x"] = true,
}
}


Line 187: Line 198:
["t"] = "t", ["ts"] = "ts", ["tʃ"] = "tʃ", ["v"] = "f",
["t"] = "t", ["ts"] = "ts", ["tʃ"] = "tʃ", ["v"] = "f",
["z"] = "s", ["ʒ"] = "ʃ", ["θ"] = "θ",  
["z"] = "s", ["ʒ"] = "ʃ", ["θ"] = "θ",  
-- allophones --
["x"] = "x",
}
}
Line 195: Line 210:
["t"] = "d", ["ts"] = "dz", ["tʃ"] = "dʒ", ["v"] = "v",
["t"] = "d", ["ts"] = "dz", ["tʃ"] = "dʒ", ["v"] = "v",
["z"] = "z", ["ʒ"] = "ʒ", ["θ"] = "ð",  
["z"] = "z", ["ʒ"] = "ʒ", ["θ"] = "ð",  
-- allophones --
["x"] = "ɣ",
}
}
Line 272: Line 291:
["t"] = true, ["d"] = true,
["t"] = true, ["d"] = true,
-- allophones --
["x"] = true,
}
}


Line 283: Line 306:
["s"] = true, ["ʃ"] = true, ["z"] = true, ["ʒ"] = true,  
["s"] = true, ["ʃ"] = true, ["z"] = true, ["ʒ"] = true,  
-- allophones --
["x"] = true,
}
}


Line 291: Line 318:
["t"] = true, ["ts"] = true, ["tʃ"] = true,
["t"] = true, ["ts"] = true, ["tʃ"] = true,
["z"] = true, ["ʒ"] = true, ["θ"] = true,
["z"] = true, ["ʒ"] = true, ["θ"] = true,
-- allophones --
["x"] = true, ["ʝ"] = true,
}
}


Line 299: Line 330:
["v"] = true,
["v"] = true,
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
["z"] = true, ["ʒ"] = true, ["θ"] = true,  
-- allophones --
["x"] = true,
}
}
local CN = continuant
local CN = continuant
Line 595: Line 630:
end
end


function resolve_consonants(phones, hj_dv)
function resolve_consonants(phones, hj_dv, phon)
local working_phones = phones
local working_phones = phones
mw.log("————— BEGINNING CONSONANT RESOLUTION —————")
mw.log("————— BEGINNING CONSONANT RESOLUTION —————")
Line 644: Line 679:
-- Resolution of hjádvanþs --
-- Resolution of hjádvanþs --
if hj_dv == false then
if not hj_dv then
if p_current == "ç" then
if p_current == "ç" then
mw.log("hjádvanþs = false:")
mw.log("hj = false:")
p_Convert("ʃ")
p_Convert("ʃ")
elseif p_current == "j" and (boundary[p_prev] or p_prev == nil) and consonant[p_next] then
elseif p_current == "j" and (boundary[p_prev] or p_prev == nil) and consonant[p_next] then
mw.log("hjádvanþs = false:")
mw.log("hj = false:")
p_Convert("ʒ")
p_Convert("ʒ")
end
end
Line 686: Line 721:
mw.log("[d][ʃ] → [dʒ] in position " .. i .. ".")
mw.log("[d][ʃ] → [dʒ] in position " .. i .. ".")
end
end
end
end
Line 729: Line 765:
mw.log("No cluster found.")
mw.log("No cluster found.")
end
end
end
-- Progressive voicing assimilation of Cv --
if p_current == "v" and not obstruent_voiced[p_prev] then
p_Resolve("f")
mw.log("[" .. p_current .. "][v] → [" .. p_current .. "][f] in position " .. i .. ".")
end
end
Line 736: Line 779:
p_RemoveNext()
p_RemoveNext()
mw.log("Geminate [" .. p_current .. "] removed in final position at position " .. i .. ".")
mw.log("Geminate [" .. p_current .. "] removed in final position at position " .. i .. ".")
end
-- PHONETIC RESOLUTION --
if phon == true then
if p_current == "h" and not vowel[p_next] then
mw.log("phon = true:")
p_Resolve("x")
elseif p_current == "h" and p_next == "j" then
mw.log("phon = true:")
p_Resolve("ç")
p_RemoveNext()
end
end
end
Line 868: Line 923:
elseif Cr[p_current] and p_next == "r" then -- C | *C*r …
elseif Cr[p_current] and p_next == "r" then -- C | *C*r …
JV(true) -- C | *C*r(J)V
JV(true) -- C | *C*r(J)V
elseif Cv[p_current] and p_next == "v" then -- C | *C*v …
elseif Cv[p_current] and (p_next == "v" or p_next == "f") then -- C | *C*v …
JV(true) -- C | *C*v(J)V
JV(true) -- C | *C*v(J)V
elseif CN[p_current] and nasal[p_next] then -- C | *C*N …
elseif CN[p_current] and nasal[p_next] then -- C | *C*N …
Line 1,145: Line 1,200:
end
end
end
end
boundary["·"] = false
return output
return output
Line 1,153: Line 1,206:
function resolve_syllables(syllables)
function resolve_syllables(syllables)


end
mw.log("————— RESOLVING SYLLABLES —————")
 
function export.generate(frame)
local args = getArgs(frame)
local outputIPA = generate_IPA(args[1])
local hj = args[2] or false
if hj == "false" then
hj = false
end
outputIPA = resolve_vowels(outputIPA)
if #syllables > 1 then
outputIPA = resolve_consonants(outputIPA, hj)
outputIPA = get_syllables(outputIPA)
outputIPA = tag_syllables(outputIPA)
outputIPA = get_stress(outputIPA)
local output = ""
for i = 1, #syllables - 1 do
for i = 1, #outputIPA do
local onset = ""
local working_cluster = {}
local coda = ""
local stress=""
if (syllables[i]["coda"] or syllables[i+1]["onset"]) and syllables[i+1] and type(syllables[i]) == "table" and type(syllables[i+1]) == "table" then
-- mw.log("Resolving clusters in syllables " .. i .. " and " .. i + 1 .. ".")
if type(outputIPA[i]) == "table" then
-- get intersyllabic clusters --
if syllables[i]["coda"] then
for j = 1, #syllables[i]["coda"] do
table.insert(working_cluster, syllables[i]["coda"][j])
end
end
if syllables[i+1]["onset"] then
for j = 1, #syllables[i+1]["onset"] do
table.insert(working_cluster, syllables[i+1]["onset"][j])
end
end
-- mw.log("Cluster to be resolved: " .. table.concat(working_cluster))
local p_last = working_cluster[#working_cluster]
local p_last2 = working_cluster[#working_cluster-1]
local p_last3 = working_cluster[#working_cluster-2]
local p_last4 = working_cluster[#working_cluster-3]
local new_coda = {}
local new_onset = {}
if outputIPA[i]["onset"] then
-- splits the current cluster into new coda and new onset and re-assigns them to the syllables --
onset = table.concat(outputIPA[i]["onset"])
end
if outputIPA[i]["coda"] then
local function split(point)
coda = table.concat(outputIPA[i]["coda"])
if point < 1 or point > 3 or point == nil then
error("split() must take integer values between 1 to 4 inclusive")
end
for j = #working_cluster + 1 - point, #working_cluster do
table.insert(new_onset, working_cluster[j])
end
if #working_cluster - point > 0 then
for j = 1, #working_cluster - point do
table.insert(new_coda, working_cluster[j])
end
end
mw.log("σ" .. i .. " | σ" .. i+1 .. " : … " .. table.concat(new_coda) .. " | " .. table.concat(new_onset) .. " …")
syllables[i]["coda"] = new_coda
syllables[i+1]["onset"] = new_onset
end
end
if outputIPA[i]["stress"] then
-- determine syllable boundary --
stress = "ˈ"
end
if outputIPA[i]["stress2"] then
if glide[p_last] and nasal[p_last2] and CN[p_last3] and p_last4 then -- C|CNJ
stress = "ˌ"
split(3)
elseif nasal[p_last] and CN[p_last2] and p_last3 then -- C|CN
split(2)
elseif glide[p_last] and p_last2 == "r" and Cr[p_last3] and p_last4 then -- C|CrJ
split(3)
elseif p_last == "r" and Cr[p_last2] and p_last3 then -- C|Cr
split(2)
elseif glide[p_last] and p_last2 == "l" and Cl[p_last3] and p_last4 then -- C|ClJ
split(3)
elseif p_last == "l" and Cl[p_last2] and p_last3 then -- C|Cl
split(2)
elseif glide[p_last] and (p_last2 == "v" or p_last2 == "f") and Cv[p_last3] and p_last4 then -- C|CvJ
split(3)
elseif (p_last == "v" or p_last == "f") and Cv[p_last2] and p_last3 then -- C|Cv
split(2)
elseif glide[p_last] and p_last2 then -- C|CJ
split(2)
else -- C|C
split(1)
end
end
output = output .. stress .. onset .. outputIPA[i]["nucleus"] .. coda
else
output = output .. outputIPA[i]
end
end
end
end
return syllables
end
function syllables_to_string(syllables)
local output = ""
for i = 1, #syllables do
local onset = ""
local coda = ""
local stress=""
if type(syllables[i]) == "table" then
if syllables[i]["onset"] then
onset = table.concat(syllables[i]["onset"])
end
if syllables[i]["coda"] then
coda = table.concat(syllables[i]["coda"])
end
if syllables[i]["stress"] then
stress = "ˈ"
end
if syllables[i]["stress2"] then
stress = "ˌ"
end
output = output .. stress .. onset .. syllables[i]["nucleus"] .. coda
else
output = output .. syllables[i]
end
end
end
return output
mw.log(output)
end
return output
 
function export.generate(frame)
local args = getArgs(frame)
local outputIPA = generate_IPA(args[1])
local parameters = {}
local p = 2
mw.log("——— Parameters ———")
while args[p] do
parameters[args[p]] = true
mw.log(args[p] .. " = true")
p = p + 1
end
outputIPA = resolve_vowels(outputIPA)
outputIPA = resolve_consonants(outputIPA, parameters["hj"], parameters["phon"])
outputIPA = get_syllables(outputIPA)
outputIPA = tag_syllables(outputIPA)
outputIPA = get_stress(outputIPA)
outputIPA = resolve_syllables(outputIPA)
outputIPA = syllables_to_string(outputIPA)
mw.log(outputIPA)
return outputIPA
end
end