মডিউল:fr-headword

উইকিঅভিধান, মুক্ত অভিধান থেকে

এই মডিউলের জন্য মডিউল:fr-headword/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

local export = {}
local pos_functions = {}
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rsubn = mw.ustring.gsub
local rsplit = mw.text.split

local lang = require("Module:languages").getByCode("fr")
		
local suffix_categories = {
	["adjectives"] = true,
	["adverbs"] = true,
	["nouns"] = true,
	["verbs"] = true,
	["prepositional phrases"] = true,
}

-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
	local retval = rsubn(term, foo, bar)
	return retval
end

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

-- mw.title.new() returns nil if there are weird chars in
-- the pagename.
local function exists(pagename)
	local title = mw.title.new(pagename)
	return title and title.exists
end

local function add_suffix(list, suffix)
	local newlist = {}
	for _, item in ipairs(list) do
		local form
		if suffix == "s" then
			if rfind(item, "[sx]$") then
				form = item
			elseif rfind(item, "al$") then
				form = rsub(item, "al$", "aux")
			else
				form = item .. suffix
			end
		elseif suffix == "e" then
			if rfind(item, "e$") then
				form = item
			elseif rfind(item, "en$") then
				form = item .. "ne"
			elseif rfind(item, "er$") then
				form = rsub(item, "er$", "ère")
			elseif rfind(item, "el$") then
				form = item .. "le"
			elseif rfind(item, "et$") then
				form = item .. "te"
			elseif rfind(item, "on$") then
				form = item .. "ne"
			elseif rfind(item, "ieur$") then
				form = item .. "e"
			elseif rfind(item, "teur$") then
				form = rsub(item, "teur$", "trice")
			elseif rfind(item, "eu[rx]$") then
				form = rsub(item, "eu[rx]$", "euse")
			elseif rfind(item, "if$") then
				form = rsub(item, "if$", "ive")
			elseif rfind(item, "c$") then
				form = rsub(item, "c$", "que")
			else
				form = item .. suffix
			end
		else
			form = item .. suffix
		end
		table.insert(newlist, form)
	end
	return newlist
end

local no_split_words = {
	["c'est"] = true,
	["quelqu'un"] = true,
	["aujourd'hui"] = true,
}

-- Auto-add links to a "space word" (after splitting on spaces). We split off
-- final punctuation, and then split on hyphens if split_dash is given, and
-- also split on apostrophes, including the apostrophe in the link to its left
-- (so we auto-split "l'eau" as "[[l']][[eau]]).
local function add_space_word_links(space_word, split_dash)
	local space_word_no_punct, punct = rmatch(space_word, "^(.*)([,;:?!])$")
	space_word_no_punct = space_word_no_punct or space_word
	punct = punct or ""
	local words
	-- don't split prefixes and suffixes
	if not split_dash or rfind(space_word_no_punct, "^%-") or rfind(space_word_no_punct, "%-$") then
		words = {space_word_no_punct}
	else
		words = rsplit(space_word_no_punct, "%-")
	end
	local linked_words = {}
	for _, word in ipairs(words) do
		if not no_split_words[word] and rfind(word, "'") then
			word = rsub(word, "([^']+')", "[[%1]]")
			word = rsub(word, "%]([^%[%]]*)$", "][[%1]]")
		else
			word = "[[" .. word .. "]]"
		end
		table.insert(linked_words, word)
	end
	return table.concat(linked_words, "-") .. punct
end

-- Auto-add links to a lemma. We split on spaces, and also on hyphens
-- if split_dash is given or the word has no spaces. In addition, we split
-- on apostrophes, including the apostrophe in the link to its left
-- (so we auto-split "de l'eau" as "[[de]] [[l']][[eau]]"). We don't always
-- split on hyphens because of cases like "boire du petit-lait" where
-- "petit-lait" should be linked as a whole, but provide the option to do it
-- for cases like "croyez-le ou non". If there's no space, however, then
-- it makes sense to split on hyphens by default (e.g. for "avant-avant-hier").
-- Cases where only some of the hyphens should be split can always be handled
-- by explicitly specifying the head (e.g. "Nord-Pas-de-Calais").
local function add_lemma_links(lemma, split_dash)
	if not rfind(lemma, " ") then
		split_dash = true
	end
	local words = rsplit(lemma, " ")
	local linked_words = {}
	for _, word in ipairs(words) do
		table.insert(linked_words, add_space_word_links(word, split_dash))
	end
	local retval = table.concat(linked_words, " ")
	-- If we ended up with a single link consisting of the entire lemma,
	-- remove the link.
	local unlinked_retval = rmatch(retval, "^%[%[([^%[%]]*)%]%]$")
	return unlinked_retval or retval
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local PAGENAME = mw.title.getCurrentTitle().text
	
	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},
		["suff"] = {type = "boolean"},
		["splitdash"] = {type = "boolean"},
	}

	if rfind(PAGENAME, " ") then
		track("space")
	end

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

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

	local heads = args["head"]
	if pos_functions[poscat] and pos_functions[poscat].param1_is_head and args[1] then
		-- FIXME! REMOVE ME! Hack to correspond to previous template code in {{fr-adv}}.
		if args[1] == "-" then
			track("arg1dash")
		else
			table.insert(heads, 1, args[1])
		end
	end
	local auto_linked_head = add_lemma_links(PAGENAME, args["splitdash"])
	if #heads == 0 then
		heads = {auto_linked_head}
	else
		for _, head in ipairs(heads) do
			if head == auto_linked_head then
				track("redundant-head")
			end
		end
	end
		
	local data = {lang = lang, pos_category = poscat, categories = {}, heads = heads, genders = {}, inflections = {}, categories = {}}
	
	if args["suff"] then
		data.pos_category = "suffixes"
		
		if suffix_categories[poscat] then
			local singular_poscat = poscat:gsub("s$", "")
			table.insert(data.categories, lang:getCanonicalName() .. " " .. singular_poscat .. "-forming suffixes")
		else
			error("No category exists for suffixes forming " .. poscat .. ".")
		end
	end
	
	if pos_functions[poscat] then
		pos_functions[poscat].func(args, data)
	end
	
	return require("Module:headword").full_headword(data)
end

local allowed_genders = {
	["m"] = true,
	["f"] = true,
	["m-p"] = true,
	["f-p"] = true,
	["m-s"] = true,
	["f-s"] = true,
}

local function get_noun_pos(is_proper)
	return {
		params = {
			[1] = {},
			["g"] = {list = true},
			[2] = {list = true},
			["f"] = {list = true},
			["m"] = {list = true},
			["dim"] = {list = true},
			},
		func = function(args, data)
			local PAGENAME = mw.title.getCurrentTitle().text
			
			local function default_plural()
				if rfind(PAGENAME, 'x$') then
					track("default-x")
				end
				if rfind(PAGENAME, 'z$') then
					track("default-z")
				end
				if rfind(PAGENAME, '[sxz]$') then
					return PAGENAME
				elseif rfind(PAGENAME, '[ae]u$') then
					return "x"
				elseif rfind(PAGENAME, 'al$') then
					return mw.ustring.sub(PAGENAME, 1, -3) .. 'aux'
				else
					return "s"
				end
			end

			-- Gather genders
			local function insert_gender(g)
				if g == "mf" then
					table.insert(data.genders, "m")
					table.insert(data.genders, "f")
				else
					table.insert(data.genders, g)
				end
			end
			insert_gender(args[1])
			for _, g in ipairs(args.g) do
				insert_gender(g)
			end

			-- Gather all the plural parameters from the numbered parameters.
			local plurals = args[2]
			plurals.label = "plural"
			plurals.accel = {form = "p"}
			plurals.request = true
			
			-- Gather all the feminine parameters
			local feminines = args["f"]
			feminines.label = "feminine"
			
			-- Gather all the masculine parameters
			local masculines = args["m"]
			masculines.label = "masculine"
			
			-- Add categories for genders
			if #data.genders == 0 then
				table.insert(data.genders, "?")
			end
			
			local mode = nil
			
			for _, g in ipairs(data.genders) do
				if g == "m-p" or g == "f-p" then
					mode = "p"
				end

				if g == "?" and (is_proper or mw.title.getCurrentTitle().nsText == "Template") then
					-- allow unknown gender in template example and proper nouns,
					-- since there are currently so many proper nouns with
					-- unspecified gender
				elseif g and g ~= "" and not allowed_genders[g] then
					error("Unrecognized French gender: " .. g)
				end

				if g == "m" or g == "m-p" or g == "m-s" then
					table.insert(data.categories, "French masculine nouns")
				elseif g == "f" or g == "f-p" or g == "f-s" then
					table.insert(data.categories, "French feminine nouns")
				end
			end
			
			-- Decide how to show the plurals
			mode = mode or plurals[1]
			
			-- Plural is not attested
			if mode == "!" then
				table.insert(data.inflections, {label = "plural not attested"})
				table.insert(data.categories, "French nouns with unattested plurals")
			-- Plural-only noun, doesn't have a plural
			elseif mode == "p" then
				table.insert(data.inflections, {label = "plural only"})
				table.insert(data.categories, "French pluralia tantum")
			else
				-- Plural is unknown
				if mode == "?" then
					table.remove(plurals, 1)  -- Remove the mode parameter
				-- Uncountable noun; may occasionally have a plural
				elseif mode == "-" then
					table.remove(plurals, 1)  -- Remove the mode parameter
					table.insert(data.categories, "French uncountable nouns")
				
					-- If plural forms were given explicitly, then show "usually"
					if #plurals > 0 then
						track("count-uncount")
						table.insert(data.inflections, {label = "usually [[Appendix:Glossary#uncountable|uncountable]]"})
						table.insert(data.categories, "French countable nouns")
					else
						table.insert(data.inflections, {label = "[[Appendix:Glossary#uncountable|uncountable]]"})
					end
				-- Mixed countable/uncountable noun, always has a plural
				elseif mode == "~" then
					table.remove(plurals, 1)  -- Remove the mode parameter
					table.insert(data.inflections, {label = "[[Appendix:Glossary#countable|countable]] and [[Appendix:Glossary#uncountable|uncountable]]"})
					table.insert(data.categories, "French uncountable nouns")
					table.insert(data.categories, "French countable nouns")
				
					-- If no plural was given, add a default one now
					if #plurals == 0 then
						table.insert(plurals, default_plural())
					end
				-- Default proper noun; uncountable unless plural(s) specified
				elseif is_proper then
					if #plurals > 0 then
						table.insert(data.categories, "French countable nouns")
					else
						table.insert(data.categories, "French uncountable nouns")
					end
				-- The default, always has a plural
				else
					table.insert(data.categories, "French countable nouns")
					
					-- If no plural was given, add a default one now
					if #plurals == 0 then
						table.insert(plurals, default_plural())
					end
				end
				
				-- Process the plural forms
				for i, pl in ipairs(plurals) do
					if pl == "*" then
						pl = PAGENAME
					elseif pl == "s" then
						pl = PAGENAME .. "s"
					elseif pl == "x" then
						pl = PAGENAME .. "x"
					end

					if not exists(pl) then
						table.insert(data.categories, "French nouns with red links in their headword lines")
					end
					
					plurals[i] = pl
				end
		
				-- Add the plural forms; do this in some cases even if no plurals
				-- specified so we get a "please provide plural" message.
				if mode ~= "-" and (not is_proper or mode) or #plurals > 0 then
					table.insert(data.inflections, plurals)
				end
			end
			
			-- Add the feminine forms
			if #feminines > 0 then
				table.insert(data.inflections, feminines)
				
				for _, f in ipairs(feminines) do
					if not exists(f) then
						table.insert(data.categories, "French nouns with red links in their headword lines")
					end
				end
			end
			
			-- Add the masculine forms
			if #masculines > 0 then
				table.insert(data.inflections, masculines)
				
				for _, m in ipairs(masculines) do
					if not exists(m) then
						table.insert(data.categories, "French nouns with red links in their headword lines")
					end
				end
			end

			-- Handle diminutives
			if #args.dim > 0 then
				local dims_infl = mw.clone(args.dim)
				dims_infl.label = "diminutive"
				dims_infl.accel = {form = "diminutive"}
				table.insert(data.inflections, dims_infl)
			end
		end
	}
end

pos_functions["nouns"] = get_noun_pos(false)

pos_functions["proper nouns"] = get_noun_pos(true)

pos_functions["pronouns"] = {
	params = {
		["head"] = {list = true},
		[1] = {alias_of = "g"},
		["g"] = {list = true},
		["f"] = {list = true},
		["fqual"] = {list = true, allow_holes = true},
		["m"] = {list = true},
		["mqual"] = {list = true, allow_holes = true},
		["fp"] = {list = true},
		["fpqual"] = {list = true, allow_holes = true},
		["mp"] = {list = true},
		["mpqual"] = {list = true, allow_holes = true},
		["p"] = {list = true},
		["pqual"] = {list = true, allow_holes = true},
		},
	func = function(args, data)
		local PAGENAME = mw.title.getCurrentTitle().text
		
		-- Gather genders
		local function insert_gender(g)
			if g == "mf" then
				table.insert(data.genders, "m")
				table.insert(data.genders, "f")
			else
				table.insert(data.genders, g)
			end
		end
		for _, g in ipairs(args.g) do
			insert_gender(g)
		end

		local function process_inflection(label, infls, quals)
			infls.label = label
			for i, infl in ipairs(infls) do
				if quals[i] then
					infls[i] = {term = infl, qualifiers = {quals[i]}}
				end
			end
		end

		-- Gather all inflections.
		process_inflection("masculine", args["m"], args["mqual"])			
		process_inflection("feminine", args["f"], args["fqual"])			
		process_inflection("masculine plural", args["mp"], args["mpqual"])			
		process_inflection("feminine plural", args["fp"], args["fpqual"])			
		process_inflection("plural", args["p"], args["pqual"])			

		-- Add categories for genders
		if #data.genders == 0 then
			table.insert(data.genders, "?")
		end

		-- Validate/canonicalize genders			
		for i, g in ipairs(data.genders) do
			if g == "m." then
				data.genders[i] = "m"
			elseif g == "f." then
				data.genders[i] = "f"
			elseif g == "?" and mw.title.getCurrentTitle().nsText == "Template" then
				-- allow unknown gender in template example
			elseif g == "?" then
				-- FIXME, remove this branch once we've added the required genders
				track("missing-pron-gender")
			elseif g and g ~= "" and not allowed_genders[g] then
				error("Unrecognized French gender: " .. g)
			end
		end

		-- Add the inflections
		if #args["m"] > 0 then
			table.insert(data.inflections, args["m"])
		end
		if #args["f"] > 0 then
			table.insert(data.inflections, args["f"])
		end
		if #args["mp"] > 0 then
			table.insert(data.inflections, args["mp"])
		end
		if #args["fp"] > 0 then
			table.insert(data.inflections, args["fp"])
		end
		if #args["p"] > 0 then
			table.insert(data.inflections, args["p"])
		end
	end
}


local function get_misc_pos()
	return {
		param1_is_head = true,
		params = {
			[1] = {},
		},
		func = function(args, data)
		end
	}
end

pos_functions["adverbs"] = get_misc_pos()
	
pos_functions["prepositions"] = get_misc_pos()

pos_functions["phrases"] = get_misc_pos()

pos_functions["prepositional phrases"] = get_misc_pos()

pos_functions["proverbs"] = get_misc_pos()

pos_functions["punctuation marks"] = get_misc_pos()

pos_functions["diacritical marks"] = get_misc_pos()

pos_functions["interjections"] = get_misc_pos()

pos_functions["prefixes"] = get_misc_pos()

pos_functions["abbreviations"] = get_misc_pos()

pos_functions["adjectives"] = {
	params = {
		[1] = {},
		["inv"] = {},
		["m2"] = {},
		["onlyg"] = {},
		["f"] = {list = true},
		["mp"] = {list = true},
		["fp"] = {list = true},
		["p"] = {list = true},
		["current"] = {list = true},
		["comp"] = {list = true},
		["sup"] = {list = true},
		},
	func = function(args, data)
		local PAGENAME = mw.title.getCurrentTitle().text
		if args.onlyg == "p" or args.onlyg == "m-p" or args.onlyg == "f-p" then
			table.insert(data.categories, "French pluralia tantum")
		end
		if args.onlyg == "s" or args.onlyg == "f-s" or args.onlyg == "f-s" then
			table.insert(data.categories, "French singularia tantum")
		end
		if args.onlyg then
			table.insert(data.categories, "French defective adjectives")
		end
		if args.onlyg == "p" then
			table.insert(data.inflections, {label = "plural only"})
			if args[1] ~= "mf" then
				-- Handle feminine plurals
				if #args.fp > 0 then
					local fplurals_infl = mw.clone(args.fp)
					fplurals_infl.label = "feminine plural"
					fplurals_infl.accel = {form = "f|p"}
					table.insert(data.inflections, fplurals_infl)
				end
			end
		elseif args.onlyg == "s" then
			table.insert(data.inflections, {label = "singular only"})
			if not (args[1] == "mf" or #args.f == 0 and rfind(PAGENAME, "e$")) then
				-- Handle feminines
				local feminines = #args.f > 0 and args.f or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "e")
				local feminines_infl = mw.clone(feminines)
				feminines_infl.label = "feminine singular"
				feminines_infl.accel = {form = "f|s"}
				table.insert(data.inflections, feminines_infl)
			end
		elseif args.onlyg == "m" then
			table.insert(data.genders, "m")
			table.insert(data.inflections, {label = "masculine only"})
			-- Handle masculine plurals
			local mplurals = #args.mp > 0 and args.mp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
			local mplurals_infl = mw.clone(mplurals)
			mplurals_infl.label = "masculine plural"
			mplurals_infl.accel = {form = "m|p"}
			table.insert(data.inflections, mplurals_infl)
		elseif args.onlyg == "f" then
			table.insert(data.genders, "f")
			table.insert(data.inflections, {label = "feminine only"})
			-- Handle feminine plurals
			local fplurals = #args.fp > 0 and args.fp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
			local fplurals_infl = mw.clone(fplurals)
			fplurals_infl.label = "feminine plural"
			fplurals_infl.accel = {form = "f|p"}
			table.insert(data.inflections, fplurals_infl)
		elseif args.onlyg then
			table.insert(data.genders, args.onlyg)
			table.insert(data.inflections, {label = "defective"})
		else
			-- Gather genders
			local gender = args[1]
			-- Default to mf if base form ends in -e and no feminine,
			-- feminine plural or gender specified
			if not gender and #args.f == 0 and #args.fp == 0 and rfind(PAGENAME, "e$") then
				gender = "mf"
			end
			
			if #args.current > 0 then
				track("adj-current")
			end
			
			if args.inv then
				table.insert(data.inflections, {label = "invariable"})
			end
			
			-- Handle plurals of mf adjectives
			local plurals = #args.p > 0 and args.p or {PAGENAME .. "s"}
			if not args.inv and gender == "mf" then
				local plurals_infl = mw.clone(plurals)
				plurals_infl.label = "plural"
				plurals_infl.accel = {form = "p"}
				table.insert(data.inflections, plurals_infl)
			end
			
			if not args.inv and gender ~= "mf" then
				-- Handle case of special masculine singular before vowel
				if args.m2 then
					local masc_before_vowel = {args.m2}
					masc_before_vowel.label = "masculine singular before vowel"
					masc_before_vowel.accel = {form = "m|s"}
					table.insert(data.inflections, masc_before_vowel)
				end
				
				-- Handle feminines
				local feminines = #args.f > 0 and args.f or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "e")
				local feminines_infl = mw.clone(feminines)
				feminines_infl.label = "feminine singular"
				feminines_infl.accel = {form = "f|s"}
				table.insert(data.inflections, feminines_infl)
				
				-- Handle masculine plurals
				local mplurals = #args.mp > 0 and args.mp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
				local mplurals_infl = mw.clone(mplurals)
				mplurals_infl.label = "masculine plural"
				mplurals_infl.accel = {form = "m|p"}
				table.insert(data.inflections, mplurals_infl)
				
				-- Handle feminine plurals
				local fplurals = #args.fp > 0 and args.fp or add_suffix(feminines, "s")
				local fplurals_infl = mw.clone(fplurals)
				fplurals_infl.label = "feminine plural"
				fplurals_infl.accel = {form = "f|p"}
				table.insert(data.inflections, fplurals_infl)
			end
		end
		
		-- Handle comparatives
		if #args.comp > 0 then
			local comps_infl = mw.clone(args.comp)
			comps_infl.label = "comparative"
			comps_infl.accel = {form = "comparative"}
			table.insert(data.inflections, comps_infl)
		end
		
		-- Handle superlatives
		if #args.sup > 0 then
			local sups_infl = mw.clone(args.sup)
			sups_infl.label = "superlative"
			sups_infl.accel = {form = "superlative"}
			table.insert(data.inflections, sups_infl)
		end
		
		-- Check existence
		for key, val in pairs(data.inflections) do
			for i, form in ipairs(val) do
				if not exists(form) then
					table.insert(data.categories, "French adjectives with red links in their headword lines")
					return
				end
			end
		end
	end
}

pos_functions["verbs"] = {
	param1_is_head = true,
	params = {
		[1] = {},
		["type"] = {list = true},
	},
	func = function(args, data)
		local PAGENAME = mw.title.getCurrentTitle().text
		for _, ty in ipairs(args.type) do
			local category, label
			if ty == "auxiliary" then
				category = "auxiliary verbs"
			elseif ty == "defective" then
				category = "defective verbs"
				label = "[[defective]]"
			elseif ty == "impersonal" then
				category = "impersonal verbs"
				label = "[[impersonal]]"
			elseif ty == "modal" then
				category = "modal verbs"
			elseif ty == "reflexive" then
				category = "reflexive verbs"
			elseif ty == "transitive" then
				label = "[[transitive]]"
			elseif ty == "intransitive" then
				label = "[[intransitive]]"
			elseif ty == "ambitransitive" or ty == "ambi" then
				label = "[[transitive]] and [[intransitive]]"
			end
			if category then
				table.insert(data.categories, "French " .. category)
			end
			if label then
				table.insert(data.inflections, {label = label})
			end
		end
	end
}

pos_functions["ক্রিয়া বিশেষণ"] = pos_functions["adverbs"]

pos_functions["介詞"] = pos_functions["prepositions"]

pos_functions["বাক্যাংশ"] = pos_functions["phrases"]

pos_functions["বিশেষ্য"] = pos_functions["nouns"]

pos_functions["介詞短語"] = pos_functions["prepositional phrases"]

pos_functions["যতিচিহ্ন"] = pos_functions["punctuation marks"]

pos_functions["বৈশিষ্ট্যসূচক চিহ্ন"] = pos_functions["diacritical marks"]

pos_functions["ক্রিয়া"] = pos_functions["verbs"]

pos_functions["বিশেষণ"] = pos_functions["adjectives"]

pos_functions["後綴"] = pos_functions["postfixes"]

pos_functions["উপসর্গ"] = pos_functions["prefixes"]

pos_functions["অন্তর্ভাবমূলক"] = pos_functions["interjections"]

pos_functions["সংক্ষেপণ"] = pos_functions["abbreviations"]

pos_functions["সর্বনাম"] = pos_functions["pronouns"]

return export

-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet: