Module:an-headword

adaptation of Module:es-headoword local export = {} local pos_functions = {}

local u = mw.ustring.char local rfind = mw.ustring.find local rmatch = mw.ustring.match local rsplit = mw.text.split

local m_links = require("Module:links") local com = require("Module:es-common") --using the Spanish module

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

local PAGENAME = mw.title.getCurrentTitle.text

local V = com.V -- vowel regex class local AV = com.AV -- accented vowel regex class local C = com.C -- consonant regex class

local rsub = com.rsub

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

local prepositions = { "a ", "cara ", "con ", "contra ", "cuentra ", "de ", "dende ", "dica ", "en ", "enta ", "entre ", "pa ", "por ", "seguntes ", "sin ", "sobre ", "ta ", }

-- Add links around words. If multiword_only, do it only in multiword forms. local function add_links(form, multiword_only) if form == "" or form == " " then return form end if not form:find("%[%[") then if rfind(form, "[%s%p]") then --optimization to avoid loading Module:headword on single-word forms local m_headword = require("Module:headword") if m_headword.head_is_multiword(form) then form = m_headword.add_multiword_links(form) end end if not multiword_only and not form:find("%[%[") then form = "" .. form .. "" end end return form end

local function track(page) require("Module:debug").track("es-headword/" .. page) return true end

local function glossary_link(entry, text) text = text or entry return "" .. text .. "" end

local function check_all_missing(forms, plpos, tracking_categories) for _, form in ipairs(forms) do		if type(form) == "table" then form = form.term end if form then local title = mw.title.new(form) if title and not title.exists then table.insert(tracking_categories, langname .. " " .. plpos .. " with red links in their headword lines") end end end end

-- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local tracking_categories = {}

local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")

local params = { ["head"] = {list = true}, ["json"] = {type = "boolean"}, ["id"] = {}, }

local parargs = frame:getParent.args if poscat == "nouns" and (not parargs[2] or parargs[2] == "") and parargs.pl2 then track("noun-pl2-without-pl") end

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 data = { lang = lang, pos_category = poscat, categories = {}, heads = args["head"], genders = {}, inflections = {}, id = args["id"], }

local lemma = m_links.remove_links(data.heads[1] or PAGENAME) if lemma:find("^%-") then -- suffix if poscat:find(" forms?$") then data.pos_category = "suffix forms" else data.pos_category = "suffixes" end

if suffix_categories[poscat] then local singular_poscat = poscat:gsub("s$", "") table.insert(data.categories, langname .. " " .. singular_poscat .. "-forming suffixes") end end

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

if args["json"] then return require("Module:JSON").toJSON(data) end

return require("Module:headword").full_headword(data) .. require("Module:utilities").format_categories(tracking_categories, lang) end

local function make_plural(form, special) local retval = require("Module:romance utilities").handle_multiword(form, special, make_plural, prepositions) if retval then return retval end -- ends in -ero -> -ers (the excepctions which have to be given manually) if rfind(form, "ero$") then return {rsub(form, "ero", "ers")} end --ends in -no/lo -> -ns/ls, -nos/los if rfind(form, "no$") then return {rsub(form, "no", "nos"),rsub(form, "no", "ns")} end if rfind(form, "lo$") and not rfind(form, "llo$") then return {rsub(form, "lo", "los"),rsub(form, "lo", "ls")} end -- ends in vowel. Note that nouns with a final epenthetic -e like abete (alternative form of abet) form their plurals as if they ended in -t (for example abete->abets) if rfind(form, "[áéíóúaeiou]$") then return {form .. "s"} end

--ends in -p/c/l/n/r/f/ll/ny/nt if rfind(form, "[pclnrf]$") or rfind(form, "ll$") or rfind(form, "ny$") or rfind(form, "nt$") then return {form .. "s"} end

-- ends in -Vt/-rt. Some loanwords might have a plural in -s if rfind(form, "[aeiou]t$") then return {form .. "z"} end if rfind(form, "[aeiou]rt$") then return {form .. "z"} end -- ends in s with more than 1 syllable, last syllable unstressed local syllables = com.syllabify(form) if syllables[2] and rfind(form, "s$") and not rfind(syllables[#syllables], AV) then return {form} end -- ends in -ch/s/x/z -> -itudis if rfind(form, "és$") then return {rsub(form, "és", "eses")} end if rfind(form, "ch$") then return {form .. "es"} end if rfind(form, "[sxz]$") then return {form .. "es"} end

return nil end

local function make_feminine(form, special) local retval = require("Module:romance utilities").handle_multiword(form, special, make_feminine, prepositions) if retval then if #retval ~= 1 then error("Internal error: Should have one return value for make_feminine: " .. table.concat(retval, ",")) end return retval[1] end if form:find("o$") then local retval = form:gsub("o$", "a") -- discard second retval return retval end if form:find("aire$") then local retval = form:gsub("$", "") return retval end if form:find("ce$") then local retval = form:gsub("ce$", "za") return retval end

if form:find("e$") then local retval = form:gsub("e$", "a") return retval end if form:find("eu$") then --in Latinisms the ending is -ea local retval = form:gsub("eu$", "eua") return retval end if form:find("au$") then local retval = form:gsub("au$", "ada") return retval end if form:find("íu$") then local retval = form:gsub("íu$", "ida") return retval end return form end

local function make_masculine(form, special) local retval = require("Module:romance utilities").handle_multiword(form, special, make_masculine, prepositions) if retval then if #retval ~= 1 then error("Internal error: Should have one return value for make_masculine: " .. table.concat(retval, ",")) end return retval[1] end

if form:find("ora$") then local retval = form:gsub("ora$", "ol") -- discard second retval return retval end

if form:find("a$") then local retval = form:gsub("a$", "u") -- discard second retval return retval end if form:find("á$") then local retval = form:gsub("á$", "au") -- discard second retval return retval end

return form end

local function do_adjective(args, data, tracking_categories, is_superlative) local feminines = {} local plurals = {} local masculine_plurals = {} local feminine_plurals = {}

if args.sp and not require("Module:romance utilities").allowed_special_indicators[args.sp] then local indicators = {} for indic, _ in pairs(require("Module:romance utilities").allowed_special_indicators) do table.insert(indicators, "'" .. indic .. "'") end table.sort(indicators) error("Special inflection indicator beginning can only be " ..			require("Module:table").serialCommaJoin(indicators, {dontTag = true}) .. ": " .. args.sp) end

local argsf = args.f or {} local argspl = args.pl or {} local argsmpl = args.mpl or {} local argsfpl = args.fpl or {}

if args.inv then -- invariable adjective table.insert(data.inflections, {label = "invariable"}) table.insert(data.categories, langname .. " indeclinable adjectives") if args.sp or #argsf > 0 or #argspl > 0 or #argsmpl > 0 or #argsfpl > 0 then error("Can't specify inflections with an invariable adjective") end else local lemma = m_links.remove_links(data.heads[1] or PAGENAME)

-- Gather feminines. if #argsf == 0 then argsf = {"+"} end for _, f in ipairs(argsf) do			if f == "+" then -- Generate default feminine. f = make_feminine(lemma, args.sp) elseif f == "#" then f = lemma end table.insert(feminines, f)		end

if #argspl > 0 and (#argsmpl > 0 or #argsfpl > 0) then error("Can't specify both pl= and mpl=/fpl=") end if #feminines == 1 and feminines[1] == lemma then -- Feminine like the masculine; just generate a plural if #argspl == 0 then argspl = {"+"} end elseif #argspl == 0 then -- Distinct masculine and feminine plurals if #argsmpl == 0 then argsmpl = {"+"} end if #argsfpl == 0 then argsfpl = {"+"} end end

for _, pl in ipairs(argspl) do			if pl == "+" then -- Generate default plural. local defpls = make_plural(lemma, args.sp) if not defpls then error("Unable to generate default plural of '" .. lemma .. "'") end for _, defpl in ipairs(defpls) do					table.insert(plurals, defpl) end elseif pl == "#" then table.insert(plurals, lemma) else table.insert(plurals, pl) end end

for _, mpl in ipairs(argsmpl) do			if mpl == "+" then -- Generate default masculine plural. local defpls = make_plural(lemma, args.sp) if not defpls then error("Unable to generate default plural of '" .. lemma .. "'") end for _, defpl in ipairs(defpls) do					table.insert(masculine_plurals, defpl) end elseif mpl == "#" then table.insert(masculine_plurals, lemma) else table.insert(masculine_plurals, mpl) end end

for _, fpl in ipairs(argsfpl) do			if fpl == "+" then for _, f in ipairs(feminines) do -- Generate default feminine plural. local defpls = make_plural(f, args.sp) if not defpls then error("Unable to generate default plural of '" .. f .. "'") end for _, defpl in ipairs(defpls) do						table.insert(feminine_plurals, defpl) end end elseif fpl == "#" then table.insert(feminine_plurals, lemma) else table.insert(feminine_plurals, fpl) end end

if args.mapoc then check_all_missing(args.mapoc, "adjectives", tracking_categories) end check_all_missing(feminines, "adjectives", tracking_categories) check_all_missing(plurals, "adjectives", tracking_categories) check_all_missing(masculine_plurals, "adjectives", tracking_categories) check_all_missing(feminine_plurals, "adjectives", tracking_categories)

if args.mapoc and #args.mapoc > 0 then args.mapoc.label = "masculine singular before a noun" table.insert(data.inflections, args.mapoc) end

-- Make sure there are feminines given and not same as lemma. if #feminines > 0 and not (#feminines == 1 and feminines[1] == lemma) then feminines.label = "feminine" feminines.accel = {form = "f|s"} table.insert(data.inflections, feminines) end

if #plurals > 0 then plurals.label = "plural" plurals.accel = {form = "p"} table.insert(data.inflections, plurals) end

if #masculine_plurals > 0 then masculine_plurals.label = "masculine plural" masculine_plurals.accel = {form = "m|p"} table.insert(data.inflections, masculine_plurals) end

if #feminine_plurals > 0 then feminine_plurals.label = "feminine plural" feminine_plurals.accel = {form = "f|p"} table.insert(data.inflections, feminine_plurals) end end

if args.comp and #args.comp > 0 then check_all_missing(args.comp, "adjectives", tracking_categories) args.comp.label = "comparative" table.insert(data.inflections, args.comp) end

if args.sup and #args.sup > 0 then check_all_missing(args.sup, "adjectives", tracking_categories) args.sup.label = "superlative" table.insert(data.inflections, args.sup) end

if args.irreg and is_superlative then table.insert(data.categories, langname .. " irregular superlative adjectives") end end

pos_functions["adjectives"] = { params = { ["inv"] = {type = "boolean"}, --invariable ["sp"] = {}, -- special indicator: "first", "first-last", etc.		["f"] = {list = true}, --feminine form(s) ["pl"] = {list = true}, --plural override(s) ["fpl"] = {list = true}, --feminine plural override(s) ["mpl"] = {list = true}, --masculine plural override(s) ["mapoc"] = {list = true}, --masculine apocopated (before a noun) ["comp"] = {list = true}, --comparative(s) ["sup"] = {list = true}, --superlative(s) },	func = function(args, data, tracking_categories) return do_adjective(args, data, tracking_categories, false) end }

pos_functions["comparative adjectives"] = { params = { ["inv"] = {type = "boolean"}, --invariable ["sp"] = {}, -- special indicator: "first", "first-last", etc.		["f"] = {list = true}, --feminine form(s) ["pl"] = {list = true}, --plural override(s) ["fpl"] = {list = true}, --feminine plural override(s) ["mpl"] = {list = true}, --masculine plural override(s) },	func = function(args, data, tracking_categories) return do_adjective(args, data, tracking_categories, false) end }

pos_functions["superlative adjectives"] = { params = { ["inv"] = {type = "boolean"}, --invariable ["sp"] = {}, -- special indicator: "first", "first-last", etc.		["f"] = {list = true}, --feminine form(s) ["pl"] = {list = true}, --plural override(s) ["fpl"] = {list = true}, --feminine plural override(s) ["mpl"] = {list = true}, --masculine plural override(s) ["irreg"] = {type = "boolean"}, },	func = function(args, data, tracking_categories) return do_adjective(args, data, tracking_categories, true) end }

pos_functions["past participles"] = { params = { [1] = {}, --FIXME: ignore this until we've fixed the uses ["inv"] = {type = "boolean"}, --invariable ["sp"] = {}, -- special indicator: "first", "first-last", etc.	}, func = function(args, data, tracking_categories) return do_adjective(args, data, tracking_categories, false) end }

pos_functions["adverbs"] = { params = { ["sup"] = {list = true}, --superlative(s) },	func = function(args, data, tracking_categories, frame) if #args.sup > 0 then check_all_missing(args.sup, "adverbs", tracking_categories) args.sup.label = "superlative" table.insert(data.inflections, args.sup) end end, }

pos_functions["cardinal numbers"] = { params = { ["f"] = {list = true}, --feminine(s) ["mapoc"] = {list = true}, --masculine apocopated form(s) },	func = function(args, data, tracking_categories, frame) data.pos_category = "numerals" table.insert(data.categories, 1, langname .. " cardinal numbers")

if #args.f > 0 then table.insert(data.genders, "m") check_all_missing(args.f, "numerals", tracking_categories) args.f.label = "feminine" table.insert(data.inflections, args.f)		end if #args.mapoc > 0 then check_all_missing(args.mapoc, "numerals", tracking_categories) args.mapoc.label = "masculine before a noun" table.insert(data.inflections, args.mapoc) end end, }

-- Display information for a noun's gender -- This is separate so that it can also be used for proper nouns function noun_gender(args, data) local gender = args[1] table.insert(data.genders, gender) if #data.genders == 0 then table.insert(data.genders, "?") end end

pos_functions["proper nouns"] = { params = { [1] = {},		},	func = function(args, data) noun_gender(args, data) end }

-- Display additional inflection information for a noun pos_functions["nouns"] = { params = { [1] = {required = true, default = "m"}, --gender ["g2"] = {}, --second gender ["e"] = {type = "boolean"}, --epicene [2] = {list = "pl"}, --plural override(s) ["f"] = {list = true}, --feminine form(s) ["m"] = {list = true}, --masculine form(s) ["fpl"] = {list = true}, --feminine plural override(s) ["mpl"] = {list = true}, --masculine plural override(s) ["dim"] = {list = true}, --diminutive(s) ["aug"] = {list = true}, --diminutive(s) ["pej"] = {list = true}, --pejorative(s) },	func = function(args, data, tracking_categories) local allowed_genders = { ["m"] = true, ["f"] = true, ["m-p"] = true, ["f-p"] = true, ["mf"] = true, ["mf-p"] = true, ["mfbysense"] = true, ["mfbysense-p"] = true, }

local lemma = m_links.remove_links(			(#data.heads > 0 and data.heads[1]) or PAGENAME		)

if args[1] == "m-f" then args[1] = "mf" elseif args[1] == "mfp" or args[1] == "m-f-p" then args[1] = "mf-p" end

if not allowed_genders[args[1]] then error("Unrecognized gender: " .. args[1]) end

table.insert(data.genders, args[1])

if args.g2 then table.insert(data.genders, args.g2) end

if args["e"] then table.insert(data.categories, langname .. " epicene nouns") table.insert(data.inflections, {label = glossary_link("epicene")}) end

local plurals = {}

if args[1]:find("%-p$") then table.insert(data.inflections, {label = glossary_link("plural only")}) if #args[2] > 0 then error("Can't specify plurals of a plurale tantum noun") end else -- Gather plurals, handling requests for default plurals for _, pl in ipairs(args[2]) do				if pl == "+" then local default_pls = make_plural(lemma) for _, defp in ipairs(default_pls) do						table.insert(plurals, defp) end elseif pl == "#" then table.insert(plurals, lemma) elseif pl:find("^%+") then pl = require("Module:romance utilities").get_special_indicator(pl) local default_pls = make_plural(lemma, pl) for _, defp in ipairs(default_pls) do						table.insert(plurals, defp) end else table.insert(plurals, pl) end end

-- Check for special plural signals local mode = nil

if #plurals > 0 and #plurals[1] == 1 then if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter else error("Unexpected plural code") end end

if mode == "?" then -- Plural is unknown table.insert(data.categories, langname .. " nouns 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 .. " nouns with unattested plurals") return elseif mode == "-" then -- Uncountable noun; may occasionally have a plural table.insert(data.categories, langname .. " uncountable nouns")

-- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, langname .. " countable nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end else -- Countable or mixed countable/uncountable if #plurals == 0 then local pls = make_plural(lemma) if pls then for _, pl in ipairs(pls) do							table.insert(plurals, pl) end end 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 nouns") table.insert(data.categories, langname .. " countable nouns") else -- Countable nouns table.insert(data.categories, langname .. " countable nouns") end end end

-- Gather masculines/feminines. For each one, generate the corresponding plural(s). local function handle_mf(mfs, inflect, default_plurals) local retval = {} for _, mf in ipairs(mfs) do				if mf == "1" then track("noun-mf-1") end if mf == "1" or mf == "+" then -- Generate default feminine. mf = inflect(lemma) elseif mf == "#" then mf = lemma end local special = require("Module:romance utilities").get_special_indicator(mf) if special then mf = inflect(lemma, special) end table.insert(retval, mf) local mfpls = make_plural(mf, special) if mfpls then for _, mfpl in ipairs(mfpls) do						-- Add an accelerator for each masculine/feminine plural whose lemma -- is the corresponding singular, so that the accelerated entry -- that is generated has a definition that looks like -- # 						table.insert(default_plurals, {term = mfpl, accel = {form = "p", lemma = mf}}) end end end return retval end

local feminine_plurals = {} local feminines = handle_mf(args.f, make_feminine, feminine_plurals) local masculine_plurals = {} local masculines = handle_mf(args.m, make_masculine, masculine_plurals)

local function handle_mf_plural(mfpl, default_plurals, singulars) local new_mfpls = {} for i, mfpl in ipairs(mfpl) do				local accel if #mfpl == #singulars then -- If same number of overriding masculine/feminine plurals as singulars, -- assume each plural goes with the corresponding singular -- and use each corresponding singular as the lemma in the accelerator. -- The generated entry will have # as the -- definition. accel = {form = "p", lemma = singulars[i]} else accel = nil end if mfpl == "+" then for _, defpl in ipairs(default_plurals) do						-- defpl is already a table table.insert(new_mfpls, defpl) end elseif mfpl == "#" then table.insert(new_mfpls, {term = lemma, accel = accel}) elseif mfpl:find("^%+") then mfpl = require("Module:romance utilities").get_special_indicator(mfpl) for _, mf in ipairs(singulars) do						local default_mfpls = make_plural(mf, mfpl) for _, defp in ipairs(default_mfpls) do							table.insert(new_mfpls, {term = defp, accel = accel}) end end else table.insert(new_mfpls, {term = mfpl, accel = accel}) end end return new_mfpls end

if #args.fpl > 0 then -- Override any existing feminine plurals. feminine_plurals = handle_mf_plural(args.fpl, feminine_plurals, feminines) end

if #args.mpl > 0 then -- Override any existing masculine plurals. masculine_plurals = handle_mf_plural(args.mpl, masculine_plurals, masculines) end

check_all_missing(plurals, "nouns", tracking_categories) check_all_missing(feminines, "nouns", tracking_categories) check_all_missing(feminine_plurals, "nouns", tracking_categories) check_all_missing(masculines, "nouns", tracking_categories) check_all_missing(masculine_plurals, "nouns", tracking_categories) check_all_missing(args.dim, "nouns", tracking_categories) check_all_missing(args.aug, "nouns", tracking_categories) check_all_missing(args.pej, "nouns", tracking_categories)

local function redundant_plural(pl) for _, p in ipairs(plurals) do				if p == pl then return true end end return false end

for _, mpl in ipairs(masculine_plurals) do			if redundant_plural(mpl) then track("noun-redundant-mpl") end end

for _, fpl in ipairs(feminine_plurals) do			if redundant_plural(fpl) then track("noun-redundant-fpl") end end

if #plurals > 0 then plurals.label = "plural" plurals.accel = {form = "p"} table.insert(data.inflections, plurals) end

if #feminines > 0 then feminines.label = "feminine" feminines.accel = {form = "f"} table.insert(data.inflections, feminines) end

if #feminine_plurals > 0 then feminine_plurals.label = "feminine plural" table.insert(data.inflections, feminine_plurals) end

if #masculines > 0 then masculines.label = "masculine" table.insert(data.inflections, masculines) end

if #masculine_plurals > 0 then masculine_plurals.label = "masculine plural" table.insert(data.inflections, masculine_plurals) end

if #args.dim > 0 then args.dim.label = glossary_link("diminutive") table.insert(data.inflections, args.dim) end

if #args.aug > 0 then args.aug.label = glossary_link("augmentative") table.insert(data.inflections, args.aug) end

if #args.pej > 0 then args.pej.label = glossary_link("pejorative") table.insert(data.inflections, args.pej) end end }

return export