Module:pine-noun: Difference between revisions
Jump to navigation
Jump to search
(Created page with "local export = {} local m_u = require('Module:utilities') local m_l = require('Module:links') local m_pron = require('Module:pine-pron') local lang = require('Module:languages').getByCode("pine") local sub = mw.ustring.sub local find = mw.ustring.find local match = mw.ustring.match local gmatch = mw.ustring.gmatch local gsub = mw.ustring.gsub local u = mw.ustring.char local split = mw.text.split local gsplit = mw.text.gsplit local PAGENAME = mw.title.getCurrentTitle()...") |
No edit summary |
||
| (24 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
local m_u = require('Module:utilities') | local m_u = require('Module:utilities') | ||
local m_su = require('Module:string utilities') | |||
local m_l = require('Module:links') | local m_l = require('Module:links') | ||
local m_t = require('Module:table') | |||
local m_pron = require('Module:pine-pron') | local m_pron = require('Module:pine-pron') | ||
local m_data = require('Module:pine-noun/data') | |||
local lang = require('Module:languages').getByCode("pine") | local lang = require('Module:languages').getByCode("pine") | ||
local sub = | local sub = m_su.sub | ||
local find = | local find = m_su.find | ||
local match = | local match = m_su.match | ||
local gmatch = | local gmatch = m_su.gmatch | ||
local gsub = | local gsub = m_su.gsub | ||
local u = | local u = m_su.char | ||
local split = | local split = m_su.split | ||
local gsplit = | local gsplit = m_su.gsplit | ||
local len = m_su.len | |||
local unpack = unpack or table.unpack -- Lua 5.2 compatibility | |||
local PAGENAME = mw. | local PAGENAME = mw.loadData("Module:headword/data").pagename | ||
local NAMESPACE = mw.title.getCurrentTitle().nsText | --local NAMESPACE = mw.title.getCurrentTitle().nsText | ||
local function detect_decl(word) | local vowels = "[aeiouyůảẻỉỏủỷį]" | ||
local consonants = "[rṛtpsṡdḍgġhḥkḳlḷƛvbnṇmṃ]" | |||
local labial = m_t.listToSet({ | |||
"m", "ṃ", "p", "b", "v" | |||
}, "labial") | |||
local coronal = m_t.listToSet({ | |||
"t", "d", "ḍ", "s", "ṡ", "r", "ṛ", "l", "ḷ", "ƛ", "n", "ṇ", | |||
"ts", "tṡ", "lį", "ḷį", "nį", "ṇį", "dn", "ng", "kn" | |||
}, "coronal") | |||
local dorsal = m_t.listToSet({ | |||
"k", "g", "ġ", "h", "ḥ", | |||
"hį", "kṇ", "tġ" | |||
}, "dorsal") | |||
local front = m_t.listToSet({ | |||
"e", "i", "ů", "y", "ả", "ẻ", "ỉ", "ỷ", | |||
"ai", "ůa" | |||
}, "front") | |||
local back = m_t.listToSet({ | |||
"a", "o", "u", "ỏ", "ủ", | |||
"oa", "oi", | |||
}, "back") | |||
local function quality_lookup(segment, tables) | |||
if not segment then return nil end | |||
for _, tbl in ipairs(tables) do | |||
if tbl[segment] then return tbl[segment] end | |||
end | |||
-- fallback to first letter | |||
local first = sub(segment,1,1) | |||
for _, tbl in ipairs(tables) do | |||
if tbl[first] then return tbl[first] end | |||
end | |||
end | |||
local function detect_decl(word, args) | |||
local syllabified = m_pron.syllabify_from_spelling(word) | |||
--syllabified = gsub(syllabified, "·(" .. consonants .. ")%1", "%1·%1") | |||
--syllabified = gsub(syllabified, "t·(t[sṡ])", "%1·%1") | |||
local syllables = split(syllabified, "·") | |||
local syll_count = #syllables | |||
local stressed_syllable = syllables[1] | |||
local last_syllable = syllables[syll_count] | |||
local nucleus = match(stressed_syllable, "^" .. consonants .. "*į?(" .. vowels .. "+)") | |||
local last_vowel = match(last_syllable, "į?(" .. vowels .. "+)$") -- nil if consonant-final | |||
if syll_count == 1 then | |||
nucleus = not front[nucleus] and not back[nucleus] and sub(nucleus, 1, 1) or nucleus | |||
if last_vowel then | |||
last_vowel = not front[last_vowel] and not back[last_vowel] and sub(last_vowel, -1, -1) or last_vowel | |||
end | |||
end | |||
local polarity = {front, back} | |||
local pol_nucleus = quality_lookup(nucleus, polarity) | |||
local pol_last = quality_lookup(last_vowel, polarity) | |||
local phonicity = not last_vowel and "consonantal" or pol_nucleus == pol_last and "symphonic" or "antiphonic" | |||
local teleutophonic_ending = m_data.teleutophonic_ending(word) | |||
if teleutophonic_ending then | |||
return "teleutophonic-" .. teleuphonic_ending | |||
elseif syll_count == 1 then --monosyllabic | |||
-- "There is unfortunately no way to tell whether a monosyllabic noun ending in a consonant belongs to | |||
-- the consonantal declension group of the schizaphonic declension group" (p. 119) | |||
if phonicity == "consonantal" then | |||
if args.schiz == nil then | |||
error(word .. " is a monosyllabic noun ending in a consonant. Disambiguation is needed between consonantal and schizophonic declensions.") | |||
else | |||
return "monosyllabic-" .. (args.schiz and "schizaphonic" or "consonantal") | |||
end | |||
else | |||
return "monosyllabic-diphthongal-" .. phonicity | |||
end | |||
return phonicity | |||
else | |||
local onset = match(stressed_syllable, "^" .. consonants .. "+") -- nil if vowel-initial | |||
local coda = match(stressed_syllable, consonants .. "$") or match(syllables[2], "^" .. consonants .. "+") | |||
local poas = {labial, coronal, dorsal} | |||
local poa_onset = quality_lookup(onset, poas) | |||
local poa_coda = quality_lookup(coda, poas) | |||
local aphonicity = onset and "archeaphonic" or "enteraphonic" | |||
local organicity = poa_onset and (poa_onset == poa_coda and "homorganic" or "heterorganic") or nil | |||
if syll_count == 2 or syll_count == 4 then -- bi- and polysyllabic (4) | |||
return "bisyllabic-" .. (phonicity == "consonantal" and phonicity or aphonicity .. "-" .. (onset and organicity .. "-" or "") .. phonicity) | |||
elseif syll_count == 3 or syll_count >= 5 then -- trisyllabic and polysyllabic (5 or more) | |||
local last_cluster = match(word, "(" .. consonants .. "+)" .. vowels .. "*t?$") | |||
local asematic_endings = { | |||
{ "ng", "n" }, { "[tbnṇmṃd]?[nṇmṃ]", "n" }, | |||
{ "[lḷƛ]", "l" }, | |||
{ "^[rṛ]", "r" }, | |||
{ "^ḍ", "ts" }, { "^tt?[sṡ]", "ts" }, | |||
{ "^[sh]", "s" }, | |||
{ "^[ġḥvį]", "ġ" }, | |||
} | |||
local apocope = args.apo or "t" -- default to -t | |||
if not args.apo then | |||
for _, triggers_result in ipairs(spec) do | |||
local triggers, result = unpack(triggers_result) | |||
if match(last_cluster, triggers) then | |||
apocope = result | |||
end | |||
end | |||
end | |||
return "trisyllabic-" .. ((phonicity == "consonantal" and not args.apo) and phonicity or "apocoptic-" .. apocope) | |||
end | |||
end | |||
end | |||
local function make_table(data) | |||
local wikicode = mw.getCurrentFrame():expandTemplate{ | |||
title = 'inflection-table-top', | |||
args = { | |||
title = 'Declension of {word} ({decl})', | |||
palette = 'brown', | |||
} | |||
} .. [=[ | |||
| class="Tugv" style="font-size: 400%; color: #b41a00; min-width: 0" | <span style="position: relative; top: -10px;">x</span> | |||
! singular | |||
! plural | |||
|- | |||
! asematic | |||
| {word} | |||
| {word} | |||
|- | |||
! sematic | |||
| {word} | |||
| {word} | |||
|- | |||
! class="secondary" | inessive | |||
| {word} | |||
| {word} | |||
|- | |||
! class="secondary" | illative | |||
| {word} | |||
| {word} | |||
|- | |||
! class="secondary" | elative | |||
| {word} | |||
| {word} | |||
|- | |||
! class="secondary" | comitative | |||
| {word} | |||
| {word} | |||
|- | |||
! class="secondary" | essive | |||
| {word} | |||
| {word} | |||
|- | |||
]=] .. mw.getCurrentFrame():expandTemplate{ | |||
title = 'inflection-table-bottom', | |||
} | |||
local forms = {} | |||
forms.word = data.word | |||
forms.decl = data.decl | |||
return require('Module:string_utilities').format(wikicode, forms) | |||
end | end | ||
-- The main entry point. | -- The main entry point. | ||
function export.show(frame) | function export.show(frame) | ||
local params = { | |||
[1] = {default = pagename, template_default = "goka"}, | |||
["decl"] = {}, | |||
["schiz"] = {type = "boolean"}, | |||
["apo"] = {}, | |||
} | |||
local parent_args = frame:getParent().args | local parent_args = frame:getParent().args | ||
local args = require("Module:parameters").process(parent_args, params) | |||
local data = {} | |||
data.word = args[1] | |||
data.decl = args.decl or detect_decl(args[1], args.schiz) | |||
-- make the table | -- make the table | ||
| Line 29: | Line 214: | ||
end | end | ||
return export | return export | ||
Latest revision as of 00:37, 29 November 2025
- The following documentation is located at Module:pine-noun/doc.[edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
local export = {}
local m_u = require('Module:utilities')
local m_su = require('Module:string utilities')
local m_l = require('Module:links')
local m_t = require('Module:table')
local m_pron = require('Module:pine-pron')
local m_data = require('Module:pine-noun/data')
local lang = require('Module:languages').getByCode("pine")
local sub = m_su.sub
local find = m_su.find
local match = m_su.match
local gmatch = m_su.gmatch
local gsub = m_su.gsub
local u = m_su.char
local split = m_su.split
local gsplit = m_su.gsplit
local len = m_su.len
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local PAGENAME = mw.loadData("Module:headword/data").pagename
--local NAMESPACE = mw.title.getCurrentTitle().nsText
local vowels = "[aeiouyůảẻỉỏủỷį]"
local consonants = "[rṛtpsṡdḍgġhḥkḳlḷƛvbnṇmṃ]"
local labial = m_t.listToSet({
"m", "ṃ", "p", "b", "v"
}, "labial")
local coronal = m_t.listToSet({
"t", "d", "ḍ", "s", "ṡ", "r", "ṛ", "l", "ḷ", "ƛ", "n", "ṇ",
"ts", "tṡ", "lį", "ḷį", "nį", "ṇį", "dn", "ng", "kn"
}, "coronal")
local dorsal = m_t.listToSet({
"k", "g", "ġ", "h", "ḥ",
"hį", "kṇ", "tġ"
}, "dorsal")
local front = m_t.listToSet({
"e", "i", "ů", "y", "ả", "ẻ", "ỉ", "ỷ",
"ai", "ůa"
}, "front")
local back = m_t.listToSet({
"a", "o", "u", "ỏ", "ủ",
"oa", "oi",
}, "back")
local function quality_lookup(segment, tables)
if not segment then return nil end
for _, tbl in ipairs(tables) do
if tbl[segment] then return tbl[segment] end
end
-- fallback to first letter
local first = sub(segment,1,1)
for _, tbl in ipairs(tables) do
if tbl[first] then return tbl[first] end
end
end
local function detect_decl(word, args)
local syllabified = m_pron.syllabify_from_spelling(word)
--syllabified = gsub(syllabified, "·(" .. consonants .. ")%1", "%1·%1")
--syllabified = gsub(syllabified, "t·(t[sṡ])", "%1·%1")
local syllables = split(syllabified, "·")
local syll_count = #syllables
local stressed_syllable = syllables[1]
local last_syllable = syllables[syll_count]
local nucleus = match(stressed_syllable, "^" .. consonants .. "*į?(" .. vowels .. "+)")
local last_vowel = match(last_syllable, "į?(" .. vowels .. "+)$") -- nil if consonant-final
if syll_count == 1 then
nucleus = not front[nucleus] and not back[nucleus] and sub(nucleus, 1, 1) or nucleus
if last_vowel then
last_vowel = not front[last_vowel] and not back[last_vowel] and sub(last_vowel, -1, -1) or last_vowel
end
end
local polarity = {front, back}
local pol_nucleus = quality_lookup(nucleus, polarity)
local pol_last = quality_lookup(last_vowel, polarity)
local phonicity = not last_vowel and "consonantal" or pol_nucleus == pol_last and "symphonic" or "antiphonic"
local teleutophonic_ending = m_data.teleutophonic_ending(word)
if teleutophonic_ending then
return "teleutophonic-" .. teleuphonic_ending
elseif syll_count == 1 then --monosyllabic
-- "There is unfortunately no way to tell whether a monosyllabic noun ending in a consonant belongs to
-- the consonantal declension group of the schizaphonic declension group" (p. 119)
if phonicity == "consonantal" then
if args.schiz == nil then
error(word .. " is a monosyllabic noun ending in a consonant. Disambiguation is needed between consonantal and schizophonic declensions.")
else
return "monosyllabic-" .. (args.schiz and "schizaphonic" or "consonantal")
end
else
return "monosyllabic-diphthongal-" .. phonicity
end
return phonicity
else
local onset = match(stressed_syllable, "^" .. consonants .. "+") -- nil if vowel-initial
local coda = match(stressed_syllable, consonants .. "$") or match(syllables[2], "^" .. consonants .. "+")
local poas = {labial, coronal, dorsal}
local poa_onset = quality_lookup(onset, poas)
local poa_coda = quality_lookup(coda, poas)
local aphonicity = onset and "archeaphonic" or "enteraphonic"
local organicity = poa_onset and (poa_onset == poa_coda and "homorganic" or "heterorganic") or nil
if syll_count == 2 or syll_count == 4 then -- bi- and polysyllabic (4)
return "bisyllabic-" .. (phonicity == "consonantal" and phonicity or aphonicity .. "-" .. (onset and organicity .. "-" or "") .. phonicity)
elseif syll_count == 3 or syll_count >= 5 then -- trisyllabic and polysyllabic (5 or more)
local last_cluster = match(word, "(" .. consonants .. "+)" .. vowels .. "*t?$")
local asematic_endings = {
{ "ng", "n" }, { "[tbnṇmṃd]?[nṇmṃ]", "n" },
{ "[lḷƛ]", "l" },
{ "^[rṛ]", "r" },
{ "^ḍ", "ts" }, { "^tt?[sṡ]", "ts" },
{ "^[sh]", "s" },
{ "^[ġḥvį]", "ġ" },
}
local apocope = args.apo or "t" -- default to -t
if not args.apo then
for _, triggers_result in ipairs(spec) do
local triggers, result = unpack(triggers_result)
if match(last_cluster, triggers) then
apocope = result
end
end
end
return "trisyllabic-" .. ((phonicity == "consonantal" and not args.apo) and phonicity or "apocoptic-" .. apocope)
end
end
end
local function make_table(data)
local wikicode = mw.getCurrentFrame():expandTemplate{
title = 'inflection-table-top',
args = {
title = 'Declension of {word} ({decl})',
palette = 'brown',
}
} .. [=[
| class="Tugv" style="font-size: 400%; color: #b41a00; min-width: 0" | <span style="position: relative; top: -10px;">x</span>
! singular
! plural
|-
! asematic
| {word}
| {word}
|-
! sematic
| {word}
| {word}
|-
! class="secondary" | inessive
| {word}
| {word}
|-
! class="secondary" | illative
| {word}
| {word}
|-
! class="secondary" | elative
| {word}
| {word}
|-
! class="secondary" | comitative
| {word}
| {word}
|-
! class="secondary" | essive
| {word}
| {word}
|-
]=] .. mw.getCurrentFrame():expandTemplate{
title = 'inflection-table-bottom',
}
local forms = {}
forms.word = data.word
forms.decl = data.decl
return require('Module:string_utilities').format(wikicode, forms)
end
-- The main entry point.
function export.show(frame)
local params = {
[1] = {default = pagename, template_default = "goka"},
["decl"] = {},
["schiz"] = {type = "boolean"},
["apo"] = {},
}
local parent_args = frame:getParent().args
local args = require("Module:parameters").process(parent_args, params)
local data = {}
data.word = args[1]
data.decl = args.decl or detect_decl(args[1], args.schiz)
-- make the table
return make_table(data)
end
return export