Module:snon-headword: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| (25 intermediate revisions by the same user not shown) | |||
| Line 19: | Line 19: | ||
} | } | ||
local function | 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 | end | ||
-- The main entry point. | -- The main entry point. | ||
function export.show(frame) | 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 poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") | ||
| Line 74: | Line 76: | ||
----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ||
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", | |||
"m-s", "f-s", "mf-s", "mfbysense-s", "mfequiv-s", "gneut-s", "n-s", | |||
"?", "?-p", "?-s" | |||
} | |||
-- Extensible table for default plural endings by gender | |||
local default_plural_endings = { | |||
m = "ar", | |||
f = "ir", | |||
-- Easily add more later, e.g., n = "ur" | |||
} | |||
local function validate_genders(genders) | local function validate_genders(genders) | ||
| Line 87: | Line 99: | ||
end | end | ||
end | end | ||
end | |||
-- Extracts the base gender ("m", "f", etc.) ignoring number suffixes like "-p" or "-s" | |||
local function get_base_gender(g) | |||
if type(g) == "table" then g = g.spec end | |||
g = g:gsub("%-p$", ""):gsub("%-s$", "") | |||
if g == "mf" then return {"m", "f"} end | |||
if default_plural_endings[g] then return {g} end | |||
return {} | |||
end | end | ||
| Line 95: | Line 116: | ||
validate_genders(args[1]) | validate_genders(args[1]) | ||
data.genders = args[1] | data.genders = args[1] | ||
-- Check for specific genders and pluralia tantum. | -- Check for specific genders and pluralia tantum. | ||
local base_genders_present = {} | |||
for _, g in ipairs(args[1]) do | for _, g in ipairs(args[1]) do | ||
if type(g) == "table" then | if type(g) == "table" then | ||
| Line 102: | Line 125: | ||
if g:find("-p$") then | if g:find("-p$") then | ||
is_plurale_tantum = true | is_plurale_tantum = true | ||
end | |||
for _, bg in ipairs(get_base_gender(g)) do | |||
base_genders_present[bg] = true | |||
end | end | ||
end | end | ||
local lemma = data.pagename | local lemma = data.pagename | ||
local plurals = {} | local plurals = {} | ||
if is_plurale_tantum then | if is_plurale_tantum then | ||
| Line 126: | Line 139: | ||
error("Can't specify plurals of plurale tantum " .. category_pos) | error("Can't specify plurals of plurale tantum " .. category_pos) | ||
end | end | ||
else | else | ||
plurals = m_hw_util.parse_term_list_with_modifiers { | plurals = m_hw_util.parse_term_list_with_modifiers { | ||
| Line 133: | Line 145: | ||
splitchar = ",", | splitchar = ",", | ||
} | } | ||
-- Check for special plural signals | -- Check for special plural signals | ||
local mode = nil | local mode = nil | ||
local pl1 = plurals[1] | local pl1 = plurals[1] | ||
if pl1 and #pl1.term == 1 then | if pl1 and #pl1.term == 1 then | ||
| Line 149: | Line 161: | ||
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 | ||
table.insert(data.inflections, {label = "sometimes " .. glossary_link("plural only") .. ", in variation"}) | |||
end | end | ||
if mode == "?" then | if mode == "?" then | ||
table.insert(data.categories, langname .. " " .. data.pos_category .. " with unknown or uncertain plurals") | |||
elseif mode == "!" then | elseif mode == "!" then | ||
table.insert(data.inflections, {label = "plural not attested"}) | |||
table.insert(data.categories, langname .. " " .. data.pos_category .. " with unattested plurals") | |||
insert(data.categories, langname .. " " .. | |||
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 '!'") | ||
end | end | ||
elseif mode == "-" then | elseif mode == "-" then | ||
table.insert(data.categories, langname .. " uncountable " .. data.pos_category) | |||
if plurals[1] then | if plurals[1] then | ||
insert(data.inflections, {label = "usually " . | table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) | ||
insert(data.categories, langname .. " countable " .. | table.insert(data.categories, langname .. " countable " .. data.pos_category) | ||
else | else | ||
insert(data.inflections, {label = | table.insert(data.inflections, {label = glossary_link("uncountable")}) | ||
end | end | ||
else | else | ||
if not plurals[1] and not is_proper then | if not plurals[1] and not is_proper then | ||
plurals[1] = {term = "+"} | plurals[1] = {term = "+"} | ||
end | end | ||
if mode == "~" then | if mode == "~" then | ||
table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) | |||
table.insert(data.categories, langname .. " uncountable " .. data.pos_category) | |||
insert(data.categories, langname .. " uncountable " .. | table.insert(data.categories, langname .. " countable " .. data.pos_category) | ||
insert(data.categories, langname .. " countable " .. | |||
elseif plurals[1] then | elseif plurals[1] then | ||
table.insert(data.categories, langname .. " countable " .. data.pos_category) | |||
else | else | ||
table.insert(data.categories, langname .. " uncountable " .. data.pos_category) | |||
end | end | ||
end | end | ||
local new_plurals = {} | |||
local | |||
for _, pl in ipairs(plurals) do | for _, pl in ipairs(plurals) do | ||
if pl.term | if pl.term == "+" then | ||
local generated_any = false | |||
-- Generate default plurals for all matched base genders | |||
for bg, _ in pairs(base_genders_present) do | |||
table.insert(new_plurals, {term = lemma .. default_plural_endings[bg]}) | |||
generated_any = true | |||
end | |||
-- Fallback if no specific gender mapped | |||
if not generated_any then | |||
table.insert(new_plurals, {term = lemma .. "ar"}) | |||
end | end | ||
else | |||
table.insert(new_plurals, pl) | |||
end | end | ||
end | end | ||
plurals = new_plurals | |||
insert_inflection(data, plurals, "plural", "p") | |||
if plurals[2] then | if plurals[2] then | ||
insert(data.categories, langname .. " " .. | table.insert(data.categories, langname .. " " .. data.pos_category .. " with multiple plurals") | ||
end | |||
end | |||
-- Generalized handler for other gendered forms with specific default suffixes | |||
local function process_gender_form(param, label, accel, default_suffix) | |||
local forms = m_hw_util.parse_term_list_with_modifiers { | |||
paramname = param, | |||
forms = args[param], | |||
splitchar = ",", | |||
} | |||
if forms[1] then | |||
local new_forms = {} | |||
for _, f in ipairs(forms) do | |||
if f.term == "+" and default_suffix then | |||
table.insert(new_forms, {term = lemma .. default_suffix}) | |||
else | |||
table.insert(new_forms, f) | |||
end | |||
end | |||
insert_inflection(data, new_forms, label, accel) | |||
end | end | ||
end | end | ||
process_gender_form("m", "masculine", "m") | |||
process_gender_form("f", "feminine", "f") | |||
process_gender_form("mpl", "masculine plural", "m|p", default_plural_endings["m"]) | |||
process_gender_form("fpl", "feminine plural", "f|p", default_plural_endings["f"]) | |||
-- Extensible for new forms like neuter: | |||
-- process_gender_form("n", "neuter", "n") | |||
-- process_gender_form("npl", "neuter plural", "n|p", default_plural_endings["n"]) | |||
end | end | ||
| Line 224: | Line 263: | ||
[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}, | ||
[" | ["m"] = {list = true}, | ||
["f"] = {list = true}, | |||
["mpl"] = {list = true}, | |||
["fpl"] = {list = true}, | |||
["mut"] = {set = {"r", "l", "e"}} | |||
} | } | ||
end | end | ||
| Line 238: | Line 281: | ||
do_noun(args, data, "is proper noun") | do_noun(args, data, "is proper noun") | ||
end, | end, | ||
} | |||
----------------------------------------------------------------------------------------- | |||
-- Adjectives -- | |||
----------------------------------------------------------------------------------------- | |||
local function do_adj(args, data) | |||
local lemma = data.pagename | |||
if args.inv then | |||
table.insert(data.inflections, {label = glossary_link("invariable")}) | |||
table.insert(data.categories, langname .. " indeclinable " .. data.pos_category) | |||
else | |||
local function process_adj_form(param, default_suffix, label, accel) | |||
local forms = m_hw_util.parse_term_list_with_modifiers { | |||
paramname = param, | |||
forms = args[param], | |||
splitchar = ",", | |||
} | |||
if not forms[1] then | |||
forms = {{term = lemma .. default_suffix}} | |||
else | |||
local new_forms = {} | |||
for _, f in ipairs(forms) do | |||
if f.term == "+" then | |||
table.insert(new_forms, {term = lemma .. default_suffix}) | |||
else | |||
table.insert(new_forms, f) | |||
end | |||
end | |||
forms = new_forms | |||
end | |||
insert_inflection(data, forms, label, accel) | |||
end | |||
process_adj_form("comp", "ar", "comparative", "comp") | |||
process_adj_form("sup", "ast", "superlative", "sup") | |||
end | |||
end | |||
pos_functions["adjectives"] = { | |||
params = { | |||
["comp"] = {list = true, disallow_holes = true}, | |||
["sup"] = {list = true, disallow_holes = true}, | |||
["inv"] = {type = "boolean"}, | |||
}, | |||
func = do_adj, | |||
} | |||
----------------------------------------------------------------------------------------- | |||
-- Verbs -- | |||
----------------------------------------------------------------------------------------- | |||
local function do_verb(args, data) | |||
local lemma = data.pagename | |||
if args.irr then | |||
table.insert(data.categories, langname .. " irregular verbs") | |||
else | |||
local function process_verb_form(param, default_suffix, label) | |||
local forms = m_hw_util.parse_term_list_with_modifiers { | |||
paramname = param, | |||
forms = args[param], | |||
splitchar = ",", | |||
} | |||
if not forms[1] then | |||
forms = {{term = lemma .. default_suffix}} | |||
else | |||
local new_forms = {} | |||
for _, f in ipairs(forms) do | |||
if f.term == "+" then | |||
table.insert(new_forms, {term = lemma .. default_suffix}) | |||
else | |||
table.insert(new_forms, f) | |||
end | |||
end | |||
forms = new_forms | |||
end | |||
insert_inflection(data, forms, label) | |||
end | |||
process_verb_form("pres", "ir", "present") | |||
process_verb_form("past", "adhir", "past") | |||
process_verb_form("imp", "adhist", "imperative") | |||
process_verb_form("fut", "ist", "future") | |||
end | |||
end | |||
pos_functions["verbs"] = { | |||
params = { | |||
["pres"] = {list = true, disallow_holes = true}, | |||
["past"] = {list = true, disallow_holes = true}, | |||
["imp"] = {list = true, disallow_holes = true}, | |||
["fut"] = {list = true, disallow_holes = true}, | |||
["irr"] = {type = "boolean"}, | |||
}, | |||
func = do_verb, | |||
} | } | ||
return export | return export | ||
Latest revision as of 18:58, 12 May 2026
- This module lacks a documentation subpage. Please create it.
- Useful links: subpage list • links • transclusions • testcases • sandbox
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.
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"
}
-- Extensible table for default plural endings by gender
local default_plural_endings = {
m = "ar",
f = "ir",
-- Easily add more later, e.g., n = "ur"
}
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
-- Extracts the base gender ("m", "f", etc.) ignoring number suffixes like "-p" or "-s"
local function get_base_gender(g)
if type(g) == "table" then g = g.spec end
g = g:gsub("%-p$", ""):gsub("%-s$", "")
if g == "mf" then return {"m", "f"} end
if default_plural_endings[g] then return {g} end
return {}
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.
local base_genders_present = {}
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
for _, bg in ipairs(get_base_gender(g)) do
base_genders_present[bg] = true
end
end
local lemma = data.pagename
local plurals = {}
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
table.insert(data.inflections, {label = "sometimes " .. glossary_link("plural only") .. ", in variation"})
end
if mode == "?" then
table.insert(data.categories, langname .. " " .. data.pos_category .. " with unknown or uncertain plurals")
elseif mode == "!" then
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
table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
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
if not plurals[1] and not is_proper then
plurals[1] = {term = "+"}
end
if mode == "~" then
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
table.insert(data.categories, langname .. " countable " .. data.pos_category)
else
table.insert(data.categories, langname .. " uncountable " .. data.pos_category)
end
end
local new_plurals = {}
for _, pl in ipairs(plurals) do
if pl.term == "+" then
local generated_any = false
-- Generate default plurals for all matched base genders
for bg, _ in pairs(base_genders_present) do
table.insert(new_plurals, {term = lemma .. default_plural_endings[bg]})
generated_any = true
end
-- Fallback if no specific gender mapped
if not generated_any then
table.insert(new_plurals, {term = lemma .. "ar"})
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
-- Generalized handler for other gendered forms with specific default suffixes
local function process_gender_form(param, label, accel, default_suffix)
local forms = m_hw_util.parse_term_list_with_modifiers {
paramname = param,
forms = args[param],
splitchar = ",",
}
if forms[1] then
local new_forms = {}
for _, f in ipairs(forms) do
if f.term == "+" and default_suffix then
table.insert(new_forms, {term = lemma .. default_suffix})
else
table.insert(new_forms, f)
end
end
insert_inflection(data, new_forms, label, accel)
end
end
process_gender_form("m", "masculine", "m")
process_gender_form("f", "feminine", "f")
process_gender_form("mpl", "masculine plural", "m|p", default_plural_endings["m"])
process_gender_form("fpl", "feminine plural", "f|p", default_plural_endings["f"])
-- Extensible for new forms like neuter:
-- process_gender_form("n", "neuter", "n")
-- process_gender_form("npl", "neuter plural", "n|p", default_plural_endings["n"])
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},
["m"] = {list = true},
["f"] = {list = true},
["mpl"] = {list = true},
["fpl"] = {list = 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 lemma = data.pagename
if args.inv then
table.insert(data.inflections, {label = glossary_link("invariable")})
table.insert(data.categories, langname .. " indeclinable " .. data.pos_category)
else
local function process_adj_form(param, default_suffix, label, accel)
local forms = m_hw_util.parse_term_list_with_modifiers {
paramname = param,
forms = args[param],
splitchar = ",",
}
if not forms[1] then
forms = {{term = lemma .. default_suffix}}
else
local new_forms = {}
for _, f in ipairs(forms) do
if f.term == "+" then
table.insert(new_forms, {term = lemma .. default_suffix})
else
table.insert(new_forms, f)
end
end
forms = new_forms
end
insert_inflection(data, forms, label, accel)
end
process_adj_form("comp", "ar", "comparative", "comp")
process_adj_form("sup", "ast", "superlative", "sup")
end
end
pos_functions["adjectives"] = {
params = {
["comp"] = {list = true, disallow_holes = true},
["sup"] = {list = true, disallow_holes = true},
["inv"] = {type = "boolean"},
},
func = do_adj,
}
-----------------------------------------------------------------------------------------
-- Verbs --
-----------------------------------------------------------------------------------------
local function do_verb(args, data)
local lemma = data.pagename
if args.irr then
table.insert(data.categories, langname .. " irregular verbs")
else
local function process_verb_form(param, default_suffix, label)
local forms = m_hw_util.parse_term_list_with_modifiers {
paramname = param,
forms = args[param],
splitchar = ",",
}
if not forms[1] then
forms = {{term = lemma .. default_suffix}}
else
local new_forms = {}
for _, f in ipairs(forms) do
if f.term == "+" then
table.insert(new_forms, {term = lemma .. default_suffix})
else
table.insert(new_forms, f)
end
end
forms = new_forms
end
insert_inflection(data, forms, label)
end
process_verb_form("pres", "ir", "present")
process_verb_form("past", "adhir", "past")
process_verb_form("imp", "adhist", "imperative")
process_verb_form("fut", "ist", "future")
end
end
pos_functions["verbs"] = {
params = {
["pres"] = {list = true, disallow_holes = true},
["past"] = {list = true, disallow_holes = true},
["imp"] = {list = true, disallow_holes = true},
["fut"] = {list = true, disallow_holes = true},
["irr"] = {type = "boolean"},
},
func = do_verb,
}
return export