Module:User:AmazingJus/ga

From Wiktionary, the free dictionary
Jump to navigation Jump to search

170 of 218 tests failed. (refresh)

TextExpectedActual
test_pron:
Failedacadamhˈakəd̪ˠəwakad̪ˠaw
Failedadhairtəiɾˠtʲəiɾʲtʲ
Passedaghaidhəijəij
Failedaidheəiajɛ
Failedaidhleannˈəilʲən̪ˠajlʲanˠnˠ
Failedaigheəiajɛ
Failedaighneasəinʲəsˠajnʲasˠ
Failedamhantarˈəun̪ˠt̪ˠəɾˠə̃ũnˠt̪ˠaɾˠ
Failedbacaighˈbˠakiːbˠakaj
Passedbodhairbˠəuɾʲbˠəuɾʲ
Passedbodharbˠəuɾˠbˠəuɾˠ
Failedbodhránˈbˠəuɾˠɑːnˠbˠɔɣɾˠɑːnˠ
Passedboghabˠəubˠəu
Failedbriseadhˈbʲɾʲɪʃəbʲɾʲɪʃaɣ
Passedbroghaisbˠɾˠəuʃbˠɾˠəuʃ
Failedcaigheankəinˠkajanˠ
Failedciumhaiscuːʃcũːʃ
Failedcleachtaidhˈclʲaxt̪ˠiːclʲaxt̪ˠaj
Failedcoilighˈkɛlʲiːkɔɪlʲɪj
Failedcomharkoːɾˠkõːɾˠ
Failedcreideamhˈcɾʲɛdʲəwcɾʲɛdʲaw
Failedcumhraˈkuːɾˠəkʊwɾˠa
Faileddeaghad̪ˠəidʲəi
Faileddoghraˈd̪ˠəuɾˠəd̪ˠɔɣɾˠa
Faileddomhaind̪ˠoːnʲd̪ˠõːnʲ
FailedDomhnachˈd̪ˠoːnˠəxd̪ˠɔwnˠax
Faileddubhd̪ˠʊwd̪ˠʊ(w)
Passedeidheannəin̪ˠəin̪ˠ
FailedFeabhraˈfʲəuɾˠəfʲawɾˠa
Passedfeidhmfʲəimʲfʲəimʲ
Passedfeighilfʲəilʲfʲəilʲ
Failedfeighlíˈfʲəilʲiːfʲəilʲiː
Failedguighgiːɡɪj
Passedleabhairl̠ʲəuɾʲl̠ʲəuɾʲ
Passedleigheasl̠ʲəisˠl̠ʲəisˠ
Failedlighl̠ʲiːl̠ʲɪj
Passedlobhairl̪ˠəuɾʲl̪ˠəuɾʲ
Passedlobharl̪ˠəuɾˠl̪ˠəuɾˠ
Failedlobhraˈl̪ˠəuɾˠəl̪ˠɔwɾˠa
Passedloighicl̪ˠəicl̪ˠəic
Failedmargadhˈmˠaɾˠəɡəmˠaɾˠɡaɣ
Failedmeadhgmʲəiɡmʲaɣɡ
Passedmeidhirmʲəiɾʲmʲəiɾʲ
FailedMumhanˈmˠuːnˠmˠũːnˠ
Failedoidheannaəin̪ˠəəin̪ˠa
Failedoidhreəiɾʲəəiɾʲɛ
Passedoigheannəin̪ˠəin̪ˠ
Failedoighreachˈəiɾʲəxəiɾʲax
Failedramhraighˈɾˠəuɾˠiːɾˠawɾˠaj
Failedsabhallsˠəul̪ˠsˠəulˠlˠ
Failedsaghsannaˈsˠəisˠən̪ˠəsˠaɣsˠan̪ˠa
FailedSamhainsˠəunʲsˠə̃ũnʲ
Failedtiubhtʲʊwtʲʊ(w)
Failedtuillidhˈt̪ˠɪl̠ʲiːt̪ˠɪlʲlʲɪj
Failedaguisínˈaɡəʃiːnʲaɡɪʃiːnʲ
Failedagusˈaɡəsˠaɡʊsˠ
Failedairdeɑːɾˠdʲəaɾʲdʲɛ
Failedairneɑːɾˠn̠ʲəaɾʲnʲɛ
Failedamɑːmˠamˠ
Failedannɑːn̪ˠanˠnˠ
Failedanoisəˈnˠɪʃanˠɔɪʃ
Failedanseo (respelled anseò)ənʲˈʃɔanˠsˠɔ
Failedarmónachˈaɾˠəmˠoːnəxaɾˠmˠoːnˠax
Failedbaileˈbˠalʲəbˠalʲɛ
Failedbailiúˈbˠalʲuːbˠalʲuː
Failedbarrbˠɑːɾˠbˠaɾˠ
Passedbeanbʲanˠbʲanˠ
Failedbeannaíonnˈbʲan̪ˠiːnˠbʲanˠnˠiːn̪ˠ
Failedbearnaˈbʲɑːɾˠn̪ˠəbʲaɾˠnˠa
Passedbiorbʲɪɾˠbʲɪɾˠ
Failedbiánˈbʲiːɑːnˠbʲɪɑːnˠ
Passedbliainbʲlʲiənʲbʲlʲiənʲ
Failedboichtbˠɔxtʲbˠɔɪçtʲ
Failedbordbˠoːɾˠd̪ˠbˠɔɾˠd̪ˠ
Failedbriogáidˈbʲɾʲʊɡɑːdʲbʲɾʲʊɡɑːdʲ
Failedbuidéalˈbˠɪdʲeːlˠbˠɪdʲeːlˠ
Failedburlaˈbˠuːɾˠl̪ˠəbˠʊɾˠlˠa
Passedbus (respelled bùs)bˠɔsˠbˠɔsˠ
Passedbuíghbˠiːjbˠiːj
Passedbuíonbˠiːnˠbˠiːnˠ
Failedbádóirˈbˠɑːd̪ˠoːrʲbˠɑːd̪ˠoːɾʲ
Passedbánbˠɑːnˠbˠɑːnˠ
Failedcaillteˈkɑːl̠ʲtʲəkalʲlʲtʲɛ
Failedcailínˈkalʲiːnʲkalʲiːnʲ
Failedcaisleáinˈkaʃl̠ʲɑːnʲkaʃlʲaːnʲ
Failedcaisleánˈkaʃl̠ʲɑːnˠkaʃlʲaːnˠ
Failedcarnánˈkɑːɾˠn̪ˠɑːnˠkaɾˠnˠɑːnˠ
Failedceardaícɑːɾˠd̪ˠiːcaɾˠd̪ˠiː
Failedceirdceːɾˠdʲcɛɾʲdʲ
Failedceirnínˈceːɾˠnʲiːnʲcɛɾʲnʲiːnʲ
Passedceistcɛʃtʲcɛʃtʲ
Passedceolcoːlˠcoːlˠ
Failedcillciːl̠ʲcɪl̠ʲ
Failedcinnteˈciːn̠ʲtʲəcɪn̠ʲtʲɛ
Passedcioncɪnˠcɪnˠ
Passedciúincuːnʲcuːnʲ
Failedcloicheˈklˠɛçəklˠɔɪçɛ
Failedcloisfidhˈkl̪ˠɔʃiːklˠɔɪʃfʲɪj
Passedclub (respelled clùb)klˠɔbˠklˠɔbˠ
Failedcnoicknˠɪcknˠɔɪc
Failedcoillteˈkəil̠ʲtʲəkɔɪlʲlʲtʲɛ
Failedcoimeádˈkɪmʲɑːd̪ˠkɔɪmʲaːd̪ˠ
Failedcoirnéalˈkoːɾˠn̠ʲeːlˠkɔɪɾʲnʲeːlˠ
Failedcoiskɔʃkɔɪʃ
Failedconradhˈkʊnˠɾˠəkɔnˠɾˠaɣ
Failedcosúilˈkɔsˠuːlʲkɔsˠuːlʲ
Failedcothromˈkɔɾˠəmˠkɔhɾˠɔmˠ
Failedcrainnkɾˠɑːn̠ʲkɾˠan̠ʲ
Failedcreimeadhˈcɾʲɪmʲəcɾʲɛmʲaɣ
Failedcromógˈkɾˠʊmˠoːɡkɾˠɔmˠoːɡ
Failedcroíleacánˈkɾˠiːlʲəkɑːnˠkɾˠiːlʲakɑːnˠ
Failedcroíonnaˈkɾˠiːn̪ˠəkɾˠiːnˠnˠa
Failedcruógˈkɾˠuːoːɡkɾˠuːoːɡ
Faileddeoch (respelled deòch)dʲɔx/dʲɔx
FailedDiarmaiddʲiərmədʲdʲiəɾˠmˠadʲ
Faileddoirseˈd̪ɔɾˠʃəd̪ˠɔɪɾʲʃɛ
Faileddreoilínˈdʲɾʲoːlʲiːnʲdʲɾʲoːlʲiːnʲ
Faileddroimd̪ˠɾˠiːmʲd̪ˠɾˠɔɪmʲ
Failedduineˈd̪ˠɪnʲəd̪ˠɪnʲɛ
Failedduirlingˈd̪ˠuːɾˠlʲənʲd̪ˠɪɾʲlʲɪnʲɟ
Failedduánˈd̪ˠuːɑːnˠd̪ˠuːaːnˠ
Passeddáild̪ˠɑːlʲd̪ˠɑːlʲ
Faileddéanamhˈdʲeːnˠəwdʲeːnˠaw
Failedéadroimeeːdˠɾˠəmʲəeːd̪ˠɾˠɔɪmʲɛ
Failedeirleachˈeːɾˠl̠ʲəxɛɾʲlʲax
Failedeochair (respelled eòchair)ˈɔxəɾʲɔxaɾʲ
Failedeolaisˈoːlˠəʃoːlˠaʃ
Passedfanfˠanˠfˠanˠ
Failedfaoistinˈfˠiːʃtʲənʲfˠiːʃtʲɪnʲ
Failedfeallfʲɑːl̪ˠfʲalˠlˠ
Failedfeanntachˈfʲɑːn̪ˠt̪ˠəxfʲanˠnˠt̪ˠax
Failedfearrfʲɑːɾˠfʲaɾˠɾˠ
Failedfionnfʲʊn̪ˠfʲɪnˠnˠ
Passedfiosfʲɪsˠfʲɪsˠ
Passedfliuchfʲlʲʊxfʲlʲʊx
Failedfoinnfˠiːnʲfˠɔɪnʲnʲ
Failedfonnfˠuːn̪ˠfˠɔn̪ˠ
Failedfriotháilˈfʲɾʲɪhɑːlʲfʲɾʲɪhɑːlʲ
Passedfuairfˠuəɾʲfˠuəɾʲ
Passedfuarfˠuəɾˠfˠuəɾˠ
Failedfuáilˈfˠuːɑːlʲfˠuːaːlʲ
Failedgabháilˈɡawɑːlʲɡawɑːlʲ
FailedGaeilgeˈɡeːlʲɟəɡeːlʲɟɛ
FailedGaelachˈɡeːlˠəxɡeːlʲax
Passedgaoisɡiːʃɡiːʃ
Failedgardaˈɡɑːɾˠd̪ˠəɡaɾˠd̪ˠa
Failedgiodamˈɟɪd̪ˠəmˠɟɪd̪ˠamˠ
Failedgiotaˈɟɪt̪ˠəɟɪt̪ˠa
Failedgloineˈɡlˠɪnʲəɡlˠɔɪnʲɛ
Passedgnímhɟnʲiːvʲɟnʲiːvʲ
Failedgoillgəil̠ʲɡɔɪlʲlʲ
Failedgoirtɡɔɾˠtʲɡɔɪɾʲtʲ
Failedgreimɟɾʲiːmʲɟɾʲɛmʲ
Failedgrióirˈɟɾʲiːoːɾʲɟɾʲiːoːɾʲ
Failedgutaíˈɡʊt̪ˠiːɡʊt̪ˠiː
Failedifreannˈɪfʲɾʲən̪ˠɪfʲɾʲanˠnˠ
Failedimiːmʲɪmʲ
Failedinniúilˈɪn̠ʲuːlʲɪnʲnʲuːlʲ
Failediongaˈʊŋɡəɪnˠɡa
Failedliomlʲʊmˠl̠ʲʊmˠ
Failedliáinˈl̠ʲiːɑːnʲl̠ʲɪɑːnʲ
Failedloingeˈl̪ˠɪɲɟəl̪ˠɔɪnʲɟɛ
Failedlongl̪ˠuːŋɡl̪ˠɔnˠɡ
Failedluóigeˈl̪ˠuːoːɟəl̪ˠuːoːɟɛ
Failedmallmˠɑːl̪ˠmˠal̪ˠ
Passedmaíghmˠiːjmˠiːj
Failedmeáinmʲɑːnʲmʲaːnʲ
Failedmomˠəmˠɔ
Failedmurnánˈmˠuːɾˠn̪ˠɑːnˠmˠʊɾˠnˠɑːnˠ
Failedmálaˈmˠɑːlˠəmˠɑːlˠa
Failedmíleˈmʲiːlʲəmʲiːlʲɛ
Passedmóinmˠoːnʲmˠoːnʲ
Failednaoiˈn̪ˠiːn̪ˠiː
Failednaíonánˈn̪ˠiːnˠɑːnˠn̪ˠiːnˠɑːnˠ
Failedoibreˈɛbʲɾʲəɔɪbʲɾʲɛ
Failedoirdoːɾˠdʲɔɪɾʲdʲ
Failedoirthearˈɔɾˠhəɾˠɔɪɾʲhaɾˠ
Failedólannˈoːlˠən̪ˠoːlˠanˠnˠ
Failedorlachˈoːɾˠl̪ˠəxɔɾˠlˠax
Passedpicpʲɪcpʲɪc
Failedpiógˈpʲiːoːɡpʲiːoːɡ
Passedpostpˠɔsˠt̪ˠpˠɔsˠt̪ˠ
Failedpuinnpˠiːn̠ʲpˠɪnʲnʲ
Failedpáipéirˈpˠɑːpʲeːɾʲpˠɑːpʲeːɾʲ
Passedpógpˠoːɡpˠoːɡ
Failedroimhɾˠɪvʲɾˠɔɪvʲ
Failedruánˈɾˠuːɑːnˠɾˠuːaːnˠ
Passedsaolsˠiːlˠsˠiːlˠ
Failedsceimhleˈʃcɪvʲlʲəʃcɛvʲlʲɛ
Failedscoilsˠkɛlʲsˠkɔɪlʲ
Passedscéimhʃceːvʲʃceːvʲ
Failedseinmˈʃɪnʲəmʲʃɛnʲmʲ
Failedseiseanˈʃɛʃənˠʃɛʃanˠ
Failedseo (respelled seò)ˈʃɔʃɔ
FailedSeánʃɑːnˠʃaːnˠ
FailedSiobhánˈʃʊwɑːnˠʃʊwɑːnˠ
Failedsiopaˈʃʊpˠəʃʊpˠa
Failedsiógˈʃiːoːɡʃiːoːɡ
Passedsiúlʃuːlˠʃuːlˠ
Failedsuimsˠiːmʲsˠɪmʲ
Passedʃeːʃeː
Passedsíolʃiːlˠʃiːlˠ
Failedsúilsuːlʲsˠuːlʲ
Failedtaoiseachˈt̪ˠiːʃəxt̪ˠiːʃax
Failedtarlúˈt̪ˠɑːɾˠl̪ˠuːt̪ˠaɾˠlˠuː
Passedtetʲɛtʲɛ
Failedthoirhɛɾʲhɔɪɾʲ
Failedtiocfaidhˈtʲʊkiːtʲʊkfˠaj
Failedtiomáinˈtʲʊmɑːnʲtʲʊmˠɑːnʲ
Failedtoitínˈt̪ˠɛtʲiːnʲt̪ˠɔɪtʲiːnʲ
Failedtroidt̪ˠɾˠɛdʲt̪ˠɾˠɔɪdʲ
Failedtromt̪ˠɾˠuːmˠt̪ˠɾˠɔmˠ
Failedtuillteanachˈt̪ˠiːl̠ʲtʲənˠəxt̪ˠɪlʲlʲtʲanˠax
Failedtuirneˈt̪ˠuːɾˠn̠ʲət̪ˠɪɾʲnʲɛ
Passedtúst̪ˠuːsˠt̪ˠuːsˠ
Passedveainvʲanʲvʲanʲ
FailedBaile Átha Cliath (respelled Bleá Cliath)ˌbʲlʲɑː ˈclʲiəbʲlʲaː clʲiəh
Failedgo raibh maith agatɡəɾˠəˈmˠahəɡət̪ˠ,ɡəɾˠəmˠəˈhaɡət̪ˠɡɔ ɾˠavʲ mˠah aɡat̪ˠ

local export = {}

local lang = require("Module:languages").getByCode("ga")
local sc = require("Module:scripts").getByCode("Latn")

function export.tag_text(text, face)
	return require("Module:script utilities").tag_text(text, lang, sc, face)
end

function export.link(term, face)
	return require("Module:links").full_link( { term = term, lang = lang, sc = sc }, face )
end

local find = mw.ustring.find
local gsub = mw.ustring.gsub
local len = mw.ustring.len
local lower = mw.ustring.lower
local match = mw.ustring.match
local sub = mw.ustring.sub

local CONS = "[bcdfghjklLmnNŋpqrRstvwxyz]h?" -- consonants
local FRNT = "eiéí" -- front vowels
local BACK = "aouáóúòù" -- back vowels
local VOWL = FRNT .. BACK -- all vowels
local SYLL = "[^" .. VOWL .. "]" -- syllable boundary (should not be a vowel)
local BROD = "ˠ" -- broad mark
local SLND = "ʲ" -- slender mark

--[[
	list of various spelling-to-phoneme correspondences
	dialect order: ulster, connacht, munster
]]
-- vowel substitutions
local vowel_rules = {
	-- mixed vowel + consonant forms
	["mixed"] = {
		["e?abhai?"] = {"oː", "əu", "əu"},
		["e?a[dg]hai?"] = {"eː", "əi", "əi"},
		["ai?[dg]hai?"] = "əi",
		["e?amhai?"] = "ə̃ũ",
		["ei[dg]hi?"] = {"eː", "əi", "əi"},
		["ei[dg]hea"] = {"eː", "əi", "əi"},
		["oi[dg]hi?"] = "əi",
		["oi[dg]hea"] = "əi",
		["e?o[bdg]hai?"] = {"oː", "əu", "əu"},
		["e?omhai?"] = "õː",
		["i?ubh"] = {"uː", "ʊ(w)", "ʊw"},
		["i?umhai?"] = "ũː"
	},
	-- vowel-only forms
	["vowels"] = {
		-- a
		["aei?"] = "eː",
		["aoi"] = "iː",
		["aío?"] = "iː",
		["ai"] = {
			["r[dln]"] = "aː",
			["R"] = "aː",
			["[LN]"] = {"a", "aː", "əi"},
			[false] = "a"
		},
		["ao"] = {"iː", "iː", "eː"},
		["a"] = {
			["r[dlnr]"] = "aː",
			["[LmN]" .. SYLL] = {"a", "aː", "əu"},
			[false] = "a"
		},
		-- e
		["eai?"] = {
			["r[dln]"] = "aː",
			["R"] = "aː",
			["[LN]"] = {"a", "aː", "əu"},
			[false] = "a",
		},
		["eoi?"] = "oː",
		["eái?"] = "aː",
		["eòi?"] = "ɔ",
		["ei?"] = {
			["r[dln]"] = "eː",
			["[mN]" .. SYLL] = {"ɪ", "iː", "əi"},
			["mh?"] = "ɪ",
			["n"] = "ɪ",
			[false] = "ɛ"
		},
		-- i
		["iai?"] = "iə",
		["iói?"] = "iːoː",
		["iúi?"] = "uː",
		["io"] = {
			["th"] = "ɪ",
			["[dlnrst]"] = "ɪ",
			["N" .. SYLL] = {"ɪ", "ʊ", "uː"},
			[false] = {"ɪ", "ʊ", "ʊ"},
		},
		["iu"] = "ʊ",
		["i"] = {
			["[LmN]"] = {"ɪ", "iː", "iː"},
			[false] = "ɪ",
		},
		-- o
		["oío?"] = "iː",
		["o"] = {
			["r[dln]"] = "oː",
			["[nm]"] = {"ɔ", "ʊ", "ʊ"},
			["[mN]" .. SYLL] = {"ɔ", "uː", "əu"},
			["ng" .. SYLL] = {"ɔ", "uː", "əu"},
			[false] = "ɔ",
		},
		-- u
		["uai?"] = "uə",
		["uái?"] = "uːaː",
		["uío?"] = "iː",
		["uói?"] = "uːoː",
		["ui"] = {
			["r[dln]"] = {"ɪ", "uː", "uː"},
			["[LmN]" .. SYLL] = {"ɪ", "iː", "iː"},
			[false] = "ɪ",
		},
		["u"] = {
			["r[dln]"] = "uː",
			[false] = "ʊ",
		},
		["ù"] = "ɔ",

		-- á
		["ái?"] = {"æː", "ɑː", "ɑː"},
		-- é
		["é[ai]?"] = "eː",
		-- í
		["ío?"] = "iː",
		-- ó
		["ói?"] = "oː",
		-- ú
		["úi?"] = "uː"
	}
}

-- consonant substitutions
local cons_rules = {
	-- initial mutation forms
	["mut"] = {
		["bhf"] = "mh", -- eclipsis of f
		["bp"] = "b", -- eclipsis of p
		["dt"] = "d", -- eclipsis of t
		["gc"] = "g", -- eclipsis of c
		["mb"] = "m", -- eclipsis of b
		["nd"] = "n", -- eclipsis of d
		["ng"] = "ŋ", -- eclipsis of g
		["ph"] = "f", -- lenition of f
		["ts"] = "t", -- lenition of s after 'an'
		["l"] = "L", -- /l/ is always fortis word-initially
		["n"] = "N", -- /n/ is always fortis word-initially
		["r"] = "R" -- /ɾ/ is always fortis word-initially
	},
	-- general respelling forms
	["respell"] = {
		["j"] = "dz",
		["[kq]"] = "c",
		["ll"] = "L", -- respell ll for more efficient parsing
		["nn"] = "N", -- respell nn for more efficient parsing
		["rr"] = "R", -- respell rr for more efficient parsing
		["w"] = "v",
		["x"] = "cs",
		["y"] = "i",
		["n([cg])"] = "ŋ%1", -- n is velarised before velar consonants
		["r([dlnst])"] = "R%1", -- r is always broad before coronal consonants
	},
	-- parse rules (broad, slender)
	["parse"] = {
		["[bm]h"] = {"w", "v" .. SLND},
		["ch"] = {"x", "ç"},
		["[dg]h"] = {"ɣ", "j"},
		["fh"] = "",
		["[st]h"] = "h",
		["b"] = {"b" .. BROD, "b" .. SLND},
		["c"] = {"k", "c"},
		["d"] = {"d̪" .. BROD, "d" .. SLND},
		["f"] = {"f" .. BROD, "f" .. SLND},
		["g"] = {"ɡ", "ɟ"},
		["h"] = "h",
		["l"] = {"l" .. BROD, "l" .. SLND},
		["L"] = {"l̪" .. BROD, "l̠" .. SLND},
		["m"] = {"m" .. BROD, "m" .. SLND},
		["n"] = {"n" .. BROD, "n" .. SLND},
		["N"] = {"n̪" .. BROD, "n̠" .. SLND},
		["ŋ"] = {"ŋ", "ɲ"},
		["p"] = {"p" .. BROD, "p" .. SLND},
		["r"] = {"ɾ".. BROD, "ɾ" .. SLND},
		["R"] = "ɾ" .. BROD,
		["s"] = {"s" .. BROD, "ʃ"},
		["t"] = {"t̪" .. BROD, "t" .. SLND},
		["v"] = {"w", "v" .. SLND},
		["z"] = {"z" .. BROD, "ʒ"},
	}
}
-- rules applied after parse
local after_parse = {
	["brsl"] = {
		["^s" .. SLND .. "([fmpɾ])"] = "s" .. BROD .. "%1", -- /s/ is always broad word-initially before /f, m, p, ɾ/
		["([dlnɾst]h?)ˠ (" .. CONS .. ")ʲ"] = "%1ʲ %2ʲ", -- broad word-final coronal consonants turn slender before a slender word-initial consonant
		["([dlnɾst]h?)ʲ (" .. CONS .. ")ˠ"] = "%1ˠ %2ˠ", -- same vice versa
	}
}

-- prioritise longer matches for each table
local function sort_table(tbl)
	local sorted_patterns = {}

	for pattern in pairs(tbl) do
		table.insert(sorted_patterns, pattern)
	end
	table.sort(sorted_patterns, function(a, b) return #a > #b end)

	return sorted_patterns
end

-- sort those tables
local vowels_sorted = sort_table(vowel_rules.vowels)
local mixed_sorted = sort_table(vowel_rules.mixed)
local cons_sorted = sort_table(cons_rules.parse)

-- determine whether following consonant is broad/slender
local function get_brsl(vowel)
	return find(BACK, vowel) and "br" or "sl"
end

-- parse phonemes
local function parse(term)
	local phones = {}
	local i = 1
	local brsl = get_brsl(match(term, "[" .. VOWL .. "]") or "")

	-- loop over every character until reached word-final token
	while sub(term, i, i) ~= "#" do
		local pattern_matched = nil
		local matched = false

		-- match mixed forms first
		for _, pattern in ipairs(mixed_sorted) do
			local value = vowel_rules.mixed[pattern]
			pattern_matched = match(sub(term, i), "^" .. pattern)
			if pattern_matched then
				matched = true
				-- retrieve appropriate dialectal pronunciation
				local replacement = type(value) == "table" and value[2] or value
				table.insert(phones, replacement)
				i = i + len(pattern_matched)
				brsl = get_brsl(sub(pattern_matched, -1))
				break
			end
		end

		-- match vowel-only forms
		if not matched then
			for _, pattern in ipairs(vowels_sorted) do
				local value = vowel_rules.vowels[pattern]
				pattern_matched = match(sub(term, i), "^" .. pattern)
				if pattern_matched then
					matched = true
					local replacement = type(value) == "table" and value[2] or value
					if type(value) == "table" then
						-- lookahead for consonant(s)
						for subpattern, subvalue in pairs(value) do
							if subpattern == false or match(sub(term, i + len(pattern_matched)), "^" .. subpattern) then
								replacement = type(subvalue) == "table" and subvalue[2] or subvalue
								break
							end
						end
					end
					table.insert(phones, replacement)
					i = i + len(pattern_matched)
					brsl = get_brsl(sub(pattern_matched, -1))
					break
				end
			end
		end

		-- match a consonant
		if not matched then
			for _, pattern in ipairs(cons_sorted) do
				local value = cons_rules.parse[pattern]
				pattern_matched = match(sub(term, i), "^" .. pattern)
				if pattern_matched then
					matched = true
					-- apply broad/slender rules to consonant
					local replacement = type(value) == "table" and value[brsl == "br" and 1 or 2] or value
					table.insert(phones, replacement)
					i = i + len(pattern_matched)
					break
				end
			end
		end

		-- otherwise return error
		if not matched then
			error("Invalid character at position" .. i .. ": " .. sub(term, i, i))
		end
	end

	return table.concat(phones)
end

-- main export function
function export.toIPA(term)
	if type(term) == "table" then
		term = term.args[1]
	end

	-- add word-final token # for parsing and make all text lowercase
	term = lower(gsub(term, "[^ ]+", "%1#"))

	-- loop over every word in the string
	return gsub(term, "[^ ]+", function(word)
		-- apply word-initial mutation rules
		for k, v in pairs(cons_rules.mut) do
			word = gsub(word, "^" .. k, v)
		end

		-- apply general respelling forms
		word = gsub(word, "..?", cons_rules.respell)

		-- parse string
		word = parse(word)

		-- apply further mutation rules
		for k, v in pairs(after_parse.brsl) do
			word = gsub(word, k, v)
		end

		return word
	end)
end

return export