Module:pine-noun: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
(14 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_t = require('Module:table')
Line 8: Line 9:
local lang = require('Module:languages').getByCode("pine")
local lang = require('Module:languages').getByCode("pine")


local sub = mw.ustring.sub
local sub = m_su.sub
local find = mw.ustring.find
local find = m_su.find
local match = mw.ustring.match
local match = m_su.match
local gmatch = mw.ustring.gmatch
local gmatch = m_su.gmatch
local gsub = mw.ustring.gsub
local gsub = m_su.gsub
local u = mw.ustring.char
local u = m_su.char
local split = mw.text.split
local split = m_su.split
local gsplit = mw.text.gsplit
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 PAGENAME = mw.loadData("Module:headword/data").pagename
Line 54: Line 57:
     end
     end
     -- fallback to first letter
     -- fallback to first letter
     local first = segment:sub(1,1)
     local first = sub(segment,1,1)
     for _, tbl in ipairs(tables) do
     for _, tbl in ipairs(tables) do
         if tbl[first] then return tbl[first] end
         if tbl[first] then return tbl[first] end
Line 60: Line 63:
end
end


local function detect_decl(word, schiz)
local function detect_decl(word, args)
local syllabified = m_pron.syllabify_from_spelling(word)
local syllabified = m_pron.syllabify_from_spelling(word)
--syllabified = gsub(syllabified, "·(" .. consonants .. ")%1", "%1·%1")
--syllabified = gsub(syllabified, "·(" .. consonants .. ")%1", "%1·%1")
Line 71: Line 74:
local nucleus = match(stressed_syllable, "^" .. consonants .. "*į?(" .. vowels .. "+)")
local nucleus = match(stressed_syllable, "^" .. consonants .. "*į?(" .. vowels .. "+)")
local last_vowel = match(last_syllable, "(" .. vowels .. "+)$") -- nil if consonant-final
local last_vowel = match(last_syllable, "į?(" .. vowels .. "+)$") -- nil if consonant-final
--[[if syll_count == 1 then
if syll_count == 1 then
nucleus = sub(gsub(nucleus, "į",""), 1, 1)
nucleus = not front[nucleus] and not back[nucleus] and sub(nucleus, 1, 1) or nucleus
if last_vowel then
if last_vowel then
last_vowel = sub(last_vowel, -1, -1)
last_vowel = not front[last_vowel] and not back[last_vowel] and sub(last_vowel, -1, -1) or last_vowel
end
end
end]]
end
local polarity = {front, back}
local polarity = {front, back}
Line 84: Line 87:
local phonicity = not last_vowel and "consonantal" or pol_nucleus == pol_last and "symphonic" or "antiphonic"
local phonicity = not last_vowel and "consonantal" or pol_nucleus == pol_last and "symphonic" or "antiphonic"
if m_data.teleutophonic_ending(word) then
local teleutophonic_ending = m_data.teleutophonic_ending(word)
if teleutophonic_ending then
return "teleutophonic-" .. teleuphonic_ending
return "teleutophonic-" .. teleuphonic_ending
elseif syll_count == 1 then --monosyllabic
elseif syll_count == 1 then --monosyllabic
-- "There is unfortunately no way to tell whether a monosyllabic noun ending in a consonant belongs to
-- "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)
-- the consonantal declension group of the schizaphonic declension group" (p. 119)
if phoniticy == "consonantal" then
if phonicity == "consonantal" then
if args.schiz ~= nil then
if args.schiz == nil then
return "monosyllabic-" .. (schiz .. "schizophonic" or "consonantal")
error(word .. " is a monosyllabic noun ending in a consonant. Disambiguation is needed between consonantal and schizophonic declensions.")
else
else
error(word .. " is a monosyllabic noun ending in a consonant. Disambiguation is needed between consonantal and schizophonic declensions.")
return "monosyllabic-" .. (args.schiz and "schizaphonic" or "consonantal")
end
end
else
else
return "monosyllabic-diphthongal-" .. phonicity
return "monosyllabic-diphthongal-" .. phonicity
end
end
return phonicity
else
else
local onset = match(stressed_syllable, "^" .. consonants .. "+") -- nil if vowel-initial
local onset = match(stressed_syllable, "^" .. consonants .. "+") -- nil if vowel-initial
Line 108: Line 113:
local organicity = poa_onset and (poa_onset == poa_coda and "homorganic" or "heterorganic") or nil
local organicity = poa_onset and (poa_onset == poa_coda and "homorganic" or "heterorganic") or nil
if syll_count == 2 then --bisyllabic
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)
return "bisyllabic-" .. (phonicity == "consonantal" and phonicity or aphonicity .. "-" .. (onset and organicity .. "-" or "") .. phonicity)
elseif syll_count == 3 then --trisyllabic
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
end
Line 117: Line 143:


local function make_table(data)
local function make_table(data)
return data.decl
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


Line 125: Line 199:
[1] = {default = pagename, template_default = "goka"},
[1] = {default = pagename, template_default = "goka"},
["decl"] = {},
["decl"] = {},
["schiz"] = {},
["schiz"] = {type = "boolean"},
["apo"] = {},
}
}


Line 132: Line 207:
local data = {}
local data = {}
data.word = args[1]
data.decl = args.decl or detect_decl(args[1], args.schiz)
data.decl = args.decl or detect_decl(args[1], args.schiz)

Latest revision as of 00:37, 29 November 2025



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