Module:pi-decl/noun
- පහත දැක්වෙන උපදෙස්, Module:pi-decl/noun/documentation හි පිහිටා ඇත. Module:pi-decl/noun/documentation]]. [සංස්කරණය]
- ප්රයෝජනවත් සබැඳි: root page • root page’s subpages • සබැඳි • transclusions • testcases • sandbox
Purpose
සංස්කරණයThis module provides inflection tables for Pali for nouns, adjectives and pronouns. For pronouns, one currently uses the interface for nouns, while for adjectives one uses separate invocations for each gender.
Some functions are exported from this module to service the testing of noun inflection. The module also provides utility functions for the conjugation of verbs.
Normal Use
සංස්කරණයThe normal way to use this module is to invoke the template {{pi-decl-noun}}
, which see for the interface. This invokes the exported function show
.
Data tables
සංස්කරණයThe primary data table for the inflections is the data module Module:pi-decl/noun/Latn, which contains the Latin script tables. These are supplemented by identically structured tables for each of the other supported scripts. If the table for a particular paradigm is missing from one of these, the table will be generated using the transliteration functions in Module:pi-Latn-translit. The data modules for the other scripts are:
- Module:pi-decl/noun/Thai
- Module:pi-decl/noun/Deva
- Module:pi-decl/noun/Brah
- Module:pi-decl/noun/Beng
- Module:pi-decl/noun/Sinh
- Module:pi-decl/noun/Mymr
- Module:pi-decl/noun/Lana
- Module:pi-decl/noun/Laoo
- Module:pi-decl/noun/Khmr
- Module:pi-decl/noun/Latn
With the exception of the masculine and neuter thematic nouns, the Thai and Lao tables are not used for declension with explicit vowels.
There is no such redundant table for the Chakma script.
Deliberately Exported Functions
සංස්කරණයThe following Lua functions are exported by this module:
orJoin()
joinSuffix
arrcat_nodup
present
show
Function orJoin
සංස්කරණයFunction joinSuffix
සංස්කරණයThe original idea was to share this function with the code for verb conjugation. However, the conjugation of verbs in the Thai and Lao scripts is more complicated, and there is therefore a more general function in use for verbs.
Function arrcat_nodup
සංස්කරණයFunction present()
සංස්කරණයFunction show()
සංස්කරණයOther exported functions
සංස්කරණයdetectEnding()
joinSuffixes
getSuffixes
modify
Algorithm
සංස්කරණයThe paradigm to use is determined using the script of the stem, the ending of the stem (for which there are a few conventional values - see {{pi-decl-noun}}
) and gender of the stem. The script is always deduced from the script of the stem, while the ending may be supplied explicitly (in Latin script) or deduced from the stem. The gender is always supplied explicitly. The deduction of the ending from the stem is performed by function detectEnding
.
The set of suffixes is obtained by function getSuffixes
. This first attempts to load the paradigm from the data files. However, if the paradigm is unacceptable or missing, it will generate it itself. Paradigms from data files are only acceptable for some combinations of settings. At present, they are not acceptable for non-Roman scripts when using explicit vowels, except for the conventional ending 'ah', which denotes masculine or neuter nouns with stems in explicit -a. (The convention was chosen because the explicit vowel also represents the Sanskrit ending -aḥ.)
When paradigms are generated internally, they are converted from Latin script to the required script and implicit vowel settings. This is implemented in function convert_suffixes
.
The second stage of the generation, applicable to the Lao script only, is to, where needed, convert the ablative and instrumental plural in -bhi to the correct forms. The editor specifies the correct form using the parameter |liap=
.
The third stage of the generation, applicable to Lao script only, is to, where needed, convert the letter corresponding to <y> in the suffixes to the correct letter. This setting is treated as orthogonal to the choice between using or not using implicit vowels.
The endings are then attached to the stem using the function joinSuffixes
. This invokes function joinSuffixes
to apply the writing system-dependent rules for the attachment of suffixes. There is one user-controlled input to this process, the parameter |aa=
, which is applicable to the Burmes and Tai Tham scripts.
Next, the function modify
is applied to add, remove or replace the forms generated so far in accordance a list of modifications included in the invocation of {{pi-decl-noun}}
.
Finally, the function present
formats the list of forms for each combination of case and number. This formatting includes adding the transliteration, which is done in function orJoin
. Function show
then returns the inflection table for display on the page.
local export = {}
local links = require("Module:links")
local lang = require("Module:languages").getByCode("pi")
local en_lang
local m_parameters = require("Module:parameters")
local m_translit
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local sub = mw.ustring.sub
local u = mw.ustring.char -- For readability.
local load = mw.loadData
local ti = table.insert
local currentScript
local scriptCode
local genders = {
["m"] = "masculine", ["f"] = "feminine", ["n"] = "neuter",
}
local rows = {
"Nominative (first)", "Accusative (second)", "Instrumental (third)", "Dative (fourth)",
"Ablative (fifth)", "Genitive (sixth)", "Locative (seventh)", "Vocative (calling)",
}
local endings = {
["one"] = {
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah Cakm
["a"] = {},
["ā"] = { "า", "ा", "आ", "া", "আ", "ါ", "ာ", " ႃ", "ᩣ", "ᩤ", "າ", "ា", u(0x17A4),
"ා", "ආ", "𑀸", "𑀆", "𑄂" },
["i"] = { "ิ", "ि", "इ", "ি", "ই", "ိ", "ဣ", "ᩥ", "ᩍ", "ິ", "ិ", "ឥ",
"ි", "ඉ", "𑀺", "𑀇", "𑄨" },
["ī"] = { "ี", "ी", "ई", "ী", "ঈ", "ီ", "ဳ", "ဤ", "ᩦ", "ᩎ", "ີ", "ី", "ឦ",
"ී", "ඊ", "𑀻", "𑀈", "𑄩" },
["u"] = { "ุ", "ु", "उ", "ু", "উ", "ု", "ဥ", "ᩩ", "ᩏ", "ຸ", "ុ", "ឧ",
"ු", "උ", "𑀼", "𑀉", "𑄪" },
["ū"] = { "ู", "ू", "ऊ", "ূ", "ঊ", "ူ", "ဦ", "ᩪ", "ᩐ", "ູ", "ូ", "ឨ", "ឩ",
"ූ", "ඌ", "𑀽", "𑀊", "𑄫" },
["ah"] = { "ะ", "ະ"},
},
["two"] = {
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah Cakm
["ar"] = { "รฺ", "ัร", "र्", "র্", "ရ်", "ᩁ᩺", "ᩁ᩼", "ຣ໌", "ຣ຺", "ັຣ", "រ៑",
"ර්", "𑀭𑁆", "𑄢𑄴"},
["as"] = { "สฺ", "ัส", "स्", "স্", "သ်", "ᩈ᩺", "ᩈ᩼", "ສ໌", "ສ຺", "ັສ", "ស៑",
"ස්", "𑀲𑁆", "𑄥𑄴" },
["an"] = { "นฺ", "ัน", "न्", "ন্", "န်", "ᨶ᩺", "ᨶ᩼", "ນ໌", "ນ຺", "ັນ", "ន៑",
"න්", "𑀦𑁆", "𑄚𑄴"},
ent = { "นต", "ນຕ"},
["in"] = { "ิน", "ິນ"},
},
three = {
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah Cakm
ant = { "ันต" , "ັນຕ"},
ent = {},
ont = {},
["in"] = { "ินฺ", "िन्", "িন্", "ိန်", "ᩥᨶ᩺", "ິນ", "ិន៑",
"ින්", "𑀺𑀦𑁆", "𑄨𑄚𑄴" },
},
four = {
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah Cakm
ant = { "นฺตฺ", "न्त्", "ন্ত্", "န္တ်", "ᨶ᩠ᨲ᩺", "ᨶ᩠ᨲ᩼", "ນ຺ຕ໌", "ນ຺ຕ຺", "ន្ត៑",
"න්ත්", "𑀦𑁆𑀢𑁆", "𑄚𑄴𑄖𑄴" },
vant = { "วันต", "ວັນຕ" },
mant = { "มันต", "ມັນຕ" },
},
five = { -- 'ent' and 'ont' are discontiguous for Thai and Lao. Assume NFC (as above).
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah Cakm
antT = { "න්ත්" },
vant = { "วนฺตฺ", "वन्त्", "ৱন্ত্","ৰন্ত্", "ွန္တ်", "ဝန္တ်", "ᩅᨶ᩠ᨲ᩺", "ᩅᨶ᩠ᨲ᩼", "ວນ຺ຕ຺", "ວນ຺ຕ໌", "វន្ត៑",
"වන්ත්", "𑀯𑀦𑁆𑀢𑁆", "𑅇𑄚𑄴𑄖𑄴" },
mant = { "มนฺตฺ", "मन्त्", "মন্ত্", "မန္တ်", "ᨾᨶ᩠ᨲ᩺", "ᨾᨶ᩠ᨲ᩼", "ມນ຺ຕ຺", "ມນ຺ຕ໌", "មន្ត៑",
"ᩜᨶ᩠ᨲ᩺", "ᩜᨶ᩠ᨲ᩼",
"මන්ත්", "𑀫𑀦𑁆𑀢𑁆", "𑄟𑄚𑄴𑄖𑄴"},
ent = { "ेन्त्", "েন্ত্", "ေန္တ်", "ᩮᨶ᩠ᨲ᩺", "ᩮᨶ᩠ᨲ᩼", "េន្ត៑",
"एन्त्", "এন্ত্", "ဧန္တ်", "ᩑᨶ᩠ᨲ᩺", "ᩑᨶ᩠ᨲ᩼", "ឯន្ត៑",
"ෙන්ත්", "𑁂𑀦𑁆𑀢𑁆", "𑄬𑄚𑄴𑄖𑄴" ,
"එන්ත්", "𑀏𑀦𑁆𑀢𑁆" },
ont = { "ोन्त्", "োন্ত্", "ာန္တ်", "ါန္တ်", "ᩣᨶ᩠ᨲ᩺", "ᩣᨶ᩠ᨲ᩼", "ោន្ត៑",
"ᩤᨶ᩠ᨲ᩺", "ᩤᨶ᩠ᨲ᩼",
"ओन्त्", "ওন্ত্", "ဩန္တ်", "ᩰᨶ᩠ᨲ᩺", "ᩰᨶ᩠ᨲ᩼", "ឲន្ត៑",
"ᩒᨶ᩠ᨲ᩺", "ᩒᨶ᩠ᨲ᩼",
"ොන්ත්", "𑁄𑀦𑁆𑀢𑁆", "𑄮𑄚𑄴𑄖𑄴",
"ඔන්ත්", "𑀑𑀦𑁆𑀢𑁆"},
},
six = {
-- key(Ln) Thai Deva Beng Mymr Lana Laoo Khmr
-- Sinh Brah
vantT = {"වන්ත්" },
mantT = {"මන්ත්" },
entT = {"ෙන්ත්",
"එන්ත්" },
ontT = {"ොන්ත්",
"ඔන්ත්" },
},
}
function export.detectEnding(stem, options)
-- Correct checking order is last 6, last 5, last 4, last 3, last 2, last 1, but we
-- Can do slightly better by knowing the data.
local oneLetter = sub(stem, -1)
for key, arr in pairs(endings.one) do
if oneLetter == key then
return key
end
for _, val in ipairs(arr) do
if oneLetter == val then
return key
end
end
end
-- Check Latin script first
local fourLetters = sub(stem, -4)
if 'mant' == fourLetters or 'vant' == fourLetters then
return fourLetters
end
local wordEnd = sub(stem, -6)
for key, arr in pairs(endings.six) do
-- if wordEnd == key then
-- return key
-- end
for _, val in ipairs(arr) do
if wordEnd == val then
return key
end
end
end
wordEnd = sub(stem, -5)
for key, arr in pairs(endings.five) do
-- if wordEnd == key then
-- return key
-- end
for _, val in ipairs(arr) do
if wordEnd == val then
return key
end
end
end
for key, arr in pairs(endings.four) do
if fourLetters == key then return key end
for _, val in ipairs(arr) do
if fourLetters == val then
-- Scripts with visually ordered preposed vowels have not been checked thoroughly
if key == 'ant' and
(oneLetter == u(0x0E3A) or oneLetter == u(0xECC) or
oneLetter == u(0x0EBA)) then
local pm6 = sub(stem, -6, -6)
if match(pm6, '[เโເໂ]') then -- 1 char onset
return 'ent' -- 'ent' for 'ont' matters not.
elseif match(pm6, '['..u(0x0E3A)..u(0x0EBA)..']')
and match(sub(stem, -8, -8), '[เโເໂ]') then -- 2 char onset
return 'ent' -- 'ent' for 'ont' matters not.
else
return key
end
else
return key
end
end
end
end
local threeLetters = sub(stem, -3)
for key, arr in pairs(endings.three) do
if threeLetters == key then
return key
end
for _, val in ipairs(arr) do
if threeLetters == val then return key; end
end
end
local impl = options and options.impl or 'yes' -- Fudge to pass old tests.
wordEnd = sub(stem, -2)
for key, arr in pairs(endings.two) do
if wordEnd == key then
return key
end
for _, val in ipairs(arr) do
if wordEnd == val then
if key == 'ent' then
local pm3 = sub(stem, -3, -3)
if match(pm3, '['..u(0x0e31)..u(0xeb1)..']') then
-- Recognise below
return 'ant'
elseif match(sub(stem, -4, -3), '[เโເໂ][ก-ฮກ-ຮ]') then -- 1 char onset
return 'ent'
elseif match(sub(stem, -5, -3), '[เโເໂ][ก-ฮກ-ຮ][ก-ฮກ-ຮ]') then -- 2 char onset
return 'ent'
end
elseif wordEnd == "ิน" or wordEnd == "ິນ" then
if impl == 'yes' then
return 'a'
elseif impl == 'both' then
error("Does "..stem.." end in -in or -ina?")
else
return key
end
else
return key
end
end
end
end
return "a"
end
-- Selectively converts touching to conjoining.
local sinh_flip = {["කⒿ්ව"]="ක්ව",
["තⒿ්ථ"]="ත්ථ", ["තⒿ්ව"]="ත්ව",
["නⒿ්ථ"]="න්ථ", ["නⒿ්ද"]="න්ද", ["නⒿ්ධ"]="න්ධ", ["නⒿ්ව"]="න්ව",
}
-- Argument option is optional.
function export.joinSuffix(scriptCode, stem, suffixes, option)
if stem == nil then
errmes = {}
table.insert(errmes, 'joinSuffix('..scriptCode)
table.insert(errmes, tostring(stem))
table.insert(errmes, tostring(suffixes))
table.insert(errmes, tostring(option)..')')
error(table.concat(errmes, ','))
end
local output = {}
local term
local aa = option and option.aa or "default"
local join, term2
if scriptCode == 'Lana' or scriptCode == 'Mymr' or scriptCode == 'Sinh' then
join = 'Ⓙ'
else
join = ""
end
for _,suffix in ipairs(suffixes) do
if match(suffix, "^⌫⌫⌫⌫⌫") then --backspace
term = sub(stem, 1, -6) .. join .. sub(suffix, 6, -1)
elseif match(suffix, "^⌫⌫⌫⌫") then --backspace
term = sub(stem, 1, -5) .. join .. sub(suffix, 5, -1)
elseif match(suffix, "^⌫⌫⌫") then --backspace
term = sub(stem, 1, -4) .. join .. sub(suffix, 4, -1)
elseif match(suffix, "^⌫⌫") then --backspace
term = sub(stem, 1, -3) .. join .. sub(suffix, 3, -1)
elseif match(suffix, "^⌫") then --backspace
term = sub(stem, 1, -2) .. join .. sub(suffix, 2, -1)
else
term = stem .. join .. suffix
end
--note: Sinh conjuncts are already ready.
if scriptCode == "Thai" then
term = gsub(term, "(.)↶([เโ])", "%2%1") --swap
elseif scriptCode == "Mymr" then
-- term = gsub(term, "င္", "င်္") -- Pali doesn't have -Vr mid-word like Sanskrit, so no need to include repha.
term = gsub(term, "(င်္)([ခဂငဒပဝ])(ေ?)Ⓙာ", "%1%2%3ါ") -- redundant!
-- term = gsub(term, "္[ယရ]", { ["္ယ"] = "ျ", ["္ရ"] = "ြ" }) --these not need tall aa
term = gsub(term, "Ⓙ္[ယရ]", { ["Ⓙ္ယ"] = "ျ", ["Ⓙ္ရ"] = "ြ" }) --these not need tall aa
term = gsub(term, "^([ခဂငဒပဝ])Ⓙ(ေ?)ာ", "%1%2ါ")
term = gsub(term, "([^္])([ခဂငဒပဝ])Ⓙ(ေ?)ာ", "%1%2%3ါ")
term = gsub(term, "([^္])Ⓙ([ခဂငဒပဝ])(ေ?)ာ", "%1%2%3ါ")
term = gsub(term, "([ခဂငဒပဝ])(္[က-အဿ])Ⓙ(ေ?)ာ", "%1%2%3ါ")
term = gsub(term, "([ခဂငဒပဝ])Ⓙ(္[က-အဿ])(ေ?)ာ", "%1%2%3ါ")
-- term = gsub(term, "္[ဝဟ]", { ["္ဝ"] = "ွ", ["္ဟ"] = "ှ" })
-- term = gsub(term, "ဉ္ဉ", "ည")
-- term = gsub(term, "သ္သ", "ဿ")
term = gsub(term, 'Ⓙ', '')
elseif scriptCode == "Lana" then
if aa == "both" then
term2 = gsub(term, 'Ⓙ', '')
end
if aa == "tall" or aa == "both" then
term = gsub(term, "^([ᨣᨴᨵᨷᩅ])Ⓙ(ᩮ?)ᩣ", "%1%2ᩤ")
term = gsub(term, "([^᩠])([ᨣᨴᨵᨷᩅ])Ⓙ(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([^᩠])Ⓙ([ᨣᨴᨵᨷᩅ])(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([ᨣᨴᨵᨷᩅ])(᩠[ᨠ-ᩌᩔ])Ⓙ(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([ᨣᨴᨵᨷᩅ])Ⓙ(᩠[ᨠ-ᩌᩔ])(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "(ᨻᩛ)Ⓙ(ᩮ?)ᩣ", "%1%2ᩤ")
term = gsub(term, 'Ⓙ', '')
if aa == "tall" then
term2 = term
end
elseif aa == "round" then
term = gsub(term, 'Ⓙ', '')
term2 = term
elseif aa == "default" then
-- term = gsub(term, "ᨦ᩠", "ᩘ")
term = gsub(term, "^([ᨣᨴᨵᨷᩅ])Ⓙ(ᩮ?)ᩣ", "%1%2ᩤ")
term = gsub(term, "([^᩠])([ᨣᨴᨵᨷᩅ])Ⓙ(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([^᩠])Ⓙ([ᨣᨴᨵᨷᩅ])(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([ᨣᨴᨵᨷᩅ])(᩠[ᨠ-ᩌᩔ])Ⓙ(ᩮ?)ᩣ", "%1%2%3ᩤ")
term = gsub(term, "([ᨣᨴᨵᨷᩅ])Ⓙ(᩠[ᨠ-ᩌᩔ])(ᩮ?)ᩣ", "%1%2%3ᩤ")
-- term = gsub(term, "᩠[ᩁᩃ]", { ["᩠ᩁ"] = "ᩕ", ["᩠ᩃ"] = "ᩖ" })
-- term = gsub(term, "([ᨭ-ᨱ])᩠ᨮ", "%1ᩛ")
-- term = gsub(term, "([ᨷ-ᨾ])᩠ᨻ", "%1ᩛ")
-- term = gsub(term, "ᩈ᩠ᩈ", "ᩔ")
term = gsub(term, 'Ⓙ', '')
term2 = term
else
error('Parameter aa has undefined value "'..aa..'".')
end
if term ~= term2 then table.insert(output, term2) end
elseif scriptCode == "Beng" then
term = gsub(term, "ৰ্", "ৰ"..u(0x200d).."্") -- ৰ্(v-) needs ZWJ to display correctly
elseif scriptCode == "Laoo" then
term = gsub(term, "(.຺?)↶([ເໂ])", "%2%1")
elseif scriptCode == "Sinh" then
-- Assume cluster formation appends the joiner.
term = gsub(term, "[කතන]Ⓙ..[ථදධව]", sinh_flip)
term = gsub(term, 'Ⓙ', '')
end
table.insert(output, term)
end
return output
end
function export.joinSuffixes(scriptCode, stem, pattern, option)
local forms = {}
for i,_ in ipairs(rows) do
forms[2*i-1] = export.joinSuffix(scriptCode, stem, pattern[2 * i - 1],
option)
forms[2*i] = export.joinSuffix(scriptCode, stem, pattern[2 * i],
option)
end
return forms
end
function export.orJoin(script, list, options) -- options is optional!
local output = {};
local scriptCode = script:getCode()
local showtr = options and options.showtr or 'plain'
local sep = ''
if 'Latn' == scriptCode then showtr = 'none' end
for _,term in ipairs(list) do
local item = {sc = script}
ti(output, sep)
sep = " <small style=\"color:888\">or</small> "
item.term = term;
item.lang = lang;
if showtr == 'none' then
item.tr = '-'
else
if options and options.subst then
-- Legal stuff:
-- The contents of this block were lifted from English Wiktionary Module:usex lines 97 to 101
-- of 3 July 2021, which see for attribution, and then localised.
local substs = mw.text.split(options.subst, ",")
for _, subpair in ipairs(substs) do
local subsplit =
mw.text.split(subpair, mw.ustring.find(subpair, "//") and "//" or "/")
term = mw.ustring.gsub(term, subsplit[1], subsplit[2])
end
end
local aslat = nil
if (scriptCode == 'Thai' and options and options.impl == 'no' or
scriptCode == 'Laoo') then
m_translit = m_translit or require("Module:pi-translit")
aslat = m_translit.trwo(term, 'pi', scriptCode, options)
elseif term ~= item.term then -- Must complete transliteration
aslat = (lang:transliterate(term, script))
end
if showtr == 'plain' then
item.tr = aslat
elseif showtr == 'link' then
aslat = aslat or (lang:transliterate(term, script))
item.tr = links.full_link({term = aslat, lang = lang})
else
item.tr = '-'
error('Bad value for option showtr.')
end
end
if (item.tr and item.tr ~= '-') then
en_lang = en_lang or require("Module:languages").getByCode("en")
item.lang = en_lang -- Suppress transliteration by links.full_link
item.term = item.term .. '#pi'
else
item.lang = lang
end
ti(output, links.full_link(item))
end
return table.concat(output)
end
-- convert Latin script inflections to another script
local convert_suffixes = function(stem, nstrip, suffixes, sc, impl)
local form, pre
local xlitend = {}
local strip = string.rep("⌫", nstrip)
local option = {impl = impl}
local to_script = require("Module:pi-Latn-translit").tr
local c2
if nstrip > 0 and sc == 'Mymr' then
c2 = sub(to_script(stem, sc, option), 2, 2)
end
-- Seemingly #suffixes doesn't work because the module is loaded!
-- Testing didn't reveal a problem, but avoiding it solved the problem!
-- for k = 1, #suffixes do
if #suffixes ~= 16 then error('#suffixes = '..tostring(#suffixes)) end
for k, _ in ipairs(suffixes) do
xlitend[k] = {}
form = export.joinSuffix('Latn', stem, suffixes[k])
for ia, va in pairs(form) do
local altform = sub(to_script(va..'#', sc, option), 1, -2)
-- Special handling is needed for a preposed vowel.
pre = match(altform, "^[เโເໂ]")
if pre then
xlitend[k][ia] = strip .. "↶" .. pre .. sub(altform, 3)
-- Quick cheat for Myanmar script variants.
elseif c2 and c2 == sub(altform,2,2) then
xlitend[k][ia] = sub(strip, 2) .. sub(altform, 3)
-- Back to the normal case.
else
xlitend[k][ia] = strip .. sub(altform, 2)
end
end
end
return xlitend
end
local liapise = function(retval, liap) -- Change Lao abl/ins plural
-- Copy list to avoid changing data from data module.
local oval = retval retval = {}
for _, forms in ipairs(oval) do table.insert(retval, forms) end
local dob = nil local dobh = nil local sena = nil
if liap == 'b' then
dob = 1
elseif liap == 'bh' then
dobh = 1
elseif liap == 'b.' then
sena = 1
elseif liap == 'bbh' then
dob = 1 dobh = 1
elseif liap == 'bb.' then
dob = 1 sena = 1
elseif liap == 'bhb.' then
dobh = 1 sena = 1
elseif liap == 'none' then
elseif liap == 'all' or liap == 'bbhb.' then
dob = 1 dobh = 1 sena = 1
else
error('Value "'..liap..'" of liap is not understood.')
end
for caseno = 6, 10, 4 do
local forms = retval[caseno]
local nuforms = {}
for _, form in ipairs(forms) do
if sub(form, -2, -1) == 'ຠິ' then
if dob then table.insert(nuforms, sub(form,1,-3)..'ພິ') end
if dobh then table.insert(nuforms, form) end
if sena then table.insert(nuforms, sub(form,1,-3)..'ພ຺ິ') end
else
table.insert(nuforms, form)
end
end
retval[caseno] = nuforms
end
return retval
end
local yselect = function(retval, yval) -- Change Lao case ending
-- Copy list to avoid changing data from data module.
local oval = retval retval = {}
for _, forms in ipairs(oval) do table.insert(retval, forms) end
local yung = nil local yaa = nil
if yval == 'both' then
yung = 1
yaa = 1
elseif yval == 'ຍ' then
yung = 1
elseif yval == 'ຢ' then
yaa = 1
elseif yval == 'yung' then
yung = 1
elseif yval == 'yaa' then
yaa = 1
else
error('Value "'..yval..'" of argument y is not understood.')
end
for caseno = 1, 16 do
local forms = retval[caseno]
local nuforms = {}
for _, form in ipairs(forms) do
if yung then
local s = gsub(form, '[ຍຢ]', 'ຍ') -- gsub() is a bad actual arg!
table.insert(nuforms, s)
end
if yaa then
local s = gsub(form, '[ຍຢ]', 'ຢ')
table.insert(nuforms, s)
end
end
retval[caseno] = nuforms
end
return retval
end
function export.arrcat_nodup(a1, a2) -- Concatenate two arrays without duplication
-- One of the arrays may have been 'loaded', so cannot use the # operator.
local n1 = 0
local cat = {}
for _, a1v in ipairs(a1) do
n1 = n1 + 1
cat[n1] = a1v
end
for _, a2v in ipairs(a2) do
local met = false
for j = 1, n1 do
if a2v == cat[j] then
met = true
break
end
end
if not met then
n1 = n1 + 1
cat[n1] = a2v
end
end
return cat
end
local arrcat = export.arrcat_nodup
local both_sets = function(scriptCode, ending, g, option)
option.impl= 'yes'
iset = export.getSuffixes(scriptCode, ending, g, option)
option.impl = 'no'
eset = export.getSuffixes(scriptCode, ending, g, option)
retval = {}
-- error('i='..iset[3][1]..' e='..eset[3][1])
for ic = 1, 16 do
retval[ic] = arrcat(iset[ic], eset[ic])
end
-- error('m1='..'<'..tostring(retval[1][1])..'>'..' m2='..'<'..tostring(retval[1][2])..'>')
return retval
end
function export.getSuffixes(scriptCode, ending, g, option)
local impl = option and option.impl or 'yes'
if (impl == 'both') then
return both_sets(scriptCode, ending, g, option)
end
local pattern = load("Module:pi-decl/noun/" .. scriptCode)
local applicable = pattern and pattern[ending] and pattern[ending][g]
if applicable then
if impl == 'yes' or ending == 'ah' then
return applicable
end
elseif 'Latn' == scriptCode then
return nil
elseif 'ah' == ending then
ending = 'a'
impl = 'no'
end
pattern = require("Module:pi-decl/noun/Latn") -- Why doesn't load work with testcases?
local tabulated_ending = ending
if 'T' == sub(ending, -1) then
tabulated_ending = sub(ending, 1, -2)
end
applicable = pattern and pattern[tabulated_ending] and
pattern[tabulated_ending][g]
if not applicable then
error('Not even Latin script has ' .. g .. ' -'..tabulated_ending..
' endings.')
return nil -- If you don't like the message above!
end
local antlen = {yes = 4, no = 3} -- Length by implicitness.
local inlen = {yes = 3, no = 2}
local way = {
a = {pseudoStem = 'ka', ndel = 0},
ar = {pseudoStem = 'kar', ndel = 2},
as = {pseudoStem = 'kas', ndel = 2},
an = {pseudoStem = 'kan', ndel = 2},
ant = {pseudoStem = 'kant', ndel = antlen[impl]},
ent = {pseudoStem = 'kant', ndel = antlen[impl]},
ont = {pseudoStem = 'kant', ndel = antlen[impl]},
mant = {pseudoStem = 'kant', ndel = antlen[impl]},
vant = {pseudoStem = 'kant', ndel = antlen[impl]},
antT = {pseudoStem = 'kant', ndel = 5},
entT = {pseudoStem = 'kant', ndel = 5},
ontT = {pseudoStem = 'kant', ndel = 5},
mantT = {pseudoStem = 'kant', ndel = 5},
vantT = {pseudoStem = 'kant', ndel = 5},
["ā"] = {pseudoStem = 'kā', ndel = 1},
i = {pseudoStem = 'ki', ndel = 1},
["ī"] = {pseudoStem = 'kī', ndel = 1},
["in"]= {pseudoStem = 'kin', ndel = inlen[impl]},
u = {pseudoStem = 'ku', ndel = 1},
["ū"] = {pseudoStem = 'kū', ndel = 1},
}
if impl == 'no' then
way.a = {pseudoStem = 'ka', ndel = 1}
way.ent = {pseudoStem = 'knt', ndel = 2}
way.ont = {pseudoStem = 'knt', ndel = 2}
end
way = way[ending]
if not way then return nil end
return convert_suffixes(way.pseudoStem, way.ndel, applicable,
scriptCode, impl)
end
function export.present(stem, g, forms, number, options) -- options is optional
local gmark, dos, dop
if 'no' == g then
gmark = ''
else
gmark = ' (' .. genders[g] .. ')'
end
if not number or number == 'both'then
dos = 1; dop = 1
elseif number == 's' then
dos = 1; dop = nil;
elseif number == 'p' then
dos = nil; dop = 1;
else
error('Parameter "number" has meaningless value "'..number..'".' )
end
local output = {}
table.insert(output, '<div class="NavFrame" style="min-width:30%"><div class="NavHead" style="background:#d9ebff">Declension table of "' .. stem .. '"' .. gmark..'</div><div class="NavContent">')
table.insert(output, '<table class="inflection-table" style="background:#F9F9F9;text-align:center;width:100%"><tr><th style="background:#eff7ff">Case \\ Number</th>')
if dos then
table.insert(output, '<th style="background:#eff7ff">Singular</th>')
end
if dop then
table.insert(output, '<th style="background:#eff7ff">Plural</th></tr>')
end
for i,v in ipairs(rows) do
if #forms[2*i-1] > 0 or #forms[2*i] > 0 then
table.insert(output, "<tr><td style=\"background-color:#eff7ff;\">" .. v .. "</td>")
if dos then
table.insert(output, "<td>")
table.insert(output, export.orJoin(currentScript, forms[2 * i - 1], options))
table.insert(output, "</td>")
end
if dop then
table.insert(output, "<td>")
table.insert(output, export.orJoin(currentScript, forms[2 * i], options))
table.insert(output, "</td>")
end
table.insert(output, "</tr>")
end
end
table.insert(output, "</table></div></div>")
return table.concat(output)
end
function export.modify(forms, args)
local mod_default = 'after'
local params = {
[1] = {alias_of = 'stem'},
[2] = {alias_of = 'ending'},
[3] = {alias_of = 'g'},
stem = {},
ending = {},
g = {required = true},
gender = {alias_of = 'g'},
v = {},
variation = {alias_of = 'v'},
label = {},
number = {},
showtr = {},
subst = {},
sc = {},
aa = {default = 'default'},
liap = {default = 'default'},
impl = {default = 'yes'},
y = {default = 'default'},
nonom = {type = 'boolean'},
noms = {list = true},
noms_mod = {default = mod_default},
nomp = {list = true},
nomp_mod = {default = mod_default},
noacc = {type = 'boolean'},
accs = {list = true},
accs_mod = {default = mod_default},
accp = {list = true},
accp_mod = {default = mod_default},
noins = {type = 'boolean'},
inss = {list = true},
inss_mod = {default = mod_default},
insp = {list = true},
insp_mod = {default = mod_default},
nodat = {type = 'boolean'},
dats = {list = true},
dats_mod = {default = mod_default},
datp = {list = true},
datp_mod = {default = mod_default},
noabl = {type = 'boolean'},
abls = {list = true},
abls_mod = {default = mod_default},
ablp = {list = true},
ablp_mod = {default = mod_default},
nogen = {type = 'boolean'},
gens = {list = true},
gens_mod = {default = mod_default},
genp = {list = true},
genp_mod = {default = mod_default},
noloc = {type = 'boolean'},
locs = {list = true},
locs_mod = {default = mod_default},
locp = {list = true},
locp_mod = {default = mod_default},
novoc = {type = 'boolean'},
vocs = {list = true},
vocs_mod = {default = mod_default},
vocp = {list = true},
vocp_mod = {default = mod_default},
}
local at = m_parameters.process(args, params)
for i, v in ipairs(rows) do
local name = string.lower(string.sub(v,1,3))
if at['no'..name] then
forms[2*i] = {}
forms[2*i-1] = {}
else
local alts = at[name..'s']
if alts and #alts > 0 then
local way = at[name..'s_mod']
if 'after' == way then
forms[2*i-1] = arrcat(forms[2*i-1], alts)
elseif 'before' == way then
forms[2*i-1] = arrcat(alts, forms[2*i-1])
elseif 'replace' == way then
forms[2*i-1] = alts;
else
error('Bad value for parameter '..name..'s_mod')
end
end
alts = at[name..'p']
if alts and #alts > 0 then
local way = at[name..'p_mod']
if 'after' == way then
forms[2*i] = arrcat(forms[2*i], alts)
elseif 'before' == way then
forms[2*i] = arrcat(alts, forms[2*i])
elseif 'replace' == way then
forms[2*i] = alts;
else
error('Bad value for parameter '..name..'p_mod')
end
end
end
end
return forms;
end
function export.show(frame)
local args = frame:getParent().args
local PAGENAME = mw.title.getCurrentTitle().text
local stem = args[1] or args["stem"] or PAGENAME
currentScript = lang:findBestScript(stem)
scriptCode = currentScript:getCode()
if scriptCode == "None" and args["sc"] then
scriptCode = args["sc"]
currentScript = require("Module:scripts").getByCode(scriptCode, "No such script as "..scriptCode)
end
local g = args[3] or args["g"] or args["gender"] -- for each gender only
local variation = args["v"] or args["variation"] -- for some scripts
if not g then
error("A gender is required to display proper declensions.")
end
local lookup_g = g
if 'no' == lookup_g then lookup_g = 'm' end -- Arbitrary!
local option = {impl = args["impl"] or 'yes'}
local xlit_options = {}
xlit_options.impl = option.impl
xlit_options.showtr = args.showtr
local ending = args[2] or args["ending"] or export.detectEnding(stem, option)
if ending == 'ah' then xlit_options.impl = 'no' end
local selectedPattern =
export.getSuffixes(scriptCode, ending, lookup_g, option)
if args["liap"] and (scriptCode == 'Laoo') then
selectedPattern = liapise(selectedPattern, args["liap"])
end
if args.y and (scriptCode == 'Laoo') then
selectedPattern = yselect(selectedPattern, args.y)
xlit_options.y = args.y
end
option.aa = args["aa"] -- Reusable!
local forms = export.joinSuffixes(scriptCode, stem, selectedPattern, option)
export.modify(forms, args)
for ic = 1, 16 do forms[ic] = arrcat({}, forms[ic]) end -- Remove duplicates.
xlit_options.subst = args["subst"]
return export.present(args["label"] or stem, g, forms, args["number"], xlit_options)
end
return export