Module:snon-headword: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
(23 intermediate revisions by the same user not shown)
Line 19: Line 19:
}
}


local function do_inflection(data, forms, label, accel)
local function glossary_link(...)
if forms and #forms > 0 then
return m_hw_util.glossary_link(...)
forms.label = label
end
if accel then
 
forms.accel = accel
local function insert_inflection(data, terms, label, accel)
end
m_hw_util.insert_inflection {
table.insert(data.inflections, forms)
headdata = data,
end
terms = terms,
label = label,
accel = accel and {form = accel} or nil,
}
end
end


Line 74: Line 77:
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------


local allowed_genders = m_table.listToSet(
local allowed_genders = m_table.listToSet{
    {"m", "f", "mf", "mfbysense", "mfequiv", "gneut", "n", "m-p", "f-p", "mf-p", "mfbysense-p", "mfequiv-p", "gneut-p", "n-p", "?", "?-p"}
"m", "f", "mf", "mfbysense", "mfequiv", "gneut", "n",
)
"m-p", "f-p", "mf-p", "mfbysense-p", "mfequiv-p", "gneut-p", "n-p",
"m-s", "f-s", "mf-s", "mfbysense-s", "mfequiv-s", "gneut-s", "n-s",
"?", "?-p", "?-s"
}


local function validate_genders(genders)
local function validate_genders(genders)
Line 108: Line 114:


local plurals = {}
local plurals = {}
local function insert_noun_inflection(terms, label, accel)
m_hw_util.insert_inflection {
headdata = data,
terms = terms,
label = label,
accel = accel and {form = accel} or nil,
}
end
local function make_plural(term)
local function make_plural(term)
return {{term .. "arr"}, {term .. "ar", l = "VE"}}
return {{term = term .. "ar"}}
end
end
Line 126: Line 123:
error("Can't specify plurals of plurale tantum " .. category_pos)
error("Can't specify plurals of plurale tantum " .. category_pos)
end
end
insert(data.inflections, {label = m_hw_util.glossary_link("plural only")})
else
else
plurals = m_hw_util.parse_term_list_with_modifiers {
plurals = m_hw_util.parse_term_list_with_modifiers {
Line 149: Line 145:
end
end
end
end
 
if args.mut then
local mutation = {
["r"] = "radical", ["l"] = "lenite", ["e"] = "eclipse"
}
table.insert(data.inflections, {label = mutation[args.mut]})
end
if is_plurale_tantum then
if is_plurale_tantum then
-- both singular and plural
-- both singular and plural
insert(data.inflections, {label = "sometimes " .. m_hw_util.glossary_link("plural only") .. ", in variation"})
table.insert(data.inflections, {label = "sometimes " .. glossary_link("plural only") .. ", in variation"})
end
end
if mode == "?" then
if mode == "?" then
-- Plural is unknown
-- Plural is unknown
insert(data.categories, langname .. " " .. category_plpos .. " with unknown or uncertain plurals")
table.insert(data.categories, langname .. " " .. data.pos_category .. " with unknown or uncertain plurals")
elseif mode == "!" then
elseif mode == "!" then
-- Plural is not attested
-- Plural is not attested
insert(data.inflections, {label = "plural not attested"})
table.insert(data.inflections, {label = "plural not attested"})
insert(data.categories, langname .. " " .. category_plpos .. " with unattested plurals")
table.insert(data.categories, langname .. " " .. data.pos_category .. " with unattested plurals")
if plurals[1] then
if plurals[1] then
error("Can't specify any plurals along with unattested plural code '!'")
error("Can't specify any plurals along with unattested plural code '!'")
Line 166: Line 170:
elseif mode == "-" then
elseif mode == "-" then
-- Uncountable noun; may occasionally have a plural
-- Uncountable noun; may occasionally have a plural
insert(data.categories, langname .. " uncountable " .. category_plpos)
table.insert(data.categories, langname .. " uncountable " .. data.pos_category)


-- If plural forms were given explicitly, then show "usually"
-- If plural forms were given explicitly, then show "usually"
if plurals[1] then
if plurals[1] then
insert(data.inflections, {label = "usually " .. m_hw_util.glossary_link("uncountable")})
table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")})
insert(data.categories, langname .. " countable " .. category_plpos)
table.insert(data.categories, langname .. " countable " .. data.pos_category)
else
else
insert(data.inflections, {label = m_hw_util.glossary_link("uncountable")})
table.insert(data.inflections, {label = glossary_link("uncountable")})
end
end
else
else
Line 182: Line 186:
if mode == "~" then
if mode == "~" then
-- Mixed countable/uncountable noun, always has a plural
-- Mixed countable/uncountable noun, always has a plural
insert(data.inflections, {label = m_hw_util.glossary_link("countable") .. " and " .. m_hw_util.glossary_link("uncountable")})
table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")})
insert(data.categories, langname .. " uncountable " .. category_plpos)
table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
insert(data.categories, langname .. " countable " .. category_plpos)
table.insert(data.categories, langname .. " countable " .. data.pos_category)
elseif plurals[1] then
elseif plurals[1] then
-- Countable nouns
-- Countable nouns
insert(data.categories, langname .. " countable " .. category_plpos)
table.insert(data.categories, langname .. " countable " .. data.pos_category)
else
else
-- Uncountable nouns
-- Uncountable nouns
insert(data.categories, langname .. " uncountable " .. category_plpos)
table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
end
end
end
end


-- Gather plurals, handling requests for default plurals.
local new_plurals = {}
local has_default_or_hash = false
for _, pl in ipairs(plurals) do
for _, pl in ipairs(plurals) do
if pl.term:find("^%+") or pl.term:find("#") then
if pl.term == "+" then
has_default_or_hash = true
for _, generated_pl in ipairs(make_plural(lemma)) do
break
table.insert(new_plurals, generated_pl)
end
end
 
if has_default_or_hash then
for _, pl in ipairs(plurals) do
if pl.term == "+" then
-- make_plural should never return nil
pl = make_plural(lemma)
end
end
else
table.insert(new_plurals, pl)
end
end
end
end
plurals = new_plurals


insert_noun_inflection(plurals, "plural", "p")
insert_inflection(data, plurals, "plural", "p")


if plurals[2] then
if plurals[2] then
insert(data.categories, langname .. " " .. category_plpos .. " with multiple plurals")
table.insert(data.categories, langname .. " " .. data.pos_category .. " with multiple plurals")
end
end
end
end
Line 224: Line 222:
[1] = {list = "g", disallow_holes = true, required = not is_proper, default = "?", type = "genders", flatten = true},
[1] = {list = "g", disallow_holes = true, required = not is_proper, default = "?", type = "genders", flatten = true},
[2] = {list = "pl", disallow_holes = true},
[2] = {list = "pl", disallow_holes = true},
["w"] = {list = true, disallow_holes = true},
["mut"] = {set = {"r", "l", "e"}}
}
}
end
end
Line 238: Line 236:
do_noun(args, data, "is proper noun")
do_noun(args, data, "is proper noun")
end,
end,
}
-----------------------------------------------------------------------------------------
--                                Adjectives                                          --
-----------------------------------------------------------------------------------------
local function do_adj(args, data)
local category_pos = m_en_util.singularize(data.pos_category)
local lemma = data.pagename
if args.inv then
-- invariable adjective
table.insert(data.inflections, {label = glossary_link("invariable")})
table.insert(data.categories, langname .. " indeclinable " .. data.pos_category)
else
local comps = m_hw_util.parse_term_list_with_modifiers {
paramname = "comp",
forms = args.comp,
splitchar = ",",
}
if not comps[1] then
comps = {{term = lemma .. "ir"}}
else
local new_comps = {}
for _, c in ipairs(comps) do
if c.term == "+" then
table.insert(new_comps, {term = lemma .. "ir"})
else
table.insert(new_comps, c)
end
end
comps = new_comps
end
local sups = m_hw_util.parse_term_list_with_modifiers {
paramname = "sup",
forms = args.sup,
splitchar = ",",
}
if not sups[1] then
sups = {{term = lemma .. "ist"}}
else
local new_sups = {}
for _, s in ipairs(sups) do
if s.term == "+" then
table.insert(new_sups, {term = lemma .. "ist"})
else
table.insert(new_sups, s)
end
end
sups = new_sups
end
insert_inflection(data, comps, "comparative", "comp")
insert_inflection(data, sups, "superlative", "sup")
end
end
pos_functions["adjectives"] = {
params = {
["sup"] = {list = true, disallow_holes = true},
["comp"] = {list = true, disallow_holes = true},
["inv"] = {type = "boolean"},
},
func = do_adj,
}
-----------------------------------------------------------------------------------------
--                                    Verbs                                          --
-----------------------------------------------------------------------------------------
local function do_verb(args, data)
local category_pos = m_en_util.singularize(data.pos_category)
local lemma = data.pagename
if args.irr then
-- irregular verb
table.insert(data.categories, langname .. " irregular verbs")
else
local presents = m_hw_util.parse_term_list_with_modifiers {
paramname = "pres",
forms = args.pres,
splitchar = ",",
}
if not presents[1] then
presents = {{term = lemma .. "ir"}}
else
local new_presents = {}
for _, p in ipairs(presents) do
if p.term == "+" then
table.insert(new_presents, {term = lemma .. "ir"})
else
table.insert(new_presents, p)
end
end
presents = new_presents
end
local pasts = m_hw_util.parse_term_list_with_modifiers {
paramname = "past",
forms = args.past,
splitchar = ",",
}
if not pasts[1] then
pasts = {{term = lemma .. "adhir"}}
else
local new_pasts = {}
for _, p in ipairs(pasts) do
if p.term == "+" then
table.insert(new_pasts, {term = lemma .. "adhir"})
else
table.insert(new_pasts, p)
end
end
pasts = new_pasts
end
local futures = m_hw_util.parse_term_list_with_modifiers {
paramname = "fut",
forms = args.fut,
splitchar = ",",
}
if not futures[1] then
futures = {{term = lemma .. "ist"}}
else
local new_futures = {}
for _, f in ipairs(futures) do
if f.term == "+" then
table.insert(new_futures, {term = lemma .. "ist"})
else
table.insert(new_futures, f)
end
end
futures = new_futures
end
local statives = m_hw_util.parse_term_list_with_modifiers {
paramname = "stat",
forms = args.stat,
splitchar = ",",
}
if not statives[1] then
statives = {{term = lemma .. "adhist"}}
else
local new_statives = {}
for _, s in ipairs(statives) do
if s.term == "+" then
table.insert(new_statives, {term = lemma .. "adhist"})
else
table.insert(new_statives, s)
end
end
statives = new_statives
end
insert_inflection(data, presents, "present")
insert_inflection(data, pasts, "past")
insert_inflection(data, futures, "future")
insert_inflection(data, statives, "stative")
end
end
pos_functions["verbs"] = {
params = {
["pres"] = {list = true, disallow_holes = true},
["past"] = {list = true, disallow_holes = true},
["fut"] = {list = true, disallow_holes = true},
["stat"] = {list = true, disallow_holes = true},
["irr"] = {type = "boolean"},
},
func = do_verb,
}
}


return export
return export

Latest revision as of 20:10, 7 May 2026



local export = {}
local pos_functions = {}

local m_links = require("Module:links")
local m_table = require("Module:table")
local m_en_util = require("Module:en-utilities")
local m_hw_util = require("Module:headword utilities")

local lang = require("Module:languages").getByCode("snon")
local langname = lang:getCanonicalName()

local pagename = mw.loadData("Module:headword/data").pagename

local suffix_categories = {
	["adjectives"] = true,
	["adverbs"] = true,
	["nouns"] = true,
	["verbs"] = true,
}

local function glossary_link(...)
	return m_hw_util.glossary_link(...)
end

local function insert_inflection(data, terms, label, accel)
	m_hw_util.insert_inflection {
		headdata = data,
		terms = terms,
		label = label,
		accel = accel and {form = accel} or nil,
	}
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")
	local parargs = frame:getParent().args

	local params = {
		["head"] = {list = true, disallow_holes = true},
		["nomut"] = {type = "boolean"},
	}

	if pos_functions[poscat] then
		for key, val in pairs(pos_functions[poscat].params) do
			params[key] = val
		end
	end

	local args = require("Module:parameters").process(parargs, params)

	local heads = args.head
	if #heads == 0 then
		heads = {pagename}
	end

	local data = {
		lang = lang,
		pos_category = poscat,
		categories = {},
		heads = heads,
		genders = {},
		inflections = {},
		pagename = pagename,
	}

	if pos_functions[poscat] then
		pos_functions[poscat].func(args, data)
	end

	return require("Module:headword").full_headword(data)
end

-----------------------------------------------------------------------------------------
--                                          Nouns                                      --
-----------------------------------------------------------------------------------------

local allowed_genders = m_table.listToSet{
	"m", "f", "mf", "mfbysense", "mfequiv", "gneut", "n",
	"m-p", "f-p", "mf-p", "mfbysense-p", "mfequiv-p", "gneut-p", "n-p",
	"m-s", "f-s", "mf-s", "mfbysense-s", "mfequiv-s", "gneut-s", "n-s",
	"?", "?-p", "?-s"
}

local function validate_genders(genders)
	for _, g in ipairs(genders) do
		if type(g) == "table" then
			g = g.spec
		end
		if not allowed_genders[g] then
			error("Unrecognized gender: " .. g)
		end
	end
end

local function do_noun(args, data, is_proper)
	local is_plurale_tantum = false
	local category_pos = m_en_util.singularize(data.pos_category)

	validate_genders(args[1])
	data.genders = args[1]
	-- Check for specific genders and pluralia tantum.
	for _, g in ipairs(args[1]) do
		if type(g) == "table" then
			g = g.spec
		end
		if g:find("-p$") then
			is_plurale_tantum = true
		end
	end

	local lemma = data.pagename

	local plurals = {}
	
	local function make_plural(term)
		return {{term = term .. "ar"}}
	end
	
	if is_plurale_tantum then
		if args[2][1] then
			error("Can't specify plurals of plurale tantum " .. category_pos)
		end
	else
		plurals = m_hw_util.parse_term_list_with_modifiers {
			paramname = {2, "pl"},
			forms = args[2],
			splitchar = ",",
		}
		-- Check for special plural signals
		local mode = nil

		local pl1 = plurals[1]
		if pl1 and #pl1.term == 1 then
			mode = pl1.term
			if mode == "?" or mode == "!" or mode == "-" or mode == "~" then
				pl1.term = nil
				if next(pl1) then
					error(("Can't specify inline modifiers with plural code '%s'"):format(mode))
				end
				table.remove(plurals, 1)  -- Remove the mode parameter
			elseif mode ~= "+" and mode ~= "#" then
				error(("Unexpected plural code '%s'"):format(mode))
			end
		end
		
		if args.mut then
			local mutation = {
				["r"] = "radical", ["l"] = "lenite", ["e"] = "eclipse"
			}
			
			table.insert(data.inflections, {label = mutation[args.mut]})
		end
		
		if is_plurale_tantum then
			-- both singular and plural
			table.insert(data.inflections, {label = "sometimes " .. glossary_link("plural only") .. ", in variation"})
		end
		if mode == "?" then
			-- Plural is unknown
			table.insert(data.categories, langname .. " " .. data.pos_category .. " with unknown or uncertain plurals")
		elseif mode == "!" then
			-- Plural is not attested
			table.insert(data.inflections, {label = "plural not attested"})
			table.insert(data.categories, langname .. " " .. data.pos_category .. " with unattested plurals")
			if plurals[1] then
				error("Can't specify any plurals along with unattested plural code '!'")
			end
		elseif mode == "-" then
			-- Uncountable noun; may occasionally have a plural
		table.insert(data.categories, langname .. " uncountable " .. data.pos_category)

			-- If plural forms were given explicitly, then show "usually"
			if plurals[1] then
				table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")})
				table.insert(data.categories, langname .. " countable " .. data.pos_category)
			else
				table.insert(data.inflections, {label = glossary_link("uncountable")})
			end
		else
			-- Countable or mixed countable/uncountable
			if not plurals[1] and not is_proper then
				plurals[1] = {term = "+"}
			end
			if mode == "~" then
				-- Mixed countable/uncountable noun, always has a plural
				table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")})
				table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
				table.insert(data.categories, langname .. " countable " .. data.pos_category)
			elseif plurals[1] then
				-- Countable nouns
				table.insert(data.categories, langname .. " countable " .. data.pos_category)
			else
				-- Uncountable nouns
				table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
			end
		end

		local new_plurals = {}
		for _, pl in ipairs(plurals) do
			if pl.term == "+" then
				for _, generated_pl in ipairs(make_plural(lemma)) do
					table.insert(new_plurals, generated_pl)
				end
			else
				table.insert(new_plurals, pl)
			end
		end
		plurals = new_plurals

		insert_inflection(data, plurals, "plural", "p")

		if plurals[2] then
			table.insert(data.categories, langname .. " " .. data.pos_category .. " with multiple plurals")
		end
	end
end

local function get_noun_params(is_proper)
	return {
		[1] = {list = "g", disallow_holes = true, required = not is_proper, default = "?", type = "genders", flatten = true},
		[2] = {list = "pl", disallow_holes = true},
		["mut"] = {set = {"r", "l", "e"}}
	}
end

pos_functions["nouns"] = {
	params = get_noun_params(),
	func = do_noun,
}

pos_functions["proper nouns"] = {
	params = get_noun_params("is proper"),
	func = function(args, data)
		do_noun(args, data, "is proper noun")
	end,
}

-----------------------------------------------------------------------------------------
--                                 Adjectives                                          --
-----------------------------------------------------------------------------------------

local function do_adj(args, data)
	local category_pos = m_en_util.singularize(data.pos_category)
	local lemma = data.pagename
	
	if args.inv then
		-- invariable adjective
		table.insert(data.inflections, {label = glossary_link("invariable")})
		table.insert(data.categories, langname .. " indeclinable " .. data.pos_category)
	else
		local comps = m_hw_util.parse_term_list_with_modifiers {
			paramname = "comp",
			forms = args.comp,
			splitchar = ",",
		}
		
		if not comps[1] then
			comps = {{term = lemma .. "ir"}}
		else
			local new_comps = {}
			for _, c in ipairs(comps) do
				if c.term == "+" then
					table.insert(new_comps, {term = lemma .. "ir"})
				else
					table.insert(new_comps, c)
				end
			end
			comps = new_comps
		end
		
		local sups = m_hw_util.parse_term_list_with_modifiers {
			paramname = "sup",
			forms = args.sup,
			splitchar = ",",
		}
		
		if not sups[1] then
			sups = {{term = lemma .. "ist"}}
		else
			local new_sups = {}
			for _, s in ipairs(sups) do
				if s.term == "+" then
					table.insert(new_sups, {term = lemma .. "ist"})
				else
					table.insert(new_sups, s)
				end
			end
			sups = new_sups
		end
	
		insert_inflection(data, comps, "comparative", "comp")
		insert_inflection(data, sups, "superlative", "sup")
	end
end

pos_functions["adjectives"] = {
	params = {
		["sup"] = {list = true, disallow_holes = true},
		["comp"] = {list = true, disallow_holes = true},
		["inv"] = {type = "boolean"},
	},
	func = do_adj,
}

-----------------------------------------------------------------------------------------
--                                     Verbs                                           --
-----------------------------------------------------------------------------------------

local function do_verb(args, data)
	local category_pos = m_en_util.singularize(data.pos_category)
	local lemma = data.pagename
	
	if args.irr then
		-- irregular verb
		table.insert(data.categories, langname .. " irregular verbs")
	else
		local presents = m_hw_util.parse_term_list_with_modifiers {
			paramname = "pres",
			forms = args.pres,
			splitchar = ",",
		}
		
		if not presents[1] then
			presents = {{term = lemma .. "ir"}}
		else
			local new_presents = {}
			for _, p in ipairs(presents) do
				if p.term == "+" then
					table.insert(new_presents, {term = lemma .. "ir"})
				else
					table.insert(new_presents, p)
				end
			end
			presents = new_presents
		end
		
		local pasts = m_hw_util.parse_term_list_with_modifiers {
			paramname = "past",
			forms = args.past,
			splitchar = ",",
		}
		
		if not pasts[1] then
			pasts = {{term = lemma .. "adhir"}}
		else
			local new_pasts = {}
			for _, p in ipairs(pasts) do
				if p.term == "+" then
					table.insert(new_pasts, {term = lemma .. "adhir"})
				else
					table.insert(new_pasts, p)
				end
			end
			pasts = new_pasts
		end
		
		local futures = m_hw_util.parse_term_list_with_modifiers {
			paramname = "fut",
			forms = args.fut,
			splitchar = ",",
		}
		
		if not futures[1] then
			futures = {{term = lemma .. "ist"}}
		else
			local new_futures = {}
			for _, f in ipairs(futures) do
				if f.term == "+" then
					table.insert(new_futures, {term = lemma .. "ist"})
				else
					table.insert(new_futures, f)
				end
			end
			futures = new_futures
		end
		
		local statives = m_hw_util.parse_term_list_with_modifiers {
			paramname = "stat",
			forms = args.stat,
			splitchar = ",",
		}
		
		if not statives[1] then
			statives = {{term = lemma .. "adhist"}}
		else
			local new_statives = {}
			for _, s in ipairs(statives) do
				if s.term == "+" then
					table.insert(new_statives, {term = lemma .. "adhist"})
				else
					table.insert(new_statives, s)
				end
			end
			statives = new_statives
		end
	
		insert_inflection(data, presents, "present")
		insert_inflection(data, pasts, "past")
		insert_inflection(data, futures, "future")
		insert_inflection(data, statives, "stative")
	end
end

pos_functions["verbs"] = {
	params = {
		["pres"] = {list = true, disallow_holes = true},
		["past"] = {list = true, disallow_holes = true},
		["fut"] = {list = true, disallow_holes = true},
		["stat"] = {list = true, disallow_holes = true},
		["irr"] = {type = "boolean"},
	},
	func = do_verb,
}

return export