Module:qhv-headword: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
(77 intermediate revisions by the same user not shown)
Line 5: Line 5:
local find = mw.ustring.find
local find = mw.ustring.find
local match = mw.ustring.match
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local gsub = mw.ustring.gsub
local gsub = mw.ustring.gsub
local u = mw.ustring.char
local u = mw.ustring.char
local split = mw.text.split
local split = mw.text.split
local gsplit = mw.text.gsplit
local gsplit = mw.text.gsplit
local PAGENAME = mw.title.getCurrentTitle().text
local NAMESPACE = mw.title.getCurrentTitle().nsText
local SUBPAGENAME = mw.title.getCurrentTitle().subpageText


local legal_gender = {
local legal_gender = {
Line 14: Line 19:
["lun"] = true,
["lun"] = true,
["sol"] = true,
["sol"] = true,
["ter"] = true,  
["ter"] = true,
["p"] = true,
["?"] = true,
}
}


Line 22: Line 27:
["lun"] = "lunar",
["lun"] = "lunar",
["sol"] = "solar",
["sol"] = "solar",
["ter"] = "terrestrial"
["ter"] = "terrestrial",
["?"] = "unknown",
}
}


Line 37: Line 43:
local lang = require("Module:languages").getByCode("qhv")
local lang = require("Module:languages").getByCode("qhv")
local m_data = require("Module:qhv-noun/data")
local m_data = require("Module:qhv-noun/data")
local function glossary_link(entry, text)
text = text or entry
return "[[wikt:Appendix:Glossary#" .. entry .. "|" .. text .. "]]"
end


local function detect_gender(word)
local function detect_gender(word)
local ending = sub(word, -1)
local ending = word:sub(-1)
if find(word, "[aeioy]$") then
if word:find("illa$") then
return "aq"
elseif word:find("[aeioy]$") then
return "lun"
return "lun"
elseif ending == "r" then
elseif ending == "r" then
Line 51: Line 64:
end
end


local function generate_genitive(word, args, data, decl_type)
local function generate_gen_sg(word, rc, rp)
return m_data[word] and m_data[word](args, data) or m_data[decl_type](args, data)
local genitive = {}
local r = rc and "gen_co"
for alt in gmatch(require("Module:qhv-noun/head").pass_to_module((rc and "gen_co" or rp and "gen_pa" or "gen_sg"), word), "[^,]+") do
table.insert(genitive, alt)
end
return genitive
end
 
local function generate_nom_pl(word)
local plural = {}
for alt in gmatch(require("Module:qhv-noun/head").pass_to_module("nom_pl", word), "[^,]+") do
table.insert(plural, alt)
end
return plural
end
end


Line 58: Line 84:
-- This is the only function that can be invoked from a template.
-- This is the only function that can be invoked from a template.
function export.show(frame)
function export.show(frame)
if NAMESPACE == "Template" and SUBPAGENAME ~= "doc" then return end
local parent_args = frame:getParent().args
local parent_args = frame:getParent().args
PAGENAME = mw.title.getCurrentTitle().text
local head = parent_args["head"]; if head == "" then head = nil end
local head = parent_args["head"] or PAGENAME:match("%s") and require("Module:linkeach").link_for_modules(PAGENAME) or nil
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.")
local class = frame.args[2]; if class == "" then class = nil end
local class = frame.args[2]; if class == "" then class = nil end
local data = {lang = lang, pos_category = poscat, categories = {}, heads = {head}, genders = {}, inflections = {}}
local data = {
lang = lang,
heads = head,
inflections = {},
genders = {},
pos_category = poscat,
categories = {"Contionary"},
}
if pos_functions[poscat] then
if pos_functions[poscat] then
pos_functions[poscat](class, args, data)
pos_functions[poscat](class, parent_args, data)
end
end
Line 77: Line 110:
pos_functions.nouns = function(class, args, data)
pos_functions.nouns = function(class, args, data)
local params = {
local params = {
[1] = {list = "g", default = detect_gender(PAGENAME)},
[1] = {default = detect_gender(PAGENAME)},
[2] = {list = "gen"},
[2] = {default = PAGENAME},
[3] = {list = "pl"},
["nopl"] = {},
[4] = {list = "dim"},
["noinf"] = {type = "boolean", default = false},
["number"] = {},
["gen"] = {},
["class"] = {},
["pl"] = {},
["head"] = {default = PAGENAME},
["head"] = {},
["m"] = {list = true},
["rc"] = {type = "boolean"},
["f"] = {list = true},
["rp"] = {type = "boolean"},
["og"] = {},
}
}
local args = require("Module:parameters").process(args, params)
local args = require("Module:parameters").process(args, params)
local decl_type = require("Module:qhv-noun").detect_decl(table.concat(data.heads), args["number"], args["class"])
--data.heads = {args["head"]}
local decl_args = require("Module:parameters").process(parent_args, m_data[decl_type].params, true)
data.heads = {args["head"]}
table.insert(data.genders, args[1])
table.insert(data.categories, "High Valyrian " .. (args[1] == "?" and "" or gender_names[args[1]]) .. " " .. data.pos_category)
if not args["noinf"] then
args["gen"] = generate_gen_sg(args["og"] or args[2], args["rc"], args["rp"])
-- Gender
for i, form in ipairs(args["gen"]) do
for _, g in ipairs(args[1]) do
args["gen"][i] = {term = form}
if legal_gender[g] then
table.insert(data.genders, g)
if g == "p" then
table.insert(data.categories, "High Valyrian pluralia tantum")
end
else
table.insert(data.genders, "?")
end
end
args["gen"].label = "genitive"
table.insert(data.inflections, args["gen"])
end
end
-- Genitive
if not args[2][1] then
table.insert(args[2], generate_genitive(data.heads, args, data))
end
for i, form in ipairs(args[2]) do
args[2][i] = {term = form}
end
args[2].accel = {form = "gen|s"}
args[2].label = "genitive"
table.insert(data.inflections, args[2])
if args[1][1] ~= "p" then
-- Plural
if not args[3][1] and data.pos_category == "nouns" then
table.insert(args[3], PAGENAME .. "en")
end
if args[3][1] == "-" then
if data.pos_category == "nouns" and not args["noinf"] then
table.insert(data.inflections, {label = "no plural"})
if not args["nopl"] then
table.insert(data.categories, "German uncountable nouns")
args["pl"] = generate_nom_pl(args["og"] or args[2])
elseif #args[3] > 0 then
for i, form in ipairs(args[3]) do
for i, form in ipairs(args["pl"]) do
args[3][i] = {term = form}
args["pl"][i] = {term = form}
end
end
args[3].accel = {form = "p"}
args["pl"].label = "plural"
args[3].label = "plural"
table.insert(data.inflections, args["pl"])
table.insert(data.inflections, args[3])
end
end
-- Diminutive
if #args[4] > 0 then
for i, form in ipairs(args[4]) do
args[4][i] = {term = form, genders = {"n"}}
end
end
args[4].accel = {form = "diminutive", gender = "n"}
args[4].label = "diminutive"
table.insert(data.inflections, args[4])
end
-- Other gender
if #args.f > 0 then
args.f.label = "female"
table.insert(data.inflections, args.f)
end
if #args.m > 0 then
args.m.label = "male"
table.insert(data.inflections, args.m)
end
end
end
end
Line 165: Line 155:
pos_functions.adjectives = function(class, args, data)
pos_functions.adjectives = function(class, args, data)
local params = {
local params = {
[1] = {list = "comp"},
[1] = {list = "eq"},
[2] = {list = "sup"},
[2] = {list = "comp"},
[3] = {list = "sup"},
["unc"] = {type = "boolean"},
["indecl"] = {type = "boolean"},
["head"] = {},
["head"] = {},
}
}
local args = require("Module:parameters").process(args, params)
local args = require("Module:parameters").process(args, params)
local isdet = data.pos_category == "determiners"
data.heads = {args["head"]}
data.heads = {args["head"]}
if args[1][1] == "-" then
table.insert(data.categories, "High Valyrian " .. data.pos_category)
table.insert(data.inflections, {label = "not comparable"})
if args["unc"] or isdet then
table.insert(data.categories, "German uncomparable adjectives")
table.insert(data.inflections, {label = "not " .. glossary_link("comparable")})
return
if not isdet then table.insert(data.categories, "High Valyrian uncomparable adjectives") end
end
elseif args["indecl"] then
table.insert(data.inflections, {label = glossary_link("indeclinable")})
if #args[1] > 0 then
table.insert(data.categories, "High Valyrian indeclinable " .. data.pos_category)
for i, form in ipairs(args[1]) do
args[1][i] = {term = (form == "er" and PAGENAME .. "er" or form),
accel = {form = "comparative"}}
end
else
else
args[1] = {request = true}
args[1] = require("Module:qhv-adj/head").fetch("eq")
table.insert(data.categories, "de-adj lacking comparative")
args[2] = require("Module:qhv-adj/head").fetch("comp")
end
args[3] = require("Module:qhv-adj/head").fetch("sup")
args[1].label = "[[Appendix:Glossary#comparative|comparative]]"
table.insert(data.inflections, args[1])
args[1].label = glossary_link("equative")
if #args[2] > 0 then
args[2].label = glossary_link("comparative")
for i, form in ipairs(args[2]) do
args[3].label = glossary_link("superlative")
args[2][i] = {
term = "am [[" ..  (form == "sten" and PAGENAME .. "sten" or form) .. "]]",
table.insert(data.inflections, args[1])
accel = {form = "superlative"}}
table.insert(data.inflections, args[2])
end
table.insert(data.inflections, args[3])
else
args[2] = {request = true}
table.insert(data.categories, "de-adj lacking superlative")
end
end
args[2].label = "[[Appendix:Glossary#superlative|superlative]]"
table.insert(data.inflections, args[2])
end
end


pos_functions["proper nouns"] = pos_functions.nouns
pos_functions["proper nouns"] = pos_functions.nouns
pos_functions["determiners"] = pos_functions.adjectives


pos_functions.verbs = function(class, args, data)
pos_functions.verbs = function(class, args, data)
if args[2] then -- old-style
local params = {
local params = {
[1] = {list = "pres"},
[1] = {list = "pres", required = true},
[2] = {list = "subj"},
["pres_qual"] = {list = "pres=_qual", allow_holes = true},
[3] = {list = "pp"},
[2] = {list = "past", required = true},
["head"] = {},
["past_qual"] = {list = "past=_qual", allow_holes = true},
}
[3] = {list = "pp", required = true},
["pp_qual"] = {list = "pp=_qual", allow_holes = true},
local args = require("Module:parameters").process(args, params)
[4] = {list = "pastsubj"},
data.heads = {args["head"]}
["pastsubj_qual"] = {list = "pastsubj=_qual", allow_holes = true},
["aux"] = {list = true},
table.insert(data.categories, "High Valyrian " .. data.pos_category)
["aux_qual"] = {list = "aux=_qual", allow_holes = true},
["head"] = {list = true},
args[1] = require("Module:qhv-verb/head").fetch("act_ind_prs_1sg")
["class"] = {list = true},
args[2] = require("Module:qhv-verb/head").fetch("act_sub_prs_1sg")
}
args[3] = require("Module:qhv-verb/head").fetch("act_part_prf")
 
local args = require("Module:parameters").process(args, params)
args[1].label = "first-person singular present indicative"
data.heads = args["head"]
args[2].label = "first-person singular present subjunctive"
 
args[3].label = "perfect participle"
local function collect_forms(label, accel_form, forms, qualifiers)
if forms[1] == "-" then
table.insert(data.inflections, args[1])
return {label = "no " .. label}
table.insert(data.inflections, args[2])
else
table.insert(data.inflections, args[3])
local into_table = accel_form and {label = label, accel = {form = accel_form}} or {label = label}
for i, form in ipairs(forms) do
table.insert(into_table, {term = form, qualifiers = qualifiers[i] and {qualifiers[i]} or nil})
end
return into_table
end
end
 
if #args.class > 0 then
local class_descs, cats = require("Module:de-verb").process_verb_classes(args.class)
for _, cats in ipairs(cats) do
table.insert(data.categories, cats)
end
table.insert(data.inflections, {label = require("Module:table").serialCommaJoin(class_descs, {conj = "or"})})
end
table.insert(data.inflections, collect_forms("third-person singular present", "3|s|pres", args[1], args.pres_qual))
table.insert(data.inflections, collect_forms("past tense", "1//3|s|pret", args[2], args.past_qual))
table.insert(data.inflections, collect_forms("past participle", "perf|part", args[3], args.pp_qual))
if #args[4] > 0 then
table.insert(data.inflections, collect_forms("past subjunctive", "1//3|s|sub|II", args[4], args.pastsubj_qual))
end
if #args.aux > 0 then
table.insert(data.inflections, collect_forms("auxiliary", nil, args.aux, args.aux_qual))
end
return
end
 
local function get_headword_inflection(forms, label, accel_form)
if forms then
local inflection = accel_form and {label = label, accel = {form = accel_form}} or {label = label}
for _, form in ipairs(forms) do
local qualifiers
if form.footnotes then
qualifiers = {}
for _, footnote in ipairs(form.footnotes) do
footnote = footnote:gsub("^%[(.*)%]$", "%1")
table.insert(qualifiers, footnote)
end
end
table.insert(inflection, {term = form.form, qualifiers = qualifiers})
end
return inflection
elseif label then
return {label = "no " .. label}
else
return {}
end
end
 
local alternant_multiword_spec = require("Module:de-verb").do_generate_forms(args, "from headword")
for _, cat in ipairs(alternant_multiword_spec.categories) do
table.insert(data.categories, cat)
end
table.insert(data.inflections, {label = table.concat(alternant_multiword_spec.verb_types, " or ")})
 
if #data.heads == 0 then
for _, head in ipairs(alternant_multiword_spec.forms.infinitive_linked) do
table.insert(data.heads, head.form)
end
end
table.insert(data.inflections, get_headword_inflection(alternant_multiword_spec.forms.pres_3s,
"third-person singular present", "3|s|pres"))
local pret_3s = alternant_multiword_spec.forms.pret_3s
table.insert(data.inflections, get_headword_inflection(pret_3s, "past tense", "1//3|s|pret"))
table.insert(data.inflections, get_headword_inflection(alternant_multiword_spec.forms.perf_part,
"past participle", "perf|part"))
-- See if we need the past subjunctive, i.e. there exist past subjunctive forms whose stem is not the
-- same as some past tense form. To facilitate comparison, we truncate final -e in both preterite 3s
-- and past subjunctive 3s, to handle cases like subjunctive 'ginge aus' vs. preterite 'ging aus'.
-- We need to compare 3s forms (and not e.g. 3p forms, where the issue with truncating -e doesn't
-- occur) so we work correctly with impersonal verbs.
local need_past_subj
local truncated_pret_3s_forms = {}
if pret_3s then
for _, form in ipairs(pret_3s) do
local truncated_form = form.form:gsub("e$", ""):gsub("e ", " ") -- discard 2nd retval
table.insert(truncated_pret_3s_forms, truncated_form)
end
end
local subii_3s = alternant_multiword_spec.forms.subii_3s
local truncated_subii_3s_forms = {}
if subii_3s then
for _, form in ipairs(subii_3s) do
local truncated_form = form.form:gsub("e$", ""):gsub("e ", " ") -- discard 2nd retval
table.insert(truncated_subii_3s_forms, truncated_form)
end
end
for _, past_subj_form in ipairs(truncated_subii_3s_forms) do
local saw_same = false
for _, pret_3s_form in ipairs(truncated_pret_3s_forms) do
if past_subj_form == pret_3s_form then
saw_same = true
break
end
end
if not saw_same then
need_past_subj = true
break
end
end
if need_past_subj then
table.insert(data.inflections, get_headword_inflection(subii_3s, "past subjunctive", "1//3|s|sub|II"))
end
 
local auxes = alternant_multiword_spec.forms.aux
table.insert(data.inflections, get_headword_inflection(auxes, "auxiliary"))
end
end


return export
return export

Latest revision as of 20:58, 15 May 2021



local export = {}
local pos_functions = {}

local sub = mw.ustring.sub
local find = mw.ustring.find
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local gsub = mw.ustring.gsub
local u = mw.ustring.char
local split = mw.text.split
local gsplit = mw.text.gsplit

local PAGENAME = mw.title.getCurrentTitle().text
local NAMESPACE = mw.title.getCurrentTitle().nsText
local SUBPAGENAME = mw.title.getCurrentTitle().subpageText

local legal_gender = {
	["aq"] = true,
	["lun"] = true,
	["sol"] = true,
	["ter"] = true,
	["?"] = true,
}

local gender_names = {
	["aq"] = "aquatic",
	["lun"] = "lunar",
	["sol"] = "solar",
	["ter"] = "terrestrial",
	["?"] = "unknown",
}

local legal_verb_classes = { -- TBD
	["1"] = true,
	["2"] = true,
	["3"] = true,
	["4"] = true,
	["5"] = true,
	["6"] = true,
	["7"] = true,
}

local lang = require("Module:languages").getByCode("qhv")
local m_data = require("Module:qhv-noun/data")

local function glossary_link(entry, text)
	text = text or entry
	return "[[wikt:Appendix:Glossary#" .. entry .. "|" .. text .. "]]"
end

local function detect_gender(word)
	local ending = word:sub(-1)
	if word:find("illa$") then
		return "aq"
	elseif word:find("[aeioy]$") then
		return "lun"
	elseif ending == "r" then
		return "aq"
	elseif ending == "s" then
		return "sol"
	elseif ending == "n" then
		return "ter"
	else return "?" end
end

local function generate_gen_sg(word, rc, rp)
	local genitive = {}
	local r = rc and "gen_co"
	for alt in gmatch(require("Module:qhv-noun/head").pass_to_module((rc and "gen_co" or rp and "gen_pa" or "gen_sg"), word), "[^,]+") do
		table.insert(genitive, alt)
	end
	return genitive
end

local function generate_nom_pl(word)
	local plural = {}
	for alt in gmatch(require("Module:qhv-noun/head").pass_to_module("nom_pl", word), "[^,]+") do
		table.insert(plural, alt)
	end
	return plural
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	if NAMESPACE == "Template" and SUBPAGENAME ~= "doc" then return end
	local parent_args = frame:getParent().args
	
	local head = parent_args["head"] or PAGENAME:match("%s") and require("Module:linkeach").link_for_modules(PAGENAME) or nil
	
	local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")
	local class = frame.args[2]; if class == "" then class = nil end
	
	local data = {
		lang = lang,
		heads = head,
		inflections = {},
		genders = {},
		pos_category = poscat,
		categories = {"Contionary"},
	}
	
	if pos_functions[poscat] then
		pos_functions[poscat](class, parent_args, data)
	end
	
	return require("Module:headword").full_headword(data)
end

pos_functions.nouns = function(class, args, data)
	local params = {
		[1] = {default = detect_gender(PAGENAME)},
		[2] = {default = PAGENAME},
		["nopl"] = {},
		["noinf"] = {type = "boolean", default = false},
		["gen"] = {},
		["pl"] = {},
		["head"] = {},
		["rc"] = {type = "boolean"},
		["rp"] = {type = "boolean"},
		["og"] = {},
	}
	
	local args = require("Module:parameters").process(args, params)
	--data.heads = {args["head"]}
	
	table.insert(data.genders, args[1])
	table.insert(data.categories, "High Valyrian " .. (args[1] == "?" and "" or gender_names[args[1]]) .. " " .. data.pos_category)
	
	if not args["noinf"] then
		args["gen"] = generate_gen_sg(args["og"] or args[2], args["rc"], args["rp"])
	
		for i, form in ipairs(args["gen"]) do
			args["gen"][i] = {term = form}
		end
		
		args["gen"].label = "genitive"
		table.insert(data.inflections, args["gen"])
	end
		
	if data.pos_category == "nouns" and not args["noinf"] then
		if not args["nopl"] then
			args["pl"] = generate_nom_pl(args["og"] or args[2])
			
			for i, form in ipairs(args["pl"]) do
				args["pl"][i] = {term = form}
			end
			
			args["pl"].label = "plural"
			table.insert(data.inflections, args["pl"])
		end
	end
end

pos_functions.adjectives = function(class, args, data)
	local params = {
		[1] = {list = "eq"},
		[2] = {list = "comp"},
		[3] = {list = "sup"},
		["unc"] = {type = "boolean"},
		["indecl"] = {type = "boolean"},
		["head"] = {},
	}
	
	local args = require("Module:parameters").process(args, params)
	local isdet = data.pos_category == "determiners"
	data.heads = {args["head"]}
	
	table.insert(data.categories, "High Valyrian " .. data.pos_category)
	if args["unc"] or isdet then
		table.insert(data.inflections, {label = "not " .. glossary_link("comparable")})
		if not isdet then table.insert(data.categories, "High Valyrian uncomparable adjectives") end
	elseif args["indecl"] then
		table.insert(data.inflections, {label = glossary_link("indeclinable")})
		table.insert(data.categories, "High Valyrian indeclinable " .. data.pos_category)
	else
		args[1] = require("Module:qhv-adj/head").fetch("eq")
		args[2] = require("Module:qhv-adj/head").fetch("comp")
		args[3] = require("Module:qhv-adj/head").fetch("sup")
		
		
		args[1].label = glossary_link("equative")
		args[2].label = glossary_link("comparative")
		args[3].label = glossary_link("superlative")
		
		table.insert(data.inflections, args[1])
		table.insert(data.inflections, args[2])
		table.insert(data.inflections, args[3])
	end
end

pos_functions["proper nouns"] = pos_functions.nouns
pos_functions["determiners"] = pos_functions.adjectives

pos_functions.verbs = function(class, args, data)
	local params = {
		[1] = {list = "pres"},
		[2] = {list = "subj"},
		[3] = {list = "pp"},
		["head"] = {},
	}
	
	local args = require("Module:parameters").process(args, params)
	data.heads = {args["head"]}
	
	table.insert(data.categories, "High Valyrian " .. data.pos_category)
	
	args[1] = require("Module:qhv-verb/head").fetch("act_ind_prs_1sg")
	args[2] = require("Module:qhv-verb/head").fetch("act_sub_prs_1sg")
	args[3] = require("Module:qhv-verb/head").fetch("act_part_prf")
		
	args[1].label = "first-person singular present indicative"
	args[2].label = "first-person singular present subjunctive"
	args[3].label = "perfect participle"
		
	table.insert(data.inflections, args[1])
	table.insert(data.inflections, args[2])
	table.insert(data.inflections, args[3])
end

return export