Module:User:Benwing/fro-verb
Jump to navigation
Jump to search
- This module sandbox lacks a documentation subpage. You may create it.
- Useful links: root page • root page’s subpages • links • transclusions • testcases • user page • user talk page • userspace
This is a private module sandbox of Benwing, for their own experimentation. Items in this module may be added and removed at Benwing's discretion; do not rely on this module's stability.
local m_links = require("Module:links")
local m_utilities = require("Module:utilities")
local lang = require("Module:languages").getByCode("fro")
local export = {}
-- Functions that do the actual inflecting by creating the forms of a basic term.
local inflections = {}
local rfind = mw.ustring.find
local rsub = mw.ustring.gsub
local rmatch = mw.ustring.match
local function ine(x) -- If Not Empty
if x == "" then
return nil
else
return x
end
end
local function ined(x) -- If Not Empty or Dash
if x == "" or x == "-" then
return nil
else
return x
end
end
----------------------------------------------------------------------------
-- Functions for working with stems
-- Given the stem as it appears before a soft-vowel ending (e/i), generate
-- the corresponding stem for a hard-vowel ending (a/o/u).
function stemv_to_stemc(stemv)
if rfind(stemv, "c$") then
-- Need to assign to a var because rsub returns 2 values, and
-- assigning to one var fetches only the first one
local stemc = rsub(stemv, "c$", "ç")
return stemc
elseif rfind(stemv, "g$") then
local stemc = rsub(stemv, "g$", "j")
return stemc
else
return stemv
end
end
-- Given the stem as it appears before a hard-vowel ending, generate
-- the corresponding stem for a soft-vowel ending.
function stemc_to_stemv(stemc)
if rfind(stemc, "c$") then
-- Need to assign to a var because rsub returns 2 values, and
-- assigning to one var fetches only the first one
local stemv = rsub(stemc, "c$", "qu")
return stemv
elseif rfind(stemc, "g$") then
local stemv = rsub(stemc, "g$", "gu")
return stemv
elseif rfind(stemc, "ç$") then
local stemv = rsub(stemc, "ç$", "c")
return stemv
else
return stemc
end
end
-- Get the stem from the infinitive. Return stem and whether stem is
-- soft-vowel (true except for -re and -oir verbs).
--
-- Currently we rely on the IER argument being set in order to remove
-- -ier from an infinitive. An alternative is to always check for -ier
-- and assume that cases like 'signifier' which is an '-er' verb with a
-- stem 'signifi' are handled by explicitly specifying the stem. (We
-- assume this anyway in the case of any '-ir' verb whose stem ends
-- in '-o', such as 'oir' "to hear".)
local function get_stem_from_inf(inf, ier)
local nsub = 0
-- if 'ier' arg given and stem ends in -ier, strip it off.
if ier then
stem, nsub = rsub(inf, "ier$", "")
if nsub > 0 then
return stem, "ier", true
end
end
-- Check for -er, -oir, -eir, -ir, -re in sequence.
-- Must check for -oir, -eir before -ir.
stem, nsub = rsub(inf, "er$", "")
if nsub > 0 then
return stem, "er", true
end
stem, nsub = rsub(inf, "oir$", "")
if nsub > 0 then
return stem, "oir", false
end
stem, nsub = rsub(inf, "eir$", "")
if nsub > 0 then
return stem, "eir", true
end
stem, nsub = rsub(inf, "ir$", "")
if nsub > 0 then
return stem, "ir", true
end
stem, nsub = rsub(inf, "re$", "")
if nsub > 0 then
return stem, "re", false
end
error("Unrecognized infinitive '" .. inf .. "'")
end
-- Get the stem, either explicitly passed in as the first arg or
-- implicitly through the page name, assumed to be the same as the
-- infinitive. Currently we rely on the 'ier' argument being set in
-- order to remove -ier from an infinitive. An alternative is to
-- always check for -ier an assume that cases like 'signifier' which
-- is an '-er' verb with a stem 'signifi' are handled by explicitly
-- specifying the stem. (We assume this anyway in the case of any '-ir'
-- verb whose stem ends in '-o', such as 'oir' "to hear".)
local function get_stem_from_frame(frame)
local stem = frame.args[1]
-- if stem passed in and non-blank, use it.
if ine(stem) then
return stem
end
local inf = mw.title.getCurrentTitle().text
local ier = ine(frame.args["ier"])
local stem, ending, is_soft = get_stem_from_inf(inf, ier)
return stem
end
-- External entry point for get_stem_from_frame(). Optional stem is first
-- argument, optional 'ier' argument is used for -ier verbs (see
-- get_stem_from_frame()).
function export.get_stem(frame)
return get_stem_from_frame(frame)
end
----------------------------------------------------------------------------
-- Functions for generating arrays of endings
-- Generate an ending array (five-element, see below), where a supporting ''e''
-- is needed.
local function supporting_e(extra)
local text = "In the present tense an extra supporting ''e'' is needed in the first-person singular indicative and throughout the singular subjunctive, and the third-person singular subjunctive ending ''-t'' is lost. "
text = text .. extra
return {"", "e", "es", "e", text}
end
-- Generate a general ending array (five-element, see below).
local function mod3(ending, zero, s, t)
local text = nil
if ending == zero then
text = string.format("The forms that would normally end in *''-%ss'', *''-%st'' are modified to ''%s'', ''%s''. ",
ending, ending, s, t)
else
text = string.format("The forms that would normally end in *''-%s'', *''-%ss'', *''-%st'' are modified to ''%s'', ''%s'', ''%s''. ",
ending, ending, ending, zero, s, t)
end
return {ending, zero, s, t, text}
end
-- Return the stem and an array of five elements. In the array, the first
-- is the ending to be substitute, the second is the add_zero ending to
-- substitute, the third is the add_s ending to substitute, the fourth is
-- the add_t ending to substitute and the fifth is the text going into the
-- comment at the top of the conj table. The IER parameter should be
-- specified for -ier verbs, which only occur with palatal(ized) final
-- consonants, and causes a different interpretation of certain consonants,
-- esp. final l.
local function get_endings(stem, ier)
-- local args = frame:getParent().args or {}
local ret = {"", "", "s", "t", ""}
local ending = nil
local prev = nil
-- canonicalize ngn to gn when after vowel or r, l
if rfind(stem, "[aeiourl]ngn$") then
ending = "ngn"
stem = rsub(stem, "ngn$", "gn")
end
-- canonicalize double letter to single after vowel, except for l
-- we need to treat Cill and Cil differently
if rfind(stem, "[aeiou]([bcdfghjkmnpqrstvwxz])%1$") then
ending = rmatch(stem, "(..)$")
stem = rsub(stem, "([bcdfghjkmnpqrstvwxz])%1$", "%1")
end
if rfind(stem, "mb$") then
ret = mod3("mb", "mp", "ns", "nt")
elseif rfind(stem, "mp$") then
ret = mod3("mp", "mp", "ns", "nt")
elseif rfind(stem, "([aeiourlmn])b$") then
ret = mod3(ending or "b", "p", "s", "t")
elseif rfind(stem, "([aeiourlmn])v$") then
ret = mod3(ending or "v", "f", "s", "t")
elseif rfind(stem, "([aeiourlmn])d$") then
ret = mod3(ending or "d", "t", "z", "t")
elseif rfind(stem, "([aeiourlmn])c$") then
ret = mod3(ending or "c", "z", "z", "zt")
ret[5] = ret[5] .. "In addition, ''c'' becomes ''ç'' before an ''a'' or an ''o'' to keep the /ts/ sound intact. "
elseif rfind(stem, "([aeiourlmn])[pfk]$") then
local lastchar = rmatch(stem, "(.)$")
ret = mod3(ending or lastchar, lastchar, "s", "t")
elseif rfind(stem, "([aeiourlmn])t$") then
ret = mod3(ending or "t", "t", "z", "t")
elseif rfind(stem, "([aeiourlmn])z$") then
ret = mod3(ending or "z", "z", "z", "zt")
elseif rfind(stem, "([aeiourlmn])c?qu$") then
ending = rmatch(stem, "(c?qu)$")
ret = mod3(ending, "c", "s", "t")
elseif rfind(stem, "([aeiourlmn])g?gu$") then
ending = rmatch(stem, "(g?gu)$")
ret = mod3(ending, "c", "s", "t")
elseif rfind(stem, "([aeiourlmn])ct$") then
-- convicter, paincter. Best guess here
ret = mod3("ct", "ct", "cz", "ct")
elseif rfind(stem, "([aeiourlmn])st$") then
ret = mod3("st", "st", "z", "st")
elseif rfind(stem, "([aeiourlmn])sd$") then
-- brosder. Best guess here
ret = mod3("sd", "st", "z", "st")
elseif rfind(stem, "([aeo])ill?$") or (rfind(stem, "[aeo]ll?$") and ier) then
ending = rmatch(stem, "([aeo]i?ll?)$")
prev = rmatch(stem, "([aeo])i?ll?$")
ret = mod3(ending, prev .. "il", prev .. "uz", prev .. "ut")
elseif rfind(stem, "uill?$") or (rfind(stem, "ull?$") and ier) then
ending = rmatch(stem, "(ui?ll?)$")
ret = mod3(ending, "uil", "uz", "ut")
elseif rfind(stem, "ill$") or (rfind(stem, "il$") and ier) then
ending = rmatch(stem, "(ill?)$")
ret = mod3(ending, "il", "iz", "it")
elseif rfind(stem, "([^iu])ell?$") then
ending = rmatch(stem, "(ell?)$")
ret = mod3(ending, "el", "eaus", "eaut")
elseif rfind(stem, "([aeo])ll?$") then
ending = rmatch(stem, "([iu]ell?)$") or rmatch(stem, "([ao]ll?)$")
prev = rmatch(stem, "([iu]e)ll?$") or rmatch(stem, "([ao])ll?$")
ret = mod3(ending, prev .. "l", prev .. "us", prev .. "ut")
elseif rfind(stem, "([iu])ll?$") then
ending = rmatch(stem, "([iu]ll?)$")
prev = rmatch(stem, "([iu])ll?$")
ret = mod3(ending, prev .. "l", prev .. "s", prev .. "t")
elseif rfind(stem, "ign$") then
ret = mod3("i" .. (ending or "gn"), "ing", "inz", "int")
elseif rfind(stem, "lgn$") then
ret = mod3("l" .. (ending or "gn"), "lng", "lnz", "lnt")
elseif rfind(stem, "rgn$") then
ret = mod3("r" .. (ending or "gn"), "rng", "rz", "rt")
elseif rfind(stem, "([aeou])gn$") then
prev = rmatch(stem, "([aeou])gn$")
ret = mod3(prev .. (ending or "gn"), prev .. "ing", prev .. "inz", prev .. "int")
elseif rfind(stem, "rm$") then
ret = mod3("rm", "rm", "rs", "rt")
elseif rfind(stem, "rn$") then
ret = mod3("rn", "rn", "rz", "rt")
elseif rfind(stem, "[aeioul]m$") then
ret = mod3(ending or "m", "m", "ns", "nt")
elseif rfind(stem, "s$") then
ret = mod3(ending or "s", "s", "s", "st")
elseif rfind(stem, "g$") then
ret = supporting_e("In addition, ''g'' becomes ''j'' before an ''a'' or an ''o'' to keep the /dʒ/ sound intact. ")
elseif rfind(stem, "j$")
or rfind(stem, "[^aeiou][bcdfghjklmnpqrtvwxz]$") then
ret = supporting_e("")
end
return ret
end
----------------------------------------------------------------------------
-- Functions for handling particular sorts of endings
-- Convert a stressed verb stem to the form used with a zero ending
-- (1st sing pres indic, also, 1st sing pres subj of -er verbs).
-- See get_endings() for meaning of IER.
function add_zero(stem, ier)
local e = get_endings(stem, ier)
-- We need to assign to a variable here because rsub() returns multiple
-- values and we want only the first returned. Return rsub() directly
-- and all values get returned and appended to the string.
local ret, nsub = rsub(stem, e[1] .. "$", e[2])
assert(nsub == 1)
return ret
end
-- Convert a stressed verb stem to the form used with a -s ending
-- (2nd sing pres indic of -ir/-oir/-re verbs, 2nd sing pres subj of
-- -er verbs). Same code could be used to add -s to nouns except that
-- handling of -c stems needs to be different (need to treat as hard /k/
-- not /ts/). See get_endings() for meaning of IER.
function add_s(stem, ier)
local e = get_endings(stem, ier)
-- We need to assign to a variable here because rsub() returns multiple
-- values and we want only the first returned. Return rsub() directly
-- and all values get returned and appended to the string.
local ret, nsub = rsub(stem, e[1] .. "$", e[3])
assert(nsub == 1)
return ret
end
-- Convert a stressed verb stem to the form used with a -t ending
-- (3rd sing pres indic of -ir/-oir/-re verbs, 3rd sing pres subj of
-- -er verbs). See get_endings() for meaning of IER.
function add_t(stem, ier)
local e = get_endings(stem, ier)
-- We need to assign to a variable here because rsub() returns multiple
-- values and we want only the first returned. Return rsub() directly
-- and all values get returned and appended to the string.
local ret, nsub = rsub(stem, e[1] .. "$", e[4])
assert(nsub == 1)
return ret
end
-- External entry point for add_zero(). Optional stem is first argument,
-- optional 'ier' argument is used for -ier verbs (see get_ending()).
function export.add_zero(frame)
local stem = get_stem_from_frame(frame)
local ier = ine(frame.args["ier"])
return add_zero(stem, ier)
end
-- External entry point for add_s(). Optional stem is first argument,
-- optional 'ier' argument is used for -ier verbs (see get_ending()).
function export.add_s(frame)
local stem = get_stem_from_frame(frame)
local ier = ine(frame.args["ier"])
return add_s(stem, ier)
end
-- External entry point for add_t(). Optional stem is first argument,
-- optional 'ier' argument is used for -ier verbs (see get_ending()).
function export.add_t(frame)
local stem = get_stem_from_frame(frame)
local ier = ine(frame.args["ier"])
return add_t(stem, ier)
end
----------------------------------------------------------------------------
-- Functions for handling comments at the top of conjugation tables
-- Return comment describing phonetic changes to the verb in the present
-- tense. Appears near the top of the conjugation chart. STEM is the stressed
-- stem. See get_endings() for meaning of IER.
function verb_comment(stem, ier)
local e = get_endings(stem, ier)
return e[5]
end
-- Return comment describing phonetic and stem changes to the verb in the
-- present tense. Appears near the top of the conjugation chart. STEMV is
-- the unstressed stem before e/i, STEMC the unstressed stem before a/o/u,
-- STEMS the stressed stem. See get_endings() for meaning of IER.
function full_verb_comment(stemv, stemc, stems, ier)
local com = ""
if stemv ~= stems then
com = com .. "In addition, it has a stressed stem ''" .. stems .. "'' distinct from the unstressed stem ''" .. stemv .. "''. "
end
com = com .. verb_comment(stems, ier)
return com
end
-- External entry point for verb_comment(). Optional stem is first argument,
-- optional 'ier' argument is used for -ier verbs (see get_ending()).
function export.verb_comment(frame)
local stem = get_stem_from_frame(frame)
local ier = ine(frame.args["ier"])
return verb_comment(stem, ier)
end
----------------------------------------------------------------------------
-- Main inflection-handling functions
-- Main entry point
function export.froconj(frame)
local args = frame:getParent().args
-- Create the forms
local data = {forms = {}, categories = {}, comment = "", refl = ine(args["refl"]), ier = ine(args["ier"])}
data.forms.aux = {data.refl and "estre" or mw.text.trim(ine(args["aux"]) or "avoir")}
data.forms.infinitive =
{ine(args["inf"]) or mw.title.getCurrentTitle().text}
-- Set the soft ('stemv') and hard ('stemc') vowel infinitive stems.
-- They can be explicitly set using 'stemv' and 'stemc' params.
-- If one is set, the other is inferred from it. If neither is set,
-- both are inferred from the infinitive.
data.stemv = ine(args["stemv"])
data.stemc = ine(args["stemc"])
local inf_stem, inf_ending, inf_is_soft =
get_stem_from_inf(data.forms.infinitive[1], data.ier)
if not data.stemv and not data.stemc then
if inf_is_soft then
data.stemv = inf_stem
else
data.stemc = inf_stem
end
end
if not data.stemv then data.stemv = stemc_to_stemv(data.stemc) end
if not data.stemc then data.stemc = stemv_to_stemc(data.stemv) end
-- Find what type of verb is it (hard-coded in the template).
-- Generate standard conjugated forms for each type of verb.
local infl_type = frame.args["type"]
if not ine(infl_type) then
error("Verb type (infl_type) not specified.")
elseif inflections[infl_type] then
inflections[infl_type](args, data)
else
error("Verb type " .. infl_type .. " not supported.")
end
table.insert(data.categories, "Old French " .. data.group .. " group verbs")
table.insert(data.categories, "Old French verbs ending in -" .. inf_ending)
-- Get overridden forms
process_overrides(args, data)
-- Add links
add_links(args, data)
-- Add reflexive pronouns
if data.refl then
add_reflexive_pronouns(args, data)
end
return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end
-- If ARGBASE == "foo", return an array of
-- {args["foo"],args["foo2"],...,args["foo9"]}.
function get_args(args, argbase)
local theargs = {args[argbase]}
for j = 2, 9 do
table.insert(theargs, args[argbase .. j])
end
return theargs
end
-- Replaces terms with overridden ones that are given as additional named parameters.
function process_overrides(args, data)
-- Each term in current is overridden by one in override, if it exists.
local function override(current, override)
current = current or {}
local ret = {}
local i = 1
-- First see if any of the existing items in current have an override specified.
while current[i] do
if ine(override[i]) then
if override[i] ~= "-" then
table.insert(ret, override[i])
end
else
table.insert(ret, current[i])
end
i = i + 1
end
-- We've reached the end of current.
-- Look in the override list to see if there are any extra forms to add on to the end.
while override[i] do
if ine(override[i]) and override[i] ~= "-" then
table.insert(ret, override[i])
end
i = i + 1
end
return ret
end
-- Mark terms with any additional statement as irregular.
for k,v in pairs(args) do
if k ~= 'stemv' and k ~= 'aux' and k ~= 'ier' and mw.text.trim(v) ~= '' then
table.insert(data.categories, 'Old French irregular verbs')
break
end
end
--[[
This function replaces former code like this:
data.forms.pret_indc_1sg = override(data.forms.pret_indc_1sg, {args["pret1s"], args["pret1s2"], args["pret1s3"]})
data.forms.pret_indc_2sg = override(data.forms.pret_indc_2sg, {args["pret2s"], args["pret2s2"], args["pret2s3"]})
data.forms.pret_indc_3sg = override(data.forms.pret_indc_3sg, {args["pret3s"], args["pret3s2"], args["pret3s3"]})
data.forms.pret_indc_1pl = override(data.forms.pret_indc_1pl, {args["pret1p"], args["pret1p2"], args["pret1p3"]})
data.forms.pret_indc_2pl = override(data.forms.pret_indc_2pl, {args["pret2p"], args["pret2p2"], args["pret2p3"]})
data.forms.pret_indc_3pl = override(data.forms.pret_indc_3pl, {args["pret3p"], args["pret3p2"], args["pret3p3"]})
except that there are 9 overrides for each tense-person-number combo,
not just 2 or 3.
--]]
local function handle_tense_override(tense, short)
local pnums = {"1sg", "2sg", "3sg", "1pl", "2pl", "3pl"}
local pnums_short = {"1s", "2s", "3s", "1p", "2p", "3p"}
for pn = 1, #pnums do
local pnum = pnums[pn]
local pnum_short = pnums_short[pn]
local theargs = get_args(args, short .. pnum_short)
local tensepnum = tense .. "_" .. pnum
data.forms[tensepnum] = override(data.forms[tensepnum], theargs)
end
end
-- Non-finite forms
data.forms.infinitive = override(data.forms.infinitive, {args["inf"]})
data.forms.pres_ptc = override(data.forms.pres_ptc, get_args(args, "presp"))
data.forms.past_ptc = override(data.forms.past_ptc, get_args(args, "pastp"))
handle_tense_override("pres_indc", "pres") -- Present
handle_tense_override("impf_indc", "imperf") -- Imperfect
handle_tense_override("pret_indc", "pret") -- Preterite
handle_tense_override("futr_indc", "fut") -- Future
handle_tense_override("cond", "cond") -- Conditional
handle_tense_override("pres_subj", "sub") -- Present subjunctive
handle_tense_override("impf_subj", "impsub") -- Imperfect subjunctive
-- Imperative
data.forms.impr_2sg = override(data.forms.impr_2sg, get_args(args, "imp2s"))
data.forms.impr_1pl = override(data.forms.impr_1pl, get_args(args, "imp1p"))
data.forms.impr_2pl = override(data.forms.impr_2pl, get_args(args, "imp2p"))
end
-- Adds reflexive pronouns to the appropriate forms
function add_reflexive_pronouns(args, data)
-- Gather pronoun parameters
local cprons = {}
local vprons = {}
cprons["1sg"] = ine(args["me"]) or "me "
cprons["2sg"] = ine(args["te"]) or "te "
cprons["3sg"] = ine(args["se"]) or "se "
cprons["1pl"] = ine(args["nos"]) or "nos "
cprons["2pl"] = ine(args["vos"]) or "vos "
cprons["3pl"] = cprons["3sg"]
vprons["1sg"] = ine(args["me"]) or "m'"
vprons["2sg"] = ine(args["te"]) or "t'"
vprons["3sg"] = ine(args["se"]) or "s'"
vprons["1pl"] = ine(args["nos"]) or "nos "
vprons["2pl"] = ine(args["vos"]) or "vos "
vprons["3pl"] = vprons["3sg"]
function add_refl(person, form)
mw.log(form)
-- FIXME! YUCK! This hard-codes knowledge of how the links are formatted.
-- Perhaps we should go back to the old way of having the reflexive code
-- also insert links.
if rfind(form, "^<span.*>[^a-zA-Z]*[aeiouAEIOU]") then
return vprons[person] .. form
else
return cprons[person] .. form
end
end
-- Go over all the forms in the list
for key, subforms in pairs(data.forms) do
-- Extract the person/number from the last 3 characters of the key
local person = key:sub(-3)
-- Skip these three, as they already had pronouns added earlier
if cprons[person] and key ~= "impr_2sg" and key ~= "impr_1pl" and key ~= "impr_2pl" then
-- Go through each of the alternative subforms and add the pronoun
for key2, subform in ipairs(subforms) do
data.forms[key][key2] = add_refl(person, subform)
end
end
end
-- Handle infinitive
for key, subform in ipairs(data.forms.infinitive) do
data.forms.infinitive[key] = add_refl("3sg", subform)
end
-- Handle imperatives
for key, subform in ipairs(data.forms.impr_2sg) do
data.forms.impr_2sg[key] = subform .. "-toi"
end
for key, subform in ipairs(data.forms.impr_1pl) do
data.forms.impr_1pl[key] = subform .. "-nos"
end
for key, subform in ipairs(data.forms.impr_2pl) do
data.forms.impr_2pl[key] = subform .. "-vos"
end
end
-- Adds links to appropriate forms
function add_links(args, data)
-- Go over all the forms in the list
for key, subforms in pairs(data.forms) do
-- Go through each of the alternative subforms and add the pronoun
for key2, subform in ipairs(subforms) do
data.forms[key][key2] = make_link(subform)
end
end
end
-- Inflection functions
-- Add to DATA the inflections for the tense indicated by TENSE (the prefix
-- in the data.forms names, e.g. 'impf_subj'), formed by combining the STEMS
-- (either a single string or a sequence of six strings) with the
-- ENDINGS (a sequence of six values, each of which is either a string
-- or a sequence of one or more possible endings). If existing
-- inflections already exist, they will be added to, not overridden.
function inflect_tense(data, tense, stems, endings)
local pnums = {"1sg", "2sg", "3sg", "1pl", "2pl", "3pl"}
-- First, initialize any nil entries to sequences.
for i, pnum in ipairs(pnums) do
if data.forms[tense .. "_" .. pnum] == nil then
data.forms[tense .. "_" .. pnum] = {}
end
end
-- Now add entries
for i = 1, #pnums do
-- Extract endings for this person-number combo
local ends = endings[i]
if type(ends) == "string" then ends = {ends} end
-- Extract stem for this person-number combo
local stem = stems
if type(stem) == "table" then stem = stem[i] end
-- Add entries for stem + endings
for j, ending in ipairs(ends) do
table.insert(data.forms[tense .. "_" .. pnums[i]], stem .. ending)
end
end
end
-- Add to DATA the endings for the preterite and imperfect
-- subjunctive, with unstressed stem STEMU, stressed stem STEMS, and
-- conjugation type PTY.
function inflect_past_impf_subj(data, stemu, stems, pty)
-- WARNING: If the second person singular of any of these is not a
-- simple string, you will need to modify the handling below of
-- the imperfect subjunctive, which relies on this form.
local all_endings =
-- weak-a (-er) and weak-a2 (-ier) are handled separately by the
-- handlers for -er and -ier. In any case the code here doesn't
-- properly handle the stemv vs. stemc distinction necessary for these
-- verbs, and the code below to handle the imperfect subjunctive doesn't
-- work for them because 1pl, 2pl have -is- not -as-.
--
--pty == "weak-a" and {"ai","as",{"a","aṭ"},"ames","astes","erent"} or
--pty == "weak-a2" and {"ai","as",{"a","aṭ"},"ames","astes","ierent"} or
pty == "weak-i" and {"i","is",{"i","iṭ"},"imes","istes","irent"} or
pty == "weak-i2" and {"i","is",{"ié","iéṭ"},"imes","istes","ierent"} or
pty == "strong-i" and {"","is","t","imes","istes","rent"} or
pty == "strong-id" and {"","is","t","imes","istes",{"drent","rent"}} or
pty == "weak-u" and {"ui","us",{"u","uṭ"},"umes","ustes","urent"} or
pty == "strong-u" and {"ui","eüs","ut","eümes","eüstes","urent"} or
pty == "strong-o" and {"oi","eüs","ot","eümes","eüstes","orent"} or
pty == "strong-st" and {"s","sis","st","simes","sistes","strent"} or
pty == "strong-sd" and {"s","ṣis","st","ṣimes","ṣistes","sdrent"} or
ine(pty) and error("Unrecognized pty value '" .. pty .. "'") or
error("Unspecified pty value")
-- Always use weak stem unless we have strong-stem endings
local stems =
(rfind(pty, "^strong-") and {stems, stemu, stems, stemu, stemu, stems}
or stemu)
inflect_tense(data, "pret_indc", stems, all_endings)
-- Handle imperfect subj, which follows the same types as the preterite
-- and is built off of the 2nd person singular form
inflect_tense(data, "impf_subj", stemu .. all_endings[2],
{"se","ses","t",{"sons","siens"},{"soiz","sez","siez"},"sent"})
end
-- Add to DATA the endings for the preterite and
-- imperfect subjunctive, based on the strong and weak stems and past ending
-- type(s) given in ARGS. For each weak past ending type 'pasttyN' there
-- should be a corresponding stem in 'pastN' and for each strong past ending
-- type 'pasttyN' there should be corresponding unstressed and stressed stems
-- in 'pastuN' and 'pastsN'. If no past ending types given, default to the
-- past type in PTY and stem in STEM, which serves for both unstressed and
-- stressed stems.
function handle_past_impf_subj(args, data, stem, pty)
if not ined(args["pastty"]) then
inflect_past_impf_subj(data, stem, stem, pty)
else
if ined(args["pastty"]) then
inflect_past_impf_subj(data,
ine(args["pastu"]) or args["past"] or stem,
ine(args["pasts"]) or ine(args["pastu"]) or args["past"] or stem,
args["pastty"])
end
for i = 2, 9 do
if ined(args["pastty" .. i]) then
inflect_past_impf_subj(data,
ine(args["pastu" .. i]) or args["past" .. i] or stem,
ine(args["pasts" .. i]) or ine(args["pastu" .. i]) or args["past" .. i] or stem,
args["pastty" .. i])
end
end
end
end
-- Add to DATA the endings for the future and conditional, with the stems in
-- STEM, a sequence (generally the infinitive or some modified version).
-- Values in STEM that are empty or "-" are ignored.
function inflect_future_cond(data, stems)
for _, stem in ipairs(stems) do
if ined(stem) then
inflect_tense(data, "futr_indc", stem,
{"ai","as","a","ons",{"ez","eiz"},"ont"})
inflect_tense(data, "cond", stem,
{{"oie","eie"},{"oies","eies"},{"oit","eit"},
{"iens","iiens"},{"iez","iiez"},{"oient","eient"}})
end
end
end
-- Add to DATA the endings for the future and conditional based on the
-- future stem(s) in ARGS. If no future stems given, use STEM.
function handle_future_cond(args, data, stem)
if not ined(args["fut"]) then
inflect_future_cond(data, {stem})
else
inflect_future_cond(data, get_args(args, "fut"))
end
end
-- Add to DATA the endings for an -er or -ier verb, based on the arguments
-- in ARGS.
inflections["i"] = function(args, data)
local stemv = data.stemv
local stemc = data.stemc
local stems = ine(args["stems"]) or stemv
local i = data.ier and "i" or ""
if data.ier then
data.comment = "This verb conjugates as a first-group verb ending in ''-ier'', with a palatal stem. These verbs are conjugated mostly like verbs in ''-er'', but there is an extra ''i'' before the ''e'' of some endings. "
else
data.comment = "This verb conjugates as a first-group verb ending in ''-er''. "
end
data.comment =
data.comment .. full_verb_comment(stemv, stemc, stems, data.ier)
data.group = "first"
data.forms.pres_ptc = {stemc .. "ant"}
data.forms.past_ptc = {stemv .. i .. "é", stemv .. i .. "ez"}
data.forms.pres_indc_1sg = {add_zero(stems, data.ier)}
data.forms.pres_indc_2sg = {stems .. "es"}
data.forms.pres_indc_3sg = {stems .. "e"}
data.forms.pres_indc_1pl = {stemc .. "ons"}
data.forms.pres_indc_2pl = {stemv .. i .. "ez"}
data.forms.pres_indc_3pl = {stems .. "ent"}
data.forms.pres_subj_1sg = {add_zero(stems, data.ier)}
data.forms.pres_subj_2sg = {add_s(stems, data.ier)}
data.forms.pres_subj_3sg = {add_t(stems, data.ier)}
data.forms.pres_subj_1pl = {stemc .. "ons"}
data.forms.pres_subj_2pl = {stemv .. i .. "ez"}
data.forms.pres_subj_3pl = {stems .. "ent"}
data.forms.impr_2sg = {stems .. "e"}
data.forms.impr_1pl = {stemc .. "ons"}
data.forms.impr_2pl = {stemv .. i .. "ez"}
data.forms.impf_indc_1sg = {stemc .. "oie", stemv .. "eie", stemc .. "oe", stemv .. i .. "eve"}
data.forms.impf_indc_2sg = {stemc .. "oies", stemv .. "eies", stemc .. "oes", stemv .. i .. "eves"}
data.forms.impf_indc_3sg = {stemc .. "oit", stemv .. "eit", stemc .. "ot", stemv .. i .. "eve"}
data.forms.impf_indc_1pl = {stemv .. "iiens", stemv .. "iens"}
data.forms.impf_indc_2pl = {stemv .. "iiez", stemv .. "iez"}
data.forms.impf_indc_3pl = {stemc .. "oient", stemv .. "eient", stemc .. "oent", stemv .. i .. "event"}
data.forms.pret_indc_1sg = {stemc .. "ai"}
data.forms.pret_indc_2sg = {stemc .. "as"}
data.forms.pret_indc_3sg = {stemc .. "a"}
data.forms.pret_indc_1pl = {stemc .. "ames"}
data.forms.pret_indc_2pl = {stemc .. "astes"}
data.forms.pret_indc_3pl = {stemv .. i .. "erent"}
data.forms.impf_subj_1sg = {stemc .. "asse"}
data.forms.impf_subj_2sg = {stemc .. "asses"}
data.forms.impf_subj_3sg = {stemc .. "ast"}
data.forms.impf_subj_1pl = {stemv .. "issons"}
data.forms.impf_subj_2pl = {stemv .. "issez", stemv .. "issiez"}
data.forms.impf_subj_3pl = {stemc .. "assent"}
handle_future_cond(args, data, stemv .. "er")
end
-- Add to DATA the endings for a type 2 verb (-ir, with -iss- infix),
-- based on the arguments in ARGS.
inflections["ii"] = function(args, data)
local stemv = data.stemv
data.comment = "This verb conjugates as a second-group verb (ending in ''-ir'', with an ''-iss-'' infix). "
data.group = "second"
data.forms.pres_ptc = {stemv .. "issant"}
data.forms.past_ptc = {stemv .. "i", stemv .. "iz"}
data.forms.pres_indc_1sg = {stemv .. "is"}
data.forms.pres_indc_2sg = {stemv .. "is"}
data.forms.pres_indc_3sg = {stemv .. "ist"}
data.forms.pres_indc_1pl = {stemv .. "issons"}
data.forms.pres_indc_2pl = {stemv .. "issez"}
data.forms.pres_indc_3pl = {stemv .. "issent"}
data.forms.pres_subj_1sg = {stemv .. "isse"}
data.forms.pres_subj_2sg = {stemv .. "isses"}
data.forms.pres_subj_3sg = {stemv .. "isse"}
data.forms.pres_subj_1pl = {stemv .. "issons"}
data.forms.pres_subj_2pl = {stemv .. "issez"}
data.forms.pres_subj_3pl = {stemv .. "issent"}
data.forms.impr_2sg = {stemv .. "is"}
data.forms.impr_1pl = {stemv .. "issons"}
data.forms.impr_2pl = {stemv .. "issez"}
data.forms.impf_indc_1sg = {stemv .. "issoie", stemv .. "isseie"}
data.forms.impf_indc_2sg = {stemv .. "issoies", stemv .. "isseies"}
data.forms.impf_indc_3sg = {stemv .. "issoit", stemv .. "isseit"}
data.forms.impf_indc_1pl = {stemv .. "issiiens", stemv .. "issiens"}
data.forms.impf_indc_2pl = {stemv .. "issiiez", stemv .. "issiez"}
data.forms.impf_indc_3pl = {stemv .. "issoient", stemv .. "isseient"}
handle_past_impf_subj(args, data, stemv, "weak-i")
handle_future_cond(args, data, stemv .. "ir")
end
-- Add to DATA the endings for a type 3 verb (-ir without -iss- infix, or
-- -re or -oir), based on the arguments in ARGS.
inflections["iii"] = function(args, data)
local stemv = data.stemv
local stemc = data.stemc
local stems = ine(args["stems"]) or stemv
local i = data.ier and "i" or ""
data.comment = "This verb conjugates as a third-group verb (mostly irregular). "
if data.ier then
data.comment = data.comment .. "This verb ends in a palatal stem, so there is an extra ''i'' before the ''e'' of some endings. "
end
data.comment =
data.comment .. full_verb_comment(stemv, stemc, stems, data.ier)
data.group = "third"
data.forms.pres_ptc = {stemc .. "ant"}
data.forms.past_ptc = {stemc .. "u", stemc .. "uz"}
data.forms.pres_indc_1sg = {add_zero(stems, data.ier)}
data.forms.pres_indc_2sg = {add_s(stems, data.ier)}
data.forms.pres_indc_3sg = {add_t(stems, data.ier)}
data.forms.pres_indc_1pl = {stemc .. "ons"}
data.forms.pres_indc_2pl = {stemv .. i .. "ez"}
data.forms.pres_indc_3pl = {stems .. "ent"}
data.forms.pres_subj_1sg = {add_zero(stems, data.ier)}
data.forms.pres_subj_2sg = {stems .. "es"}
data.forms.pres_subj_3sg = {stems .. "e"}
data.forms.pres_subj_1pl = {stemc .. "ons"}
data.forms.pres_subj_2pl = {stemv .. i .. "ez"}
data.forms.pres_subj_3pl = {stemv .. "ent"}
data.forms.impr_2sg = {stems .. "e"}
data.forms.impr_1pl = {stemc .. "ons"}
data.forms.impr_2pl = {stemv .. i .. "ez"}
data.forms.impf_indc_1sg = {stemc .. "oie", stemv .. "eie"}
data.forms.impf_indc_2sg = {stemc .. "oies", stemv .. "eies"}
data.forms.impf_indc_3sg = {stemc .. "oit", stemv .. "eit"}
data.forms.impf_indc_1pl = {stemv .. "iiens", stemv .. "iens"}
data.forms.impf_indc_2pl = {stemv .. "iiez", stemv .. "iez"}
data.forms.impf_indc_3pl = {stemc .. "oient", stemv .. "eient"}
handle_past_impf_subj(args, data, stemv, "weak-i")
handle_future_cond(args, data, stemc .. "r")
end
-- Shows the table with the given forms
function make_table(data)
return data.comment .. [=[Old French conjugation varies significantly by date and by region. The following conjugation should be treated as a guide.
<div class="NavFrame" style="clear:both;margin-top:1em">
<div class="NavHead" align=left> Conjugation of ]=] .. m_links.full_link(nil, data.forms.infinitive[1], lang, nil, "term", nil, nil, nil) .. [=[
<span style="font-size:90%;">(see also [[Appendix:Old French verbs]])</span></div>
<div class="NavContent" align=center>
{| style="width: 100%; background:#F0F0F0;border-collapse:separate;border-spacing:2px" class="inflection-table"
|-
! colspan="2" style="background:#e2e4c0" |
! colspan="3" style="background:#e2e4c0" | simple
! colspan="3" style="background:#e2e4c0" | compound
|-
! colspan="2" style="background:#e2e4c0" | infinitive
| colspan="3" | ]=] .. show_form(data.forms.infinitive) .. [=[
| colspan="3" | ]=] .. show_form(data.forms.aux) .. " " .. show_form(data.forms.past_ptc) .. [=[
|-
! colspan="2" style="background:#e2e4c0" | gerund
| colspan="3" | en ]=] .. show_form(data.forms.pres_ptc) .. [=[
| colspan="3" | Use the gerund of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! colspan="2" style="background:#e2e4c0" | present participle
| colspan="3" | ]=] .. show_form(data.forms.pres_ptc) .. [=[
|-
! colspan="2" style="background:#e2e4c0" | past participle
| colspan="3" | ]=] .. show_form(data.forms.past_ptc) .. [=[
|-
! colspan="2" rowspan="2" style="background:#C0C0C0" | person
! colspan="3" style="background:#C0C0C0" | singular
! colspan="3" style="background:#C0C0C0" | plural
|-
! style="background:#C0C0C0;width:12.5%" | first
! style="background:#C0C0C0;width:12.5%" | second
! style="background:#C0C0C0;width:12.5%" | third
! style="background:#C0C0C0;width:12.5%" | first
! style="background:#C0C0C0;width:12.5%" | second
! style="background:#C0C0C0;width:12.5%" | third
|-
! style="background:#c0cfe4" colspan="2" | indicative
! style="background:#c0cfe4" | jeo, jou
! style="background:#c0cfe4" | tu
! style="background:#c0cfe4" | il
! style="background:#c0cfe4" | nos, nous
! style="background:#c0cfe4" | vos, vous
! style="background:#c0cfe4" | ils
|-
! rowspan="5" style="background:#c0cfe4" | simple<br>tenses
! style="height:3em;background:#c0cfe4" | present
| ]=] .. show_form(data.forms.pres_indc_1sg) .. [=[
| ]=] .. show_form(data.forms.pres_indc_2sg) .. [=[
| ]=] .. show_form(data.forms.pres_indc_3sg) .. [=[
| ]=] .. show_form(data.forms.pres_indc_1pl) .. [=[
| ]=] .. show_form(data.forms.pres_indc_2pl) .. [=[
| ]=] .. show_form(data.forms.pres_indc_3pl) .. [=[
|-
! style="height:3em;background:#c0cfe4" | imperfect
| ]=] .. show_form(data.forms.impf_indc_1sg) .. [=[
| ]=] .. show_form(data.forms.impf_indc_2sg) .. [=[
| ]=] .. show_form(data.forms.impf_indc_3sg) .. [=[
| ]=] .. show_form(data.forms.impf_indc_1pl) .. [=[
| ]=] .. show_form(data.forms.impf_indc_2pl) .. [=[
| ]=] .. show_form(data.forms.impf_indc_3pl) .. [=[
|-
! style="height:3em;background:#c0cfe4" | preterite
| ]=] .. show_form(data.forms.pret_indc_1sg) .. [=[
| ]=] .. show_form(data.forms.pret_indc_2sg) .. [=[
| ]=] .. show_form(data.forms.pret_indc_3sg) .. [=[
| ]=] .. show_form(data.forms.pret_indc_1pl) .. [=[
| ]=] .. show_form(data.forms.pret_indc_2pl) .. [=[
| ]=] .. show_form(data.forms.pret_indc_3pl) .. [=[
|-
! style="height:3em;background:#c0cfe4" | future
| ]=] .. show_form(data.forms.futr_indc_1sg) .. [=[
| ]=] .. show_form(data.forms.futr_indc_2sg) .. [=[
| ]=] .. show_form(data.forms.futr_indc_3sg) .. [=[
| ]=] .. show_form(data.forms.futr_indc_1pl) .. [=[
| ]=] .. show_form(data.forms.futr_indc_2pl) .. [=[
| ]=] .. show_form(data.forms.futr_indc_3pl) .. [=[
|-
! style="height:3em;background:#c0cfe4" | conditional
| ]=] .. show_form(data.forms.cond_1sg) .. [=[
| ]=] .. show_form(data.forms.cond_2sg) .. [=[
| ]=] .. show_form(data.forms.cond_3sg) .. [=[
| ]=] .. show_form(data.forms.cond_1pl) .. [=[
| ]=] .. show_form(data.forms.cond_2pl) .. [=[
| ]=] .. show_form(data.forms.cond_3pl) .. [=[
|-
! rowspan="5" style="background:#c0cfe4" | compound<br>tenses
! style="height:3em;background:#c0cfe4" | present perfect
! colspan="6" style="background:#C0C0C0" | Use the present tense of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! style="height:3em;background:#c0cfe4" | pluperfect
! colspan="6" style="background:#C0C0C0" | Use the imperfect tense of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! style="height:3em;background:#c0cfe4" | past anterior
! colspan="6" style="background:#C0C0C0" | Use the preterite tense of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! style="height:3em;background:#c0cfe4" | future perfect
! colspan="6" style="background:#C0C0C0" | Use the future tense of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! style="height:3em;background:#c0cfe4" | conditional perfect
! colspan="6" style="background:#C0C0C0" | Use the conditional tense of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! style="background:#c0e4c0" colspan="2" | subjunctive
! style="background:#c0e4c0" | que jeo, jou
! style="background:#c0e4c0" | que tu
! style="background:#c0e4c0" | qu’il
! style="background:#c0e4c0" | que nos, nous
! style="background:#c0e4c0" | que vos, vous
! style="background:#c0e4c0" | qu’ils
|-
! rowspan="2" style="background:#c0e4c0" | simple<br>tenses
! style="height:3em;background:#c0e4c0" | present
| ]=] .. show_form(data.forms.pres_subj_1sg) .. [=[
| ]=] .. show_form(data.forms.pres_subj_2sg) .. [=[
| ]=] .. show_form(data.forms.pres_subj_3sg) .. [=[
| ]=] .. show_form(data.forms.pres_subj_1pl) .. [=[
| ]=] .. show_form(data.forms.pres_subj_2pl) .. [=[
| ]=] .. show_form(data.forms.pres_subj_3pl) .. [=[
|-
! style="height:3em;background:#c0e4c0" rowspan="1" | imperfect
| ]=] .. show_form(data.forms.impf_subj_1sg) .. [=[
| ]=] .. show_form(data.forms.impf_subj_2sg) .. [=[
| ]=] .. show_form(data.forms.impf_subj_3sg) .. [=[
| ]=] .. show_form(data.forms.impf_subj_1pl) .. [=[
| ]=] .. show_form(data.forms.impf_subj_2pl) .. [=[
| ]=] .. show_form(data.forms.impf_subj_3pl) .. [=[
|-
! rowspan="2" style="background:#c0e4c0" | compound<br>tenses
! style="height:3em;background:#c0e4c0" | past
! colspan="6" style="background:#C0C0C0" | Use the present subjunctive of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! rowspan="1" style="height:3em;background:#c0e4c0" | pluperfect
! colspan="6" style="background:#C0C0C0" | Use the imperfect subjunctive of ]=] .. show_form(data.forms.aux) .. [=[ followed by the past participle
|-
! colspan="2" rowspan="2" style="height:3em;background:#e4d4c0" | imperative
! style="background:#e4d4c0" | –
! style="background:#e4d4c0" | tu
! style="background:#e4d4c0" | –
! style="background:#e4d4c0" | nos, nous
! style="background:#e4d4c0" | vos, vous
! style="background:#e4d4c0" | –
|-
| —
| ]=] .. show_form(data.forms.impr_2sg) .. [=[
| —
| ]=] .. show_form(data.forms.impr_1pl) .. [=[
| ]=] .. show_form(data.forms.impr_2pl) .. [=[
| —
|-
|}</div></div>]=]
end
-- Create a link for a form
function make_link(subform)
return m_links.full_link(subform, nil, lang, nil, nil, nil, {},
mw.title.getCurrentTitle().prefixedText)
end
-- Shows forms with links, or a dash if empty
function show_form(subforms)
if not subforms then
return "—"
elseif type(subforms) ~= "table" then
error("a non-table value was given in the list of inflected forms.")
elseif #subforms == 0 then
return "—"
end
local ret = {}
-- Go over each subform and insert links
for key, subform in ipairs(subforms) do
table.insert(ret, subform)
end
return table.concat(ret, ", ")
end
return export