Module:User:Benwing/fro-verb

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, "^[^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. Conjugation of ]=] .. m_links.full_link(nil, data.forms.infinitive[1], lang, nil, "term", nil, nil, nil) .. [=[ (see also Appendix:Old French verbs) 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 "&mdash;" elseif type(subforms) ~= "table" then error("a non-table value was given in the list of inflected forms.") elseif #subforms == 0 then return "&mdash;" 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