ဝိက်ရှေန်နရဳ
mnwwiktionary
https://mnw.wiktionary.org/wiki/%E1%80%9D%E1%80%AD%E1%80%80%E1%80%BA%E1%80%9B%E1%80%BE%E1%80%B1%E1%80%94%E1%80%BA%E1%80%94%E1%80%9B%E1%80%B3:%E1%80%99%E1%80%AF%E1%80%80%E1%80%BA%E1%80%9C%E1%80%AD%E1%80%80%E1%80%BA%E1%80%90%E1%80%99%E1%80%BA
MediaWiki 1.47.0-wmf.9
case-sensitive
မဳဒဳယာ
တၟေင်
ဓရီုကျာ
ညးလွပ်
ညးလွပ် ဓရီုကျာ
ဝိက်ရှေန်နရဳ
ဝိက်ရှေန်နရဳ ဓရီုကျာ
ဝှာင်
ဝှာင် ဓရီုကျာ
မဳဒဳယာဝဳကဳ
မဳဒဳယာဝဳကဳ ဓရီုကျာ
ထာမ်ပလိက်
ထာမ်ပလိက် ဓရီုကျာ
ရီု
ရီု ဓရီုကျာ
ကဏ္ဍ
ကဏ္ဍ ဓရီုကျာ
အဆက်လက္ကရဴ
အဆက်လက္ကရဴ ဓရီုကျာ
ကာရန်
ကာရန် ဓရီုကျာ
အဘိဓာန်
အဘိဓာန် ဓရီုကျာ
ဗီုပြၚ်သိုၚ်တၟိ
ဗီုပြၚ်သိုၚ်တၟိ ဓရီုကျာ
TimedText
TimedText talk
မဝ်ဂျူ
မဝ်ဂျူ ဓရီုကျာ
Event
Event talk
က
0
104
397730
372286
2026-07-01T05:37:33Z
Htawmonzel
48
397730
wikitext
text/x-wiki
{{also/auto}}
{{character info|image=Ka Mon and Burmese.gif}}
=={{=mnw=}}==
=== ဗွဟ်ရမ္သာင် ===
* {{IPA|mnw|/kaˀ/}}
* {{audio|my|က.ogg}}
===အက္ခရ်===
{{head|mnw|အက္ခရ်|tr=ka}}
# ပၞောဝ် ဗျည်မန်ဂမၠိုင် မဒှ် ဗျည် ကိုပ်ကၠာအိုတ်။
=== တြာဲ ===
the first consonant of the Mon alphabet
===နာမ်၁===
# {{mnw-noun|tr=ka}} သတ်တိရစ္ဆာန် မပဒတဴ ပ္ဍဲ ဍာ်၊ လ္ၚဵု မနွံ ကုဂစှ်ေ၊ မယီု နမပၠုပ်ပ္တိတ်ဍာ် နူ ကုခၟာ်၊ ဖျုန်ဍေဟ်တအ် ဗွဲမဂၠိုင် စ နဒဒှ် စၞ။
#* ပ္ဍဲ ကၟာ က နွံဗွဲမဂၠိုင်။
#* ပိုယ် ဍုန်စ သွက။
===လဟီု===
* ကဇၞော် စ ကဍောတ်၊ ကဍောတ် စ အိက်ၚာ် (မၞိဟ်ဒြဟတ်ဇၞော် ပမာန် ကုမၞိဟ်ဒြဟတ်ဍောတ်)
* က ဗၠး ကဇၞော်၊ (ကောန်ဗော် ကောန်ချိုတ်) (အရာ မဆောမ်လေင်အာဂှ် စှ်ေစိုတ် မခိုဟ် နူ မနွံဒၟံင်လၟုဟ်)
* က,လေင် အကြာ ကဝေက် (ပရေင်ဂိုတ်ဂစာန်ဇကု သီုဟွံဂွံဒုင်ယၟု ဒးဒုင်စကာ ကုညးတၞဟ်)
* ကဇၞော် မံင် ဍာ်ဒမျိုဟ် (အရေဝ်ဇြိုဟ်ဟ် နွံ ပ္ဍဲ ညးဇၞော်)
* က ထေဲ ကုဍာ် သၠာက်တိုန်ဒဵု (ထေဲ ကုဒၞာဲဇကု အာ ဒၞာဲတၞဟ်၊ ဒှ် အန္တရာယ်လမျီု)
* ကမွဲအုဲ အုဲ သီုဂၠုင် (မၞိဟ်မွဲမွဲ ပရေအ်မ္ဂး ဒးဒုင်ပရေအ် သီု ညးဖအိုတ်)
* က ဟွံဆဵုထၞောန် (မၞိဟ် ဟွံဆဵု အန္တရာယ်၊ ညာတ်ဗဵု ဆဖိုလ်ဇကု)
===နာမ်၂===
# {{mnw-noun|tr=ka}}
#* အရာ မဒုင်လဝ် သွက် အရာတၞဟ် ညံင်ဟွံဂွံပၠဴစှ်ေ၊ ဟွံဂွံဒတုံစှ်ေ၊ အရာ မဒုင် အကြာၜါ။
===နာမ်၃===
{{mnw-noun|tr=ka}}
# ဇုက် မပယျေဝ်စိင်၊ ပယျေဝ်ချေဟ်။
#* ကစိင် (ဆင်ကကြိုးတန်ဆာ)
#* ကချေဟ် (မြင်းကြိုးတန်ဆာ)
=== တြာဲ ===
* မြန်မာ : (ဆင်၊ မြင်း) ကကြိုးတန်ဆာ။
* English : howdah, harness, saddle.
===နိရုတ်===
ဝေါဟာကၠုင်နူ {{inh|mnw|omx|မကး}}၊ မန်လဒေါဝ် {{inh|mnw|mkh-mmn|မက}}(မွဲပြကာ)၊ မန်တၟိ ဟွံက။ (ဗၟာလွဳစလဝ် မက)
===ကြိယာ ===
{{mnw-verb|tr=ka}}
ဒဒှ် မဂၠိုင် နူမွဲ၊
* သဘင်ဂှ် မၞိဟ် ကၠုင် ၜိုတ်ကၠံ ဒှ်ဟာ၊ ကဒၟံင်ဟာ။ အဲထေင်ကေတ် နွံရောင် ၜိုတ် ကၠံမသုန်စှ်ော။
* ယင်ကြိယာက္တောရ် မအာဒိနောရ် ရူပ်စိင် ရူပ်ဇာဒိသိင် ရူပ်တြောပ်ပုမိည် ရူပ်နာဂ် ရူပ်သုပရ် မကးမောယ်ပြကာရ် ညးတဂေါး သ္ပ္ကင်ရင်၊ (ယင်ကိရိယာကတောဝ် မပတံ ရုပ်စိင်၊ ရုပ်ဇာဒိသိုင်၊ ရုပ်ထမာဲ၊ ရုပ်နာ်၊ ရုပ်သပဝ် မဟွံကမွဲပြကာ ညးတအ် ဂွံပကင်ရင်။) (ယှိုယ်သဳခုင် ဂ၊ ၂၅-၂၈)
* ဓဝ်လောဘဂှ် မနွံဒုဟ် မဂၠိုင် မကမွဲသာ်ရ။ (ဇာတ် ၄၄၀၊ အစွောအ်)
* ဂၠိုင် ကုအခိုက် ကွိင်ကွိုက်ဒယှ်ေလှ်ေ မကမွဲပြကာရ။ (ဇာတ် ၅၂၆၊ အစွောအ်)
===မဒုင်လွဳစ===
* {{desc|my|မက|bor=1}}
=== တြာဲ ===
* မြန်မာ : မက။
* English : more than.
{{DEFAULTSORT:က}}
[[ကဏ္ဍ:အေန်သတဳကျုတ်ဘာသာမန်]]
==ပါဠိမန်==
===ဗီုပြင်စွံသမ္တီလဝ်===
(ဗီုပြင်စွံသမ္တီလဝ်နကဵုပၟိက်မွဲမွဲသာ် ဝါ ဟွံတီကၠးယၟုလိင်)
:'''{{PAGENAME}}({{#invoke:mnw-translit|tr|[[{{PAGENAME}}]]|Mymr}})'''
[[ကဏ္ဍ:ဝေါဟာအဓိကပါဠိမန်ဂမၠိုင်]]
# ဍာ်။
{{stub|pi}}
trqk4rkqtlb8838e152vdpttggvv957
ထဝ်
0
19798
397731
372892
2026-07-01T08:17:07Z
Htawmonzel
48
397731
wikitext
text/x-wiki
=={{=mnw=}}==
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|mnw|omx|ထရ်|tr=thaw}}
===ဗွဟ်ရမ္သာၚ်===
* {{a|မန်ဍုၚ်ဗၟာ}} {{IPA|mnw|/tʰɔ/}}
* {{a|မန်ဍုၚ်သေံ}} {{IPA|mnw|/tʰɔː/}}
===နာမ်===
{{mnw-noun}}
# ထဝ်၊ ထဝ်ဩန်၊ ၚုဟ်မးမပ္တဝ်သ္ပလဝ်အစာံကဵုထဝ်။
==={{Translate}}===
{{VN
|my=[[ရွှေ]]
|en=[[gold]]
|ko=[[금]]
|th=[[ทอง]]
|ar= [[مُذَهَّب]]
|km=[[មាស]]
|lo=[[ທອງ]]
|shn=[[ၶမ်း]]
}}
ff8cjwv1k5mr8wiy9ws86ejxjujh6zj
397732
397731
2026-07-01T08:18:38Z
Htawmonzel
48
397732
wikitext
text/x-wiki
=={{=mnw=}}==
===နိရုတ်===
ဝေါဟာကၠုင်နူ {{inh|mnw|omx|ထရ်|tr=thaw}}
===ဗွဟ်ရမ္သာင်===
* {{IPA|mnw|/tʰɔ/}}
* {{IPA|mnw|/tʰɔː/}}
===နာမ်===
{{mnw-noun}}
# ထဝ်၊ ထဝ်ဩန်၊ ၚုဟ်မးမပ္တဝ်သ္ပလဝ်အစာံကဵုထဝ်။
==={{Translate}}===
{{VN
|my=[[ရွှေ]]
|en=[[gold]]
|ko=[[금]]
|th=[[ทอง]]
|ar= [[مُذَهَّب]]
|km=[[មាស]]
|lo=[[ທອງ]]
|shn=[[ၶမ်း]]
}}
juthb1tdpy851cvq2q9nw7uo671yt9q
မဝ်ဂျူ:es-verb
828
28544
397713
158095
2026-06-30T13:23:24Z
咽頭べさ
33
397713
Scribunto
text/plain
local export = {}
--[=[
Authorship: Ben Wing <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of tense/mood/person/number/etc.
Example slot names for verbs are "pres_1s" (present indicative first-person singular), "pres_sub_2sv" (present
subjunctive second-person singular voseo form) "impf_sub_ra_3p" (imperfect subjunctive -ra form third-person
plural), "imp_1p_comb_lo" (imperative first-person plural combined with clitic [[lo]]).
Each slot is filled with zero or more forms.
-- "form" = The conjugated Spanish form representing the value of a given slot.
-- "lemma" = The dictionary form of a given Spanish term. For Spanish, always the infinitive.
]=]
--[=[
FIXME:
1. Implement no_pres_stressed for aterir, garantir. (NOTE: Per RAE, garantir used in all forms in Argentina/Uruguay.) [DONE]
2. Support concluyo. [DONE]
3. Fixes for veo -> ve vs. preveo -> prevé. [DONE]
4. Various more irregular verbs, e.g. predecir, redecir, bendecir, maldecir. [DONE]
5. Raising of e -> i, o -> u before -iendo, -ió, etc. occurs only in -ir verbs. [DONE]
6. Raising of e -> i, o -> u happens before subjunctive -amos, -áis in -ir verbs. [DONE]
7. Implement reflexive verbs. [DONE]
8. Implement categories. [DONE]
9. Implement show_forms. [DONE]
10. Reconcile stems.vowel_alt from irregular verbs with vowel_alt from indicators. May require
moving the irregular-verb handling code in construct_stems() into detect_indicator_spec(). [DONE]
11. Implement make_table. [DONE]
12. Vowel alternation should show u-ue (jugar), i-ie (adquirir), e-í (reír) alternations specially. [DONE]
13. Handle linking of multiword forms as is done in [[Module:es-headword]]. [DONE]
14. Implement comparison against previous module. [DONE]
15. Implement categorization of irregularities for individual tenses.
16. Support nocomb=1. [DONE]
17. (Possibly) display irregular forms in a different color, as with the old module.
18. (Possibly) display a "rule" description indicating the types of alternations.
19. Implement replace_reflexive_indicators(). [NOT DONE; SUPPORT REMOVED]
20. Implement verbs with attached clitics e.g. [[pasarlo]], [[corrérsela]]. [DONE]
21. When footnote + tú/vos notation, add a space before tú/vos.
22. Fix [[erguir]] so ie-i vowel alternation produces ye- at beginning of word, similarly for errar. Also allow
multiple vowel alternation specs in irregular verbs, for errar. Finally, ie should show as e-ye for errar
and as e-ye-i for erguir. [DONE]
23. Figure out why red links in combined forms show up as black not red.
24. Consider including alternative superseded forms of verbs like [[ciar]] (e.g. pret_3s = cio, ció with footnote).
25. Allow conjugation of suffixes e.g. -ir, -ecer; need to fix in [[Module:inflection utilities]]. [DONE]
26. Allow specification of stems esp. so that footnotes can be hung off them; use + for the default.
27. Don't remove monosyllabic accents when conjugating suffixes. [DONE]
28. If multiword expression with no <>, add <> after first word, as with [[Module:es-headword]]. [DONE]
29. (Possibly) link the parts of a reflexive or cliticized infinitive, as done in [[Module:es-headword]]. [DONE]
30. Final fixes to allow [[Module:es-headword]] to use this module. [DONE]
--]=]
local lang = require("Module:languages").getByCode("es")
local m_string_utilities = require("Module:string utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:es-common")
local force_cat = false -- set to true for debugging
local check_for_red_links = false -- set to false for debugging
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local rsub = com.rsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local function link_term(term)
return m_links.full_link({ lang = lang, term = term }, "term")
end
local V = com.V -- vowel regex class
local AV = com.AV -- accented vowel regex class
local C = com.C -- consonant regex class
local tuteo_link = link_term("tuteo")
local voseo_link = link_term("voseo")
local fut_sub_note = "[rare; now chiefly used in legal language]"
local pres_sub_voseo_note = "[Argentine and Uruguayan " .. voseo_link .. " prefers the " .. tuteo_link .. "-form for the present subjunctive]"
local vowel_alternants = m_table.listToSet({"ie", "ie-i", "ye", "ye-i", "ue", "ue-u", "hue", "i", "í", "ú", "+"})
local vowel_alternant_to_desc = {
["ie"] = "e-ie",
["ie-i"] = "e-ie-i",
["ye"] = "e-ye",
["ye-i"] = "e-ye-i",
["ue"] = "o-ue",
["ue-u"] = "o-ue-u",
["hue"] = "o-hue",
["i"] = "e-i",
["í"] = "i-í",
["ú"] = "u-ú",
}
local raise_vowel = {["e"] = "i", ["o"] = "u"}
local all_persons_numbers = {
["1s"] = "1|s",
["2s"] = "2|s",
["2sv"] = "2|s|voseo",
["3s"] = "3|s",
["1p"] = "1|p",
["2p"] = "2|p",
["3p"] = "3|p",
}
local person_number_list_basic = {"1s", "2s", "3s", "1p", "2p", "3p"}
local person_number_list_voseo = {"1s", "2s", "2sv", "3s", "1p", "2p", "3p"}
local imp_person_number_list = {"2s", "2sv", "3s", "1p", "2p", "3p"}
local neg_imp_person_number_list = {"2s", "3s", "1p", "2p", "3p"}
person_number_to_reflexive_pronoun = {
["1s"] = "me",
["2s"] = "te",
["2sv"] = "te",
["3s"] = "se",
["1p"] = "nos",
["2p"] = "os",
["3p"] = "se",
}
local indicator_flags = m_table.listToSet {
"no_pres_stressed", "no_pres1_and_sub",
"only3s", "only3sp", "only3p",
"no_built_in",
}
-- Initialize all the slots for which we generate forms. The particular slots may depend on whether we're generating
-- combined slots (`not alternant_multiword_spec.nocomb`, which is always false if we're dealing with a verb with an
-- attached clitic, such as [[hincarla]], or a reflexive or partly-reflexive verb, where a partly-reflexive verb is
-- a conjoined term made up of two or more verbs, where some but not all are reflexive). It may also depend on whether
-- we're being requested to generate some double-combined forms, such as [[llevándoselo]]; see the comment below for
-- `verb_slot_double_combined_rows`.
local function add_slots(alternant_multiword_spec)
-- "Basic" slots: All slots that go into the regular table (not the combined-form table).
alternant_multiword_spec.verb_slots_basic = {
{"infinitive", "inf"},
{"infinitive_linked", "inf"},
{"gerund", "ger"},
{"pp_ms", "m|s|past|part"},
{"pp_fs", "f|s|past|part"},
{"pp_mp", "m|p|past|part"},
{"pp_fp", "f|p|past|part"},
}
-- Slots that go into the combined-form table, along with double-combined slots (e.g. [[llevándoselo]]) that are
-- requested for use with {{es-verb form of}}.
alternant_multiword_spec.verb_slots_combined = {}
-- Special slots used to handle non-reflexive parts of reflexive verbs in {{es-verb form of}}.
-- For example, for a reflexive-only verb like [[jambarse]], we want to be able to use {{es-verb form of}} on
-- [[jambe]] (which should mention that it is a part of 'me jambe', first-person singular present subjunctive, and
-- 'se jambe', third-person singular present subjunctive) or on [[jambamos]] (which should mention that it is a
-- part of 'nos jambamos', first-person plural present indicative or preterite). Similarly, we want to use
-- {{es-verb form of}} on [[jambando]] (which should mention that it is a part of 'se ... jambando', syntactic
-- variant of [[jambándose]], which is the gerund of [[jambarse]]). To do this, we need to be able to map
-- non-reflexive parts like [[jambe]], [[jambamos]], [[jambando]], etc. to their reflexive equivalent(s), to the
-- tag(s) of the equivalent(s), and, in the case of forms like [[jambando]], [[jambar]] and imperatives, to the
-- separated syntactic variant of the verb+clitic combination. We do this by creating slots for the non-reflexive
-- part equivalent of each basic reflexive slot, and for the separated syntactic-variant equivalent of each basic
-- reflexive slot that is formed of verb+clitic. We use slots in this way to deal with multiword lemmas. Note that
-- we run into difficulties mapping between reflexive verbs, non-reflexive part equivalents, and separated syntactic
-- variants if a slot contains more than one form. To handle this, if there are the same number of forms in two
-- slots we're trying to match up, we assume the forms match one-to-one; otherwise we don't match up the two slots
-- (which means {{es-verb form of}} won't work in this case, but such a case is extremely rare and not worth
-- worrying about). Alternatives that handle this "properly" are significantly more complicated and require
-- non-trivial modifications to [[Module:inflection utilities]].
local need_special_verb_form_of_slots = alternant_multiword_spec.source_template == "es-verb form of" and
alternant_multiword_spec.refl
if need_special_verb_form_of_slots then
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {
{"infinitive_non_reflexive", "-"},
{"infinitive_variant", "-"},
{"gerund_non_reflexive", "-"},
{"gerund_variant", "-"},
}
else
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {}
end
-- For generating combined forms, i.e. combinations of a basic form (specifically, infinitive, gerund or an
-- imperative form) with a clitic (or in some cases, two clitics). This is a list of lists of the form
-- {BASIC_SLOT, CLITICS} where BASIC_SLOT is the slot to add the clitic pronouns to (e.g. "gerund" or "imp_2s")
-- and CLITICS is a list of the clitic pronouns to add.
alternant_multiword_spec.verb_slot_combined_rows = {}
-- For generating double combined forms (e.g. [[llevándoselo]] or [[dámela]]). This is used by {{es-verb form of}}
-- when it detects that it is being requested to find the inflection tags for a double-combined form. The number of
-- double-combined forms is relatively large, so to optimize this, [[Module:es-inflections]] (which implements
-- {{es-verb form of}}) detects which two clitics are involved, and we only generate double-combined forms
-- involving those two clitics; this is specified using `double_combined_forms_to_include`, passed into
-- do_generate_forms(). The value of this field is a list of lists of the form {SINGLE_COMB_SLOT, CLITICS} where
-- SINGLE_COMB_SLOT is the single-combined slot to add the object clitic pronouns to (e.g. "gerund_comb_se" or
-- "imp_2s_comb_me") and CLITICS is a list of the clitic pronouns to add. CLITICS will normally be a length-one
-- list whose value is one of {"lo", "la", "le", "los", "las", "les"}.
alternant_multiword_spec.verb_slot_double_combined_rows = {}
-- Add entries for a slot with person/number variants.
-- `verb_slots` is the table to add to.
-- `slot_prefix` is the prefix of the slot, typically specifying the tense/aspect.
-- `tag_suffix` is a string listing the set of inflection tags to add after the person/number tags.
-- `person_number_list` is a list of the person/number slot suffixes to add to `slot_prefix`.
local function add_personal_slot(verb_slots, slot_prefix, tag_suffix, person_number_list)
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(verb_slots, {slot, accel})
end
end
-- Add a personal slot (i.e. a slot with person/number variants) to `verb_slots_basic`.
local function add_basic_personal_slot(slot_prefix, tag_suffix, person_number_list, no_special_verb_form_of_slot,
need_variant_slot)
add_personal_slot(alternant_multiword_spec.verb_slots_basic, slot_prefix, tag_suffix, person_number_list)
-- Add special slots for handling non-reflexive parts of reflexive verbs in {{es-verb form of}}.
-- See comment above in `need_special_verb_form_of_slots`.
if need_special_verb_form_of_slots and not no_special_verb_form_of_slot then
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local basic_slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(alternant_multiword_spec.verb_slots_reflexive_verb_form_of, {basic_slot .. "_non_reflexive", "-"})
if need_variant_slot then
table.insert(alternant_multiword_spec.verb_slots_reflexive_verb_form_of, {basic_slot .. "_variant", "-"})
end
end
end
end
add_basic_personal_slot("pres", "pres|ind", person_number_list_voseo)
add_basic_personal_slot("impf", "impf|ind", person_number_list_basic)
add_basic_personal_slot("pret", "pret|ind", person_number_list_basic)
add_basic_personal_slot("fut", "fut|ind", person_number_list_basic)
add_basic_personal_slot("cond", "cond", person_number_list_basic)
add_basic_personal_slot("pres_sub", "pres|sub", person_number_list_voseo)
add_basic_personal_slot("impf_sub_ra", "impf|sub", person_number_list_basic)
add_basic_personal_slot("impf_sub_se", "impf|sub", person_number_list_basic)
add_basic_personal_slot("fut_sub", "fut|sub", person_number_list_basic)
-- Need variant slots because the imperative clitics are suffixed.
add_basic_personal_slot("imp", "imp", imp_person_number_list, nil, "need variant slot")
-- Don't need special non-reflexive-part slots because the negative imperative is multiword, of which the
-- individual words are 'no' + subjunctive.
add_basic_personal_slot("neg_imp", "neg|imp", neg_imp_person_number_list, "no special verb form of")
-- Don't need special non-reflexive-part slots because we don't want [[jambando]] mapping to [[jambándome]]
-- (only [[jambándose]]) or [[jambar]] mapping to [[jambarme]] (only [[jambarse]]).
add_basic_personal_slot("infinitive", "inf", person_number_list_basic, "no special verb form of")
add_basic_personal_slot("gerund", "ger", person_number_list_basic, "no special verb form of")
local third_person_object_clitics = {"lo", "la", "le", "los", "las", "les"}
-- Add combined-form slots.
if not alternant_multiword_spec.nocomb then
-- Add a row of slots representing the combination of a basic slot with a clitic. `basic_slot` is the basic slot
-- descriptor, `tag_prefix` is a string describing the inflection tags of the basic slot, and `personal_clitics`
-- is a list of the personal clitics ("me", "te", "se", "nos" or "os") to add to the basic slot.
local function add_combined_slot_row(basic_slot, tag_prefix, personal_clitics)
-- First, add each individual combined slot to `verb_slots_combined`.
local clitics_with_object = m_table.append(personal_clitics, third_person_object_clitics)
for _, clitic in ipairs(clitics_with_object) do
local slot = basic_slot .. "_comb_" .. clitic
-- You have to pass this through full_link() to get a Spanish-specific link
local accel = tag_prefix .. "|combined with [[" .. clitic .. "]]"
table.insert(alternant_multiword_spec.verb_slots_combined, {slot, accel})
end
-- Also, add the row to `verb_slot_combined_rows`.
table.insert(alternant_multiword_spec.verb_slot_combined_rows, {basic_slot, clitics_with_object})
-- Also do double-combined forms for a specific set of clitics, if requested. See the comment above
-- `verb_slot_double_combined_rows` above.
if alternant_multiword_spec.double_combined_forms_to_include then
-- Add a special "lxx" clitic for le/les when transformed into se in double-combined forms.
local personal_clitics_with_lxx = {unpack(personal_clitics)}
table.insert(personal_clitics_with_lxx, "lxx")
for _, personal_clitic in ipairs(personal_clitics_with_lxx) do
for _, object_clitic in ipairs(third_person_object_clitics) do
for _, form_to_include in ipairs(alternant_multiword_spec.double_combined_forms_to_include) do
local to_include_personal_clitic, to_include_object_clitic = unpack(form_to_include)
if personal_clitic == to_include_personal_clitic and object_clitic == to_include_object_clitic then
local single_comb_slot = basic_slot .. "_comb_" .. personal_clitic
local slot = single_comb_slot .. "_" .. object_clitic
accel_clitic = personal_clitic == "lxx" and "[[le]]/[[les]]" or "[[" .. personal_clitic .. "]]"
local accel = tag_prefix .. "|combined with indirect object " .. accel_clitic .. " and direct object [[" ..
object_clitic .. "]]"
table.insert(alternant_multiword_spec.verb_slots_combined, {slot, accel})
table.insert(alternant_multiword_spec.verb_slot_double_combined_rows,
{single_comb_slot, {object_clitic}})
break
end
end
end
end
end
end
add_combined_slot_row("infinitive", "inf", {"me", "te", "se", "nos", "os"})
add_combined_slot_row("gerund", "gerund", {"me", "te", "se", "nos", "os"})
local function add_combined_imp_slot_row(persnum, personal_clitics)
add_combined_slot_row("imp_" .. persnum, all_persons_numbers[persnum] .. "|imp", personal_clitics)
end
add_combined_imp_slot_row("2s", {"me", "te", "nos"})
add_combined_imp_slot_row("2sv", {"me", "te", "nos"})
add_combined_imp_slot_row("3s", {"me", "se", "nos"})
add_combined_imp_slot_row("1p", {"te", "nos", "os"})
add_combined_imp_slot_row("2p", {"me", "nos", "os"})
add_combined_imp_slot_row("3p", {"me", "se", "nos"})
end
-- Generate the list of all slots.
alternant_multiword_spec.all_verb_slots = {}
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_basic) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_combined) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_reflexive_verb_form_of) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
alternant_multiword_spec.verb_slots_basic_map = {}
for _, slotaccel in ipairs(alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
alternant_multiword_spec.verb_slots_basic_map[slot] = accel
end
alternant_multiword_spec.verb_slots_combined_map = {}
for _, slotaccel in ipairs(alternant_multiword_spec.verb_slots_combined) do
local slot, accel = unpack(slotaccel)
alternant_multiword_spec.verb_slots_combined_map[slot] = accel
end
end
-- Return true if `form` is accented and is likely monosyllabic. Used in remove_monosyllabic_accents(); if true, we
-- run the syllabification algorithm to determine the syllable count, and if monosyllabic, remove the accent. Also used
-- in conjunction with user-specified form overrides to add an asterisk to prevent accents from being removed.
local function may_need_monosyllabic_accent_removed(form)
return not rfind(form, "^%-") and rfind(form, AV) and not rfind(form, V .. C .. V)
end
local overridable_stems = {}
-- If `add_monosyllabic_asterisk` is given, add a * to accented forms that may be monosyllabic to prevent the accent
-- from being removed in remove_monosyllabic_accents().
local function allow_multiple_values_for_override(separated_groups, data, add_monosyllabic_asterisk)
local retvals = {}
for _, separated_group in ipairs(separated_groups) do
local footnotes = data.fetch_footnotes(separated_group)
local form = separated_group[1]
if add_monosyllabic_asterisk and may_need_monosyllabic_accent_removed(form) then
form = form .. "*"
end
-- Add suppress_prefix to prevent the built-in verb prefix from being added to the override.
local retval = {form = form, footnotes = footnotes, suppress_prefix = true}
table.insert(retvals, retval)
end
return retvals
end
local function simple_choice(choices)
return function(separated_groups, data)
if #separated_groups > 1 then
data.parse_err("For spec '" .. data.prefix .. ":', only one value currently allowed")
end
if #separated_groups[1] > 1 then
data.parse_err("For spec '" .. data.prefix .. ":', no footnotes currently allowed")
end
local choice = separated_groups[1][1]
if not m_table.contains(choices, choice) then
data.parse_err("For spec '" .. data.prefix .. ":', saw value '" .. choice .. "' but expected one of '" ..
table.concat(choices, ",") .. "'")
end
return choice
end
end
for _, overridable_stem in ipairs {
"pres_unstressed",
"pres_stressed",
"pres1_and_sub",
-- Don't include pres1; use pres_1s if you need to override just that form
"impf",
"full_impf",
"pret",
{"pret_conj", simple_choice({"irreg", "ar", "er", "ir"}) },
"fut",
"cond",
"pres_sub_stressed",
"pres_sub_unstressed",
"impf_sub_ra",
"impf_sub_se",
"fut_sub",
"pp",
} do
if type(overridable_stem) == "string" then
overridable_stems[overridable_stem] = allow_multiple_values_for_override
else
local stem, validator = unpack(overridable_stem)
overridable_stems[stem] = validator
end
end
local function match_against_verbs(ref_verb, prefixes)
return function(verb)
for _, prefix in ipairs(prefixes) do
if verb == prefix .. ref_verb then
return prefix, ref_verb
end
end
return nil
end
end
--[=[
Special cases for verbs:
diluviar, atardecer: impersonal; all finite non-3s forms are nonexistent or hypothetical. Handle using
'.only3s'.
empecer, atañer, concernir: all finite non-third-person forms are nonexistent or hypothetical. Handle using '.only3sp'.
desnacer: Former module claimed an irregular past participle 'desnato'. Verb is not in RAE at all and barely exists;
unlikely to have irregular past participle.
desposeer: Former module claimed an irregular past participle 'desposeso'. Not per RAE.
valer: Former module claimed an irregular imperative 'val'. Not per RAE.
manumitir: Former module claimed an irregular past participle 'manumiso'. Not per RAE.
raer: Former module claimed a pres 1sg rao. Not per RAE.
rehuir: Handle using +ú.
sustituir: Former module claimed an irregular past participle 'sustituto'. Not per RAE.
venir: Former module claimed an irregular clitic combination ven + nos -> venos. Not per native speakers.
---------
Verbs to check: rehuir (+ú), prohibir (+í), reunir (+ú)
---------
-ir verbs:
There are several types of vowel alternations:
1. No alternation. Includes some verbs in -e- and -o-, e.g. aterir(se) (no_pres_stressed), tra(n)sgredir
(pres_stressed forms rare), abolir (pres_stressed forms rare), colorir (no_pres_stressed), sumergir, divergir,
convergir, arrecir (no_pres_stressed), rostir, polir (obsolete), condir (obsolete), possibly ascondir (obsolete),
atordir (obsolete), sacodir (obsolete), sobrevendir (possible misspelling), empedernir (no_pres_stressed),
decebir (obsolete; possibly actually like concebir, i.e. decibo not decebo),
premir (obsolete), expremir (obsolete), exir (obsolete), escreuir (obsolete; fix conjugation), escrebir (obsolete),
agredir; sometimes the stressed forms are rare or disused. (Also embaír, desvaír are no_pres_stressed.)
2a. ie: Infinitive has -e-, changing to -ie- when stressed. No raising before i+V. Only hendir, cernir, discernir,
concernir (only3sp); discernir -> discierno, discerniendo, discernió, discernamos.
2b. ye: Infinitive has -e-, changing to -ye- when stressed. No raising before i+V. Does not occur (cf. errar).
3a. ie-i: Infinitive has -e- or -i-, changing to -ie- when stressed. Raising before i+V and 1p/2p pres subjunctive:
sentir -> siento, sintiendo, sintió, sintamos.
adquirir -> adquiero, adquiriendo, adquirió, adquiramos.
3b. ye-i: Infinitive has -e-, changing to -ye- when stressed. Raising before i+V and 1p/2p pres subjunctive.
Only erguir: erguir -> yergo, irguiendo, irguió, irgamos.
4. i: Infinitive has -e-, changing to -i- when stressed. Raising before i+V and 1p/2p pres subjunctive:
vestir -> visto, vistiendo, vistió, vistamos. Variant: ceñir -> ciño, ciñendo, ciñó, ciñamos.
NOTE: preterir (no_pres_stressed).
5. ue-u: Infinitive has -o-, changing to -ue- when stressed. Raising before i+V and 1p/2p pres subjunctive:
Only dormir, morir and compounds. dormir -> duermo, durmiendo, durmió, durmamos.
6. ue: This type would be parallel to 'ie' but doesn't appear to exist.
---------
Verbs to fix (extra forms need to be excised or deleted): The above verbs under type (1) -ir vowel alternations;
[[neviscar]] (impersonal), [[acaecer]] (third-person only), [[acontecer]] (third-person only),
[[cellisquear]] (impersonal), [[pintear]] (impersonal? other meaning "to play hookey" given, not in RAE),
[[diluviar]] (impersonal). [[desabrir]] (not like abrir, rare in pres_stressed/sub forms), [[jabrir]]
(not like abrir).
Verbs with existing errors:
* [[abeldar]]: (missing <ie>) [FORMS TO DELETE]
* [[acaecer]]: (used only in 3rd person) [DELETE ALL FIRST AND SECOND PERSON FORMS]
* [[acontecer]]: (used only in 3rd person) [DELETE ALL FIRST AND SECOND PERSON FORMS]
* [[anticuar]] (conjugated without ú) [FORMS TO DELETE]
* [[antojar]]: (used only in 3rd person) [DELETE ALL FIRST AND SECOND PERSON FORMS]
* [[aerografiar]]: (conjugated without í) [FORMS TO DELETE]
* [[afiliar]]: (conjugated with í/+ should be only +) [FORMS TO DELETE]
* [[agraviar]]: (wrongly has í) [FORMS TO DELETE]
* [[arrecir]]: (not given as no_pres_stressed) [FORMS TO DELETE]
* [[aserrar]]: (missing <ie>) [FORMS TO DELETE]
* [[aspaventar]]: (missing <ie>) [OK]
* [[atesar]]: (wrongly has ie) [FORMS TO DELETE]
* [[avalentar]]: (wrongly has ie) [FORMS TO DELETE]
* [[autorregularse]] (conjugated as non-reflexive) [OK]
* [[auxiliar]]: (conjugated with í/+ should be only +) [FORMS TO DELETE]
* [[balbucir]] (pres1_and_sub nonexistent) [DELETE PRES1_AND_SUB FORMS]
* [[caçar]] (conjugated as -zar) [OK]
* [[calefacer]] (extra form caleface) [FIX]
* [[cellisquear]]: (used only in 3rd person singular) [DELETE ALL FIRST AND SECOND PERSON FORMS, ALL 3RD PLURAL FORMS AND ALL PP NON-MS FORMS]
* [[chilenizar]] (conjugated with no cons alternation) [OK]
* [[colorir]]: (not given as no_pres_stressed) [FORMS TO DELETE]
* [[comisariar]] (conjugated without í) [FORMS TO DELETE]
* [[complacer]] (missing complega in imperative 3s) [OK]
* [[comprehender]] (conjugated as comprender) [OK]
* [[decebir]] (was conjugated without <i>) [FORMS TO DELETE]
* [[desafiliar]]: (conjugated with í/+ should be only +) [FORMS TO DELETE]
* [[desagregar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[desairar]]: (conjugated with í should be only +) [FORMS TO DELETE]
* [[descordar]]: (missing <ue>) [FORMS TO DELETE]
* [[deseleccionar]] (conjugated as desseleccionar) [OK]
* [[desestacionalizar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[desgonzar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[desguinzar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[deshacer]] (extra form deshace, desháceme etc.) [OK]
* [[desnacer]] (extra form desnato etc.) [DELETE PP FORMS]
* [[desposeer]] (extra form desposeso etc.) [DELETE PP FORMS]
* [[dezmar]]: (wrongly has ie) [FORMS TO DELETE]
* [[diluviar]]: (used only in 3rd person singular) [DELETE ALL FIRST AND SECOND PERSON FORMS, ALL 3RD PLURAL FORMS AND ALL PP NON-MS FORMS]
* [[draftear]] (extraneous param lang=es) [REMOVE PARAM]
* [[ejemplarizar]] (extraneous param compound=1) [compound -> combined]
* [[ejercitar]] (extraneous param compound=1) [compound -> combined]
* [[empecer]] (empezca has imperatives, 1s in its verb form entry) [FIX]
* [[encentar]]: (wrongly has ie) [OK]
* [[encubertar]]: (wrongly has ie) [FORMS TO DELETE]
* [[entrechocar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[entredecir]] (imp_2s has entredice should be entredí; extra future/cond forms entredeciré etc.) [FORMS TO DELETE/FIX]
* [[escenografiar]]: (conjugated without í) [FORMS TO DELETE]
* [[estar]] (incorrect combined forms, e.g. éstela instead of estela) [OK]
* [[extasiar]]: (conjugated with í/+ should be only í) [FORMS TO DELETE]
* [[facer]] (extra form face, fáceme, etc.) [FIX]
* [[ferrar]]: (missing <ie>) [FORMS TO DELETE]
* [[gloriar]]: (conjugated with í/+ should be only í) [FORMS TO DELETE]
* [[hacer]] (extra form hace, háceme, etc.) [DELETE hácete]
* [[homogeneizar]] (extra form homogeneízo) [DELETE homogeneízo, homogeneízas, homogeneíza, homogeneízan, homogeneícen, homogeneícemos]
* [[incensar]]: (missing <ie>) [FORMS TO DELETE]
* [[ir]] (extraneous param aux=ser) [REMOVE PARAM]
* [[jacer]] (extra form jace, jáceme, etc.) [FIX]
* [[jarrear]] (extraneous param impersonal=yes)
* [[litografiar]]: (conjugated without í) [FORMS TO DELETE]
* [[manumitir]] (extra form manumiso, etc.) [FIX; is an adjective]
* [[mecanografiar]]: (conjugated without í) [FORMS TO DELETE]
* [[mordiscar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[neviscar]]: (used only in 3rd person singular) [DELETE ALL FIRST AND SECOND PERSON FORMS, ALL 3RD PLURAL FORMS AND ALL PP NON-MS FORMS]
* [[obsipar]] (conjugated as obispar) [DELETE VERB]
* [[obstar]]: (used only in 3rd person) [DELETE ALL FIRST AND SECOND PERSON FORMS]
* [[orificar]] (conjugated as orificiar) [OK]
* [[complacer]], [[placer]] (missing plega in imperative 3s, etc.) [OK]
* [[prevaler]] (extra form preval, incorrect form prévalme etc.) [DELETE preval]
* [[preterir]]: (not given as no_pres_stressed) [FORMS TO DELETE]
* [[raer]] (extra form rao) [DELETE rao]
* [[rebordar]] (extraneous param lang=es) [REMOVE PARAM]
* [[redecir]] (incorrect imp_2s redice instead of redí) [FIX]
* [[reinstitucionalizar]] (conjugated with no cons alternation) [FORMS TO DELETE]
* [[reirse]] [DELETE]
* [[serigrafiar]]: (conjugated without í) [FORMS TO DELETE]
* [[sobresalir]] (incorrect combined forms e.g. sobrésalme) [OK]
* [[superpoblar]] (missing <ue>) [FORMS TO DELETE]
* [[sustituir]] (extra form sustituto, etc.) [OK]
* [[usucapir]]: (used only in inf and pp) [DELETE ALL FORMS BUT PP]
* [[valefacer]] (extra form valeface) [FIX]
* [[valer]] (extra form val, etc.) [OK]
* LOTS OF COMBINED FORMS OF VERBS IN -iar, -uar, -ai-, -au-, -ei-, -eu-, etc.
Example: afeitar (afeítate, afeítese, afeítense). Need a script to find them.
* [[acostar]]: normally <ue> but in meaning "arrive at the coast", <>
* [[adecuar]]: <+,ú>
* [[aerografiar]]: <í>
* [[aferrar]]: <+,ie[obsolete]>
* [[afiliar]]: <>
* [[aforar]]: in meaning "to gauge, to measure": <>; in meaning "otorgar fuero": <ue>
* [[arrecir]]: <no_pres_stressed>
* [[agraviar]]: <>
* [[agriar]]: <í,+>
* [[aserrar]]: <ie>
* [[asolar]]: in meaning "destroy": <ue,+>; in meaning "to dry up": <>
* [[aspaventar]]: <ie>
* [[atentar]]: in meaning "to commit a crime" does not have vowel alt
* [[atesar]]: <>; possibly <ie> in obsolete meaning "atiesar"
* [[atestar]]: in meaning "to pack": <ie,+>; in meaning "testify": <>
* [[autoevacuarse]]: <+,ú>
* [[auxiliar]]: <>
* [[avalentar]]: <>
* [[cimentar]]: <ie,+>
* [[colar]]: most meanings <ue> but "canonically confer (an ecclesiastical benefit)" <>
* [[colorir]]: <no_pres_stressed>
* [[comisariar]]: <í>
* [[desafiliar]]: <>
* [[desaforar]]: "to deprive of fuero": <ue,+[less common]>
* [[desairar]]: <>
* [[desolar]]: <ue,+>
* [[desmembrar]]: <ie,+>
* [[dezmar]]: <>
* [[ejecutoriar]]: <í,+>
* [[emparentar]]: <ie,+>
* [[encentar]]: <>
* [[encubertar]]: <>
* [[engrosar]]: <ue,+>
* [[escenografiar]]: <í>
* [[evacuar]]: <+,ú>
* [[expatriar]]: <í,+>
* [[extasiar]]: <í>
* [[ferrar]]: <ie>
* [[follar]]: <ue>
* [[gloriar]]: <í>
* [[hibernar]]: no vowel alt or e-ie; e-ie not in RAE, ask about it
* [[historiar]]: <í,+>
* [[incensar]]: <ie>
* [[invernar]]: <ie,+>
* [[licuar]]: <+,ú>
* [[litografiar]]: <í>
* [[mecanografiar]]: <í>
* [[paliar]]: <í,+>
* [[preterir]]: <i.no_pres_stressed>
* [[promiscuar]]: <+,ú>
* [[readecuar]]: <+,ú>
* [[repatriar]]: <í,+>
* [[retrocar]]: <ue,+>
* [[serigrafiar]]: <í>
* [[soterrar]]: <ie,+>
* [[superpoblar]]: <ue>
* [[templar]]: <+,ie[in some parts of Latin America]>
* [[vidriar]]: <í,+>
Second round of verbs to fix:
* [[apropriar]]: forms point to reflexive [FORMS TO FIX]
* [[autogobernarse]]: (missing <ie>) [FORMS TO DELETE]
* [[autorreproducirse]]: (wrongly had regular preterite and impf/fut sub) [FORMS TO DELETE]
* [[aventarse]]: (missing <ie>) [FORMS TO DELETE]
* [[aventar]]: forms point to reflexive [FORMS TO FIX]
* [[culiar]]: yo culio or culío? [VERIFY]
* [[desnacer]]: delete [[dasnatos]]
* [[poseer]]: delete [[posesa]], [[posesos]], [[posesas]]
* [[reproducir]]: (wrongly had regular preterite and impf/fut sub) [FORMS TO DELETE]
* [[trasgredir]]: (wrongly had <i>) [FORMS TO DELETE]
---------
Irregular conjugations.
Each entry is processed in turn and consists of an object with two fields:
1. match=: Specifies the irregular verbs that match this object.
2. forms=: Specifies the irregular stems and forms for these verbs.
The value of match= is either a string beginning with "^" (match only the specified verb), a string not beginning
with "^" (match any verb ending in that string), or a function that is passed in the verb and should return the
prefix of the verb if it matches, otherwise nil. The function match_against_verbs() is provided to facilitate matching
a set of verbs with a common ending and specific prefixes (e.g. [[andar]] and [[desandar]] but not [[mandar]], etc.).
The value of forms= is a table specifying stems and individual override forms. Each key of the table names either a
stem (e.g. `pres_stressed`), a stem property (e.g. `vowel_alt`) or an individual override form (e.g. `pres_1s`).
Each value of a stem can either be a string (a single stem), a list of strings, or a list of objects of the form
{form = STEM, footnotes = {FOONOTES}}. Each value of an individual override should be of exactly the same form except
that the strings specify full forms rather than stems. The values of a stem property depend on the specific property
but are generally strings or booleans.
In order to understand how the stem specifications work, it's important to understand the phonetic modifications done
by combine_stem_ending(). In general, the complexities of predictable stem and ending modifications are all handled
in this function. In particular:
1. Spelling-based modifications (c/z, g/gu, gu/gü, g/j) occur automatically as appropriate for the ending.
2. Raising of e -> i, o -> u in -ir verbs before an ending beginning with i + vowel, as well as in the 1p/2p forms of
the present subjunctive (dormir -> durmiendo, durmió, durmamos), are handled here. Raising happens only for -ir
verbs and only when the stem setting `raising_conj` is true (which is normally set to true when vowel alternations
`ie-i`, `ye-i`, `ue-u`, `i`, `í` or `ú` are specified).
3. Numerous modifications are automatically made before an ending beginning with i + vowel. These include:
a. final -i of stem absorbed: sonreír -> sonrió, sonriera, sonriendo;
b. in the preterite of irregular verbs (likewise for other tenses derived from the preterite stem, i.e. imperfect
and and future subjunctive), initial i absorbed after j and u (dijeron not #dijieron, likewise for condujeron,
trajeron; also fueron not #fuyeron). This happens only when stem setting `pret_conj` == "irreg"; this must be set
explicitly by irregular verbs. Does not apply everywhere because of cases like regular [[tejer]] (tejieron not
#tejeron), regular [[concluir]] (concluyeron not #conclueron).
c. initial i of ending -> y after vowel and word-initially: poseer -> poseyó, poseyera, poseyendo; ir -> yendo;
d. initial i of ending -> y after gü, which becomes gu: argüir -> arguyó, arguyera, arguyendo;
e. initial i of ending absorbed after ñ, ll, y: tañer -> tañó, tañera, tañendo; bullir -> bulló, bullera, bullendo
4. If the ending begins with (h)i, it gets an accent after a/e/i/o to prevent the two merging into a diphthong:
caer -> caíste, caímos; reír -> reíste, reímos (pres and pret). This does not apply after u, e.g.
concluir -> concluiste, concluimos.
5. In -uir verbs (i.e. -ir verbs with stem ending in -u), a y is added before endings beginning with a/e/o:
concluir -> concluyo, concluyen, concluya, concluyamos. Note that preterite concluyó, gerund concluyendo, etc.
are handled by a different rule above (3b).
The following stems are recognized:
-- pres_unstressed: The present indicative unstressed stem (2s voseo, 1p, 2p). Also controls the imperative 2p
and gerund. Defaults to the infinitive stem.
-- pres_stressed: The present indicative stressed stem (1s, 2s, 3s, 3p). Also controls the imperative 2s.
Default is empty if indicator `no_pres_stressed`, else a vowel alternation if such an indicator is given
(e.g. `ue`, `ì`), else the infinitive stem.
-- pres1_and_sub: Overriding stem for 1s present indicative and the entire subjunctive. Only set by irregular verbs
and by the indicator `no_pres_stressed` (since verbs of this sort, e.g. [[aterir]], are missing the entire
subjunctive as well as the forms with stressed root). Used by many irregular verbs, e.g. [[caer]], [[roer]],
[[salir]], [[tener]], [[valer]], [[venir]], etc. Some verbs set this and then supply an override for the pres_1sg
if it's irregular, e.g. [[saber]], with irregular subjunctive stem "sep-" and special 1s present indicative "sé*"
(the * indicates that the monosyllabic accent should not be removed).
-- pres1: Special stem for 1s present indicative. Normally, do not set this explicitly. If you need to specify an
irregular 1s present indicative, use the form override pres_1s= to specify the entire form. Defaults to
pres1_and_sub if given, else pres_stressed.
-- pres_sub_unstressed: The present subjunctive unstressed stem (1p, 2p, also 2s voseo for -ar verbs). Defaults to
pres1_and_sub if given, else the infinitive stem.
-- pres_sub_stressed: The present subjunctive stressed stem (1s, 2s, 3s, 1p, also 2s voseo for -er/-ir verbs). Defaults
to pres1.
-- impf: The imperfect stem. Defaults to the infinitive stem.
-- pret: The preterite stem. Defaults to the infinitive stem.
-- pret_conj: Determines the set of endings used in the preterite. Should be one of "ar", "er", "ir" or "irreg".
Defaults to the conjugation as determined from the infinitive.
-- fut: The future stem. Defaults to the infinitive stem.
-- cond: The conditional stem. Defaults to fut.
-- impf_sub_ra: The imperfect subjunctive -ra stem. Defaults to the preterite stem.
-- impf_sub_se: The imperfect subjunctive -se stem. Defaults to the preterite stem.
-- fut_sub: The future subjunctive stem. Defaults to the preterite stem.
-- pp: The past participle stem. Default is based on the verb conjugation: infinitive stem + "ad" for -ar verbs,
otherwise infinitive stem + "id".
]=]
local built_in_conjugations = {
{
-- andar, desandar
-- we don't want to match e.g. mandar.
match = match_against_verbs("andar", {"", "des"}),
forms = {pret = "anduv", pret_conj = "irreg"}
},
{
-- asir, desasir
match = "asir",
-- use 'asgu' because we're in a front environment; if we use 'asg', we'll get '#asjo'
forms = {pres1_and_sub = "asgu"}
},
{
-- abrir, cubrir and compounds
match = function(verb)
local prefix, base_verb = rmatch(verb, "^(.*)(brir)$")
-- Only match abrir, cubrir and compounds, and don't match desabrir/jabrir
if not prefix then
return nil
elseif not prefix:find("a$") and not prefix:find("cu$") then
return nil
elseif prefix == "desa" or prefix == "ja" then
return nil
else
return prefix, base_verb
end
end,
forms = {pp = "biert"}
},
{
match = "caber",
forms = {pres1_and_sub = "quep", pret = "cup", pret_conj = "irreg", fut = "cabr"}
},
{
-- caer, decaer, descaer, recaer
match = "caer",
-- use 'caigu' because we're in a front environment; if we use 'caig', we'll get '#caijo'
forms = {pres1_and_sub = "caigu"}
},
{
-- cocer, escocer, precocer, etc.
match = "cocer",
-- override cons_alt, otherwise the verb would be categorized as a c-zc alternating verb
forms = {vowel_alt = "ue", pres1 = "cuez", pres_sub_unstressed = "coz", cons_alt = "c-z"}, -- not cozco, as would normally be generated
},
{
-- dar, desdar
match = match_against_verbs("dar", {"", "des"}),
forms = {
-- we need to override various present indicative forms and add an accent for the compounds;
-- not needed for the simplex and in fact the accents will be removed in that case
pres_1s = "doy",
pres_2s = "dás",
pres_3s = "dá",
pres_2p = "dáis",
pres_3p = "dán",
pret = "d", pret_conj = "er",
pres_sub_1s = "dé*", -- * signals that the monosyllabic accent must remain
pres_sub_2s = "dés",
pres_sub_3s = "dé*",
pres_sub_2p = "déis",
pres_sub_3p = "dén",
imp_2s = "dá",
}
},
{
-- decir, redecir, entredecir
match = match_against_verbs("decir", {"", "re", "entre"}),
forms = {
-- for this and variant verbs in -decir, we set cons_alt to false because we don't want the
-- verb categorized as a c-zc alternating verb, which would happen by default
-- use 'digu' because we're in a front environment; if we use 'dig', we'll get '#dijo'
pres1_and_sub = "digu", vowel_alt = "i", cons_alt = false, pret = "dij", pret_conj = "irreg",
pp = "dich", fut = "dir",
imp_2s = "dí" -- need the accent for the compounds; it will be removed in the simplex
}
},
{
-- antedecir, interdecir
match = match_against_verbs("decir", {"ante", "inter"}),
forms = {
pres1_and_sub = "digu", vowel_alt = "i", cons_alt = false, pret = "dij", pret_conj = "irreg",
pp = "dich", fut = "dir" -- imp_2s regular
}
},
{
-- bendecir, maldecir
match = match_against_verbs("decir", {"ben", "mal"}),
forms = {
pres1_and_sub = "digu", vowel_alt = "i", cons_alt = false, pret = "dij", pret_conj = "irreg",
pp = {"decid", "dit"} -- imp_2s regular, fut regular
}
},
{
-- condecir, contradecir, desdecir, predecir, others?
match = "decir",
forms = {
pres1_and_sub = "digu", vowel_alt = "i", cons_alt = false, pret = "dij", pret_conj = "irreg",
pp = "dich", fut = {"decir", "dir"} -- imp_2s regular
}
},
{
match = "^desvaír",
forms = {
pres_2s = "desvaes",
pres_3s = "desvae",
pres_3p = "desvaen",
imp_2s = "desvae"
}
},
{
-- conducir, producir, reducir, traducir, etc.
match = "ducir",
forms = {pret = "duj", pret_conj = "irreg"}
},
{
-- elegir, reelegir; not preelegir, per RAE
match = match_against_verbs("elegir", {"", "re"}),
forms = {vowel_alt = "i", pp = {"elegid", "elect"}}
},
{
-- erguir
match = "^erguir",
forms = {
vowel_alt = {"i", "ye-i"},
-- We would not need to make this verb irregular except for the alternative unstressed present subjunctive forms
-- in yerg-. We can't use pres_sub_unstressed = {"irgu", "yergu"} because the "i" and "ye-i" vowel alternations
-- are e->i raising in the unstressed present subjunctive and we wrongly get irgamos/yirgamos etc.
pres_sub_2sv = {"irgás", "yergás"},
pres_sub_1p = {"irgamos", "yergamos"},
pres_sub_2p = {"irgáis", "yergáis"},
},
},
{
match = "^estar",
forms = {
pres_1s = "estoy",
pres_2s = "estás",
pres_2sv = "estás",
pres_3s = "está",
pres_3p = "están",
pret = "estuv",
pret_conj = "irreg",
pres_sub_1s = "esté",
pres_sub_2s = "estés",
pres_sub_2sv = "estés",
pres_sub_3s = "esté",
pres_sub_3p = "estén",
imp_2s = "está",
imp_2sv = "está",
}
},
{
-- freír, refreír
match = "freír",
forms = {vowel_alt = "í", pp = {"freíd", "frit"}}
},
{
match = "garantir",
forms = {
pres_stressed = {{form = "garant", footnotes = {"[only used in Argentina and Uruguay]"}}},
pres1_and_sub = {{form = "garant", footnotes = {"[only used in Argentina and Uruguay]"}}},
}
},
{
match = "^haber",
forms = {
pres_1s = "he",
pres_2s = "has",
pres_2sv = "has",
pres_3s = {"ha", {form = "hay", footnotes = {"[used impersonally]"}}},
pres_1p = "hemos",
pres_3p = "han",
pres1_and_sub = "hay", -- only for subjunctive as we override pres_1s
pret = "hub",
pret_conj = "irreg",
imp_2s = {"habe", "he"},
imp_2sv = {"habe", "he"},
fut = "habr",
}
},
{
match = "satisfacer",
forms = {
-- see below for cons_alt setting and pres1_and_sub setting
pres1_and_sub = "satisfagu", cons_alt = false, pret = "satisfic", pret_conj = "irreg",
pp = "satisfech", fut = "satisfar", imp_2s = {"satisface", "satisfaz"}
}
},
{
match = match_against_verbs("hacer", {"contra", "re"}),
-- contrahacer/rehacer require an extra accent in the preterite (rehíce, rehízo).
forms = {
-- see below for cons_alt setting and pres1_and_sub setting
pres1_and_sub = "hagu", cons_alt = false,
pret = "hic", pret_1s = "híce", pret_3s = "hízo", pret_conj = "irreg",
pp = "hech", fut = "har", imp_2s = "haz"
}
},
{
-- hacer, deshacer, contrahacer, rehacer, facer, desfacer, jacer
match = function(verb) return rmatch(verb, "^(.*[hjf])(acer)$") end,
forms = {
-- for these verbs, we set cons_alt to false because we don't want the verb categorized as a
-- c-zc alternating verb, which would happen by default
-- use 'agu' because we're in a front environment; if we use 'ag', we'll get '#hajo'
pres1_and_sub = "agu", cons_alt = false, pret = "ic", pret_conj = "irreg", pp = "ech",
fut = "ar", imp_2s = "az"
}
},
{
-- imprimir, reimprimir
match = "imprimir",
forms = {pp = {"imprimid", "impres"}}
},
{
-- infecir
match = "infecir",
-- override cons_alt, otherwise the verb would be categorized as a c-zc alternating verb
forms = {vowel_alt = "i", pres1 = "infiz", pres_sub_unstressed = "infez", cons_alt = "c-z"}, -- not infizco, as would normally be generated
},
{
match = "infecir",
-- override cons_alt, otherwise the verb would be categorized as a c-zc alternating verb
forms = {pres1_and_sub = "infez", cons_alt = "c-z"}, -- not mezco, as would normally be generated
},
{
match = "^ir",
forms = {
pres_1s = "voy",
pres_2s = "vas",
pres_2sv = "vas",
pres_3s = "va",
pres_1p = "vamos",
pres_2p = "vais",
pres_3p = "van",
pres1_and_sub = "vay", -- only for subjunctive as we override pres_1s
full_impf = "ib",
impf_1p = "íbamos",
pret = "fu",
pret_conj = "irreg", -- this signals that fu + -ieron -> fueron not fuyeron
pret_1s = "fui",
pret_3s = "fue",
imp_2s = "ve",
imp_2sv = "andá",
imp_1p = {"vamos", "vayamos"},
refl_imp_2p = {"idos", "iros"},
imp_2p_comb_os = {"idos", "iros"},
}
},
{
-- mecer, remecer
-- we don't want to match e.g. adormecer, estremecer
match = match_against_verbs("mecer", {"re", ""}),
-- override cons_alt, otherwise the verb would be categorized as a c-zc alternating verb
forms = {pres1_and_sub = "mez", cons_alt = "c-z"}, -- not mezco, as would normally be generated
},
{
-- morir, desmorir, premorir
match = "morir",
forms = {vowel_alt = "ue-u", pp = "muert"},
},
{
-- oír, desoír, entreoír, trasoír
match = "oír",
-- use 'oigu' because we're in a front environment; if we use 'oig', we'll get '#oijo'
forms = {pres1_and_sub = "oigu"}
},
{
match = "olver", -- solver, volver, bolver and derivatives
forms = {vowel_alt = "ue", pp = "uelt"}
},
{
match = "pagar",
forms = {pp = {"pagad", {form = "pag", footnotes = {"[Uruguay]"}}}}
},
{
-- placer, desplacer
match = "placer",
forms = {
pret_3s = {"plació", {form = "plugo", footnotes = {"[archaic]"}}},
pret_3p = {"placieron", {form = "pluguieron", footnotes = {"[archaic]"}}},
pres_sub_3s = {"plazca", {form = "plega", footnotes = {"[archaic]"}}, {form = "plegue", footnotes = {"[archaic]"}}},
impf_sub_ra_3s = {"placiera", {form = "pluguiera", footnotes = {"[archaic]"}}},
impf_sub_ra_3p = {"placieran", {form = "pluguieran", footnotes = {"[archaic]"}}},
impf_sub_se_3s = {"placiese", {form = "pluguiese", footnotes = {"[archaic]"}}},
impf_sub_se_3p = {"placiesen", {form = "pluguiesen", footnotes = {"[archaic]"}}},
fut_sub_3s = {"placiere", {form = "pluguiere", footnotes = {"[archaic]"}}},
fut_sub_3p = {"placieren", {form = "pluguieren", footnotes = {"[archaic]"}}},
}
},
{
match = "poder",
forms = {vowel_alt = "ue", pret = "pud", pret_conj = "irreg", fut = "podr", gerund = "pudiendo"}
},
{
-- poner, componer, deponer, imponer, oponer, suponer, many others
match = "poner",
forms = {
-- use 'pongu' because we're in a front environment; if we use 'pong', we'll get '#ponjo'
pres1_and_sub = "pongu", pret = "pus", pret_conj = "irreg", fut = "pondr", pp = "puest",
imp_2s = "pón" -- need the accent for the compounds; it will be removed in the simplex
}
},
{
-- proveer, desproveer
match = "proveer",
forms = {pp = {"provist", "proveíd"}},
},
{
match = "pudrir",
forms = {pp = "podrid"}
},
{
-- querer, desquerer, malquerer
match = "querer",
forms = {vowel_alt = "ie", pret = "quis", pret_conj = "irreg", fut = "querr"}
},
{
match = "^raer",
-- use 'raigu' because we're in a front environment; if we use 'raig', we'll get '#raijo'
forms = {pres1_and_sub = {"raigu", "ray"}}
},
{
-- roer, corroer
match = "roer",
-- use 'roigu' because we're in a front environment; if we use 'roig', we'll get '#roijo'
forms = {pres1_and_sub = {"ro", "roigu", "roy"}}
},
{
-- romper, entrerromper, arromper, derromper; not corromper; FIXME: not sure about interromper (obsolete)
match = function(verb)
local prefix, base_verb = rmatch(verb, "^(.*)(romper)$")
-- Don't match corromper
if prefix == "cor" then
return nil
else
return prefix, base_verb
end
end,
forms = {pp = "rot"}
},
{
-- saber, resaber
match = "saber",
forms = {
pres_1s = "sé*", -- * signals that the monosyllabic accent must remain
pres1_and_sub = "sep", -- only for subjunctive as we override pres_1s
pret = "sup",
pret_conj = "irreg",
fut = "sabr",
}
},
{
match = "salir",
forms = {
-- use 'salgu' because we're in a front environment; if we use 'salg', we'll get '#saljo'
pres1_and_sub = "salgu", fut = "saldr", imp_2s = "sal",
-- These don't exist per the RAE.
imp_2s_comb_lo = {}, imp_2s_comb_los = {}, imp_2s_comb_la = {}, imp_2s_comb_las = {},
imp_2s_comb_le = {}, imp_2s_comb_les = {},
},
},
{
match = "scribir", -- escribir, describir, proscribir, etc.
forms = {pp = {"scrit", {form = "script", footnotes = {"[Argentina and Uruguay]"}}}}
},
{
match = "^ser",
forms = {
pres_1s = "soy",
pres_2s = "eres",
pres_2sv = "sos",
pres_3s = "es",
pres_1p = "somos",
pres_2p = "sois",
pres_3p = "son",
pres1_and_sub = "se", -- only for subjunctive as we override pres_1s
full_impf = "er",
impf_1p = "éramos",
pret = "fu",
pret_conj = "irreg", -- this signals that fu + -ieron -> fueron not fuyeron
pret_1s = "fui",
pret_3s = "fue",
fut = "ser",
imp_2s = "sé*", -- * signals that the monosyllabic accent must remain
imp_2sv = "sé*",
}
},
{
match = "^soler",
forms = {
vowel_alt = "ue",
fut = {{form = "soler", footnotes = {"[rare but acceptable]"}}},
fut_sub = {{form = "sol", footnotes = {"[rare but acceptable]"}}},
pp = {{form = "solid", footnotes = {"[rare but acceptable]"}}},
}
},
{
-- tener, abstener, contener, detener, obtener, sostener, and many others
match = "tener",
forms = {
-- use 'tengu' because we're in a front environment; if we use 'teng', we'll get '#tenjo'
pres1_and_sub = "tengu", vowel_alt = "ie", pret = "tuv", pret_conj = "irreg", fut = "tendr",
imp_2s = "tén" -- need the accent for the compounds; it will be removed in the simplex
}
},
{
-- traer, atraer, detraer, distraer, extraer, sustraer, and many others
match = "traer",
-- use 'traigu' because we're in a front environment; if we use 'traig', we'll get '#traijo'
forms = {pres1_and_sub = "traigu", pret = "traj", pret_conj = "irreg"}
},
{
-- valer, equivaler, prevaler
match = "valer",
-- use 'valgu' because we're in a front environment; if we use 'valg', we'll get '#valjo'
forms = {pres1_and_sub = "valgu", fut = "valdr"}
},
{
match = "venir",
forms = {
-- use 'vengu' because we're in a front environment; if we use 'veng', we'll get '#venjo'
pres1_and_sub = "vengu", vowel_alt = "ie-i", pret = "vin", pret_conj = "irreg",
-- uniquely for this verb, pres sub 2sv/1p/2p do not raise the vowel even though we are an
-- e-ie-i verb (contrast sentir -> sintamos/sintáis)
pres_sub_2sv = "vengás", pres_sub_1p = "vengamos", pres_sub_2p = "vengáis",
fut = "vendr", imp_2s = "vén" -- need the accent for the compounds; it will be removed in the simplex
}
},
{
-- We want to match antever etc. but not atrever etc. No way to avoid listing each verb.
match = match_against_verbs("ver", {"ante", "entre", "pre", "re", "tras", ""}),
forms = {
-- we need to override various present indicative forms and add an accent for the compounds;
-- not needed for the simplex and in fact the accents will be removed in that case
pres_2s = "vés",
pres_2sv = "vés",
pres_3s = "vé",
pres_2p = "véis",
pres_3p = "vén",
pres1_and_sub = "ve",
impf = "ve", pp = "vist",
imp_2s = "vé" -- need the accent for the compounds; it will be removed in the simplex
}
},
{
-- yacer, adyacer, subyacer
match = "yacer",
-- use 'yazqu/yazgu/yagu' because we're in a front environment; see 'decir' above
forms = {pres1_and_sub = {"yazqu", "yazgu", "yagu"}, imp_2s = {"yace", "yaz"}}
},
}
local reflexive_masc_forms = {
["su"] = {"mi", "tu", "su", "nuestro", "vuestro", "su"},
["sus"] = {"mis", "tus", "sus", "nuestros", "vuestros", "sus"},
["sí"] = {"mí", "ti", "sí", "nosotros", "vosotros", "sí"},
["consigo"] = {"conmigo", "contigo", "consigo", "con nosotros", "con vosotros", "consigo"},
}
local reflexive_fem_forms = {
["su"] = {"mi", "tu", "su", "nuestra", "vuestra", "su"},
["sus"] = {"mis", "tus", "sus", "nuestras", "vuestras", "sus"},
["sí"] = {"mí", "ti", "sí", "nosotras", "vosotras", "sí"},
["consigo"] = {"conmigo", "contigo", "consigo", "con nosotras", "con vosotras", "consigo"},
}
local reflexive_forms = {
["se"] = {"me", "te", "se", "nos", "os", "se"},
["suyo"] = {"mío", "tuyo", "suyo", "nuestro", "vuestro", "suyo"},
["suya"] = {"mía", "tuya", "suya", "nuestra", "vuestra", "suya"},
["suyos"] = {"míos", "tuyos", "suyos", "nuestros", "vuestros", "suyos"},
["suyas"] = {"mías", "tuyas", "suyas", "nuestras", "vuestras", "suyas"},
}
local function skip_slot(base, slot, allow_overrides)
if not allow_overrides and (base.basic_overrides[slot] or base.combined_overrides[slot] or
base.refl and base.basic_reflexive_only_overrides[slot]) then
-- Skip any slots for which there are overrides.
return true
end
if base.only3s and (slot:find("^pp_f") or slot:find("^pp_mp")) then
-- diluviar, atardecer, neviscar; impersonal verbs have only masc sing pp
return true
end
if not slot:find("[123]") then
-- Don't skip non-personal slots.
return false
end
if base.nofinite then
return true
end
if (base.only3s or base.only3sp or base.only3p) and (slot:find("^imp_") or slot:find("^neg_imp_")) then
return true
end
if base.only3s and not slot:find("3s") then
-- diluviar, atardecer, neviscar
return true
end
if base.only3sp and not slot:find("3[sp]") then
-- atañer, concernir
return true
end
if base.only3p and not slot:find("3p") then
-- [[caer cuatro gotas]], [[caer chuzos de punta]], [[entrarle los siete males]]
return true
end
return false
end
-- Add the `stem` to the `ending` for the given `slot` and apply any phonetic modifications.
-- `is_combining_ending` is true if `ending` is actually the ending (this function is also
-- called to combine prefix + stem). WARNING: This function is written very carefully; changes
-- to it can easily have unintended consequences.
local function combine_stem_ending(base, slot, stem, ending, is_combining_ending)
if not is_combining_ending then
return stem .. ending
end
if base.stems.raising_conj and (rfind(ending, "^i" .. V) or
slot == "pres_sub_1p" or slot == "pres_sub_2p" or slot == "pres_sub_2sv") then
-- need to raise e -> i, o -> u: dormir -> durmió, durmiera, durmiendo, durmamos
stem = rsub(stem, "([eo])(" .. C .. "*)$", function(vowel, rest) return raise_vowel[vowel] .. rest end)
-- also with stem ending in -gu or -qu (e.g. erguir -> irguió, irguiera, irguiendo, irgamos)
stem = rsub(stem, "([eo])(" .. C .. "*[gq]u)$", function(vowel, rest) return raise_vowel[vowel] .. rest end)
end
-- Lots of sound changes involving endings beginning with i + vowel
if rfind(ending, "^i" .. V) then
-- (1) final -i of stem absorbed: sonreír -> sonrió, sonriera, sonriendo; note that this rule may be fed
-- by the preceding one (stem sonre- raised to sonri-, then final i absorbed)
stem = stem:gsub("i$", "")
-- (2) In the preterite of irregular verbs (likewise for other tenses derived from the preterite stem, i.e.
-- imperfect and future subjunctive), initial i absorbed after j (dijeron not #dijieron, likewise for
-- condujeron, trajeron) and u (fueron not #fuyeron). Does not apply in regular verb tejer (tejieron not
-- #tejeron) and concluir (concluyeron not #conclueron).
if base.stems.pret_conj == "irreg" and rfind(stem, "[ju]$") then
ending = ending:gsub("^i", "")
end
-- (3) initial i -> y after vowel and word-initially: poseer -> poseyó, poseyera, poseyendo;
-- concluir -> concluyó, concluyera, concluyendo; ir -> yendo; but not conseguir/delinquir
if stem == "" or (rfind(stem, V .. "$") and not rfind(stem, "[gq]u$")) then
ending = ending:gsub("^i", "y")
end
-- (4) -gü + ie- -> -guye-: argüir -> arguyó, arguyera, arguyendo
if stem:find("gü$") then
-- transfer the y to the stem to avoid gü -> gu below in front/back conversions
stem = stem:gsub("ü$", "uy")
ending = ending:gsub("^i", "")
end
-- (5) initial i absorbed after ñ, ll, y: tañer -> tañó, tañera, tañendo; bullir -> bulló, bullera, bullendo
if rfind(stem, "[ñy]$") or rfind(stem, "ll$") then
ending = ending:gsub("^i", "")
end
end
-- If ending begins with i, it must get an accent after a/e/i/o to prevent the two merging into a diphthong:
-- caer -> caíste, caímos; reír -> reíste, reímos (pres and pret). This does not apply after u, e.g.
-- concluir -> concluiste, concluimos.
if ending:find("^i") and stem:find("[aeio]$") then
ending = ending:gsub("^i", "í")
end
-- If -oír/-uir (i.e. -ir with stem ending in -o/u, e.g. oír, concluir), a y must be added before endings
-- beginning with a/e/o. Check for base.stems.pret_conj == "irreg" to exclude stem fu- of [[ir]].
if base.conj == "ir" and rfind(ending, "^[aeoáéó]") and base.stems.pret_conj ~= "irreg" then
if rfind(stem, "[aoú]$") then -- oír -> oye, rehuir -> rehúyo/rehúye (with indicator 'ú')
stem = stem .. "y"
elseif rfind(stem, "[^gq]u$") then -- concluir, but not conseguir or delinquir
stem = stem .. "y"
elseif stem:find("ü$") then -- argüir -> arguyendo
stem = stem:gsub("ü$", "uy")
end
end
-- Spelling changes in the stem; it depends on whether the stem given is the pre-front-vowel or
-- pre-back-vowel variant, as indicated by `frontback`. We want these front-back spelling changes to happen
-- between stem and ending, not between prefix and stem; the prefix may not have the same "front/backness"
-- as the stem.
local is_front = rfind(ending, "^[eiéí]")
if base.frontback == "front" and not is_front then
-- parecer -> parezco, conducir -> conduzco; use zqu to avoid triggering the following gsub();
-- the third line will replace zqu -> zc
if slot ~= "pret_3s" then -- exclude hice -> hizo (not #hizco)
stem = rsub(stem, "(" .. V .. ")c$", "%1zqu")
end
stem = stem:gsub("sc$", "squ") -- evanescer -> evanesco, fosforescer -> fosforesco
stem = stem:gsub("c$", "z") -- ejercer -> ejerzo, uncir -> unzo
stem = stem:gsub("qu$", "c") -- delinquir -> delinco, parecer -> parezqu- -> parezco
stem = stem:gsub("g$", "j") -- coger -> cojo, afligir -> aflijo
stem = stem:gsub("gu$", "g") -- distinguir -> distingo
stem = stem:gsub("gü$", "gu") -- may not occur; argüir -> arguyo handled above
elseif base.frontback == "back" and is_front then
stem = stem:gsub("gu$", "gü") -- averiguar -> averigüé
stem = stem:gsub("g$", "gu") -- cargar -> cargué
stem = stem:gsub("c$", "qu") -- marcar -> marqué
stem = rsub(stem, "[çz]$", "c") -- aderezar/adereçar -> aderecé
end
return stem .. ending
end
local function check_stems_for_suppress_prefix(slot, stems)
-- Check whether any or all stems have `suppress_prefix`.
local any_suppress_prefix = false
local any_not_suppress_prefix = false
if type(stems) == "table" then
if stems.suppress_prefix then
-- A single form object.
any_suppress_prefix = true
else
for _, stem in ipairs(stems) do
if type(stem) == "table" and stem.suppress_prefix then
any_suppress_prefix = true
else
any_not_suppress_prefix = true
end
end
end
else
any_not_suppress_prefix = true
end
if any_suppress_prefix and any_not_suppress_prefix then
-- This should never happen because suppress_prefix is set on user-specified stem and individual form
-- overrides, which should completely replace built-in overrides (which don't have suppress_prefix).
error("Internal error: For slot '" .. slot .. ", saw a mixture of suppress-prefix and non-suppress-prefix stems, and can't handle")
else
return any_suppress_prefix
end
end
local function add(base, slot, stems, endings, is_combining_ending, allow_overrides)
if skip_slot(base, slot, allow_overrides) then
return
end
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(base, slot, stem, ending, is_combining_ending)
end
iut.add_forms(base.forms, slot, stems, endings, do_combine_stem_ending, nil, nil, base.all_footnotes)
end
local function add3(base, slot, stems, endings, allow_overrides)
local suppress_prefix = base.prefix == "" or check_stems_for_suppress_prefix(slot, stems)
if suppress_prefix then
return add(base, slot, stems, endings, "is combining ending", allow_overrides)
end
if skip_slot(base, slot, allow_overrides) then
return
end
local is_combining_ending = false
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(base, slot, stem, ending, is_combining_ending)
end
-- Have to reimplement add_multiple_forms() ourselves due to the is_combining_ending
-- flag, which needs to be different when adding prefix to stems vs. stems to ending.
-- Otherwise we get e.g. #reímpreso instead of reimpreso.
local tempdest = {}
iut.add_forms(tempdest, slot, base.prefix, stems, do_combine_stem_ending)
is_combining_ending = true
iut.add_forms(base.forms, slot, tempdest[slot], endings, do_combine_stem_ending)
end
local function insert_form(base, slot, form)
if not skip_slot(base, slot) then
iut.insert_form(base.forms, slot, form)
end
end
local function insert_forms(base, slot, forms)
if not skip_slot(base, slot) then
iut.insert_forms(base.forms, slot, forms)
end
end
local function add_single_stem_tense(base, slot_pref, stems, s1, s2, s3, p1, p2, p3)
local function addit(slot, ending)
add3(base, slot_pref .. "_" .. slot, stems, ending)
end
addit("1s", s1)
addit("2s", s2)
addit("3s", s3)
addit("1p", p1)
addit("2p", p2)
addit("3p", p3)
end
local function add_present_indic(base)
local function addit(slot, stems, ending)
add3(base, "pres_" .. slot, stems, ending)
end
local s2, s2v, s3, p1, p2, p3
if base.conj == "ar" then
s2, s2v, s3, p1, p2, p3 = "as", "ás", "a", "amos", "áis", "an"
elseif base.conj == "er" then
s2, s2v, s3, p1, p2, p3 = "es", "és", "e", "emos", "éis", "en"
elseif base.conj == "ir" then
s2, s2v, s3, p1, p2, p3 = "es", "ís", "e", "imos", "ís", "en"
else
error("Internal error: Unrecognized conjugation " .. base.conj)
end
addit("1s", base.stems.pres1, "o")
addit("2s", base.stems.pres_stressed, s2)
addit("2sv", base.stems.pres_unstressed, s2v)
addit("3s", base.stems.pres_stressed, s3)
addit("1p", base.stems.pres_unstressed, p1)
addit("2p", base.stems.pres_unstressed, p2)
addit("3p", base.stems.pres_stressed, p3)
end
local function add_present_subj(base)
local function addit(slot, stems, ending)
add3(base, "pres_sub_" .. slot, stems, ending)
end
local s1, s2, s2v, s3, p1, p2, p3, voseo_stem
if base.conj == "ar" then
s1, s2, s2v, s3, p1, p2, p3 = "e", "es", "és", "e", "emos", "éis", "en"
else
s1, s2, s2v, s3, p1, p2, p3 = "a", "as", "ás", "a", "amos", "áis", "an"
end
addit("1s", base.stems.pres_sub_stressed, s1)
addit("2s", base.stems.pres_sub_stressed, s2)
addit("2sv", base.stems.pres_sub_unstressed, s2v)
addit("3s", base.stems.pres_sub_stressed, s3)
addit("1p", base.stems.pres_sub_unstressed, p1)
addit("2p", base.stems.pres_sub_unstressed, p2)
addit("3p", base.stems.pres_sub_stressed, p3)
end
local function add_imper(base)
local function addit(slot, stems, ending)
add3(base, "imp_" .. slot, stems, ending)
end
if base.conj == "ar" then
addit("2s", base.stems.pres_stressed, "a")
addit("2sv", base.stems.pres_unstressed, "á")
addit("2p", base.stems.pres_unstressed, "ad")
elseif base.conj == "er" then
addit("2s", base.stems.pres_stressed, "e")
addit("2sv", base.stems.pres_unstressed, "é")
addit("2p", base.stems.pres_unstressed, "ed")
elseif base.conj == "ir" then
addit("2s", base.stems.pres_stressed, "e")
addit("2sv", base.stems.pres_unstressed, "í")
addit("2p", base.stems.pres_unstressed, "id")
else
error("Internal error: Unrecognized conjugation " .. base.conj)
end
end
local function add_finite_non_present(base)
local function add_tense(slot, stem, s1, s2, s3, p1, p2, p3)
add_single_stem_tense(base, slot, stem, s1, s2, s3, p1, p2, p3)
end
local stems = base.stems
if stems.full_impf then
-- An override needs to be supplied for the impf_1p due to the accent on the stem.
add_tense("impf", stems.full_impf, "a", "as", "a", {}, "ais", "an")
elseif base.conj == "ar" then
add_tense("impf", stems.impf, "aba", "abas", "aba", "ábamos", "abais", "aban")
else
add_tense("impf", stems.impf, "ía", "ías", "ía", "íamos", "íais", "ían")
end
if stems.pret_conj == "irreg" then
add_tense("pret", stems.pret, "e", "iste", "o", "imos", "isteis", "ieron")
elseif stems.pret_conj == "ar" then
add_tense("pret", stems.pret, "é", "aste", "ó", "amos", "asteis", "aron")
else
add_tense("pret", stems.pret, "í", "iste", "ió", "imos", "isteis", "ieron")
end
if stems.pret_conj == "ar" then
add_tense("impf_sub_ra", stems.impf_sub_ra, "ara", "aras", "ara", "áramos", "arais", "aran")
add_tense("impf_sub_se", stems.impf_sub_se, "ase", "ases", "ase", "ásemos", "aseis", "asen")
add_tense("fut_sub", stems.fut_sub, "are", "ares", "are", "áremos", "areis", "aren")
else
add_tense("impf_sub_ra", stems.impf_sub_ra, "iera", "ieras", "iera", "iéramos", "ierais", "ieran")
add_tense("impf_sub_se", stems.impf_sub_se, "iese", "ieses", "iese", "iésemos", "ieseis", "iesen")
add_tense("fut_sub", stems.fut_sub, "iere", "ieres", "iere", "iéremos", "iereis", "ieren")
end
add_tense("fut", stems.fut, "é", "ás", "á", "emos", "éis", "án")
add_tense("cond", stems.cond, "ía", "ías", "ía", "íamos", "íais", "ían")
end
local function add_non_finite_forms(base)
local stems = base.stems
local function addit(slot, stems, ending)
add3(base, slot, stems, ending)
end
insert_form(base, "infinitive", {form = base.verb})
-- Also insert "infinitive + reflexive pronoun" combinations if we're handling a reflexive verb. See comment below for
-- "gerund + reflexive pronoun" combinations.
if base.refl then
for _, persnum in ipairs(person_number_list_basic) do
insert_form(base, "infinitive_" .. persnum, {form = base.verb})
end
end
local ger_ending = base.conj == "ar" and "ando" or "iendo"
addit("gerund", stems.pres_unstressed, ger_ending)
-- Also insert "gerund + reflexive pronoun" combinations if we're handling a reflexive verb. We insert exactly the same
-- form as for the bare gerund; later on in add_reflexive_or_fixed_clitic_to_forms(), we add the appropriate clitic
-- pronouns. It's important not to do this for non-reflexive verbs, because in that case, the clitic pronouns won't be
-- added, and {{es-verb form of}} will wrongly consider all these combinations as possible inflections of the bare
-- gerund. Thanks to [[User:JeffDoozan]] for this bug fix.
if base.refl then
for _, persnum in ipairs(person_number_list_basic) do
addit("gerund_" .. persnum, stems.pres_unstressed, ger_ending)
end
end
addit("pp_ms", stems.pp, "o")
addit("pp_fs", stems.pp, "a")
addit("pp_mp", stems.pp, "os")
addit("pp_fp", stems.pp, "as")
end
local function copy_subjunctives_to_imperatives(base)
-- Copy subjunctives to imperatives, unless there's an override for the given slot (as with the imp_1p of [[ir]]).
for _, persnum in ipairs({"3s", "1p", "3p"}) do
local from = "pres_sub_" .. persnum
local to = "imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form) return form end))
end
end
-- Remove monosyllabic accents (e.g. the 3sg preterite of fiar is fio not #fió). Note that there are a
-- few monosyllabic verb forms that intentionally have an accent, to distinguish them from other words
-- with the same pronunciation. These are as follows:
-- (1) [[sé]] 1sg present indicative of [[saber]];
-- (2) [[sé]] 2sg imperative of [[ser]];
-- (3) [[dé]] 1sg and 3sg present subjunctive of [[dar]].
-- For these, a * is added, which indicates that the accent needs to remain. If we see such a *, we remove
-- it but otherwise leave the form alone.
local function remove_monosyllabic_accents(base)
for _, slotaccel in ipairs(base.alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
if base.forms[slot] then
for _, form in ipairs(base.forms[slot]) do
if form.form:find("%*") then -- * means leave alone any accented vowel
form.form = form.form:gsub("%*", "")
elseif may_need_monosyllabic_accent_removed(form.form) then
-- Has an accented vowel and no VCV sequence and not a suffix; may be monosyllabic, in which
-- case we need to remove the accent. Check # of syllables and remove accent if only 1. Note
-- that the checks for accented vowel and VCV sequence are not strictly needed, but are
-- optimizations to avoid running the whole syllabification algorithm on every verb form.
local syllables = com.syllabify(form.form)
if #syllables == 1 then
form.form = com.remove_accent_from_syllable(syllables[1])
end
end
end
end
end
end
-- Add the appropriate clitic pronouns in `clitics` to the forms in `base_slot`. `store_cliticized_form` is a function
-- of three arguments (clitic, formobj, cliticized_form) and should store the cliticized form for the specified clitic
-- and form object.
local function add_forms_with_clitic(base, base_slot, clitics, store_cliticized_form)
-- the special slot lxx is for le/les clitics that become "se" in double clitics
if base_slot:match("_comb_lxx$") then
base_slot = base_slot:gsub("_comb_lxx$", "_comb_le")
end
if not base.forms[base_slot] then
mw.log("unhandled base_slot " .. base_slot)
-- This can happen, e.g. in only3s/only3sp/only3p verbs.
return
end
for _, formobj in ipairs(base.forms[base_slot]) do
-- Figure out the correct accenting of the verb when a clitic pronoun is attached to it. We may need to
-- add or remove an accent mark:
-- (1) No accent mark currently, none needed: infinitive sentar -> sentarlo; imperative singular ten -> tenlo;
-- (2) Accent mark currently, still needed: infinitive oír -> oírlo;
-- (3) No accent mark currently, accent needed: imperative singular siente -> siéntelo;
-- (4) Accent mark currently, not needed: imperative singular está -> estalo, sé -> selo.
local syllables = com.syllabify(formobj.form)
local sylno = com.stressed_syllable(syllables)
table.insert(syllables, "lo")
local needs_accent = com.accent_needed(syllables, sylno)
if needs_accent then
syllables[sylno] = com.add_accent_to_syllable(syllables[sylno])
else
syllables[sylno] = com.remove_accent_from_syllable(syllables[sylno])
end
table.remove(syllables) -- remove added clitic pronoun
local reaccented_form = table.concat(syllables)
for _, clitic in ipairs(clitics) do
local cliticized_form
-- Some further special cases.
if base_slot == "imp_1p" and (clitic == "nos" or clitic == "os") then
-- Final -s disappears: sintamos + nos -> sintámonos, sintamos + os -> sintámoos
cliticized_form = reaccented_form:gsub("s$", "") .. clitic
elseif base_slot == "imp_2p" and clitic == "os" then
-- Final -d disappears, which may cause an accent to be required:
-- haced + os -> haceos, sentid + os -> sentíos
if reaccented_form:find("id$") then
cliticized_form = reaccented_form:gsub("id$", "íos")
else
cliticized_form = reaccented_form:gsub("d$", "os")
end
else
cliticized_form = reaccented_form .. clitic
end
store_cliticized_form(clitic, formobj, cliticized_form)
end
end
end
-- Generate the combinations of verb form (infinitive, gerund or various imperatives) + clitic pronoun.
local function add_combined_forms(base)
for _, base_slot_and_clitics in ipairs(base.alternant_multiword_spec.verb_slot_combined_rows) do
local base_slot, clitics = unpack(base_slot_and_clitics)
add_forms_with_clitic(base, base_slot, clitics,
function(clitic, formobj, cliticized_form)
insert_form(base, base_slot .. "_comb_" .. clitic,
{form = cliticized_form, footnotes = formobj.footnotes})
end
)
end
for _, single_comb_slot_and_clitics in ipairs(base.alternant_multiword_spec.verb_slot_double_combined_rows) do
local single_comb_slot, clitics = unpack(single_comb_slot_and_clitics)
-- Handle le -> se transformation for double clitics
if single_comb_slot:match("_comb_lxx$") then
add_forms_with_clitic(base, single_comb_slot, clitics,
function(clitic, formobj, cliticized_form)
-- Only add se version for accusative clitics (lo/la/los/las)
if clitic:match("^l[aeo]") then
cliticized_form = cliticized_form:gsub("le" .. clitic .. "$", "se" .. clitic)
insert_form(base, single_comb_slot .. "_" .. clitic,
{form = cliticized_form, footnotes = formobj.footnotes})
end
end
)
end
add_forms_with_clitic(base, single_comb_slot, clitics,
function(clitic, formobj, cliticized_form)
insert_form(base, single_comb_slot .. "_" .. clitic,
{form = cliticized_form, footnotes = formobj.footnotes})
end
)
end
end
local function process_slot_overrides(base, do_basic, reflexive_only)
local overrides = reflexive_only and base.basic_reflexive_only_overrides or
do_basic and base.basic_overrides or base.combined_overrides
for slot, forms in pairs(overrides) do
local suppress_prefix = base.prefix == "" or check_stems_for_suppress_prefix(slot, forms)
add(base, slot, suppress_prefix and "" or base.prefix, forms, false, "allow overrides")
end
end
-- Prefix `form` with `clitic`, adding fixed text `between` between them. Add links as appropriate unless the user
-- requested no links. Check whether form already has brackets (as will be the case if the form has a fixed clitic).
local function add_clitic_to_form(base, clitic, between, form)
if base.alternant_multiword_spec.args.noautolinkverb then
return clitic .. between .. form
else
local clitic_pref = "[[" .. clitic .. "]]" .. between
if form:find("%[%[") then
return clitic_pref .. form
else
return clitic_pref .. "[[" .. form .. "]]"
end
end
end
-- Add a reflexive pronoun or fixed clitic, e.g. [[lo]], as appropriate to the base form that were generated.
-- `do_joined` means to do only the forms where the pronoun is joined to the end of the form; otherwise, do only the
-- forms where it is not joined and precedes the form.
local function add_reflexive_or_fixed_clitic_to_forms(base, do_reflexive, do_joined)
for _, slotaccel in ipairs(base.alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
local clitic
if not do_reflexive then
clitic = base.clitic
elseif slot:find("[123]") then
local persnum = slot:match("^.*_(.-)$")
clitic = person_number_to_reflexive_pronoun[persnum]
else
clitic = "se"
end
if base.forms[slot] then
if do_reflexive and slot:find("^pp_") or slot == "infinitive_linked" then
-- do nothing with reflexive past participles or with infinitive linked (handled at the end)
elseif slot:find("^neg_imp_") then
error("Internal error: Should not have forms set for negative imperative at this stage")
else
local slot_has_suffixed_clitic = slot:find("infinitive") or slot:find("gerund") or slot:find("^imp_")
-- Maybe generate non-reflexive parts and separated syntactic variants for use in {{es-verb form of}}.
-- See comment in add_slots() above `need_special_verb_form_of_slots`. Check for do_joined so we only
-- run this code once.
if do_reflexive and do_joined and base.alternant_multiword_spec.source_template == "es-verb form of" and
-- Skip personal variants of infinitives and gerunds so we don't think [[jambando]] is a
-- non-reflexive equivalent of [[jambándome]].
not slot:find("infinitive_") and not slot:find("gerund_") then
-- Clone the forms because we will be destructively modifying them just below, adding the reflexive
-- pronoun.
insert_forms(base, slot .. "_non_reflexive", mw.clone(base.forms[slot]))
if slot_has_suffixed_clitic then
insert_forms(base, slot .. "_variant", iut.map_forms(base.forms[slot], function(form)
return add_clitic_to_form(base, clitic, " ... ", form)
end))
end
end
if slot_has_suffixed_clitic then
if do_joined then
add_forms_with_clitic(base, slot, {clitic},
function(clitic, formobj, cliticized_form)
formobj.form = cliticized_form
end
)
end
elseif not do_joined then
-- Add clitic as separate word before all other forms.
for _, form in ipairs(base.forms[slot]) do
form.form = add_clitic_to_form(base, clitic, " ", form.form)
end
end
end
end
end
end
local function handle_infinitive_linked(base)
-- Compute linked versions of potential lemma slots, for use in {{es-verb}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs({"infinitive"}) do
insert_forms(base, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.lemma and rfind(base.linked_lemma, "%[%[") then
return base.linked_lemma
else
return form
end
end))
end
end
local function generate_negative_imperatives(base)
-- Copy subjunctives to negative imperatives, preceded by "no".
for _, persnum in ipairs(neg_imp_person_number_list) do
local from = "pres_sub_" .. persnum
local to = "neg_imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form)
if base.alternant_multiword_spec.args.noautolinkverb then
return "no " .. form
elseif form:find("%[%[") then
-- already linked, e.g. when reflexive
return "[[no]] " .. form
else
return "[[no]] [[" .. form .. "]]"
end
end))
end
end
-- Process specs given by the user using 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'.
local function process_addnote_specs(base)
for _, spec in ipairs(base.addnote_specs) do
for _, slot_spec in ipairs(spec.slot_specs) do
slot_spec = "^" .. slot_spec .. "$"
for slot, forms in pairs(base.forms) do
if rfind(slot, slot_spec) then
-- To save on memory, side-effect the existing forms.
for _, form in ipairs(forms) do
form.footnotes = iut.combine_footnotes(form.footnotes, spec.footnotes)
end
end
end
end
end
end
local function add_missing_links_to_forms(base)
-- Any forms without links should get them now. Redundant ones will be stripped later.
for slot, forms in pairs(base.forms) do
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
form.form = "[[" .. form.form .. "]]"
end
end
end
end
local function conjugate_verb(base)
add_present_indic(base)
add_present_subj(base)
add_imper(base)
add_finite_non_present(base)
add_non_finite_forms(base)
-- This should happen before add_combined_forms() so overrides of basic forms end up part of the combined forms.
process_slot_overrides(base, "do basic") -- do basic slot overrides
-- This should happen after process_slot_overrides() in case a derived slot is based on an override (as with the
-- imp_3s of [[dar]], [[estar]]).
copy_subjunctives_to_imperatives(base)
-- This should happen after process_slot_overrides() because overrides may have accents in them that need to be
-- removed. (This happens e.g. for most present indicative forms of [[ver]], which have accents in them for the
-- prefixed derived verbs, but the accents shouldn't be present in the base verb.)
remove_monosyllabic_accents(base)
if not base.nocomb then
add_combined_forms(base)
end
-- We need to add joined reflexives, then joined and non-joined clitics, then non-joined reflexives, so we get
-- [[házmelo]] but [[no]] [[me]] [[lo]] [[haga]].
if base.refl then
-- This should happen after remove_monosyllabic_accents() so the * marking the preservation of monosyllabic
-- accents doesn't end up in the middle of a word.
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", "do joined")
process_slot_overrides(base, "do basic", "do reflexive") -- do reflexive-only basic slot overrides
end
if base.clitic then
-- This should happen after reflexives are added.
add_reflexive_or_fixed_clitic_to_forms(base, false, "do joined")
add_reflexive_or_fixed_clitic_to_forms(base, false, false)
end
if base.refl then
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", false)
end
-- This should happen after add_reflexive_or_fixed_clitic_to_forms() so negative imperatives get the reflexive pronoun
-- and clitic in them.
generate_negative_imperatives(base)
if not base.nocomb then
process_slot_overrides(base, false) -- do combined slot overrides
end
-- This should happen before add_missing_links_to_forms() so that the comparison `form == base.lemma`
-- in handle_infinitive_linked() works correctly and compares unlinked forms to unlinked forms.
handle_infinitive_linked(base)
process_addnote_specs(base)
if not base.alternant_multiword_spec.args.noautolinkverb then
add_missing_links_to_forms(base)
end
end
local function parse_indicator_spec(angle_bracket_spec)
-- Store the original angle bracket spec so we can reconstruct the overall conj spec with the lemma(s) in them.
local base = {
angle_bracket_spec = angle_bracket_spec,
user_basic_overrides = {},
user_stems = {},
addnote_specs = {},
}
local function parse_err(msg)
error(msg .. ": " .. angle_bracket_spec)
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
parse_err("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
table.insert(footnotes, separated_group[j])
end
return footnotes
end
local inside = angle_bracket_spec:match("^<(.*)>$")
assert(inside)
if inside == "" then
return base
end
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = put.split_alternating_runs(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local first_element = dot_separated_group[1]
if first_element == "addnote" then
local spec_and_footnotes = fetch_footnotes(dot_separated_group)
if #spec_and_footnotes < 2 then
parse_err("Spec with 'addnote' should be of the form 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'")
end
local slot_spec = table.remove(spec_and_footnotes, 1)
local slot_spec_inside = rmatch(slot_spec, "^%[(.*)%]$")
if not slot_spec_inside then
parse_err("Internal error: slot_spec " .. slot_spec .. " should be surrounded with brackets")
end
local slot_specs = rsplit(slot_spec_inside, ",")
-- FIXME: Here, [[Module:it-verb]] called strip_spaces(). Generally we don't do this. Should we?
table.insert(base.addnote_specs, {slot_specs = slot_specs, footnotes = spec_and_footnotes})
elseif indicator_flags[first_element] then
if #dot_separated_group > 1 then
parse_err("No footnotes allowed with '" .. first_element .. "' spec")
end
if base[first_element] then
parse_err("Spec '" .. first_element .. "' specified twice")
end
base[first_element] = true
elseif rfind(first_element, ":") then
local colon_separated_groups = put.split_alternating_runs(dot_separated_group, "%s*:%s*")
local first_element = colon_separated_groups[1][1]
if #colon_separated_groups[1] > 1 then
parse_err("Can't attach footnotes directly to '" .. first_element .. "' spec; attach them to the " ..
"colon-separated values following the initial colon")
end
if overridable_stems[first_element] then
if base.user_stems[first_element] then
parse_err("Overridable stem '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_stems[first_element] = overridable_stems[first_element](colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes})
else -- assume a basic override; we validate further later when the possible slots are available
if base.user_basic_overrides[first_element] then
parse_err("Basic override '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_basic_overrides[first_element] = allow_multiple_values_for_override(
colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes},
"add monosyllabic asterisk"
)
end
else
local comma_separated_groups = put.split_alternating_runs(dot_separated_group, "%s*,%s*")
for j = 1, #comma_separated_groups do
local alt = comma_separated_groups[j][1]
if not vowel_alternants[alt] then
if #comma_separated_groups == 1 then
parse_err("Unrecognized spec or vowel alternant '" .. alt .. "'")
else
parse_err("Unrecognized vowel alternant '" .. alt .. "'")
end
end
if base.vowel_alt then
for _, existing_alt in ipairs(base.vowel_alt) do
if existing_alt.form == alt then
parse_err("Vowel alternant '" .. alt .. "' specified twice")
end
end
else
base.vowel_alt = {}
end
table.insert(base.vowel_alt, {form = alt, footnotes = fetch_footnotes(comma_separated_groups[j])})
end
end
end
return base
end
-- Normalize all lemmas, substituting the pagename for blank lemmas and adding links to multiword lemmas.
local function normalize_all_lemmas(alternant_multiword_spec, pagename)
-- (1) Add links to all before and after text. Remember the original text so we can reconstruct the verb spec later.
if not alternant_multiword_spec.args.noautolinktext then
iut.add_links_to_before_and_after_text(alternant_multiword_spec, "remember original")
end
-- (2) Remove any links from the lemma, but remember the original form
-- so we can use it below in the 'lemma_linked' form.
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.lemma == "" then
base.lemma = pagename
end
base.user_specified_lemma = base.lemma
base.lemma = m_links.remove_links(base.lemma)
local refl_verb, clitic = rmatch(base.lemma, "^(.-)(l[aeo]s?)$")
if not refl_verb then
refl_verb, clitic = base.lemma, nil
end
local verb, refl = rmatch(refl_verb, "^(.-)(se)$")
if not verb then
verb, refl = refl_verb, nil
end
base.user_specified_verb = verb
base.refl = refl
base.clitic = clitic
if base.refl and base.clitic then
-- We have to parse the verb suffix to see how to construct the base verb; e.g.
-- abrírsela -> abrir but oírsela -> oír. We parse the verb suffix again in all cases
-- in detect_indicator_spec(), after splitting off the prefix of irrregular verbs.
local actual_verb
local inf_stem, suffix = rmatch(base.user_specified_verb, "^(.*)([aáeéií]r)$")
if not inf_stem then
error("Unrecognized infinitive: " .. base.user_specified_verb)
end
if suffix == "ír" and inf_stem:find("[aeo]$") then
-- accent on suffix should remain
base.verb = base.user_specified_verb
else
base.verb = inf_stem .. com.remove_accent_from_syllable(suffix)
end
else
base.verb = base.user_specified_verb
end
local linked_lemma
if alternant_multiword_spec.args.noautolinkverb or base.user_specified_lemma:find("%[%[") then
linked_lemma = base.user_specified_lemma
elseif base.refl or base.clitic then
-- Reconstruct the linked lemma with separate links around base verb, reflexive pronoun and clitic.
linked_lemma = base.user_specified_verb == base.verb and "[[" .. base.user_specified_verb .. "]]" or
"[[" .. base.verb .. "|" .. base.user_specified_verb .. "]]"
linked_lemma = linked_lemma .. (refl and "[[" .. refl .. "]]" or "") ..
(clitic and "[[" .. clitic .. "]]" or "")
else
-- Add links to the lemma so the user doesn't specifically need to, since we preserve
-- links in multiword lemmas and include links in non-lemma forms rather than allowing
-- the entire form to be a link.
linked_lemma = iut.add_links(base.user_specified_lemma)
end
base.linked_lemma = linked_lemma
end)
end
local function construct_stems(base)
local stems = base.stems
stems.pres_unstressed = stems.pres_unstressed or base.inf_stem
stems.pres_stressed = stems.pres_stressed or
-- If no_pres_stressed given, pres_stressed stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
base.vowel_alt or
base.inf_stem
stems.pres1_and_sub = stems.pres1_and_sub or
-- If no_pres_stressed given, the entire subjunctive is missing.
base.no_pres_stressed and {} or
-- If no_pres1_and_sub given, pres1 and entire subjunctive are missing.
base.no_pres1_and_sub and {} or
nil
stems.pres1 = stems.pres1 or stems.pres1_and_sub or stems.pres_stressed
stems.impf = stems.impf or base.inf_stem
stems.pret = stems.pret or base.inf_stem
stems.pret_conj = stems.pret_conj or base.conj
stems.fut = stems.fut or base.inf_stem .. base.conj
stems.cond = stems.cond or stems.fut
stems.pres_sub_stressed = stems.pres_sub_stressed or stems.pres1
stems.pres_sub_unstressed = stems.pres_sub_unstressed or stems.pres1_and_sub or stems.pres_unstressed
stems.impf_sub_ra = stems.impf_sub_ra or stems.pret
stems.impf_sub_se = stems.impf_sub_se or stems.pret
stems.fut_sub = stems.fut_sub or stems.pret
stems.pp = stems.pp or base.conj == "ar" and
combine_stem_ending(base, "pp_ms", base.inf_stem, "ad", "is combining ending") or
-- use combine_stem_ending esp. so we get reído, caído, etc.
combine_stem_ending(base, "pp_ms", base.inf_stem, "id", "is combining ending")
end
-- Make a list of the slots given in `list1` and optionally `list2`, with `prefix` added to the beginning of each slot
-- name. The elements of each list are of the form {SLOT, ACCEL}. Used for error messages.
local function construct_possible_slots(list1, list2, prefix)
list2 = list2 or {}
prefix = prefix or ""
local slots = {}
local function insert_list_slots(list)
for _, slotaccel in ipairs(list) do
local slot, accel = unpack(slotaccel)
table.insert(slots, prefix .. slot)
end
end
insert_list_slots(list1)
insert_list_slots(list2)
return m_table.serialCommaJoin(slots)
end
local function detect_indicator_spec(base)
base.forms = {}
base.non_reflexive_forms = {}
base.stems = {}
if (base.only3s and 1 or 0) + (base.only3sp and 1 or 0) + (base.only3p and 1 or 0) > 1 then
error("Only one of 'only3s', 'only3sp' and 'only3p' can be specified")
end
base.basic_overrides = {}
base.basic_reflexive_only_overrides = {}
base.combined_overrides = {}
if not base.no_built_in then
for _, built_in_conj in ipairs(built_in_conjugations) do
if type(built_in_conj.match) == "function" then
base.prefix, base.non_prefixed_verb = built_in_conj.match(base.verb)
elseif built_in_conj.match:find("^%^") and rsub(built_in_conj.match, "^%^", "") == base.verb then
-- begins with ^, for exact match, and matches
base.prefix, base.non_prefixed_verb = "", base.verb
else
base.prefix, base.non_prefixed_verb = rmatch(base.verb, "^(.*)(" .. built_in_conj.match .. ")$")
end
if base.prefix then
-- we found a built-in verb
base.irreg_verb = true
for stem, forms in pairs(built_in_conj.forms) do
if stem:find("^refl_") then
stem = stem:gsub("^refl_", "")
if not base.alternant_multiword_spec.verb_slots_basic_map[stem] then
error("Internal error: setting for 'refl_" .. stem .. "' does not refer to a basic verb slot")
end
base.basic_reflexive_only_overrides[stem] = forms
elseif base.alternant_multiword_spec.verb_slots_basic_map[stem] then
-- an individual form override of a basic form
base.basic_overrides[stem] = forms
elseif base.alternant_multiword_spec.verb_slots_combined_map[stem] then
-- an individual form override of a combined form
base.combined_overrides[stem] = forms
else
base.stems[stem] = forms
end
end
break
end
end
end
-- Override built-in-verb stems and overrides with user-specified ones.
for stem, values in pairs(base.user_stems) do
base.stems[stem] = values
end
for override, values in pairs(base.user_basic_overrides) do
if override:find("^refl_") then
if not base.refl then
error("Can't set reflexive-only override '" .. override .. "' on a non-reflexive verb")
end
override = override:gsub("^refl_", "")
if not base.alternant_multiword_spec.verb_slots_basic_map[override] then
error("Unrecognized reflexive-only override 'refl_" .. override .. "': possible slots are " ..
construct_possible_slots(base.alternant_multiword_spec.verb_slots_basic, nil, "refl_"))
end
base.basic_reflexive_only_overrides[override] = values
elseif base.alternant_multiword_spec.verb_slots_basic_map[override] then
base.basic_overrides[override] = values
elseif base.alternant_multiword_spec.verb_slots_combined_map[override] then
base.combined_overrides[override] = values
else
error("Unrecognized override '" .. override .. "': possible slots are " ..
construct_possible_slots(base.alternant_multiword_spec.verb_slots_basic,
base.alternant_multiword_spec.verb_slots_combined))
end
end
base.prefix = base.prefix or ""
base.non_prefixed_verb = base.non_prefixed_verb or base.verb
local inf_stem, suffix = rmatch(base.non_prefixed_verb, "^(.*)([aeií]r)$")
if not inf_stem then
error("Unrecognized infinitive: " .. base.verb)
end
base.inf_stem = inf_stem
suffix = suffix == "ír" and "ir" or suffix
base.conj = suffix
base.frontback = suffix == "ar" and "back" or "front"
if base.stems.vowel_alt then -- built-in verb with specified vowel alternation
if base.vowel_alt then
error(base.verb .. " is a recognized built-in verb, and should not have vowel alternations specified with it")
end
base.vowel_alt = iut.convert_to_general_list_form(base.stems.vowel_alt)
end
-- Propagate built-in-verb indicator flags to `base` and combine with user-specified flags.
for indicator_flag, _ in pairs(indicator_flags) do
base[indicator_flag] = base[indicator_flag] or base.stems[indicator_flag]
end
-- Convert vowel alternation indicators into stems.
if base.vowel_alt then
for _, altform in ipairs(base.vowel_alt) do
altform.alt = altform.form -- save original indicator
local alt = altform.alt
if base.conj == "ir" then
local raising = (
alt == "ie-i" or alt == "ye-i" or alt == "ue-u" or alt == "i" or alt == "í" or alt == "ú"
)
if base.stems.raising_conj == nil then
base.stems.raising_conj = raising
elseif base.stems.raising_conj ~= raising then
error("Can't currently support a mixture of raising (e.g. 'ie-i') and non-raising (e.g. 'ie') vowel alternations in -ir verbs")
end
end
if alt == "+" then
altform.form = base.inf_stem
else
local normalized_alt = alt
if alt == "ie-i" or alt == "ye-i" or alt == "ue-u" then
if base.conj ~= "ir" then
error("Vowel alternation '" .. alt .. "' only supported with -ir verbs")
end
-- ie-i is like i except for the vowel raising before i+V, similarly for ye-i, ue-u,
-- so convert appropriately.
normalized_alt = alt == "ie-i" and "ie" or alt == "ye-i" and "ye" or "ue"
end
local ret = com.apply_vowel_alternation(base.inf_stem, normalized_alt)
if ret.err then
error("To use '" .. alt .. "', present stem '" .. base.inf_stem .. "' " .. ret.err)
end
altform.form = ret.ret
end
end
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
-- Propagate some settings up; some are used internally, others by [[Module:es-headword]].
iut.map_word_specs(alternant_multiword_spec, function(base)
-- Internal indicator flags. Do these before calling detect_indicator_spec() because add_slots() uses them.
for _, prop in ipairs { "refl", "clitic" } do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
base.alternant_multiword_spec = alternant_multiword_spec
-- If reflexive or fixed clitic, don't include combined forms.
alternant_multiword_spec.nocomb = alternant_multiword_spec.nocomb or base.clitic or base.refl
end)
add_slots(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
base.nocomb = alternant_multiword_spec.args.nocomb
detect_indicator_spec(base)
-- User-specified indicator flags. Do these after calling detect_indicator_spec() because the latter may set these
-- indicators for built-in verbs.
for prop, _ in pairs(indicator_flags) do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
construct_stems(base)
end)
end
local function add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
local function insert_ann(anntype, value)
m_table.insertIfNot(alternant_multiword_spec.annotation[anntype], value)
end
local function insert_cat(cat, also_when_multiword)
-- Don't place multiword terms in categories like 'Spanish verbs ending in -ar' to avoid spamming the
-- categories with such terms.
if also_when_multiword or not multiword_lemma then
-- m_table.insertIfNot(alternant_multiword_spec.categories, "Spanish " .. cat)
end
end
if check_for_red_links and alternant_multiword_spec.source_template == "es-conj" and multiword_lemma then
for _, slot_and_accel in ipairs(alternant_multiword_spec.all_verb_slots) do
local slot = slot_and_accel[1]
local forms = base.forms[slot]
local must_break = false
if forms then
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
local title = mw.title.new(form.form)
if title and not title.exists then
-- insert_cat("verbs with red links in their inflection tables")
must_break = true
break
end
end
end
end
if must_break then
break
end
end
end
insert_cat("verbs ending in -" .. base.conj)
if base.irreg_verb then
insert_ann("irreg", "irregular")
-- insert_cat("irregular verbs")
else
insert_ann("irreg", "regular")
end
if base.only3s then
insert_ann("defective", "impersonal")
-- insert_cat("impersonal verbs")
elseif base.only3sp then
insert_ann("defective", "third-person only")
-- insert_cat("third-person-only verbs")
elseif base.only3p then
insert_ann("defective", "third-person plural only")
-- insert_cat("third-person-plural-only verbs")
elseif base.no_pres_stressed or base.no_pres1_and_sub then
insert_ann("defective", "defective")
-- insert_cat("defective verbs")
else
insert_ann("defective", "regular")
end
if base.clitic then
-- insert_cat("verbs with lexical clitics")
end
if base.refl then
-- insert_cat("reflexive verbs")
end
if not base.vowel_alt then
insert_ann("vowel_alt", "non-alternating")
else
local inf_stem = base.inf_stem:gsub("[gq]u$", "x")
for _, alt in ipairs(base.vowel_alt) do
if alt.alt == "+" then
insert_ann("vowel_alt", "non-alternating")
else
local desc
if alt.alt == "ue" and rfind(inf_stem, "u" .. C .. "*$") then
desc = "u-ue alternation" -- jugar
elseif alt.alt == "ie" and rfind(inf_stem, "i" .. C .. "*$") then
desc = "i-ie alternation" -- adquirir
elseif alt.alt == "í" and rfind(inf_stem, "e" .. C .. "*$") then
desc = "e-í alternation" -- reír, freír, etc.
else
desc = vowel_alternant_to_desc[alt.alt] .. " alternation"
end
insert_ann("vowel_alt", desc)
insert_cat("verbs with " .. desc)
end
end
end
local cons_alt = base.stems.cons_alt
if cons_alt == nil then
if base.conj == "ar" then
if base.inf_stem:find("z$") then
cons_alt = "c-z"
elseif base.inf_stem:find("ç$") then
cons_alt = "c-ç"
elseif base.inf_stem:find("c$") then
cons_alt = "c-qu"
elseif base.inf_stem:find("g$") then
cons_alt = "g-gu"
elseif base.inf_stem:find("gu$") then
cons_alt = "gu-gü"
end
else
if base.no_pres_stressed or base.no_pres1_and_sub then
cons_alt = nil -- no c-zc alternation in balbucir or arrecir
elseif rfind(base.inf_stem, V .. "c$") then
cons_alt = "c-zc"
elseif base.inf_stem:find("sc$") then
cons_alt = "hard-soft"
elseif base.inf_stem:find("c$") then
cons_alt = "c-z"
elseif base.inf_stem:find("qu$") then
cons_alt = "c-qu"
elseif base.inf_stem:find("g$") then
cons_alt = "g-j"
elseif base.inf_stem:find("gu$") then
cons_alt = "g-gu"
elseif base.inf_stem:find("gü$") then
cons_alt = "gu-gü"
end
end
end
if cons_alt then
local desc = cons_alt .. " alternation"
insert_ann("cons_alt", desc)
insert_cat("verbs with " .. desc)
else
insert_ann("cons_alt", "non-alternating")
end
end
-- Compute the categories to add the verb to, as well as the annotation to display in the
-- conjugation title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
local ann = {}
alternant_multiword_spec.annotation = ann
ann.irreg = {}
ann.defective = {}
ann.vowel_alt = {}
ann.cons_alt = {}
local multiword_lemma = false
for _, form in ipairs(alternant_multiword_spec.forms.infinitive) do
if form.form:find(" ") then
multiword_lemma = true
break
end
end
iut.map_word_specs(alternant_multiword_spec, function(base)
add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
end)
local ann_parts = {}
local irreg = table.concat(ann.irreg, " or ")
if irreg ~= "" and irreg ~= "regular" then
table.insert(ann_parts, irreg)
end
local defective = table.concat(ann.defective, " or ")
if defective ~= "" and defective ~= "regular" then
table.insert(ann_parts, defective)
end
local vowel_alt = table.concat(ann.vowel_alt, " or ")
if vowel_alt ~= "" and vowel_alt ~= "non-alternating" then
table.insert(ann_parts, vowel_alt)
end
local cons_alt = table.concat(ann.cons_alt, " or ")
if cons_alt ~= "" and cons_alt ~= "non-alternating" then
table.insert(ann_parts, cons_alt)
end
alternant_multiword_spec.annotation = table.concat(ann_parts, "; ")
end
local function show_forms(alternant_multiword_spec)
local lemmas = alternant_multiword_spec.forms.infinitive
alternant_multiword_spec.lemmas = lemmas -- save for later use in make_table()
local reconstructed_verb_spec = iut.reconstruct_original_spec(alternant_multiword_spec)
-- Initialize the footnotes with those for the future subjunctive and maybe the pres subjunctive
-- voseo usage. In the latter case, we only do it if there is a distinct pres subjunctive voseo form.
local function create_footnote_obj()
local obj = iut.create_footnote_obj()
iut.get_footnote_text({fut_sub_note}, obj)
-- Compute whether the tuteo and voseo variants are different, for each voseo variant.
-- We use this later in make_table().
for _, slot in ipairs({"pres_2s", "pres_sub_2s", "imp_2s"}) do
alternant_multiword_spec["separate_" .. slot .. "v"] = false
iut.map_word_specs(alternant_multiword_spec, function(base)
if not m_table.deepEquals(base.forms[slot], base.forms[slot .. "v"]) then
alternant_multiword_spec["separate_" .. slot .. "v"] = true
end
end)
end
if alternant_multiword_spec.separate_pres_sub_2sv then
iut.get_footnote_text({pres_sub_voseo_note}, obj)
end
return obj
end
local function transform_accel_obj(slot, formobj, accel_obj)
-- No accelerators for negative imperatives, which are always multiword and derived directly from the
-- present subjunctive.
if slot:find("^neg_imp") then
return nil
end
if accel_obj then
if slot:find("^pp_") then
accel_obj.form = slot
elseif slot == "gerund" then
accel_obj.form = "gerund-" .. reconstructed_verb_spec
else
accel_obj.form = "verb-form-" .. reconstructed_verb_spec
end
end
return accel_obj
end
local props = {
lang = lang,
lemmas = lemmas,
create_footnote_obj = create_footnote_obj,
transform_accel_obj = transform_accel_obj,
}
props.slot_list = alternant_multiword_spec.verb_slots_basic
iut.show_forms(alternant_multiword_spec.forms, props)
alternant_multiword_spec.footnote_basic = alternant_multiword_spec.forms.footnote
props.create_footnote_obj = nil
props.slot_list = alternant_multiword_spec.verb_slots_combined
iut.show_forms(alternant_multiword_spec.forms, props)
alternant_multiword_spec.footnote_combined = alternant_multiword_spec.forms.footnote
end
local notes_template = [=[
<div class="roa-footnote-outer-div" style="width:100%;">
<div class="roa-footnote-inner-div">
{footnote}
</div></div>
]=]
local pres_2sv_template = '<sup><sup>tú</sup></sup><br />{pres_2sv}<sup><sup>vos</sup></sup>'
local pres_sub_2sv_template = '<sup><sup>tú</sup></sup><br />{pres_sub_2sv}<sup><sup>vos<sup class="roa-red-superscript">2</sup></sup></sup>'
local imp_2sv_template = '<sup><sup>tú</sup></sup><br />{imp_2sv}<sup><sup>vos</sup></sup>'
local basic_table = [=[
{description}<div class="NavFrame">
<div class="NavHead" align=center> Conjugation of {title} (See [[Appendix:Spanish verbs]])</div>
<div class="NavContent">
{\op}| class="roa-inflection-table"
|-
! colspan="3" class="roa-nonfinite-header" | <span title="infinitivo">ကြိယာဟွံကၠောံ</span>
| colspan="5" | {infinitive}
|-
! colspan="3" class="roa-nonfinite-header" | <span title="gerundio">ကြိယာစၞးနာမ်</span>
| colspan="5" | {gerund}
|-
! rowspan="3" colspan="2" class="roa-nonfinite-header" | <span title="participio (pasado)">past participle</span>
| colspan="2" class="roa-nonfinite-header" |
! colspan="2" class="roa-nonfinite-header" | <span title="masculino">ပုလ္လိၚ်</span>
! colspan="2" class="roa-nonfinite-header" | <span title="femenino">ဣတ္တိလိၚ်</span>
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဨကဝုစ်
| colspan="2" | {pp_ms}
| colspan="2" | {pp_fs}
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဗဟုဝစ်
| colspan="2" | {pp_mp}
| colspan="2" | {pp_fp}
|-
! colspan="2" rowspan="2" class="roa-person-number-header" |
! colspan="3" class="roa-person-number-header" | ကိုန်ဨကဝုစ်
! colspan="3" class="roa-person-number-header" | ကိုန်ဗဟုဝစ်
|-
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၁
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၂
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၃
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၁
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၂
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၃
|-{reflexive_non_finite_clause}
! rowspan="6" class="roa-indicative-left-rail" | <span title="ပရေၚ်မပ္ညုၚ်">indicative</span>
! class="roa-native-person-number-header" |
! class="roa-native-person-number-header" | yo
! class="roa-native-person-number-header" | tú<br />vos
! class="roa-native-person-number-header" | él/ella/ello<br />usted
! class="roa-native-person-number-header" | nosotros<br />nosotras
! class="roa-native-person-number-header" | vosotros<br />vosotras
! class="roa-native-person-number-header" | ellos/ellas<br />ustedes
|-
! class="roa-finite-header" | <span title="presente de indicativo">present</span>
| {pres_1s}
| {pres_2s}{pres_2sv_text}
| {pres_3s}
| {pres_1p}
| {pres_2p}
| {pres_3p}
|-
! class="roa-finite-header" | <span title="pretérito imperfecto (copréterito)">imperfect</span>
| {impf_1s}
| {impf_2s}
| {impf_3s}
| {impf_1p}
| {impf_2p}
| {impf_3p}
|-
! class="roa-finite-header" | <span title="pretérito perfecto simple (pretérito indefinido)">preterite</span>
| {pret_1s}
| {pret_2s}
| {pret_3s}
| {pret_1p}
| {pret_2p}
| {pret_3p}
|-
! class="roa-finite-header" | <span title="futuro simple (futuro imperfecto)">future</span>
| {fut_1s}
| {fut_2s}
| {fut_3s}
| {fut_1p}
| {fut_2p}
| {fut_3p}
|-
! class="roa-finite-header" | <span title="condicional simple (pospretérito de modo indicativo)">conditional</span>
| {cond_1s}
| {cond_2s}
| {cond_3s}
| {cond_1p}
| {cond_2p}
| {cond_3p}
|-
! class="roa-person-number-header" style="height:.75em" colspan="8" |
|-
! rowspan="5" class="roa-subjunctive-left-rail" | <span title="subjuntivo">အရေဝ်နိဒါန်</span>
! class="roa-native-person-number-header" |
! class="roa-native-person-number-header" | yo
! class="roa-native-person-number-header" | tú<br />vos
! class="roa-native-person-number-header" | él/ella/ello<br />usted
! class="roa-native-person-number-header" | nosotros<br />nosotras
! class="roa-native-person-number-header" | vosotros<br />vosotras
! class="roa-native-person-number-header" | ellos/ellas<br />ustedes
|-
! class="roa-finite-header" | <span title="presente de subjuntivo">present</span>
| {pres_sub_1s}
| {pres_sub_2s}{pres_sub_2sv_text}
| {pres_sub_3s}
| {pres_sub_1p}
| {pres_sub_2p}
| {pres_sub_3p}
|-
! class="roa-finite-header" | <span title="pretérito imperfecto de subjuntivo">imperfect</span><br />(ra)
| {impf_sub_ra_1s}
| {impf_sub_ra_2s}
| {impf_sub_ra_3s}
| {impf_sub_ra_1p}
| {impf_sub_ra_2p}
| {impf_sub_ra_3p}
|-
! class="roa-finite-header" | <span title="pretérito imperfecto de subjuntivo">imperfect</span><br />(se)
| {impf_sub_se_1s}
| {impf_sub_se_2s}
| {impf_sub_se_3s}
| {impf_sub_se_1p}
| {impf_sub_se_2p}
| {impf_sub_se_3p}
|-
! class="roa-finite-header" | <span title="futuro simple de subjuntivo (futuro de subjuntivo)">future</span><sup class="roa-red-superscript">1</sup>
| {fut_sub_1s}
| {fut_sub_2s}
| {fut_sub_3s}
| {fut_sub_1p}
| {fut_sub_2p}
| {fut_sub_3p}
|-
! class="roa-person-number-header" style="height:.75em" colspan="8" |
|-
! rowspan="6" class="roa-imperative-left-rail" | <span title="ဒုၚ်တဲ">imperative</span>
! class="roa-native-person-number-header" |
! class="roa-native-person-number-header" | —
! class="roa-native-person-number-header" | tú<br />vos
! class="roa-native-person-number-header" | usted
! class="roa-native-person-number-header" | nosotros<br />nosotras
! class="roa-native-person-number-header" | vosotros<br />vosotras
! class="roa-native-person-number-header" | ustedes
|-
! class="roa-finite-header" | <span title="ဒုၚ်တဲမပါဲဗလေတ်ဟွံဗၠး">affirmative</span>
|
| {imp_2s}{imp_2sv_text}
| {imp_3s}
| {imp_1p}
| {imp_2p}
| {imp_3p}
|-
! class="roa-finite-header" | <span title="မကယျာန်ပါဲမပါဲဗလေတ်ဟွံဗၠး">negative</span>
|
| {neg_imp_2s}
| {neg_imp_3s}
| {neg_imp_1p}
| {neg_imp_2p}
| {neg_imp_3p}
|{\cl}{notes_clause}</div></div>
]=]
local reflexive_non_finite_template = [=[
! rowspan="3" class="roa-nonfinite-header" | ပူဂဵုကၠောံမာန်ဟွံသေၚ်
! class="roa-native-person-number-header" |
! class="roa-native-person-number-header" | yo
! class="roa-native-person-number-header" | tú<br />vos
! class="roa-native-person-number-header" | él/ella/ello<br />usted
! class="roa-native-person-number-header" | nosotros<br />nosotras
! class="roa-native-person-number-header" | vosotros<br />vosotras
! class="roa-native-person-number-header" | ellos/ellas<br />ustedes
|-
! class="roa-finite-header" | <span title="infinitivo">ကြိယာဟွံကၠောံ</span>
| {infinitive_1s}
| {infinitive_2s}
| {infinitive_3s}
| {infinitive_1p}
| {infinitive_2p}
| {infinitive_3p}
|-
! class="roa-finite-header" | <span title="gerundio">ကြိယာစၞးနာမ်</span>
| {gerund_1s}
| {gerund_2s}
| {gerund_3s}
| {gerund_1p}
| {gerund_2p}
| {gerund_3p}
|-
! class="roa-person-number-header" style="height:.75em" colspan="8" |
|-]=]
local combined_form_combined_tu_vos_template = [=[
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဨကဝုစ် {tuteo}<i>/</i>{voseo} ပါဲဗလေတ်ဟွံဗၠး {imp_2s}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_2s_comb_me}
| {imp_2s_comb_te}
| {imp_2s_comb_le}
| {imp_2s_comb_nos}
| ''not used''
| {imp_2s_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_2s_comb_me}
| {imp_2s_comb_te}
| {imp_2s_comb_lo}, {imp_2s_comb_la}
| {imp_2s_comb_nos}
| ''not used''
| {imp_2s_comb_los}, {imp_2s_comb_las}
|-]=]
local combined_form_separate_tu_vos_template = [=[
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဨကဝုစ် {tuteo} ပါဲဗလေတ်ဟွံဗၠး {imp_2s}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_2s_comb_me}
| {imp_2s_comb_te}
| {imp_2s_comb_le}
| {imp_2s_comb_nos}
| ''not used''
| {imp_2s_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_2s_comb_me}
| {imp_2s_comb_te}
| {imp_2s_comb_lo}, {imp_2s_comb_la}
| {imp_2s_comb_nos}
| ''not used''
| {imp_2s_comb_los}, {imp_2s_comb_las}
|-
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဨကဝုစ် {voseo} ပါဲဗလေတ်ဟွံဗၠး {imp_2sv}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_2sv_comb_me}
| {imp_2sv_comb_te}
| {imp_2sv_comb_le}
| {imp_2sv_comb_nos}
| ''not used''
| {imp_2sv_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_2sv_comb_me}
| {imp_2sv_comb_te}
| {imp_2sv_comb_lo}, {imp_2sv_comb_la}
| {imp_2sv_comb_nos}
| ''not used''
| {imp_2sv_comb_los}, {imp_2sv_comb_las}
|-]=]
local combined_form_table = [=[
{description}<div class="NavFrame">
<div class="NavHead" align=center> Selected combined forms of {title}</div>
<div class="NavContent">
These forms are generated automatically and may not actually be used. Pronoun usage varies by region.
{\op}| class="inflection-table es-inflection-table"
|-
! colspan="2" rowspan="2" class="roa-person-number-header" |
! colspan="3" class="roa-person-number-header" | ကိုန်ဨကဝုစ်
! colspan="3" class="roa-person-number-header" | ကိုန်ဗဟုဝစ်
|-
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၁
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၂
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၃
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၁
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၂
! class="roa-person-number-header" | ပူဂဵုမရနုက်ကဵု ၃
|-
! rowspan="2" class="roa-combined-with-infinitive" | မၞုံကဵုကြိယာဟွံကၠောံ {infinitive}
! class="roa-finite-header" | ပြကမ္မကာရက
| {infinitive_comb_me}
| {infinitive_comb_te}
| {infinitive_comb_le}, {infinitive_comb_se}
| {infinitive_comb_nos}
| {infinitive_comb_os}
| {infinitive_comb_les}, {infinitive_comb_se}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {infinitive_comb_me}
| {infinitive_comb_te}
| {infinitive_comb_lo}, {infinitive_comb_la}, {infinitive_comb_se}
| {infinitive_comb_nos}
| {infinitive_comb_os}
| {infinitive_comb_los}, {infinitive_comb_las}, {infinitive_comb_se}
|-
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-gerund" | မၞုံကဵုကြိယာစၞးနာမ် {gerund}
! class="roa-finite-header" | ပြကမ္မကာရက
| {gerund_comb_me}
| {gerund_comb_te}
| {gerund_comb_le}, {gerund_comb_se}
| {gerund_comb_nos}
| {gerund_comb_os}
| {gerund_comb_les}, {gerund_comb_se}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {gerund_comb_me}
| {gerund_comb_te}
| {gerund_comb_lo}, {gerund_comb_la}, {gerund_comb_se}
| {gerund_comb_nos}
| {gerund_comb_os}
| {gerund_comb_los}, {gerund_comb_las}, {gerund_comb_se}
|-{tu_vos_clause}
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဨကဝုစ်ပါဲဗလေတ်ဟွံဗၠး {imp_3s}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_3s_comb_me}
| ''not used''
| {imp_3s_comb_le}, {imp_3s_comb_se}
| {imp_3s_comb_nos}
| ''not used''
| {imp_3s_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_3s_comb_me}
| ''not used''
| {imp_3s_comb_lo}, {imp_3s_comb_la}, {imp_3s_comb_se}
| {imp_3s_comb_nos}
| ''not used''
| {imp_3s_comb_los}, {imp_3s_comb_las}
|-
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုပထမကိုန်ဗဟုဝစ်ပါဲဗလေတ်ဟွံဗၠး {imp_1p}
! class="roa-finite-header" | ပြကမ္မကာရက
| ''not used''
| {imp_1p_comb_te}
| {imp_1p_comb_le}
| {imp_1p_comb_nos}
| {imp_1p_comb_os}
| {imp_1p_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| ''not used''
| {imp_1p_comb_te}
| {imp_1p_comb_lo}, {imp_1p_comb_la}
| {imp_1p_comb_nos}
| {imp_1p_comb_os}
| {imp_1p_comb_los}, {imp_1p_comb_las}
|-
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဗဟုဝစ်ပါဲဗလေတ်ဟွံဗၠး {imp_2p}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_2p_comb_me}
| ''not used''
| {imp_2p_comb_le}
| {imp_2p_comb_nos}
| {imp_2p_comb_os}
| {imp_2p_comb_les}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_2p_comb_me}
| ''not used''
| {imp_2p_comb_lo}, {imp_2p_comb_la}
| {imp_2p_comb_nos}
| {imp_2p_comb_os}
| {imp_2p_comb_los}, {imp_2p_comb_las}
|-
! class="roa-person-number-header" style="height:.35em" colspan="8" |
|-
! rowspan="2" class="roa-combined-with-imperative" | မၞုံကဵုပူဂဵုဒုတိယကိုန်ဗဟုဝစ်ပါဲဗလေတ်ဟွံဗၠး {imp_3p}
! class="roa-finite-header" | ပြကမ္မကာရက
| {imp_3p_comb_me}
| ''not used''
| {imp_3p_comb_le}
| {imp_3p_comb_nos}
| ''not used''
| {imp_3p_comb_les}, {imp_3p_comb_se}
|-
! class="roa-finite-header" | ကမ္မကာရက
| {imp_3p_comb_me}
| ''not used''
| {imp_3p_comb_lo}, {imp_3p_comb_la}
| {imp_3p_comb_nos}
| ''not used''
| {imp_3p_comb_los}, {imp_3p_comb_las}, {imp_3p_comb_se}
|{\cl}{notes_clause}</div></div>
]=]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
forms.title = link_term(alternant_multiword_spec.lemmas[1].form)
if alternant_multiword_spec.annotation ~= "" then
forms.title = forms.title .. " (" .. alternant_multiword_spec.annotation .. ")"
end
forms.description = ""
-- Format the basic table.
forms.tuteo = tuteo_link
forms.voseo = voseo_link
forms.footnote = alternant_multiword_spec.footnote_basic
forms.reflexive_non_finite_clause = alternant_multiword_spec.refl and m_string_utilities.format(reflexive_non_finite_template, forms) or ""
forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or ""
-- The separate_* values are computed in show_forms().
forms.pres_2sv_text = alternant_multiword_spec.separate_pres_2sv and m_string_utilities.format(pres_2sv_template, forms) or ""
forms.pres_sub_2sv_text = alternant_multiword_spec.separate_pres_sub_2sv and m_string_utilities.format(pres_sub_2sv_template, forms) or ""
forms.imp_2sv_text = alternant_multiword_spec.separate_imp_2sv and m_string_utilities.format(imp_2sv_template, forms) or ""
local formatted_basic_table = m_string_utilities.format(basic_table, forms)
-- Format the combined table.
local formatted_combined_table
if alternant_multiword_spec.refl or alternant_multiword_spec.args.nocomb or alternant_multiword_spec.clitic then
formatted_combined_table = ""
else
forms.footnote = alternant_multiword_spec.footnote_combined
forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or ""
-- separate_imp_2sv is computed in show_forms().
local tu_vos_template = alternant_multiword_spec.separate_imp_2sv and combined_form_separate_tu_vos_template or combined_form_combined_tu_vos_template
forms.tu_vos_clause = m_string_utilities.format(tu_vos_template, forms)
formatted_combined_table = m_string_utilities.format(combined_form_table, forms)
end
-- Paste them together.
return require("Module:TemplateStyles")("Module:roa-verb/style.css") .. formatted_basic_table .. formatted_combined_table
end
-- Externally callable function to parse and conjugate a verb given user-specified arguments.
-- Return value is WORD_SPEC, an object where the conjugated forms are in `WORD_SPEC.forms`
-- for each slot. If there are no values for a slot, the slot key will be missing. The value
-- for a given slot is a list of objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(args, source_template, headword_head, double_combined_forms_to_include)
local PAGENAME = mw.loadData("Module:headword/data").pagename
local function in_template_space()
return mw.title.getCurrentTitle().nsText == "ထာမ်ပလိက်"
end
-- Determine the verb spec we're being asked to generate the conjugation of. This may be taken from the
-- current page title or the value of |pagename=; but not when called from {{es-verb form of}}, where the
-- page title is a non-lemma form. Note that the verb spec may omit the infinitive; e.g. it may be "<ue>".
-- For this reason, we use the value of `pagename` computed here down below, when calling normalize_all_lemmas().
local pagename = source_template ~= "es-verb form of" and args.pagename or PAGENAME
local head = headword_head or pagename
local arg1 = args[1]
if not arg1 then
if (pagename == "es-conj" or pagename == "es-verb") and in_template_space() then
arg1 = "licuar<+,ú>"
elseif pagename == "es-verb form of" and in_template_space() then
arg1 = "amar"
else
arg1 = "<>"
end
end
-- When called from {{es-verb form of}}, determine the non-lemma form whose inflections we're being asked to
-- determine. This normally comes from the page title or the value of |pagename=.
local verb_form_of_form
if source_template == "es-verb form of" then
verb_form_of_form = args.pagename
if not verb_form_of_form then
if PAGENAME == "es-verb form of" and in_template_space() then
verb_form_of_form = "ame"
else
verb_form_of_form = PAGENAME
end
end
end
local incorporated_headword_head_into_lemma = false
if arg1:find("^<.*>$") then -- missing lemma
if head:find(" ") then
-- If multiword lemma, try to add arg spec after the first word.
-- Try to preserve the brackets in the part after the verb, but don't do it
-- if there aren't the same number of left and right brackets in the verb
-- (which means the verb was linked as part of a larger expression).
local refl_clitic_verb, post = rmatch(head, "^(.-)( .*)$")
local left_brackets = rsub(refl_clitic_verb, "[^%[]", "")
local right_brackets = rsub(refl_clitic_verb, "[^%]]", "")
if #left_brackets == #right_brackets then
arg1 = iut.remove_redundant_links(refl_clitic_verb) .. arg1 .. post
incorporated_headword_head_into_lemma = true
else
-- Try again using the form without links.
local linkless_head = m_links.remove_links(head)
if linkless_head:find(" ") then
refl_clitic_verb, post = rmatch(linkless_head, "^(.-)( .*)$")
arg1 = refl_clitic_verb .. arg1 .. post
else
error("Unable to incorporate <...> spec into explicit head due to a multiword linked verb or " ..
"unbalanced brackets; please include <> explicitly: " .. arg1)
end
end
else
-- Will be incorporated through `head` below in the call to normalize_all_lemmas().
incorporated_headword_head_into_lemma = true
end
end
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.pos = pos or "ကြိယာ"
alternant_multiword_spec.args = args
alternant_multiword_spec.source_template = source_template
alternant_multiword_spec.verb_form_of_form = verb_form_of_form
alternant_multiword_spec.incorporated_headword_head_into_lemma = incorporated_headword_head_into_lemma
-- Now determine if we need to generate any double-combined forms, and if so, which clitics are involved.
-- See the comment above the initialization of `verb_slot_double_combined_rows` above in add_slots().
if verb_form_of_form and rfind(verb_form_of_form, AV) then
-- All double-clitic forms have an explicit accent, so we check for this. In addition, all double-clitic forms
-- are of the form "(me|te|se|nos|os)(lo|la|le)s$". We have no alternations in Lua patterns, but we can exploit
-- the similarity of the clitics in question.
local single_comb_form, object_clitic = rmatch(verb_form_of_form, "^(.*)(l[aeo]s?)$")
if single_comb_form then
local personal_clitic = rmatch(single_comb_form, "^.*([mts]e)$")
if not personal_clitic then
personal_clitic = rmatch(single_comb_form, "^.-(n?os)$")
end
if personal_clitic then
if personal_clitic == "nos" then
-- "os" is a substring of "nos"; conceivably we could have a form ending in -n + os, and we don't
-- know whether to interpret as -n + os or - + nos.
alternant_multiword_spec.double_combined_forms_to_include =
{{"nos", object_clitic}, {"os", object_clitic}}
else
if personal_clitic == "se" then
-- Use the special "lxx" clitic for le/les when transformed into se in double-combined forms.
personal_clitic = "lxx"
end
alternant_multiword_spec.double_combined_forms_to_include = {{personal_clitic, object_clitic}}
end
end
end
end
normalize_all_lemmas(alternant_multiword_spec, pagename)
detect_all_indicator_specs(alternant_multiword_spec)
local inflect_props = {
slot_list = alternant_multiword_spec.all_verb_slots,
inflect_word_spec = conjugate_verb,
-- We add links around the generated verbal forms rather than allow the entire multiword
-- expression to be a link, so ensure that user-specified links get included as well.
include_user_specified_links = true,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- Remove redundant brackets around entire forms.
for slot, forms in pairs(alternant_multiword_spec.forms) do
for _, form in ipairs(forms) do
form.form = iut.remove_redundant_links(form.form)
end
end
compute_categories_and_annotation(alternant_multiword_spec)
if args.json and not from_headword and not from_verb_form_of then
-- There is a circular reference in `base.alternant_multiword_spec`, which points back to top level.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.alternant_multiword_spec = nil
end)
return require("Module:JSON").toJSON(alternant_multiword_spec)
end
return alternant_multiword_spec
end
-- Entry point for {{es-conj}}. Template-callable function to parse and conjugate a verb given
-- user-specified arguments and generate a displayable table of the conjugated forms.
function export.show(frame)
local parent_args = frame:getParent().args
local params = {
[1] = {},
["nocomb"] = {type = "boolean"},
["noautolinktext"] = {type = "boolean"},
["noautolinkverb"] = {type = "boolean"},
["pagename"] = {}, -- for testing/documentation pages
["json"] = {type = "boolean"}, -- for bot use
}
local args = require("Module:parameters").process(parent_args, params)
local alternant_multiword_spec = export.do_generate_forms(args, "es-conj")
if type(alternant_multiword_spec) == "string" then
-- JSON return value
return alternant_multiword_spec
end
show_forms(alternant_multiword_spec)
return make_table(alternant_multiword_spec) ..
require("Module:utilities").format_categories(alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
return export
iaqcvg0tucyz1vj13vdiypl3zmxogxm
ကညာၚ်
0
51077
397729
372305
2026-07-01T05:36:02Z
Htawmonzel
48
397729
wikitext
text/x-wiki
=={{=mnw=}}==
===ပွံင်အက္ခရ်နဲတၞဟ်===
{{der3|mnw|က္ညာင်||}}
===ဗွဟ်ရမ္သာင်===
{{IPA|mnw|/kaɲaɪn/}}
* {{audio|mnw|LL-Q13349 (mnw)-咽頭べさ-ကညာင်.wav|ရမျာင်}}
===နာမ်===
{{mnw-noun}}
# ဒဒှ် မဗရုရမ္သာင် နကုပါင် ထတ်ထတ်။
: ရမ္သာင်ကညာင် ညးဍုင်ကွာန်ဂှ် မိင်ဒၟံင်ဟာ။
===ကြိယာ===
{{mnw-verb|tr=kañāṅ}}
# (အကမ္မကြိယာ) (က္ညာင်) နမဗရုရမ္သာင် နကုပါင် ထတ်ထတ်။
: ညး က္ညာင်ကော်ဒၟံင် ညးမွဲလေဝ် ဟွံကၠုင်။
: ဍေဟ်ဖေက်တုဲ ဍေဟ်က္ညာင်တိုန်။
====တြာဲ====
{{VN|my=[[အော်]]|en=[[shout]]|da=[[råbe]]|th=[[ตะโกน]]|km=[[ស្រែក]]}}
[[ကဏ္ဍ:အေန်သတဳကျုတ်ဘာသာမန်]]
2tuqxotezy7aiht5cw72d5azc1ds0bo
မဝ်ဂျူ:ca-verb
828
72378
397723
379545
2026-06-30T14:25:29Z
咽頭べさ
33
397723
Scribunto
text/plain
--[=[
This module implements {{ca-conj}} and provides the underlying conjugation functions for {{ca-verb}}
(whose actual formatting is done in [[Module:ca-headword]]).
Authorship: Ben Wing <benwing2>
]=]
local export = {}
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of tense/mood/person/number/etc.
Example slot names for verbs are "pres_1s" (present indicative first-person singular), "pres_sub_2s" (present
subjunctive second-person singular) "impf_sub_3p" (imperfect subjunctive third-person plural).
Each slot is filled with zero or more forms.
-- "form" = The conjugated Catalan form representing the value of a given slot.
-- "lemma" = The dictionary form of a given Catalan term. For Catalan, always the infinitive.
]=]
--[=[
FIXME:
--]=]
local lang = require("Module:languages").getByCode("ca")
local m_string_utilities = require("Module:string utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:ca-common")
local force_cat = false -- set to true for debugging
local check_for_red_links = false -- set to false for debugging
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local rsubn = mw.ustring.gsub
local rsub = com.rsub
local u = mw.ustring.char
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
-- version of rsubn() that returns a 2nd argument boolean indicating whether a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
local function link_term(term, display, face)
return m_links.full_link({ lang = lang, term = term, alt = display }, face)
end
local front_vowel = "eèéiíï"
local front_vowel_c = "[" .. front_vowel .. "]"
local V = com.V -- vowel regex class
local C = com.C -- consonant regex class
-- IS_USER_STEM_OVERRIDE is prepended to user-supplied stem overrides to prevent `base.prefix` from being prepended.
-- IS_USER_FORM_OVERRIDE is similar but also prevents final devoicing (cf. Balearic pres_1s 'trob' of [[trobar]]).
-- Don't use 0xFFF0 in case we call a [[Module:parse-utilities]] function that uses it temporarily.
local IS_USER_STEM_OVERRIDE = u(0xFFF1)
local IS_USER_FORM_OVERRIDE = u(0xFFF2)
--[=[
Irregular verbs:
-ldre/-ndre verbs:
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
caldre - cal [calent] calia caldrà calgué calgui - calgut,-
coldre colc col colem colia coldré colguí colgui colguem colt,colta
doldre dolc dol dolem dolia doldré dolguí dolgui dolguem dolgut,dolguda
moldre molc mol molem molia moldré molguí molgui molguem molt,molta
oldre olc ol olem olia oldré olguí olgui olguem olgut,olguda
-soldre -solc -sol -solem -solia -soldré -solguí -solgui -solguem -solt,-solta
(absoldre, dissoldre, resoldre)
toldre tolc tol tolem tolia toldré tolguí tolgui tolguem tolt,tolta
romandre romanc roman romanem romania romandré romanguí romangui romanguem romàs,romasa,romasos
encendre encenc encén encenem encenia encendré encenguí encengui encenguem encès,encesa,encesos
fendre fenc fen/-fèn fenem fenia fendré fenguí fengui fenguem fes/-fès,fesa,fesos
(defendre, ofendre)
-pendre -depenc -pèn -penem -penia -pendré -penguí -pengui -penguem -pès,-pesa,-pesos
(dependre,despendre,expendre,suspendre)
prendre prenc pren/-prèn prenem prenia prendré prenguí prengui prenguem pres/-près,presa,presos
(aprendre, comprendre, desprendre, emprendre, reprendre, sorprendre)
-tendre -tenc -tén -tenem -tenia -tendré -tenguí -tengui -tenguem -tès,-tesa,-tesos
(pres2s: atens, pres3p: atenen)
(atendre, contendre, distendre, entendre, estendre, pretendre)
vendre venc ven venem venia vendré venguí vengui venguem venut,venuda
(malvendre, revendre)
fondre fonc fon fonem fonia fondré fonguí fongui fonguem fos/-fós,fosa,fosos
(confondre, difondre, infondre, refondre)
enfondre enfonc enfon enfonem enfonia enfondré enfonguí enfongui enfonguem enfús,enfusa,enfusos
pondre ponc pon ponem ponia pondré ponguí pongui ponguem post,posta,postos
(compondre, correspondre, descompondre, respondre)
tondre tonc ton tonem tonia tondré tonguí tongui tonguem tos,tosa,tosos
cerndre cerno cern cernem cernia cerndré cerní cerni cernem cernut,cernuda
-ler verbs (mostly like -ldre verbs):
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
caler (var. of caldre)
doler (var. of doldre)
soler solc sol solem solia soldré solguí solgui solguem solgut,solguda
valer/valdre valc val valem valia valdré valguí valgui valguem valgut,valguda
(prevaler, equivaler)
other -dre/-tre verbs (regular except sometimes pp):
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
batre bato bat batem batia batré batí bati batem batut,batuda
-metre -meto -met -metem -metia -metré -metí -meti -metem -mès,-mesa,-mesos
(ad-, co-, compro-, e-, entremetre's, mal-, o-, per-, pro-, read-, re-, retrans-, sot-, tra-, trans-)
perdre perdo perd perdem perdia perdré perdí perdi perdem perdut,perduda
-ure verbs
infinitive pres1s pres3s pres1p impf1s impf1p fut1s pret1s sub1s sub1p pp
caure caic cau caiem queia quèiem cauré caiguí caigui caiguem caigut,caiguda
(decaure, recaure)
plaure plac plau plaem plaïa plaíem plauré plaguí plagui plaguem plagut,plaguda
(complaure)
raure rac rau raem raïa raíem rauré raguí ragui raguem ragut,raguda
beure bec beu bevem bevia bevíem beuré beguí begui beguem begut,beguda
(embeure)
creure crec creu creiem creia crèiem creuré creguí cregui creguem cregut,creguda
deure dec deu devem devia devíem deuré deguí degui deguem degut,deguda
jeure jec jeu jaiem jeia jèiem jauré jaguí jegui jaguem jagut,jaguda
(ajeure)
lleure - lleu [-] llevia - lleurà llegué llegui - llegut,-
seure sec seu seiem seia sèiem seuré seguí segui seguem segut,seguda
(asseure)
treure trec treu traiem treia trèiem trauré traguí tregui traguem tret,treta
(abstreure, atreure, contreure, distreure, extreure, retreure, sostreure)
veure veig veu veiem veia vèiem veuré viu,veieres/veres, vegi vegem vist,vista,vists/vistos
(entreveure, preveure, reveure) veié/veu,veiérem/vérem
riure ric riu riem reia rèiem riuré riguí rigui riguem rigut,riguda
(somriure)
(e)scriure escric escriu escrivim escrivia escrivíem escriuré escriví/escriguí escrigui escriguem escrit,escrita
(circumscriure, descriure, inscriure, prescriure, proscriure, subscriure, transcriure)
viure visc viu vivim vivia vivíem viuré visquí visqui visquem viscut,viscuda
(conviure, sobreviure)
cloure cloc clou cloem cloïa cloíem clouré cloguí clogui cloguem clos,closa,closos
(concloure, descloure, encloure, excloure, incloure, recloure)
encloure encloc enclou encloem encloïa encloíem enclouré encloguí enclogui encloguem enclòs,enclosa,enclosos
coure coc cou coem coïa coíem couré coguí cogui coguem cuit/cogut,cuita/coguda
moure moc mou movem movia movíem mouré moguí mogui moguem mogut,moguda
(promoure)
noure noc nou noem noïa noíem nouré noguí nogui noguem nogut,noguda
ploure - plou [plovent] plovia - plourà plogué plogui - plogut,ploguda
-nyer verbs (regular except pp)
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
atènyer atenyo ateny atenyem atenyia atenyeré atenyí atenyi atenyem atès,atesa,atesos
empènyer empenyo empeny empenyem empenyia empenyeré empenyí empenyi empenyem empès,empesa,empesos
estrènyer estrenyo estreny estrenyem estrenyia estrenyeré estrenyí estrenyi estrenyem estret,estreta
estrènyer
(constrènyer,restrènyer)
fènyer fenyo feny fenyem fenyia fenyeré fenyí/fenguí fenyi fenyem fenyut/fengut,fenyuda/fenguda
pertànyer pertanyo pertany pertanyem pertanyia pertanyeré pertanyí/pertanguí pertanyi pertanyem pertanyut/pertangut,pertanyuda/pertanguda
plànyer planyo plany planyem planyia planyeré planyí/planguí planyi planyem plangut/planyut,planguda/planyuda
-xer verbs (NOTE: pres2s in -xes)
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
créixer creixo creix creixem creixia creixeré creixí/cresquí creixi creixem crescut,crescuda
(acréixer,decréixer)
conèixer conec coneix coneixem coneixia coneixeré coneguí conegui coneguem conegut,coneguda
(desconèixer,reconèixer)
merèixer mereixo mereix mereixem mereixia mereixeré mereixí/meresquí mereixi mereixem merescut,merescuda
néixer/ neixo/ neix/ naixem naixia naixeré naixí/nasquí neixi/ naixem/nasquem nascut,nascuda
nàixer naixo naix naixi
(renéixer)
parèixer parec pareix pareixem pareixia pareixeré pareguí paregui pareguem paregut,pareguda
(aparèixer,comparèixer,desaparèixer,reaparèixer)
péixer peixo peix paixem paixia paixeré paixí peixi paixem pascut,pascuda
misc. -er verbs
infinitive pres1s pres3s pres1p impf1s impf1p fut1s pret1s sub1s sub1p pp
córrer corro corre correm corria corríem correré correguí corri correm corregut,correguda
fúmer fumo fum fumem fumia fumíem fumeré fumí fumi fumem fumut,fumuda
prémer premo prem premem premia premíem premeré premí premi premem premut,premuda
(es-, re-)
témer temo tem temem temia temíem temeré temí temi temem temut,temuda
trémer [regular]
tòrcer torço torç torcem torcia torcíem torceré torcí torci torcem torçut,torçuda
(des-) [pres2s torces]
vèncer venço venç vencem vencia vencíem venceré vencí venci vencem vençut,vençuda
(con-, re-) [pres2s vences]
cabre/caber cabo cap cabem cabia cabíem cabré cabí càpiga capiguem cabut,cabuda
[sub2s càpigues]
haver he/haig ha havem/hem havia havíem hauré haguí hagi hàgim/haguem hagut,haguda
[noimp] [cond1s hauria/haguera; impsub2s haguessis/haguesses]
poder puc pot podem podia podíem podré poguí pugui puguem pogut,poguda
saber sé sap sabem sabia sabíem sabré sabí sàpiga sapiguem sabut,sabuda
[imp2s sàpigues, imp2p sapigueu]
voler vull vol volem volia volíem voldré volguí vulgui vulguem volgut,volguda
ser/ésser soc és som era érem seré fui sigui siguem estat/sigut,estada/siguda
[ger sent/essent] [cond1s seria/fora]
[pres: soc,ets,éts,som,sou,són; pret: fui,fores,fou,fórem,fóreu,foren; impsub: fos,fossis,fos,fóssim,fóssiu,fossin]
[imp: sigues,sigueu]
fer faig fa fem feia fèiem faré fiu faci fem fet,feta
[pres3p fan]
[pret: fiu,feres,feu,férem,féreu,feren]
]=]
local all_persons_numbers = {
["1s"] = "1|s",
["2s"] = "2|s",
["3s"] = "3|s",
["1p"] = "1|p",
["2p"] = "2|p",
["3p"] = "3|p",
}
local person_number_list = {"1s", "2s", "3s", "1p", "2p", "3p"}
local imp_person_number_list = {"2s", "3s", "1p", "2p", "3p"}
local neg_imp_person_number_list = {"2s", "3s", "1p", "2p", "3p"}
proclitic_non_elided_person_number_to_reflexive_pronoun = {
["1s"] = "em ",
["2s"] = "et ",
["3s"] = "es ",
["1p"] = "ens ",
["2p"] = "us ",
["3p"] = "es ",
}
proclitic_elided_person_number_to_reflexive_pronoun = {
["1s"] = "m'",
["2s"] = "t'",
["3s"] = "s'",
["1p"] = "ens ",
["2p"] = "us ",
["3p"] = "s'",
}
enclitic_non_elided_person_number_to_reflexive_pronoun = {
["1s"] = "-me",
["2s"] = "-te",
["3s"] = "-se",
["1p"] = "-nos",
["2p"] = "-vos",
["3p"] = "-se",
}
enclitic_elided_person_number_to_reflexive_pronoun = {
["1s"] = "'m",
["2s"] = "'t",
["3s"] = "'s",
["1p"] = "'ns",
["2p"] = "-us",
["3p"] = "'s",
}
local indicator_flags = m_table.listToSet {
"no_pres_stressed",
"only3s", "only3sp", "only3p", "noimp",
"pp_inv", "irreg", "no_built_in",
}
-- Initialize all the slots for which we generate forms.
local function add_slots(alternant_multiword_spec)
-- "Basic" slots: All slots that go into the regular table (not the reflexive form-of table).
alternant_multiword_spec.verb_slots_basic = {
{"infinitive", "inf"},
{"infinitive_linked", "inf"},
{"gerund", "ger"},
{"pp_ms", "m|s|past|part"},
{"pp_fs", "f|s|past|part"},
{"pp_mp", "m|p|past|part"},
{"pp_fp", "f|p|past|part"},
}
-- Special slots used to handle non-reflexive parts of reflexive verbs in {{ca-verb form of}}. For example, for a
-- reflexive-only verb like [[arrepentirse]], we want to be able to use {{ca-verb form of}} on [[arrepinta]] (which
-- should mention that it is a part of 'me arrepinta', first-person singular present subjunctive, and
-- 'se arrepinta', third-person singular present subjunctive) or on [[arrepentimos]] (which should mention that it
-- is a part of 'arrepentímonos', first-person plural present indicative or preterite). Similarly, we want to use
-- {{ca-verb form of}} on [[arrepentindo]] (which should mention that it is a part of 'se ... arrepentindo',
-- syntactic variant of [[arrepentíndose]], which is the gerund of [[arrepentirse]]). To do this, we need to be
-- able to map non-reflexive parts like [[arrepinta]], [[arrepentimos]], [[arrepentindo]], etc. to their reflexive
-- equivalent(s), to the tag(s) of the equivalent(s), and, in the case of forms like [[arrepentindo]],
-- [[arrepentir]] and imperatives, to the separated syntactic variant of the verb+clitic combination. We do this by
-- creating slots for the non-reflexive part equivalent of each basic reflexive slot, and for the separated
-- syntactic-variant equivalent of each basic reflexive slot that is formed of verb+clitic. We use slots in this
-- way to deal with multiword lemmas. Note that we run into difficulties mapping between reflexive verbs,
-- non-reflexive part equivalents, and separated syntactic variants if a slot contains more than one form. To
-- handle this, if there are the same number of forms in two slots we're trying to match up, we assume the forms
-- match one-to-one; otherwise we don't match up the two slots (which means {{ca-verb form of}} won't work in this
-- case, but such a case is extremely rare and not worth worrying about). Alternatives that handle this "properly"
-- are significantly more complicated and require non-trivial modifications to [[Module:inflection utilities]].
local need_special_verb_form_of_slots = alternant_multiword_spec.source_template == "ca-verb form of" and
alternant_multiword_spec.refl
if need_special_verb_form_of_slots then
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {
{"infinitive_non_reflexive", "-"},
{"infinitive_variant", "-"},
{"gerund_non_reflexive", "-"},
{"gerund_variant", "-"},
}
else
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {}
end
-- Add entries for a slot with person/number variants.
-- `verb_slots` is the table to add to.
-- `slot_prefix` is the prefix of the slot, typically specifying the tense/aspect.
-- `tag_suffix` is a string listing the set of inflection tags to add after the person/number tags.
-- `person_number_list` is a list of the person/number slot suffixes to add to `slot_prefix`.
local function add_personal_slot(verb_slots, slot_prefix, tag_suffix, person_number_list)
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(verb_slots, {slot, accel})
end
end
-- Add a personal slot (i.e. a slot with person/number variants) to `verb_slots_basic`.
local function add_basic_personal_slot(slot_prefix, tag_suffix, person_number_list, no_special_verb_form_of_slot)
add_personal_slot(alternant_multiword_spec.verb_slots_basic, slot_prefix, tag_suffix, person_number_list)
-- Add special slots for handling non-reflexive parts of reflexive verbs in {{ca-verb form of}}.
-- See comment above in `need_special_verb_form_of_slots`.
if need_special_verb_form_of_slots and not no_special_verb_form_of_slot then
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local basic_slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(alternant_multiword_spec.verb_slots_reflexive_verb_form_of, {basic_slot .. "_non_reflexive", "-"})
end
end
end
add_basic_personal_slot("pres", "pres|ind", person_number_list)
add_basic_personal_slot("impf", "impf|ind", person_number_list)
add_basic_personal_slot("pret", "pret|ind", person_number_list)
add_basic_personal_slot("fut", "fut|ind", person_number_list)
add_basic_personal_slot("cond", "cond", person_number_list)
add_basic_personal_slot("pres_sub", "pres|sub", person_number_list)
add_basic_personal_slot("impf_sub", "impf|sub", person_number_list)
add_basic_personal_slot("imp", "imp", imp_person_number_list)
-- Don't need special non-reflexive-part slots because the negative imperative is multiword, of which the
-- individual words are 'no' + subjunctive.
add_basic_personal_slot("neg_imp", "neg|imp", neg_imp_person_number_list, "no special verb form of")
-- Don't need special non-reflexive-part slots because we don't want [[arrependendo]] mapping to [[arrependendo-me]]
-- (only [[arrependendo-se]]) or [[arrepender]] mapping to [[arrepender-me]] (only [[arrepender-se]]).
add_basic_personal_slot("infinitive", "inf", person_number_list, "no special verb form of")
add_basic_personal_slot("gerund", "ger", person_number_list, "no special verb form of")
-- Generate the list of all slots.
alternant_multiword_spec.all_verb_slots = {}
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_basic) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_reflexive_verb_form_of) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
alternant_multiword_spec.verb_slots_basic_map = {}
for _, slotaccel in ipairs(alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
alternant_multiword_spec.verb_slots_basic_map[slot] = accel
end
end
local overridable_stems = {}
local function allow_multiple_values_for_override(separated_groups, data, is_form_override)
local retvals = {}
for _, separated_group in ipairs(separated_groups) do
local footnotes = data.fetch_footnotes(separated_group)
local form = separated_group[1]
-- Prepend marker to prevent prefixing with `base.prefix`, and (in the case of form overrides) prevent
-- final devoicing.
if is_form_override then
form = IS_USER_FORM_OVERRIDE .. form
else
form = IS_USER_STEM_OVERRIDE .. form
end
local retval = {form = form, footnotes = footnotes}
table.insert(retvals, retval)
end
return retvals
end
for _, overridable_stem in ipairs {
"stem",
"stressed_stem",
"unstressed_stem",
"pres_unstressed",
"pres_stressed",
"pres3s", -- overrides just pres_2s and pres_3s
-- Don't include pres1s, pres3p; use pres_1s etc. if you need to override just those forms
"impf1",
"impf2",
"pret",
"fut",
"cond",
"pres_sub_stressed",
"pres_sub_unstressed",
"impf_sub",
"pp",
"g_infix",
"eix_infix",
} do
-- Written so we can substitute a different validator; parallel code in [[Module:es-verb]] and [[Module:pt-verb]]
-- has simple_choice validators.
overridable_stems[overridable_stem] = allow_multiple_values_for_override
end
-- Useful as the value of the `match` property of a built-in verb. `main_verb_spec` is a Lua pattern that should match
-- the non-prefixed part of a verb, and `prefix_specs` is a list of Lua patterns that should match the prefixed part of
-- a verb. If a prefix spec is preceded by ^, it must match exactly at the beginning of the verb; otherwise, additional
-- prefixes (e.g. re-, des-) may precede. Return the prefix and main verb.
local function match_against_verbs(main_verb_spec, prefix_specs)
return function(verb)
for _, prefix_spec in ipairs(prefix_specs) do
if prefix_spec:find("^%^") then
-- must match exactly
prefix_spec = prefix_spec:gsub("^%^", "")
if prefix_spec == "" then
-- We can't use the second branch of the if-else statement because an empty () returns the current position
-- in rmatch().
local main_verb = rmatch(verb, "^(" .. main_verb_spec .. ")$")
if main_verb then
return "", main_verb
end
else
local prefix, main_verb = rmatch(verb, "^(" .. prefix_spec .. ")(" .. main_verb_spec .. ")$")
if prefix then
return prefix, main_verb
end
end
else
local prefix, main_verb = rmatch(verb, "^(.*" .. prefix_spec .. ")(" .. main_verb_spec .. ")$")
if prefix then
return prefix, main_verb
end
end
end
return nil
end
end
--[=[
Built-in (usually irregular) conjugations.
Each entry is processed in turn and consists of an object with two fields:
1. match=: Specifies the built-in verbs that match this object.
2. forms=: Specifies the built-in stems and forms for these verbs.
The value of match= is either a string beginning with "^" (match only the specified verb), a string not beginning
with "^" (match any verb ending in that string), or a function that is passed in the verb and should return the prefix
of the verb if it matches, otherwise nil. The function match_against_verbs() is provided to facilitate matching a set
of verbs with a common ending and specific prefixes (e.g. [[ter]] and [[ater]] but not [[abater]], etc.).
The value of forms= is a table specifying stems and individual override forms. Each key of the table names either a
stem (e.g. `pres_stressed`), a stem property (e.g. `g_infix`) or an individual override form (e.g. `pres_1s`).
Each value of a stem can either be a string (a single stem), a list of strings, or a list of objects of the form
{form = STEM, footnotes = {FOONOTES}}. Each value of an individual override should be of exactly the same form except
that the strings specify full forms rather than stems. The values of a stem property depend on the specific property
but are generally strings or booleans.
In order to understand how the stem specifications work, it's important to understand the phonetic modifications done
by combine_stem_ending(). In general, the complexities of predictable prefix, stem and ending modifications are all
handled in this function. In particular:
1. Spelling-based modifications (c/qu, ç/c, g/gu, j/g, gu/gü, qu/qü) occur automatically as appropriate for the ending.
2. If the ending begins with an asterisk, this is a signal to delete the accent on the last syllable of the stem, e.g.
veié -> veierem.
3. If ending begins with i, it may turn into í or ï after an unstressed vowel (in some but not all cases) to prevent the
two merging into a diphthong. See combine_stem_ending() for specifics.
The following stems are recognized [FIXME: This is not correct for Catalan, needs rewriting]:
-- pres_unstressed: The present indicative unstressed stem (1p, 2p). Also controls the imperative 2p
and gerund. Defaults to the infinitive stem (minus the ending -ar/-er/-ir/-or).
-- pres_stressed: The present indicative stressed stem (1s, 2s, 3s, 3p). Also controls the imperative 2s.
Default is empty if indicator `no_pres_stressed`, else a vowel alternation if such an indicator is given
(e.g. `ue`, `ì`), else the infinitive stem.
-- pres1: Special stem for 1s present indicative. Normally, do not set this explicitly. If you need to specify an
irregular 1s present indicative, use the form override pres_1s= to specify the entire form. Defaults to
pres_stressed.
-- pres_sub_unstressed: The present subjunctive unstressed stem (1p, 2p). Defaults to the infinitive stem.
-- pres_sub_stressed: The present subjunctive stressed stem (1s, 2s, 3s, 1p). Defaults to pres1.
-- impf: The imperfect stem (not including the -av-/-i- stem suffix, which is determined by the conjugation). Defaults
to the infinitive stem.
-- pret: The full preterite stem missing only the endings (-ste, -mos, etc.), e.g. 'fige', 'fo'. Only used for verbs
with irregular preterites (pret_conj == "irreg") such as [[facer]], [[poder]], [[traer]], etc. Defaults to
`pret_base` + the conjugation vowel.
-- fut: The future stem. Defaults to the infinitive stem + the conjugation vowel.
-- cond: The conditional stem. Defaults to `fut`.
-- impf_sub: The imperfect subjunctive stem. Defaults to `pret`.
-- pp: The masculine singular past participle. Default is based on the verb conjugation: infinitive stem + '-ado' for
-ar verbs, otherwise infinitive stem + '-ido'.
-- pp_inv: `true` if the past participle exists only in the masculine singular.
]=]
local built_in_conjugations = {
--------------------------------------------------------------------------------------------
-- -ar --
--------------------------------------------------------------------------------------------
-- Orthographic consonant alternations in endings are handled automatically in combine_stem_ending().
{
-- [[aguar]]:
-- pres agúo, agúes, agúa, agüem, agüeu, agúen
-- pres_sub aguï, aguïs, aguï, agüem, agüeu, aguïn
-- contrast a more typical verb in -guar, [[enaiguar]]:
-- pres enaiguo, enaigües, enaigua, enaigüem, enaigüeu, enaigüen
-- pres_sub enaigüi, enaigüis, enaigüi, enaigüem, enaigüeu, enaigüin
match = "^aguar",
forms = {
pres_stressed = "agú",
pres_sub_stressed = "aguï",
irreg = true,
}
},
{
-- [[anar]] (full verb); highly irregular
match = "^anar",
var = "full",
forms = {
fut = "anir",
pres_1s = "vaj", -- will be converted to 'vaig'; 'vaig' gets converted to 'vaic'
pres_2s = "vas",
pres_3s = "va",
pres_3p = "van",
pres_sub_stressed = "vagi",
imp_2s = "ves",
irreg = true,
}
},
{
-- [[anar]] (auxiliary); highly irregular
match = "^anar",
var = "aux",
forms = {
pres_1s = "vaj", -- will be converted to 'vaig'; 'vaig' gets converted to 'vaic'
pres_2s = {"vas", "vares"},
pres_3s = "va",
pres_1p = {"vam", "vàrem"},
pres_2p = {"vau", "vàreu"},
pres_3p = {"van", "varen"},
pres_sub_stressed = "vagi",
pres_sub_unstressed = "vàgi",
impf1 = {},
impf2 = {},
fut = {},
pret = {},
pp = {},
gerund = {},
noimp = true,
irreg = true,
}
},
{
-- [[dar]]
match = "^dar",
forms = {
pres_1s = {form = "do", footnotes = {"[obsolete]"}},
pres_2s = {form = "das", footnotes = {"[obsolete]"}},
pres_3s = {form = "da", footnotes = {"[obsolete]"}},
pres_3p = {form = "dan", footnotes = {"[obsolete]"}},
pres_sub_1s = {form = "de", footnotes = {"[obsolete]"}},
pres_sub_2s = {form = "des", footnotes = {"[obsolete]"}},
pres_sub_3s = {form = "de", footnotes = {"[obsolete]"}},
pres_sub_3p = {form = "den", footnotes = {"[obsolete]"}},
pret_1s = "di", -- regular except for lack of accent
pret_3s = "da", -- regular except for lack of accent
impf_sub_1s = "des", -- regular except for lack of accent
impf_sub_3s = "des", -- regular except for lack of accent
irreg = true,
}
},
{
-- [[estar]]; highly irregular
match = "^estar",
forms = {
pres_2s = "estàs",
pres_3s = "està",
pres_3p = "estan",
g_infix = "estig",
imp_2s = "estigues",
imp_2p = "estigueu",
pp = "estad",
}
},
--------------------------------------------------------------------------------------------
-- -er/-re --
--------------------------------------------------------------------------------------------
-- Regular verbs not needing entries here:
--
-- [[rebre]], [[concebre]], [[decebre]], [[percebre]]
-- [[rompre]]
-- [[fúmer]], [[prémer]], [[témer]], [[trémer]]
-- [[perdre]], [[batre]], [[botre]], [[fotre]], [[retre]]
-- [[tòrcer]], [[vèncer]]
-- etc.
------------------------------------------- -ldre/-ler/-lre --------------------------------------
{
-- [[caldre]], [[doldre]], [[condoldre's]], [[oldre]]
match = match_against_verbs("ldre", {"ca", "do", "^o"}),
forms = {
-- g_infix implies irreg = true
-- g_infix adds -g to pres_1s, sub, pret and pp stems; combine_stem_ending() changes final -g to -c
g_infix = "+",
}
},
{
-- [[caler]]
match = "caler",
like = "caldre",
},
{
-- [[doler]] and compounds
match = "doler",
like = "doldre",
},
{
-- [[dolre]]
match = "dolre",
forms = {
-- see above for g_infix effects
g_infix = "+",
}
},
{
-- [[valer]], [[equivaler]], [[prevaler]], [[sobrevaler]]
match = "valer",
forms = {
-- see above for g_infix effects
fut = "valdr",
g_infix = "+",
}
},
{
-- [[valdre]] and compounds
match = "valdre",
like = "valer",
},
{
-- [[soler]]
match = "^soler", -- this must precede -oldre rule below for alt form [[soldre]]
forms = {
-- see above for g_infix effects
fut = {},
pret = {},
impf_sub = "solgué", -- regular, but we disabled the preterite, which would normally disable impf_sub too
g_infix = "+",
pp = {},
noimp = true,
}
},
{
-- [[soldre]]
match = "^soldre", -- this must precede -oldre rule below
like = "soler",
},
{
-- [[coldre]], [[moldre]], [[absoldre]], [[dissoldre]], [[resoldre]], [[toldre]]
match = "oldre", -- this must follow [[doldre]]/[[oldre]] rule above
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "olt",
}
},
{
-- [[voler]], [[malvoler]]
match = "voler",
forms = {
fut = "voldr",
pres_1s = "vull",
pres_sub_stressed = "vulgui",
pres_sub_unstressed = "vulgue",
g_infix = "+",
imp_2s = "vulgues",
imp_2p = "vulgueu",
}
},
--------------------------------------------- -ndre ----------------------------------------
{
-- [[romandre]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("mandre", {"^ro"}),
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "màs#",
}
},
{
-- [[encendre]], [[atendre]], [[contendre]], [[desentendre's]], [[distendre]], [[entendre]], [[estendre]],
-- [[pretendre]]
match = match_against_verbs("endre", {"enc", "t"}),
forms = {
pres_3s = "én#", -- remove final accent without prefix with vowel; also removed when adding a suffix
-- see above for g_infix effects
g_infix = "+",
pp = "ès#", -- see above for effect of final #
}
},
{
-- [[vendre]], [[malvendre]], [[revendre]]
match = "vendre",
forms = {
pres_3s = "vèn#", -- see above for effect of final #
-- see above for g_infix effects
g_infix = "+",
pp = "venud", -- g_infix would normally make it vengud
}
},
{
-- [[fendre]], [[defendre]], [[ofendre]], [[dependre]], [[despendre]], [[expendre]], [[suspendre]], [[prendre]],
-- [[aprendre]], [[comprendre]], [[desprendre]], [[emprendre]], [[reprendre]], [[sorprendre]]
match = "endre", -- this must follow previous -endre rules above
forms = {
pres_3s = "èn#", -- see above for effect of final #
-- see above for g_infix effects
g_infix = "+",
pp = "ès#", -- see above for effect of final #
}
},
{
-- [[enfondre]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("fondre", {"^en"}),
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "fús#",
}
},
{
-- [[pondre]], [[compondre]], [[correspondre]], [[descompondre]], [[despondre's]], [[respondre]]
match = "pondre",
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "post",
}
},
{
-- [[fondre]], [[confondre]], [[difondre]], [[infondre]], [[refondre]], [[tondre]]
match = "ondre", -- this must follow previous -ondre rules above
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "ós#", -- see above for effect of final #
}
},
--------------------------------------------- -nyer ----------------------------------------
{
-- [[atènyer]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("tènyer", {"^a"}),
forms = {
pp = "tès#",
irreg = true,
}
},
{
-- [[empènyer]], [[espènyer]]
match = match_against_verbs("pènyer", {"^em", "^es"}),
forms = {
pp = "pès#",
irreg = true,
}
},
{
-- [[estrènyer]], [[constrènyer]], [[destrènyer]], [[restrènyer]]
match = match_against_verbs("strènyer", {"^e", "con", "^de", "^re"}),
forms = {
pp = "stret",
irreg = true,
}
},
{
-- [[fènyer]]
match = "fènyer",
forms = {
pp = {"fengud", "fenyud"},
irreg = true,
}
},
{
-- [[júnyer]]
match = "júnyer",
like = "junyir",
},
{
-- [[plànyer]], [[complànyer]], [[pertànyer]]
match = match_against_verbs("ànyer", {"pl", "pert"}),
forms = {
pp = {"angud", "anyud"},
irreg = true,
}
},
--------------------------------------------- -aure ----------------------------------------
{
-- [[caure]], [[decaure]], [[recaure]]
match = "caure",
forms = {
-- stem ending in -ai and imperfect in -ia causes special stressed imperfect logic to take effect; we get
-- impf1s queia, impf1p quèiem (preceding vowel changed to è and attached to initial consonant using
-- combine_stem_ending(), which changes c- to qu-)
stem = "caie", -- i dropped by g_infix before u
-- g_infix implies irreg = true
-- g_infix adds -g to pres_1s, sub, pret and pp stems; combine_stem_ending() changes final -g to -c
-- g_infix sets pres_stressed to end in -u, removing a preceding -i or -v
g_infix = "+",
}
},
{
-- [[plaure]], [[complaure]]
match = "plaure",
forms = {
stem = "plae", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
}
},
{
-- [[raure]]
match = "^raure",
forms = {
stem = "rae", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = {"ragud", "ras"},
}
},
--------------------------------------------- -eure ----------------------------------------
{
-- [[beure]], [[embeure]], [[deure]], [[lleure]]
match = match_against_verbs("eure", {"b", "d", "ll"}),
forms = {
stem = "eve", -- v dropped by g_infix before g and u
g_infix = "+",
}
},
{
-- [[creure]], [[seure]], [[asseure]]
match = match_against_verbs("eure", {"cr", "s"}),
forms = {
stem = "ee",
pres_unstressed = "eie", -- affects pres_1p, pres_2p, gerund, imperfect (see [[caure]])
g_infix = "+",
}
},
{
-- [[jeure]], [[ajeure]]
match = "jeure",
forms = {
fut = "jaur", -- affects future and cond
stressed_stem = "jee", -- affects stressed forms, which get g added by g_infix by added except for
-- pres_stressed, which gets u added (controls pres_3s, pres_2s, pres_3p)
unstressed_stem = "jae", -- affects unstressed_stem, which get g added by g_infix
pres_stressed = {"jeu", "jau"},
pres_unstressed = "jaie", -- affects pres_1p, pres_2p, gerund, imperfect (see [[caure]])
pres_1s = {"jec", "jac"},
impf1 = "jei", -- otherwise we'd get impf_1s '#geia' etc.
impf2 = "jèi",
g_infix = "+",
}
},
{
match = "jaure",
like = "jeure",
},
{
-- [[treure]], [[abstreure]], [[atreure]], [[bestreure]], [[contreure]], [[detreure]], [[distreure]],
-- [[extreure]], [[retreure], [[retrotreure]], [[sostreure]]
match = "treure",
forms = {
-- like [[jeure]] except for irregular pp
fut = "traur",
stressed_stem = "tree",
unstressed_stem = "trae",
pres_stressed = {"treu", "trau"},
pres_unstressed = "traie",
pres_1s = {"trec", "trac"},
g_infix = "+",
pp = "tret",
}
},
{
match = "traure",
like = "treure",
},
{
-- [[veure]], [[entreveure]], [[preveure]], [[reveure]]
match = "veure",
forms = {
stem = "veie",
-- impf1s veia, impf1p vèiem (preceding vowel changed to è)
pres_stressed = "veu",
pres_1s = "vej", -- will be converted to 'veig'; 'veig' gets converted to 'veic'
pres_sub_stressed = "vegi",
pres_sub_unstressed = "vege",
pret = {"veié", "vé"},
pret_1s = "viu",
pret_3s = {"veié", "veu"},
impf_sub = "veié",
pp = "vist",
imp_2s = "veges",
imp_2p = {"vegeu", "veieu"},
irreg = true,
}
},
--------------------------------------------- -iure ----------------------------------------
{
-- [[escriure]], [[circumscriure]], [[descriure]], [[inscriure]], [[prescriure]], [[proscriure]],
-- [[subscriure]], [[transcriure]]
match = "scriure",
forms = {
stem = "scrivi", -- v dropped by g_infix before g and u; pres_1p/pres_2p have -ir endings
g_infix = "+",
pret = {"scriví", "scrigué"},
pp = "scrit",
}
},
{
-- [[riure]], [[somriure]]
match = "riure", -- must follow rule for 'scriure'
forms = {
stem = "rie",
-- impf1s reia, impf1p rèiem (preceding vowel changed to è)
g_infix = "+",
}
},
{
-- [[viure]], [[conviure]], [[desviure's]], [[sobreviure]]
match = "viure",
forms = {
stem = "vivi", -- v dropped by g_infix before g and u; pres_1p/pres_2p have -ir endings
g_infix = "visc", -- applies to pres1s, sub, pret, pp
}
},
--------------------------------------------- -oure ----------------------------------------
{
-- [[cloure]], [[concloure]], [[descloure]], [[encloure]], [[excloure]], [[incloure]], [[recloure]]
match = "cloure",
forms = {
stem = "cloe", -- ï in impf1s cloïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = "clòs#", -- remove final accent without prefix with vowel; also removed when adding a suffix
}
},
{
-- [[coure]] "to cook"
match = "coure",
var = "cook",
forms = {
stem = "coe", -- ï in impf1s coïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = "cuit",
}
},
{
-- [[coure]] "to sting"
match = "coure",
var = "sting",
forms = {
stem = "coe", -- ï in impf1s coïa gets generated automatically by combine_stem_ending()
g_infix = "+",
-- pp regular 'cogud'
}
},
{
-- [[moure]], [[promoure]], [[remoure]], [[somoure]], [[ploure]]
match = match_against_verbs("oure", {"m", "pl"}),
forms = {
stem = "ove", -- v dropped by g_infix before g and u
g_infix = "+",
}
},
{
-- [[noure]]
match = "noure",
forms = {
stem = "noe", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
}
},
--------------------------------------------- -xer ----------------------------------------
{
-- [[conèixer]], [[desconèixer]], [[reconèixer]]
match = "conèixer",
forms = {
g_infix = "coneg",
}
},
{
-- [[créixer]], [[acréixer]], [[decréixer]], [[recréixer]], [[sobrecréixer]]
match = "créixer",
forms = {
pret = {"creixé", "cresqué"},
pres_sub_unstressed = {"creixe", "cresque"},
pp = "crescud",
irreg = true,
}
},
{
-- [[merèixer]], [[desmerèixer]], [[irèixer-se]]
match = match_against_verbs("rèixer", {"me", "^i"}),
forms = {
pret = {"reixé", "resqué"},
pres_sub_unstressed = {"reixe", "resque"},
pp = "rescud",
irreg = true,
}
},
{
-- [[néixer]]/[[nàixer]], [[renéixer]]/[[renàixer]], [[sobrenéixer]]/[[sobrenàixer]], [[péixer]]/[[pàixer]]
match = match_against_verbs("éixer", {"n", "p"}),
forms = {
stem = "aixe",
fut = "aixer",
pres_stressed = {"eix", "aix"},
pres_1s = "eixo",
pret = {"aixé", "asqué"},
pres_sub_stressed = "eixi",
pres_sub_unstressed = {"aixe", "asque"},
pp = "ascud",
irreg = true,
}
},
{
match = "àixer",
like = "éixer",
},
{
-- [[parèixer]], [[aparèixer]], [[comparèixer]], [[desaparèixer]], [[reaparèixer]]
match = "parèixer",
forms = {
g_infix = "pareg",
}
},
--------------------------------------------- misc ----------------------------------------
{
-- [[cabre]]
match = "cabre",
forms = {
pres_sub_stressed = "càpiga",
pres_sub_unstressed = "capigue",
irreg = true,
}
},
{
-- [[caber]]
match = "caber",
like = "cabre",
},
{
-- [[saber]]
match = "saber",
forms = {
fut = "sabr",
pres_1s = "sé",
pres_sub_stressed = "sàpiga",
pres_sub_unstressed = "sapigue",
imp_2s = "sàpiga",
imp_2p = "sapigueu",
irreg = true,
}
},
{
-- [[poder]]
match = "poder",
forms = {
fut = "podr",
pres_1s = "puc",
pres_sub_stressed = "pugui",
pres_sub_unstressed = "pugue",
g_infix = "pog",
imp_2s = "pugues",
imp_2p = "pugueu",
irreg = true,
}
},
{
-- [[córrer]], [[acórrer]], [[concórrer]], [[decórrer]], [[descórrer]], [[discórrer]], [[encórrer]],
-- [[escórrer]], [[incórrer]], [[ocórrer]], [[recórrer]], [[socórrer]], [[transcórrer]]
match = "córrer",
forms = {
pret = "corregué",
pres_sub_unstressed = {"corre", "corregue"},
pp = "corregud",
irreg = true,
}
},
{
-- [[metre]], [[admetre]], [[arremetre]], [[cometre]], [[comprometre]], [[demetre]], [[descomprometre]],
-- [[emetre]], [[entremetre's]], [[escometre]], [[malmetre]], [[manumetre]], [[ometre]], [[permetre]],
-- [[prometre]], [[readmetre]], [[remetre]], [[retransmetre]], [[sotmetre]], [[trametre]], [[transmetre]]
match = "metre",
forms = {
pp = "mès#",
irreg = true,
}
},
--------------------------------------------------------------------------------------------
-- -ir --
--------------------------------------------------------------------------------------------
{
-- [[acudir]]; NOTE: Separation by meaning does not occur in DCC, DIEC, DEIEC, and DCVB says the distinction
-- is geographical and makes no mention of distinction by meaning. OTOH ca.wikt does say that the pronominal
-- sense "to occur" tends to conjugate non-inchoative.
match = "acudir",
forms = {
eix_infix = {{
form = "+",
footnotes = {'[especially in the sense "to turn up, to be present"]'}
}, {
form = "-",
footnotes = {'[especially in the pronominal sense "to occur"]'}
}}
}
},
-- [[afegir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[ajupir]]
-- [[buixir]]
-- [[bullir]], [[rebullir]]
-- [[cruixir]], [[escruixir]] (Routledge says this is inchoative but DIEC, DEIEC and DCC all disagree; note
-- pres_2s 'cruixes', handled automatically)
-- [[dormir]], [[adormir]]
-- [[funyir]]
-- [[grunyir]]
-- [[munyir]], [[esmunyir]]
-- [[pudir]]
-- [[punyir]]
-- [[retrunyir]]
-- [[sentir]], [[pressentir]], [[ressentir-se]]; not [[consentir]], with can be either non-inchoative or
-- inchoative, and not [[assentir]] or [[dissentir]], which are only inchoative
match = match_against_verbs("ir", {"ajup", "buix", "bull", "cruix", "dorm", "funy", "gruny", "muny", "pud",
"puny", "retruny", "^sent", "pressent", "^ressent"}),
forms = {
eix_infix = "-",
}
},
{
-- [[arrupir-se]];
-- [[brumir]];
-- [[brunzir]];
-- [[consumir]], [[resumir]], [[presumir]] (not [[sumir]], [[assumir]], [[subsumir]], which are regular)
-- [[mentir]], [[desmentir]]
-- [[percudir]]; cf. also [[acudir]], which to some extent has separate conjugations per meaning
-- [[consentir]]
match = match_against_verbs("ir", {"arrup", "brum", "brunz", "consum", "^resum", "presum", "ment", "percud",
"consent"}),
forms = {
eix_infix = {"+", "-"},
}
},
-- [[cenyir]]: -- non-inchoative or inchoative in Balearics, inchoative elsewhere
{
-- [[cobrir]], [[descobrir]], [[encobrir]], [[recobrir]], [[redescobrir]]
match = "cobrir",
forms = {
pp = "cobert",
irreg = true,
}
},
{
-- [[collir]], [[acollir]], [[escollir]], [[recollir]]
match = "collir",
forms = {
stressed_stem = "culli",
eix_infix = "-",
irreg = true,
}
},
{
-- [[complir]], [[acomplir]], [[incomplir]]
match = "complir",
forms = {
pp = {"complert", "complid"},
irreg = true,
}
},
{
-- [[cosir]], [[descosir]], [[recosir]]
match = "cosir",
forms = {
stressed_stem = "cusi",
pres_3s = "cús#",
eix_infix = "-",
irreg = true,
}
},
{
-- [[eixir]], [[deseixir-se]]; not [[teixir]] or [[entreteixir]], and not [[reeixir]] or [[sobreeixir]],
-- which have an ï in the stem-stressed forms
match = match_against_verbs("eixir", {"^", "des"}),
forms = {
stressed_stem = "ixi",
eix_infix = "-",
irreg = true,
}
},
{
-- [[reeixir]], [[sobreeixir]]
match = match_against_verbs("eixir", {"^re", "sobre"}),
forms = {
stressed_stem = "ïxi",
eix_infix = "-",
irreg = true,
}
},
-- [[engolir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[escopir]]
match = "escopir",
forms = {
stressed_stem = "escupi",
eix_infix = "-",
irreg = true,
}
},
{
-- [[establir]], [[preestablir]], [[restablir]]
match = "establir",
forms = {
pp = {"establert", "establid"},
irreg = true,
}
},
-- [[ferir]]: -- non-inchoative in Balearics, inchoative elsewhere
-- [[fregir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[fugir]], [[confugir]], [[defugir]], [[enfugir-se]]; pres sing ''fujo, fuges, fuig'' handled by
-- combine_stem_ending(); can't be handled by rule above that lists many non-inchoative verbs because the
-- prefix would be 'fug' and the front-back alternation code doesn't apply to prefixes.
match = "fugir",
forms = {
eix_infix = "-",
}
},
{
-- [[imprimir]], [[reimprimir]], [[sobreimprimir]]; not any other verbs in -primir; write it this way so
-- there's a prefix with a vowel to prevent against the accent in the pp from being removed while still
-- removing it in the feminine.
match = match_against_verbs("primir", {"im"}),
forms = {
pp = "près#",
irreg = true,
}
},
-- [[llegir]]: -- non-inchoative in Valencia and Minorca, inchoative elsewhere
{
-- [[lluir]]: regular inchoative in the figurative meaning "to display (something), to be showy" also in the
-- legal meaning "free from a pecuniary obligation, such as a land-based tax (emphyteusis)"; irregular in the
-- literal meaning "to shine"; use <no_built_in> to get regular conjugation. In the regular conjugation,
-- umlauts appear in the following forms: pres_1p/pres_sub_1p/imp_1p lluïm, pres_2p/pres_sub_2p/imp_2p lluïu,
-- impf_1s/impf_3s lluïa, impf_2s lluïes, impf_3p lluïen, pret_2s lluïres, pret_3p lluïren,
-- impf_sub_2s lluïssis, impf_sub_3p lluïssin, throughout the pp: lluït, lluïda, lluïts, lluïdes. IN the
-- irregular conjugation, umlauts appear in the same places as well as elsewhere in the present subjunctive:
-- pres_sub_1s/pres_sub_3s/imp_3s lluï, pres_sub_2s lluïs, pres_sub_3p/imp_3p lluïn. Notably, they do *NOT*
-- appear in the gerund lluint, the infinitive lluir, or anywhere in the future or conditional. Note that
-- verbs.cat [https://www.verbs.cat/en/conjugation/899-lluir.html] lists additional irregular forms pres_1s
-- lluu, and alternative impf_sub forms in -e- instead of -i- (lluïsses, lluíssem, lluísseu, lluïssen), but
-- these are nonstandard or dialectal per both Routledge and DEIEC.
match = "^lluir",
forms = {
eix_infix = "-",
pres3s = {"lluu", "llu"}, -- generates pres_2s, imp_2s
irreg = true,
}
},
{
-- [[entrelluir]] "to be half-seen", [[relluir]] "to shine", [[traslluir-se]] "to be translucent"; either
-- inchoative or non-inchoative, not distinguished by meaning; note, [[deslluir]] and [[enlluir]] are regular
-- inchoative verbs.
match = match_against_verbs("lluir", {"entre", "^re", "tras"}),
forms = {
eix_infix = {"+", "-"},
pres3s = {"llueix", "lluu", "llú"}, -- generates pres_2s, imp_2s; note, pres_2s will end in -es due to
-- combine_stem_ending()
irreg = true,
}
},
{
-- [[morir]], [[premorir]]; but not [[atemorir]]
match = match_against_verbs("morir", {"^", "pre"}),
forms = {
eix_infix = "-",
pp = "mort",
irreg = true,
}
},
{
-- [[obrir]], [[entreobrir]], [[reobrir]]; not [[cobrir]] and derivatives, not [[empobrir]], so we have to list
-- them individually
match = match_against_verbs("obrir", {"^", "entre", "^re"}),
forms = {
eix_infix = "-",
pp = "obert",
irreg = true,
}
},
{
-- [[oferir]]; but not [[proferir]]
match = "^oferir",
forms = {
pp = {"ofert", "oferid"},
irreg = true,
}
},
-- [[oir]], [[desoir]], [[entreoir]]: -- per Routledge, non-inchoative or inchoative normally but only
-- non-inchoative in Valencian; but all dictionaries disagree and say it is a regular inchoative-only verb.
-- It has the same umlauts as lluir (and [[corroir]], another regular inchoative verb).
{
-- [[omplir]], [[desomplir-se]], [[reomplir]]; not [[complir]] and derivatives, so we have to list them
-- individually
match = match_against_verbs("omplir", {"^", "des", "^re"}),
forms = {
eix_infix = "-",
pp = {"omplert", "omplid"},
irreg = true,
}
},
-- [[penedir-se]]: -- non-inchoative in Balearics, inchoative elsewhere
{
-- [[pruir]] "to itch": same umlauts as in [[lluir]].
match = "^pruir",
forms = {
eix_infix = "-",
pres3s = {"pruu", "pru"}, -- generates pres_2s, imp_2s
irreg = true,
}
},
{
-- [[reblir]]
match = "^reblir",
forms = {
pp = {"reblert", "reblid"},
irreg = true,
}
},
-- [[renyir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[sofrir]]
match = "^sofrir",
forms = {
pp = {"sofert", "sofrid"},
irreg = true,
}
},
{
-- [[sortir]], [[ressortir]], [[sobresortir]]; but not [[assortir]], which is regular inchoative
match = match_against_verbs("sortir", {"^", "^res", "sobre"}),
forms = {
stressed_stem = "surti",
eix_infix = "-",
irreg = true,
}
},
{
-- [[suplir]]
match = "^suplir",
forms = {
pp = {"suplert", "suplid"},
irreg = true,
}
},
-- [[teixir]], [[entreteixir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[tenir]] but not any compounds; highly irregular
match = "^tenir",
forms = {
fut = "tindr",
pres_stressed = "ten",
pres_3s = "té",
imp_2s = {"té", "ten", "tingues"},
imp_2p = {"teniu", "tingueu"},
g_infix = "ting",
}
},
{
-- [[abstenir-se]], [[atenir-se]], [[captenir-se]], [[cartenir]], [[contenir]], [[detenir]], [[entretenir]],
-- [[mantenir]], [[menystenir]], [[obtenir]], [[retenir]], [[sostenir]], [[viltenir]]; highly irregular
match = "tenir",
forms = {
fut = "tindr",
pres_stressed = "ten",
pres_3s = "té",
imp_2s = {"tén", "tingues"},
imp_2p = {"teniu", "tingueu"},
g_infix = "ting",
}
},
{
-- [[tindre]]: variant of [[tenir]]
match = "tindre",
like = "tenir",
},
-- [[tenyir]], [[destenyir]]: -- non-inchoative in Valencia, but [[retenyir]] inchoative or non-inchoative in
-- Valencia? (per Routledge); regular inchoative elsewhere
{
-- [[tossir]] "to cough"
match = "^tossir",
forms = {
stressed_stem = "tussi", -- pres_2s gets 'tusses'
pres_3s = "tus", -- note, pres_3s (a single form override) not pres3s (a stem override, which also affects
-- pres_2s; but imp_2s is physically copied from pres_3s, so imp_2s correctly gets 'tus')
eix_infix = "-",
irreg = true,
}
},
{
-- [[venir]] but not any compounds; highly irregular
match = "^venir",
forms = {
fut = "vindr",
pres_stressed = "ven",
pres_3s = "ve",
imp_2s = "vine",
g_infix = "ving",
}
},
{
-- compounds of [[venir]]: [[advenir]], [[avenir]], [[contravenir]], [[convenir]], [[desavenir-se]],
-- [[desconvenir]], [[entrevenir]], [[esdevenir]], [[intervenir]], [[obvenir]], [[pervenir]], [[prevenir]],
-- [[provenir]], [[reconvenir]], [[revenir]], [[sobrevenir]], [[subvenir]]; but not [[enjovenir]] or
-- [[rejovenir]]; highly irregular
match = match_against_verbs("venir", {"^ad", "^a", "contra", "con", "desa", "entre", "esde", "inter", "ob",
"per", "pre", "pro", "^re", "sobre", "sub"}),
forms = {
fut = "vindr",
pres_stressed = "ven",
pres_3s = "vé",
imp_2s = "vén",
g_infix = "ving",
}
},
{
-- [[vindre]]: variant of [[venir]]
match = "vindre",
like = "venir",
},
-- [[vestir]], [[desvestir]], [[revestir]], maybe [[transvestir]]: non-inchoative in Valencia, inchoative or
-- non-inchoative in the Balearics; regular inchoative elsewhere; but not [[envestir]] or [[investir]], which are
-- regular inchoative everywhere
{
-- [[fer]], [[contrafer]], [[desfer]], [[estrafer]], [[perfer]], [[refer]], [[satisfer]]; highly irregular
match = "fer",
forms = {
fut = "far",
pres_1s = "faj", -- will be converted to 'faig'; 'faig' gets converted to 'faic'
pres_2s = "fàs#",
pres_3s = "fà#",
pres_3p = "fan",
pres_unstressed = "fe",
impf1 = "fei",
impf2 = "fèi",
pres_sub_stressed = "faci",
pres_sub_unstressed = "fe",
pret = "fé",
pret_1s = "fiu",
pret_3s = "feu",
impf_sub_1s = "fés#", -- regular except for base form [[fes]], lacking an accent
impf_sub_3s = "fés#", -- same
imp_2s = "fés#",
pp = "fet",
irreg = true,
}
},
{
-- [[dir]], [[adir-se]], [[contradir]], [[desdir]], [[entredir]], [[interdir]], [[maldir]], [[predir]], [[redir]];
-- behaves like an -er/-re verb
match = match_against_verbs("dir", {"^", "^a", "contra", "des", "entre", "inter", "mal", "pre", "^re"}),
forms = {
stem = "die",
g_infix = "+",
imp_2s = "digues",
imp_2p = "digueu",
pp = "dit",
}
},
{
-- [[dur]], [[endur-se]]; behaves like an -er/-re verb
match = "dur",
forms = {
stem = "due",
g_infix = "+",
pres3s = {"duu", "du"}, -- generates pres_2s, imp_2s
impf1 = "dui",
impf2 = "dúi",
pp = "dut",
}
},
{
-- [[ser]]; highly irregular
match = "^ser",
forms = {
pres_1s = "soc",
pres_2s = "ets",
pres_3s = "és",
pres_1p = "som",
pres_2p = "sou",
pres_3p = "són",
impf1 = "er",
impf2 = "ér",
pres_sub_stressed = "sigui",
pres_sub_unstressed = "sigue",
pret = "fó",
pret_1s = "fui",
pret_3s = "fou",
impf_sub_1s = "fos", -- regular except for lack of accent
impf_sub_3s = "fos", -- same
cond = {"serí", "fór"},
imp_2s = "sigues",
imp_2p = "sigueu",
pp = {"estad", "sigud"},
gerund = {"sent", "essent"},
irreg = true,
}
},
{
-- [[ésser]]; variant of [[ser]]
match = "^ésser",
like = "ser",
},
{
-- [[haver]] as auxiliary; highly irregular
match = "^haver",
var = "aux",
forms = {
pres_1s = "he",
pres_2s = "has",
pres_3s = "ha",
pres_1p = "hem",
pres_2p = "heu",
pres_3p = "han",
fut = "haur",
cond = {"haurí", "haguér"},
pres_sub_stressed = "hagi",
pres_sub_unstressed = "hàgi",
noimp = true,
g_infix = "+",
}
},
{
-- [[haver]] as full verb; highly irregular
match = "^haver",
var = "full",
forms = {
pres_1s = {"hec", "hac"},
pres_stressed = {"heu", "hau"},
fut = "haur",
pres_sub_stressed = "hegui",
g_infix = "+",
}
},
{
-- [[heure]]; variant of full verb [[haver]]
match = "^heure",
like = "haver",
likevar = "full",
},
{
-- [[haure]]; variant of full verb [[haver]]
match = "^haure",
like = "haver",
likevar = "full",
},
}
local function skip_slot(base, slot, allow_overrides)
if not allow_overrides and (base.basic_overrides[slot] or
base.refl and base.basic_reflexive_only_overrides[slot]) then
-- Skip any slots for which there are overrides.
return true
end
if base.only3s and (slot:find("^pp_f") or slot:find("^pp_mp")) then
-- diluviar, atardecer, neviscar; impersonal verbs have only masc sing pp
return true
end
if not slot:find("[123]") then
-- Don't skip non-personal slots.
return false
end
if base.nofinite then
return true
end
if (base.only3s or base.only3sp or base.only3p) and (slot:find("^imp_") or slot:find("^neg_imp_")) then
return true
end
if base.only3s and not slot:find("3s") then
-- diluviar, atardecer, neviscar
return true
end
if base.only3sp and not slot:find("3[sp]") then
-- atañer, concernir
return true
end
if base.only3p and not slot:find("3p") then
-- [[caer cuatro gotas]], [[caer chuzos de punta]], [[entrarle los siete males]]
return true
end
return false
end
local function add_stem_ending(stem, ending)
if ending == "" then
return stem
end
if stem:find("#$") then -- remove final accent when adding a suffix
stem = com.remove_accents((stem:gsub("#$", "")), "final syllable only")
end
return stem .. ending
end
local function process_stem(stem, fn)
if stem:find("#$") then
local stem_no_pound_sign = stem:match("^(.*)#$")
return fn(stem_no_pound_sign) .. "#"
else
return fn(stem)
end
end
-- Add the `stem` to the `ending` and apply any phonetic modifications. `is_full_word` indicates that we're creating
-- a "full word" not a stem, and turns on devoicing of final consonants. `dont_include_prefix` is used when creating
-- stems and indicates not to prepend the prefix in `base.prefix` to the result. `is_pres_sub_stressed` is used when
-- creating the pres_sub_stressed stem, to correctly handle both [[desaiguar]] and [[argüir]], whose respective
-- interactions between ü and i/ï are very tricky.
--
-- WARNING: This function is written very carefully; changes to it can easily have unintended consequences.
local function combine_stem_ending(base, stem, ending, is_full_word, dont_include_prefix, is_pres_sub_stressed)
-- Include the prefix in the stem unless dont_include_prefix is given (used in construct_stems()), or the value of
-- `stem` comes from a user-specified stem or form override.
if not dont_include_prefix and not stem:find(IS_USER_STEM_OVERRIDE) and not stem:find(IS_USER_FORM_OVERRIDE) then
stem = base.prefix .. stem
end
-- A * at the beginning of the ending is a signal to remove a stressed accent from the stem. This may feed any of
-- the following rules.
if ending:find("^%*") then
ending = ending:gsub("^%*", "")
stem = com.remove_accents(stem, "final syllable only")
end
-- If ending begins with s and stem ends in a sibilant, we need an e in between; cf. pres_2s 'apareixes' of
-- [[aparèixer]], pres_2s 'torces' of [[tòrcer]], pres_2s 'fuges' of [[fugir]], pres_2s 'brunzes' of [[brunzir]].
-- This may feed the next rule.
if ending:find("^s") and rfind(stem, "[çjsxz]$") then
ending = "e" .. ending
end
-- By default, stems are in their "back" (standalone) form. Before a front vowel, convert the final consonant to
-- its "front" form so the pronunciation doesn't change.
if rfind(ending, "^" .. front_vowel_c) then
-- adequar -> adeqües
-- enaiguar -> enaigües
-- pegar -> pegues
-- arranjar -> arranges
-- marcar -> marques
-- abraçar -> abraces
stem = com.back_to_front(stem)
end
-- Ending beginning in -i after diphthong ending in V + i compresses the two i's into one (cf. pret_1s 'desmaí' and
-- pres_sub_1s 'desmaï' of [[desmaiar]]). This rule doesn't apply after pseudo-vowel u in gu/qu; cf. pret_1s 'guií'
-- of [[guiar]] and contrast pret_1s 'cruí' of [[cruiar]]. This may feed the next rule.
if rfind(ending, "^[iíï]") and rfind(stem, V .. "i$") and not rfind(stem, "[gq][uü]i$") then
stem = stem:gsub("i$", "")
end
-- If ending begins with i (not í), it must get a diaeresis after a true vowel (not gu/qu, cf. pres_1p 'delinquim'
-- of [[delinquir]], not '#delinquïm'; also not a diphthong ending in u, cf. pres_sub_1s 'apreui' of [[apreuar]]
-- not '#apreuï') to prevent the two merging into a diphthong. Note that ü -> u before ï, but to simplify things
-- we leave the double umlauts in place and remove the first one during postprocessing, in fix_double_umlauts().
-- Cf.:
-- * impf_1s 'raïa' of [[raure]];
-- * pres_sub_1s 'creï' of [[crear]];
-- * pres_sub_1s 'associï' of [[associar]];
-- * impf_1s 'cloïa' of [[cloure]];
-- * pres_1p 'lluïm' of [[lluir]];
-- * pres_1p 'arguïm' of [[argüir]].
if ending:find("^i") and rfind(stem, "[aeiouü]$") and not stem:find("[aeiogq]u$") and
-- Unstressed subjunctive endings of [[enaiguar]] remain without umlaut: enaigüi/enaigüis/enaigüin;
-- but stressed endings of [[argüir]] that begin with 'i' do get an umlaut: arguït, impf. arguïa, including
-- stressed subjunctive endings arguïm/arguïu. In both cases the ending is '-i' as part of the creation of
-- the respective stems. There seems no way of distinguishing the two cases other than with a special flag.
not (rfind(stem, "[gq]ü$") and ending == "i" and is_pres_sub_stressed) then
ending = ending:gsub("^i", "ï")
end
local retval = add_stem_ending(stem, ending)
if retval:find("#$") then -- remove final accent if no vowels in prefix
retval = retval:gsub("#$", "")
if not rfind(base.prefix, V) then
retval = com.remove_accents(retval, "final syllable only")
end
end
if is_full_word then
local saw_is_user_form_override
retval, saw_is_user_form_override = rsubb(retval, IS_USER_FORM_OVERRIDE, "")
retval = retval:gsub(IS_USER_STEM_OVERRIDE, "")
if not saw_is_user_form_override then
-- Devoice final voiced obstruent (cf. pres_2s 'caps', pres_3s 'cap' of [[cabre]]). But not after a
-- consonant (cf. pres_2s 'perds', pres_3s 'perd' of [[perdre]]), except for g -> c, which operates
-- even after a consonant (pres_1s 'resolc' of [[resoldre]], pres_1s 'tinc' of [[tenir]]).
retval = retval:gsub("g(s?)$", "c%1")
retval = rsub(retval, "(" .. V .. ")([bdj])(s?)$", function(before, voiced, after)
local devoice = {
b = "p",
d = "t",
j = "ig", -- pres_3s 'fuj' of [[fugir]] -> 'fuig'
}
return before .. devoice[voiced] .. after
end)
end
end
return retval
end
local function add3(base, slot, stems, endings, footnotes, allow_overrides)
if skip_slot(base, slot, allow_overrides) then
return
end
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(base, stem, ending, "is full word")
end
iut.add_forms(base.forms, slot, stems, endings, do_combine_stem_ending, nil, nil, footnotes)
end
local function insert_form(base, slot, form)
if not skip_slot(base, slot) then
iut.insert_form(base.forms, slot, form)
end
end
local function insert_forms(base, slot, forms)
if not skip_slot(base, slot) then
iut.insert_forms(base.forms, slot, forms)
end
end
local function add_single_stem_tense(base, slot_pref, stems, s1, s2, s3, p1, p2, p3)
local function addit(slot, ending)
add3(base, slot_pref .. "_" .. slot, stems, ending)
end
addit("1s", s1)
addit("2s", s2)
addit("3s", s3)
addit("1p", p1)
addit("2p", p2)
addit("3p", p3)
end
local function map_general(stemforms, fn)
return iut.map_forms(iut.convert_to_general_list_form(stemforms), fn)
end
local function flatmap_general(stemforms, fn)
return iut.flatmap_forms(iut.convert_to_general_list_form(stemforms), fn)
end
-- Given a stem ending in a conjugation vowel -a/-e/-i/-ï, split into stem base and conjugation vowel, converting the
-- stem base to "back" form if the conjugation vowel is front (hence 'torce' of [[tòrcer]] splits into 'torç' and 'e',
-- and 'fugi' of [[fugir]] splits into 'fuj' and 'i').
local function split_conj_vowel(stem)
local stem_base, conj_vowel = rmatch(stem, "^(.*)([aeiï])$")
if not stem_base then
error(("Internal error: Stem '%s' doesn't end in conjugation vowel a/e/i"):format(stem))
end
if conj_vowel == "ï" then
-- To simplify handling of ï, convert to i. It will be converted back to ï as necessary in
-- combine_stem_ending().
conj_vowel = "i"
end
if rfind(conj_vowel, front_vowel_c) then
stem_base = com.front_to_back(stem_base)
end
return stem_base, conj_vowel
end
local function construct_stems(base)
base.output_stems = {}
local stems = base.output_stems
local bst = base.input_stems
-- YUCK, see combine_stem_ending() for the necessity of is_pres_sub_stressed.
local function combine(stem, ending, is_pres_sub_stressed)
return combine_stem_ending(base, stem, ending, false, "dont include prefix", is_pres_sub_stressed)
end
stems.irreg = bst.irreg or bst.g_infix
-- NOTE: Some stems end in a conjugation or similar vowel, specifically:
-- * `stem` (ends in conjugation vowel -a/-e/-i);
-- * `stressed_stem` (likewise);
-- * `unstressed_stem` (likewise);
-- * `pres_unstressed` (which assumes the form of the gerund minus the -nt; note that `pres_stressed` does *NOT*
-- end in a conjugation vowel, but assumes the stem form; the value of pres_3s will be derived by adding -a for
-- -ar verbs and otherwise adding an -e prop vowel when required, as in [[cobrir]], and otherwise adding no
-- vowel);
-- * `pres_sub_stressed` (which assumes the form of pres_sub_3s and hence usually ends in -i, occasionally -a);
-- * `pres_sub_unstressed` (which assumes the form of pres_sub_1p minus the -m, hence ends in -e or -i).
-- Save stem for use in add_categories_and_annotation() for determining the conjugation class.
stems.stem = bst.stem or base.stem
local eix_infix_stem
if base.conj_vowel == "i" then
-- Save eix_infix value for use in add_categories_and_annotation() for determining whether consonant
-- alternations exist.
stems.eix_infix = bst.eix_infix or bst.g_infix and "-" or "+"
eix_infix_stem = flatmap_general(stems.eix_infix, function(form)
if form == "+" then
return map_general(stems.stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, "eixe")
end)
elseif form == "-" then
return stems.stem
else
return form
end
end)
end
local stressed_stem = bst.stressed_stem or eix_infix_stem or stems.stem
local unstressed_stem = bst.unstressed_stem or stems.stem
-- Add the 'g' that is characteristic of g-infix verbs. We remove a stem-final v, e.g. [[beure]] with stem 'beve'
-- becomes 'beg'.
local function add_g(stemforms)
return map_general(stemforms, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
stem_base = stem_base:gsub("v$", "")
return combine(stem_base, "g")
end)
end
-- Add the 'u' of the pres_3s that is characteristic of g-infix verbs (and conjugation vowel 'e', later removed).
-- We remove a stem-final v, as well as i as part of a diphthong, e.g. [[beure]] with stem 'beve' becomes 'beue'
-- and [[veure]] with stem 'veie' becomes 'veue' (but [[riure]] with stem 'rie' becomes 'riue' not '#rue'). We
-- don't add -u after a consonant, e.g. [[doldre]] with stem 'dole' becomes 'dole' not '#dolue'.
local function add_u(stemforms)
return map_general(stemforms, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
if stem_base:find("v$") then
stem_base = stem_base:gsub("v$", "")
else
stem_base = rsub(stem_base, "(" .. V .. ")i$", "%1")
end
-- Add u after vowel but not after another u, so we get pres_3p 'duen' of [[dur]] not '#duuen'.
if rfind(stem_base, V .. "$") and not stem_base:find("u$") then
return combine(stem_base, "u")
else
return stem_base
end
end)
end
local stressed_g_infix, unstressed_g_infix, g_infix_pres_stressed
if bst.g_infix then
local function flatmap_g_infix(default)
return flatmap_general(bst.g_infix, function(form)
if form == "+" then
return default
else
return form
end
end)
end
stressed_g_infix = flatmap_g_infix(add_g(stressed_stem))
unstressed_g_infix = flatmap_g_infix(add_g(unstressed_stem))
g_infix_pres_stressed = add_u(stressed_stem)
end
stems.pres_unstressed = bst.pres_unstressed or unstressed_stem
stems.pres_stressed =
-- If no_pres_stressed given, pres_stressed stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
bst.pres_stressed or
g_infix_pres_stressed or
map_general(stressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return stem_base
end)
stems.pres1s =
-- If no_pres_stressed given, pres1s stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
stressed_g_infix or
map_general(stems.pres_stressed, function(form)
return combine(form, "o")
end)
stems.pres3s =
-- If no_pres_stressed given, pres3s stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
bst.pres3s or
map_general(stems.pres_stressed, function(form)
if base.conj_vowel == "a" then
return combine(form, "a")
elseif rfind(form, C .. "[lr]$") and not rfind(form, V .. "ll$") then
return combine(form, "e")
else
return form
end
end)
stems.pres3p =
-- If no_pres_stressed given, pres3p stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
map_general(stems.pres_stressed, function(form)
return combine(form, "en")
end)
local function compute_impf_stem(with_accent)
return map_general(stems.pres_unstressed, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
if conj_vowel == "a" then
return combine(stem_base, with_accent and "àv" or "av")
elseif stem_base:find("i#?$") then
form = form:gsub("i#?$", "")
return combine(rmatch(stem_base, "^(.-)" .. V .. "*$"), with_accent and "èi" or "ei")
else
return combine(stem_base, with_accent and "í" or "i") -- i -> ï after a vowel
end
end)
end
stems.impf1 = bst.impf1 or compute_impf_stem(false)
stems.impf2 = bst.impf2 or compute_impf_stem(true)
stems.pret = bst.pret or
unstressed_g_infix and map_general(unstressed_g_infix,
function(form) return combine(form, "é") end
) or
map_general(unstressed_stem, function(form)
local accent_conj_vowel = {
a = "à",
e = "é",
i = "í",
}
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, accent_conj_vowel[conj_vowel])
end)
stems.fut = bst.fut or base.inf_stem
stems.cond = bst.cond or map_general(stems.fut, function(form) return combine(form, "í") end)
stems.pres_sub_stressed = bst.pres_sub_stressed or
stressed_g_infix and map_general(stressed_g_infix, function(form) return combine(form, "i") end) or
map_general(stressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, "i", "is pres_sub_stressed")
end)
stems.pres_sub_unstressed = bst.pres_sub_unstressed or
unstressed_g_infix and map_general(unstressed_g_infix, function(form) return combine(form, "e") end) or
map_general(unstressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, conj_vowel == "i" and conj_vowel or "e")
end)
stems.impf_sub = bst.impf_sub or map_general(stems.pret, function(form)
local stem_base = rmatch(form, "^(.*)à$") -- already in "back" form, no need to convert
if stem_base then
return combine(stem_base, "é")
else
return form
end
end)
stems.pp = bst.pp or
unstressed_g_infix and map_general(unstressed_g_infix,
function(form) return combine(form, "ud") end
) or
map_general(unstressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
-- use combine() so we get 'abduïd' from 'abdu-' of [[abduir]], 'seguid' from 'seg-' from [[seguir]], etc.
return combine(stem_base, (conj_vowel == "e" and "u" or conj_vowel) .. "d")
end)
end
local function a_to_e(base, stems, suffix)
return map_general(stems, function(form)
local stem_base = form:match("^(.-)a$")
if stem_base then
suffix = "e" .. suffix
else
stem_base = form
end
return combine_stem_ending(base, stem_base, suffix, "is full word")
end)
end
local function add_present_indic(base)
local stems = base.output_stems
local function addit(slot, stems, ending)
add3(base, "pres_" .. slot, stems, ending)
end
addit("1s", stems.pres1s, "")
insert_forms(base, "pres_2s", a_to_e(base, stems.pres3s, "s"))
addit("3s", stems.pres3s, "")
insert_forms(base, "pres_1p", a_to_e(base, stems.pres_unstressed, "m"))
insert_forms(base, "pres_2p", a_to_e(base, stems.pres_unstressed, "u"))
addit("3p", stems.pres3p, "")
end
local function add_present_subj(base)
local stems = base.output_stems
local function addit(slot, stems, ending)
add3(base, "pres_sub_" .. slot, stems, ending)
end
-- Regular -ar verb: [[amar]]: ami, amis, ami, amem, ameu, amin
-- Regular -re verb: [[batre]]: bati, batis, bati, batem, bateu, batin (same as -ar verb)
-- Regular -ir verb, no -eix- infix: [[dormir]]: dormi, dormis, dormi, dormim, dormiu, dormin
-- Regular -ir verb, -eix- infix: [[imprimir]]: imprimeixi, imprimeixis, imprimeixi, imprimim, imprimiu, imprimeixin
-- Stem changing in 123s/3p vs. 12p:
-- * -eix- infix (-eix- in all stressed forms: 123s/3p of pres ind/sub, 2s imp)
-- * [[collir]]: culli, cullis, culli, collim, colliu, cullin (cull- in all stressed forms)
-- * [[cabre]]: càpiga, càpigues, càpiga, capiguem, capigueu, càpiguen (also different endings)
addit("1s", stems.pres_sub_stressed, "")
insert_forms(base, "pres_sub_2s", a_to_e(base, stems.pres_sub_stressed, "s"))
addit("3s", stems.pres_sub_stressed, "")
addit("1p", stems.pres_sub_unstressed, "m")
addit("2p", stems.pres_sub_unstressed, "u")
insert_forms(base, "pres_sub_3p", a_to_e(base, stems.pres_sub_stressed, "n"))
end
local function add_finite_non_present(base)
local stems = base.output_stems
local function add_tense(slot, stem, s1, s2, s3, p1, p2, p3)
add_single_stem_tense(base, slot, stem, s1, s2, s3, p1, p2, p3)
end
add_tense("impf", stems.impf1, "a", "es", "a", nil, nil, "en")
add_tense("impf", stems.impf2, nil, nil, nil, "em", "eu", nil)
-- pret_1s ends in -í regardless of the normal vowel of the stem.
insert_forms(base, "pret_1s", map_general(stems.pret, function(form)
local stem_base, conj_vowel = rmatch(form, "^(.*)(" .. V .. ")$")
if not stem_base then
error(("Internal error: Preterite stem '%s' doesn't end in vowel"):format(form))
end
if rfind(conj_vowel, front_vowel_c) then
stem_base = com.front_to_back(stem_base)
end
-- Use combine_stem_ending() to handle back-to-front conversions, e.g. pegà -> peguí for [[pegar]] and ensure
-- that the prefix gets added.
return combine_stem_ending(base, stem_base, "í", "is full word") end))
-- * at the beginning of the ending means to remove an accent from the last vowel of the preterite stem.
add_tense("pret", stems.pret, nil, "*res", "", "rem", "reu", "*ren")
-- * at the beginning of the ending means to remove an accent from the last vowel of the imperfect subjunctive stem.
add_tense("impf_sub", stems.impf_sub, "s", "*ssis", "s", "ssim", "ssiu", "*ssin")
add_tense("fut", stems.fut, "é", "às", "à", "em", "eu", "an")
add_tense("cond", stems.cond, "*a", "*es", "*a", "em", "eu", "*en")
end
local function add_non_finite_forms(base)
local stems = base.output_stems
local function addit(slot, stems, ending, footnotes)
add3(base, slot, stems, ending, footnotes)
end
insert_form(base, "infinitive", {form = base.orig_verb})
-- Also insert "infinitive + reflexive pronoun" combinations if we're handling a reflexive verb. See comment below
-- for "gerund + reflexive pronoun" combinations.
if base.refl then
for _, persnum in ipairs(person_number_list) do
insert_form(base, "infinitive_" .. persnum, {form = base.orig_verb})
end
end
-- Gerunds don't have an umlaut over the i in cases like 'abduint' of 'abduir' (not '#abduïnt').
local pres_unstressed_no_umlaut = map_general(stems.pres_unstressed, function(form)
return rsub(form, "ï$", "i")
end)
addit("gerund", pres_unstressed_no_umlaut, "nt")
-- Also insert "gerund + reflexive pronoun" combinations if we're handling a reflexive verb. We insert exactly the
-- same form as for the bare gerund; later on in add_reflexive_or_fixed_clitic_to_forms(), we add the appropriate
-- clitic pronouns. It's important not to do this for non-reflexive verbs, because in that case, the clitic
-- pronouns won't be added, and {{ca-verb form of}} will wrongly consider all these combinations as possible
-- inflections of the bare gerund. Thanks to [[User:JeffDoozan]] for this bug fix.
if base.refl then
for _, persnum in ipairs(person_number_list) do
addit("gerund_" .. persnum, pres_unstressed_no_umlaut, "nt")
end
end
addit("pp_ms", stems.pp, "")
if not base.pp_inv then
addit("pp_fs", stems.pp, "a")
-- make_plural() handles the complexities of e.g. 'vist' of [[veure]] -> 'vistos'/'vists' and 'romàs' of
-- [[romandre]] -> 'romasos'. We need to use flatmap_general() because make_plural() may return more than one
-- plural, and we need to use map_general() on the result, applying combine_stem_ending(), to ensure that
-- prefixes get properly added and plurals like 'amads' of stem 'amad' of [[amar]] get converted to 'amats'.
insert_forms(base, "pp_mp", map_general(flatmap_general(stems.pp, function(form)
-- Remove any # indicating that an accent will be dropped; it will be dropped in any case by make_plural().
form = form:gsub("#$", "")
return com.make_plural(form, "m")
end), function(form)
return combine_stem_ending(base, form, "", "is full word")
end))
addit("pp_fp", stems.pp, "es")
end
end
local function add_imperatives(base)
if base.noimp then
return
end
-- Copy pres3s to imperative since they are almost always the same.
insert_forms(base, "imp_2s", iut.map_forms(base.forms.pres_3s, function(form) return form end))
-- Copy pres2p to imperative plural since they are almost always the same.
insert_forms(base, "imp_2p", iut.map_forms(base.forms.pres_2p, function(form) return form end))
-- Copy subjunctives to imperatives.
for _, persnum in ipairs({"3s", "1p", "3p"}) do
local from = "pres_sub_" .. persnum
local to = "imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form) return form end))
end
end
local function fix_double_umlauts(base)
for slot, forms in pairs(base.forms) do
for _, form in ipairs(forms) do
form.form = form.form:gsub("üï", "uï")
end
end
end
local function process_slot_overrides(base, filter_slot, reflexive_only)
local overrides = reflexive_only and base.basic_reflexive_only_overrides or base.basic_overrides
for slot, forms in pairs(overrides) do
if not filter_slot or filter_slot(slot) then
add3(base, slot, forms, "", nil, "allow overrides")
end
end
end
local function link_clitic(clitic)
return (clitic:gsub("([^ %-]+)", "[[%1]]"))
end
-- Prefix `form` with `clitic`, adding fixed text `between` between them. Add links as appropriate unless the user
-- requested no links. Check whether form already has brackets (as will be the case if the form has a fixed clitic).
local function prefix_clitic_to_form(base, clitic, between, form)
if base.alternant_multiword_spec.args.noautolinkverb then
return clitic .. between .. form
else
local clitic_pref = link_clitic(clitic) .. between
if form:find("%[%[") then
return clitic_pref .. form
else
return clitic_pref .. "[[" .. form .. "]]"
end
end
end
-- Suffix `form` with `clitic`. Add links as appropriate unless the user requested no links. Check whether form already
-- has brackets (as will be the case if the form has a fixed clitic).
local function suffix_clitic_to_form(base, clitic, form)
local autolink = not base.alternant_multiword_spec.args.noautolinkverb
if base.alternant_multiword_spec.args.noautolinkverb then
return form .. clitic
else
local clitic_suf = link_clitic(clitic)
if form:find("%[%[") then
return form .. clitic_suf
else
return "[[" .. form .. "]]" .. clitic_suf
end
end
end
-- Add a reflexive pronoun or fixed clitic (FIXME: not working), as appropriate to the base forms that were generated.
-- `do_joined` means to do only the forms where the pronoun is joined to the end of the form; otherwise, do only the
-- forms where it is not joined and precedes the form.
local function add_reflexive_or_fixed_clitic_to_forms(base, do_reflexive, do_joined)
for _, slotaccel in ipairs(base.alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
local persnum
if slot:find("[123]") then
persnum = slot:match("^.*_(.-)$")
else
persnum = "3s"
end
local function get_proclitic(form)
--if not do_reflexive then
-- return base.clitic
if form:find("^[aeiouh]") then
return proclitic_elided_person_number_to_reflexive_pronoun[persnum]
else
return proclitic_non_elided_person_number_to_reflexive_pronoun[persnum]
end
end
local function get_enclitic(form)
--if not do_reflexive then
-- return base.clitic
if rfind(form, C .. "$") or rfind(form, V .. "[iu]$") and not form:find("[gq]ui$") then
return enclitic_non_elided_person_number_to_reflexive_pronoun[persnum]
else
return enclitic_elided_person_number_to_reflexive_pronoun[persnum]
end
end
if base.forms[slot] then
if do_reflexive and slot:find("^pp_") or slot == "infinitive_linked" then
-- do nothing with reflexive past participles or with infinitive linked (handled at the end)
elseif slot:find("^neg_imp_") then
error("Internal error: Should not have forms set for negative imperative at this stage")
else
local slot_has_suffixed_clitic = slot:find("infinitive") or slot:find("gerund") or slot:find("^imp_")
-- Maybe generate non-reflexive parts and separated syntactic variants for use in
-- {{ca-verb form of}}. See comment in add_slots() above `need_special_verb_form_of_slots`.
-- Check for do_joined so we only run this code once.
if do_reflexive and do_joined and base.alternant_multiword_spec.source_template == "ca-verb form of" and
-- Skip personal variants of infinitives and gerunds so we don't think [[arrependendo]] is a
-- non-reflexive equivalent of [[arrependendo-me]].
not slot:find("infinitive_") and not slot:find("gerund_") then
-- Clone the forms because we will be destructively modifying them just below, adding the reflexive
-- pronoun.
insert_forms(base, slot .. "_non_reflexive", mw.clone(base.forms[slot]))
if slot_has_suffixed_clitic then
insert_forms(base, slot .. "_variant", iut.map_forms(base.forms[slot], function(form)
return prefix_clitic_to_form(base, get_proclitic(form), "... ", form)
end))
end
end
if slot_has_suffixed_clitic then
if do_joined then
-- Add clitic after form.
for _, form in ipairs(base.forms[slot]) do
form.form = suffix_clitic_to_form(base, get_enclitic(form.form), form.form)
end
end
elseif not do_joined then
-- Add clitic before form.
for _, form in ipairs(base.forms[slot]) do
form.form = prefix_clitic_to_form(base, get_proclitic(form.form), "", form.form)
end
end
end
end
end
end
local function handle_infinitive_linked(base)
-- Compute linked versions of potential lemma slots, for use in {{ca-verb}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs({"infinitive"}) do
insert_forms(base, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.lemma and rfind(base.linked_lemma, "%[%[") then
return base.linked_lemma
else
return form
end
end))
end
end
local function generate_negative_imperatives(base)
if base.noimp then
return
end
-- Copy subjunctives to negative imperatives, preceded by "no".
for _, persnum in ipairs(neg_imp_person_number_list) do
local from = "pres_sub_" .. persnum
local to = "neg_imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form)
if base.alternant_multiword_spec.args.noautolinkverb then
return "no " .. form
elseif form:find("%[%[") then
-- already linked, e.g. when reflexive
return "[[no]] " .. form
else
return "[[no]] [[" .. form .. "]]"
end
end))
end
end
-- Process specs given by the user using 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'.
local function process_addnote_specs(base)
for _, spec in ipairs(base.addnote_specs) do
for _, slot_spec in ipairs(spec.slot_specs) do
slot_spec = "^" .. slot_spec .. "$"
for slot, forms in pairs(base.forms) do
if rfind(slot, slot_spec) then
-- To save on memory, side-effect the existing forms.
for _, form in ipairs(forms) do
form.footnotes = iut.combine_footnotes(form.footnotes, spec.footnotes)
end
end
end
end
end
end
local function add_missing_links_to_forms(base)
-- Any forms without links should get them now. Redundant ones will be stripped later.
for slot, forms in pairs(base.forms) do
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
form.form = "[[" .. form.form .. "]]"
end
end
end
end
local function conjugate_verb(base)
construct_stems(base)
add_present_indic(base)
add_present_subj(base)
add_finite_non_present(base)
add_non_finite_forms(base)
fix_double_umlauts(base)
-- do non-reflexive non-imperative slot overrides
process_slot_overrides(base, function(slot)
return not slot:find("^imp_") and not slot:find("^neg_imp_")
end)
-- This should happen after process_slot_overrides() in case a derived slot is based on an override
-- (as with the imp_3s of [[dar]], [[estar]]).
add_imperatives(base)
-- do non-reflexive positive imperative slot overrides
process_slot_overrides(base, function(slot)
return slot:find("^imp_")
end)
-- We need to add joined reflexives, then joined and non-joined clitics, then non-joined reflexives, so we get
-- [[arrepéndete]] but [[no]] [[te]] [[arrependas]].
if base.refl then
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", "do joined")
process_slot_overrides(base, nil, "do reflexive") -- do reflexive-only slot overrides
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", false)
end
-- This should happen after add_reflexive_or_fixed_clitic_to_forms() so negative imperatives get the reflexive pronoun
-- and clitic in them.
generate_negative_imperatives(base)
-- do non-reflexive negative imperative slot overrides
-- FIXME: What about reflexive negative imperatives?
process_slot_overrides(base, function(slot)
return slot:find("^neg_imp_")
end)
-- This should happen before add_missing_links_to_forms() so that the comparison `form == base.lemma`
-- in handle_infinitive_linked() works correctly and compares unlinked forms to unlinked forms.
handle_infinitive_linked(base)
process_addnote_specs(base)
if not base.alternant_multiword_spec.args.noautolinkverb then
add_missing_links_to_forms(base)
end
end
local function parse_indicator_spec(angle_bracket_spec)
-- Store the original angle bracket spec so we can reconstruct the overall conj spec with the lemma(s) in them.
local base = {
angle_bracket_spec = angle_bracket_spec,
user_basic_overrides = {},
user_stems = {},
addnote_specs = {},
}
local function parse_err(msg)
error(msg .. ": " .. angle_bracket_spec)
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
parse_err("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
table.insert(footnotes, separated_group[j])
end
return footnotes
end
local inside = angle_bracket_spec:match("^<(.*)>$")
assert(inside)
if inside == "" then
return base
end
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = put.split_alternating_runs(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local first_element = dot_separated_group[1]
if first_element == "addnote" then
local spec_and_footnotes = fetch_footnotes(dot_separated_group)
if #spec_and_footnotes < 2 then
parse_err("Spec with 'addnote' should be of the form 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'")
end
local slot_spec = table.remove(spec_and_footnotes, 1)
local slot_spec_inside = rmatch(slot_spec, "^%[(.*)%]$")
if not slot_spec_inside then
parse_err("Internal error: slot_spec " .. slot_spec .. " should be surrounded with brackets")
end
local slot_specs = rsplit(slot_spec_inside, ",")
-- FIXME: Here, [[Module:it-verb]] called strip_spaces(). Generally we don't do this. Should we?
table.insert(base.addnote_specs, {slot_specs = slot_specs, footnotes = spec_and_footnotes})
elseif indicator_flags[first_element] then
if #dot_separated_group > 1 then
parse_err("No footnotes allowed with '" .. first_element .. "' spec")
end
if base[first_element] then
parse_err("Spec '" .. first_element .. "' specified twice")
end
base[first_element] = true
elseif first_element:find("^var:") then
if #dot_separated_group > 1 then
parse_err(("Can't attach footnotes to 'var:' spec '%s'"):format(first_element))
end
base.var = first_element:match("^var:(.*)$")
elseif first_element:find(":") then
local colon_separated_groups = put.split_alternating_runs(dot_separated_group, "%s*:%s*")
local first_element = colon_separated_groups[1][1]
if #colon_separated_groups[1] > 1 then
parse_err("Can't attach footnotes directly to '" .. first_element .. "' spec; attach them to the " ..
"colon-separated values following the initial colon")
end
if overridable_stems[first_element] then
if base.user_stems[first_element] then
parse_err("Overridable stem '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_stems[first_element] = overridable_stems[first_element](colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes})
else -- assume a basic override; we validate further later when the possible slots are available
if base.user_basic_overrides[first_element] then
parse_err("Basic override '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_basic_overrides[first_element] = allow_multiple_values_for_override(colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes},
"is form override")
end
else
parse_err("Unrecognized spec '" .. first_element .. "'")
end
end
return base
end
-- Normalize all lemmas, substituting the pagename for blank lemmas and adding links to multiword lemmas.
local function normalize_all_lemmas(alternant_multiword_spec, head)
-- (1) Add links to all before and after text. Remember the original text so we can reconstruct the verb spec later.
if not alternant_multiword_spec.args.noautolinktext then
iut.add_links_to_before_and_after_text(alternant_multiword_spec, "remember original")
end
-- (2) Remove any links from the lemma, but remember the original form so we can use it below in the 'lemma_linked'
-- form.
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.lemma == "" then
base.lemma = head
end
base.user_specified_lemma = base.lemma
base.lemma = m_links.remove_links(base.lemma)
local refl_verb = base.lemma
local verb, refl = rmatch(refl_verb, "^(.-)%-(se)$")
if not verb then
verb, refl = rmatch(refl_verb, "^(.-)('s)$")
end
if not verb then
verb, refl = refl_verb, nil
end
base.user_specified_verb = verb
base.refl = refl
base.verb = base.user_specified_verb
local linked_lemma
if alternant_multiword_spec.args.noautolinkverb or base.user_specified_lemma:find("%[%[") then
linked_lemma = base.user_specified_lemma
elseif base.refl then
-- Reconstruct the linked lemma with separate links around base verb, reflexive pronoun and clitic.
linked_lemma = base.user_specified_verb == base.verb and "[[" .. base.user_specified_verb .. "]]" or
"[[" .. base.verb .. "|" .. base.user_specified_verb .. "]]"
linked_lemma = linked_lemma .. (refl and "-[[" .. refl .. "]]" or "")
else
-- Add links to the lemma so the user doesn't specifically need to, since we preserve links in multiword
-- lemmas and include links in non-lemma forms rather than allowing the entire form to be a link.
linked_lemma = iut.add_links(base.user_specified_lemma)
end
base.linked_lemma = linked_lemma
end)
end
local function detect_indicator_spec(base)
if (base.only3s and 1 or 0) + (base.only3sp and 1 or 0) + (base.only3p and 1 or 0) > 1 then
error("Only one of 'only3s', 'only3sp' and 'only3p' can be specified")
end
base.forms = {}
base.input_stems = {}
base.basic_overrides = {}
base.basic_reflexive_only_overrides = {}
base.orig_verb = base.verb -- in case of a 'like = "..."' redirect
if not base.no_built_in then
local function match_built_in_spec(verb, built_in_spec)
local prefix, non_prefixed_verb
if type(built_in_spec.match) == "function" then
prefix, non_prefixed_verb = built_in_spec.match(verb)
elseif built_in_spec.match:find("^%^") and rsub(built_in_spec.match, "^%^", "") == verb then
-- begins with ^, for exact match, and matches
prefix, non_prefixed_verb = "", verb
else
prefix, non_prefixed_verb = rmatch(verb, "^(.*)(" .. built_in_spec.match .. ")$")
end
return prefix, non_prefixed_verb
end
local function find_built_in(verb, var)
for _, built_in_spec in ipairs(built_in_conjugations) do
local prefix, non_prefixed_verb = match_built_in_spec(verb, built_in_spec)
if prefix then
if not built_in_spec.var then
if var then
error(("Can't specify a variant spec 'var:%s' with verb '%s'"):format(var, verb))
end
return prefix, non_prefixed_verb, built_in_spec
elseif not var then
local possible_vars = {}
for _, built_in_spec in ipairs(built_in_conjugations) do
local prefix, non_prefixed_verb = match_built_in_spec(verb, built_in_spec)
if prefix then
table.insert(possible_vars, built_in_spec.var)
end
end
error(("For verb '%s', must specify a variant using 'var:...'; possible values are %s"):format(
verb, table.concat(possible_vars, ", ")))
elseif built_in_spec.var == var then
return prefix, non_prefixed_verb, built_in_spec
end
end
end
return nil
end
local prefix, non_prefixed_verb, built_in_spec = find_built_in(base.verb, base.var)
if prefix then
-- we found a built-in verb
if built_in_spec.like then
-- we found a redirect to another verb that has the same conjugation, just a different infinitive
base.verb = prefix .. built_in_spec.like
local new_prefix, new_non_prefixed_verb, new_built_in_spec = find_built_in(base.verb, built_in_spec.likevar)
if new_prefix then
-- redirected to another built-in verb
base.prefix = new_prefix
base.non_prefixed_verb = new_non_prefixed_verb
built_in_spec = new_built_in_spec
else
built_in_spec = nil
end
else
base.prefix = prefix
base.non_prefixed_verb = non_prefixed_verb
end
end
if built_in_spec then
-- we found a built-in verb, possibly redirecting to another built-in verb
for stem, forms in pairs(built_in_spec.forms) do
if type(forms) == "function" then
forms = forms(base, base.prefix)
end
if stem:find("^refl_") then
stem = stem:gsub("^refl_", "")
if not base.alternant_multiword_spec.verb_slots_basic_map[stem] then
error("Internal error: setting for 'refl_" .. stem .. "' does not refer to a basic verb slot")
end
base.basic_reflexive_only_overrides[stem] = forms
elseif base.alternant_multiword_spec.verb_slots_basic_map[stem] then
-- an individual form override of a basic form
base.basic_overrides[stem] = forms
else
base.input_stems[stem] = forms
end
end
end
end
-- Override built-in-verb stems and overrides with user-specified ones.
for stem, values in pairs(base.user_stems) do
base.input_stems[stem] = values
end
for override, values in pairs(base.user_basic_overrides) do
if not base.alternant_multiword_spec.verb_slots_basic_map[override] then
error("Unrecognized override '" .. override .. "': " .. base.angle_bracket_spec)
end
base.basic_overrides[override] = values
end
base.prefix = base.prefix or ""
base.non_prefixed_verb = base.non_prefixed_verb or base.verb
local inf_stem, suffix = rmatch(base.non_prefixed_verb, "^(.*)(re)$")
if not inf_stem then
inf_stem, suffix = rmatch(base.non_prefixed_verb, "^(.*)([aeiu]r)$")
end
if not inf_stem then
error("Unrecognized infinitive: " .. base.verb)
end
-- Remove accents from e.g. [[parèixer]], [[córrer]].
inf_stem = com.remove_accents(inf_stem)
-- Save full infinitive stem for use in future and conditional.
base.inf_stem = (inf_stem .. suffix):gsub("e$", "")
local stem = inf_stem
if suffix == "re" then
-- verbs in -ldre, -ndre have stem without the d
stem = stem:gsub("([ln])d$", "%1")
elseif suffix == "ur" then
stem = stem .. "u"
end
base.conj_vowel = (suffix == "re" or suffix == "ur") and "e" or suffix:gsub("r$", "")
-- If the stem is followed by a front vowel, convert it to its "back" form before calling combine_stem_ending(),
-- which expects the "back" form of the stem and may convert it back to the "front" form. Don't do this conversion
-- for ï so we leave [[arguïr]] (underlyingly 'argüïr') as 'argu' ("back" form), which becomes 'argü' ("front" form)
-- before front vowel ï and we end up with base.stem containing the underlying form 'argüï'. We remove the first of
-- two umlauts in a row in a postprocessing step (fix_double_umlauts()).
if rfind(suffix, "^[ei]") then
stem = com.front_to_back(stem)
end
-- Use combine_stem_ending() so we get ï if necessary.
base.stem = combine_stem_ending(base, stem, base.conj_vowel, false, "dont include prefix")
-- Propagate built-in-verb indicator flags to `base` and combine with user-specified flags.
for indicator_flag, _ in pairs(indicator_flags) do
base[indicator_flag] = base[indicator_flag] or base.input_stems[indicator_flag]
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
-- Propagate some settings up; some are used internally, others by [[Module:pt-headword]].
iut.map_word_specs(alternant_multiword_spec, function(base)
-- Internal indicator flags. Do these before calling detect_indicator_spec() because add_slots() uses them.
for _, prop in ipairs { "refl", "clitic" } do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
base.alternant_multiword_spec = alternant_multiword_spec
end)
add_slots(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(base)
-- User-specified indicator flags. Do these after calling detect_indicator_spec() because the latter may set these
-- indicators for built-in verbs.
for prop, _ in pairs(indicator_flags) do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
end)
end
local function add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
local function insert_ann(anntype, value)
m_table.insertIfNot(alternant_multiword_spec.annotation[anntype], value)
end
local function insert_cat(cat, also_when_multiword)
-- Don't place multiword terms in categories like 'Catalan verbs ending in -ar' to avoid spamming the
-- categories with such terms.
if also_when_multiword or not multiword_lemma then
-- m_table.insertIfNot(alternant_multiword_spec.categories, "Catalan " .. cat)
end
end
if check_for_red_links and alternant_multiword_spec.source_template == "ca-conj" and multiword_lemma then
for _, slot_and_accel in ipairs(alternant_multiword_spec.all_verb_slots) do
local slot = slot_and_accel[1]
local forms = base.forms[slot]
local must_break = false
if forms then
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
local title = mw.title.new(form.form)
if title and not title.exists then
-- insert_cat("verbs with red links in their inflection tables")
must_break = true
break
end
end
end
end
if must_break then
break
end
end
end
map_general(base.output_stems.stem, function(stem)
local stem_base, conj_vowel = split_conj_vowel(stem)
local need_no_eix_infix = true
if conj_vowel ~= base.conj_vowel then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Irregular verbs|သမ္ဗန္ဓပံၚ်ဖနှဴ]]")
-- insert_cat("mixed conjugation verbs")
elseif conj_vowel == "a" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#First conjugation|သမ္ဗန္ဓပထမ]]")
-- insert_cat("first conjugation verbs")
elseif conj_vowel == "e" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Second conjugation|သမ္ဗန္ဓဒုတိယ]]")
-- insert_cat("second conjugation verbs")
elseif conj_vowel == "i" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Third conjugation|သမ္ဗန္ဓတတိယ]]")
-- insert_cat("third conjugation verbs")
need_no_eix_infix = false
map_general(base.output_stems.eix_infix, function(form)
if form == "+" then
insert_ann("eix_infix", "with ''-eix-''")
-- insert_cat("third conjugation verbs with -eix-")
elseif form == "-" then
insert_ann("eix_infix", "without ''-eix-''")
-- insert_cat("third conjugation verbs without -eix-")
end
end)
else
error(("Internal error: Stem '%s' doesn't end in conjugation vowel a/e/i and split_conj_vowel() didn't catch it"
):format(stem))
end
if need_no_eix_infix then
insert_ann("eix_infix", "no infix")
end
end)
if base.input_stems.g_infix then
insert_ann("g_infix", "with velar infix")
-- insert_cat("verbs with velar infix")
else
insert_ann("g_infix", "no infix")
end
if base.output_stems.irreg then
insert_ann("irreg", "irregular")
-- insert_cat("irregular verbs")
else
insert_ann("irreg", "regular")
end
if base.only3s then
insert_ann("defective", "impersonal")
-- insert_cat("impersonal verbs")
elseif base.only3sp then
insert_ann("defective", "third-person only")
-- insert_cat("third-person-only verbs")
elseif base.only3p then
insert_ann("defective", "third-person plural only")
-- insert_cat("third-person-plural-only verbs")
elseif base.no_pres_stressed then
insert_ann("defective", "defective")
-- insert_cat("defective verbs")
else
insert_ann("defective", "regular")
end
--if base.clitic then
-- insert_cat("verbs with lexical clitics")
--end
if base.refl then
-- insert_cat("reflexive verbs")
end
local stem_base, conj_vowel = split_conj_vowel(base.stem)
local cons_alt
if conj_vowel == "i" and base.output_stems.eix_infix == "+" then
-- no alternations in verbs like [[afligir]] because all endings are front
elseif stem_base:find("ç$") then
cons_alt = "ç-c"
elseif stem_base:find("c$") then
cons_alt = "c-qu"
elseif stem_base:find("g$") then
cons_alt = "g-gu"
elseif stem_base:find("gu$") then
cons_alt = "gu-gü"
elseif stem_base:find("j$") then
cons_alt = "j-g"
elseif stem_base:find("qu$") then
cons_alt = "qu-qü"
end
if cons_alt then
local desc = cons_alt .. " alternation"
insert_ann("cons_alt", desc)
-- insert_cat("verbs with " .. desc)
else
insert_ann("cons_alt", "non-alternating")
end
end
-- Compute the categories to add the verb to, as well as the annotation to display in the
-- conjugation title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
local ann = {}
alternant_multiword_spec.annotation = ann
ann.conj = {}
ann.g_infix = {}
ann.eix_infix = {}
ann.irreg = {}
ann.defective = {}
ann.cons_alt = {}
local multiword_lemma = false
for _, form in ipairs(alternant_multiword_spec.forms.infinitive) do
if form.form:find(" ") then
multiword_lemma = true
break
end
end
iut.map_word_specs(alternant_multiword_spec, function(base)
add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
end)
local ann_parts = {}
local conj = table.concat(ann.conj, " or ")
if conj ~= "" then
table.insert(ann_parts, conj)
end
local eix_infix = table.concat(ann.eix_infix, " or ")
if eix_infix ~= "" and eix_infix ~= "no infix" then
table.insert(ann_parts, eix_infix)
end
local irreg = table.concat(ann.irreg, " or ")
if irreg ~= "" and irreg ~= "regular" then
table.insert(ann_parts, irreg)
end
local g_infix = table.concat(ann.g_infix, " or ")
if g_infix ~= "" and g_infix ~= "no infix" then
table.insert(ann_parts, g_infix)
end
local defective = table.concat(ann.defective, " or ")
if defective ~= "" and defective ~= "regular" then
table.insert(ann_parts, defective)
end
local cons_alt = table.concat(ann.cons_alt, " or ")
if cons_alt ~= "" and cons_alt ~= "non-alternating" then
table.insert(ann_parts, cons_alt)
end
alternant_multiword_spec.annotation = table.concat(ann_parts, ", ")
end
local function show_forms(alternant_multiword_spec)
local lemmas = alternant_multiword_spec.forms.infinitive
alternant_multiword_spec.lemmas = lemmas -- save for later use in make_table()
local reconstructed_verb_spec = iut.reconstruct_original_spec(alternant_multiword_spec)
local function transform_accel_obj(slot, formobj, accel_obj)
-- No accelerators for negative imperatives, which are always multiword and derived directly from the
-- present subjunctive.
if slot:find("^neg_imp") then
return nil
end
if accel_obj then
accel_obj.form = "verb-form-" .. reconstructed_verb_spec
end
return accel_obj
end
local props = {
lang = lang,
lemmas = lemmas,
transform_accel_obj = transform_accel_obj,
slot_list = alternant_multiword_spec.verb_slots_basic,
}
iut.show_forms(alternant_multiword_spec.forms, props)
alternant_multiword_spec.footnote_basic = alternant_multiword_spec.forms.footnote
end
local notes_template = [=[
<div class="roa-footnote-outer-div" style="width:100%;">
<div class="roa-footnote-inner-div">
{footnote}
</div></div>
]=]
local basic_table = [=[
{description}<div class="NavFrame">
<div class="NavHead"> Central Catalan conjugation of {title}</div>
<div class="NavContent">
{\op}| class="roa-inflection-table" data-toggle-category="inflection"
|-
! colspan="3" class="roa-nonfinite-header" | <span title="infinitiu">ကြိယာဟွံကၠောံ</span>
| colspan="5" | {infinitive}
|-
! colspan="3" class="roa-nonfinite-header" | <span title="gerundi">ကြိယာစၞး</span>
| colspan="5" | {gerund}
|-
! rowspan="3" colspan="2" class="roa-nonfinite-header" | <span title="participi passat">လုပ်ကၠောန်စွံလဝ်နကဵုအတိက်</span>
| colspan="2" class="roa-nonfinite-header" |
! colspan="2" class="roa-nonfinite-header" | ပုလ္လိၚ်
! colspan="2" class="roa-nonfinite-header" | ဣတ္တိလိၚ်
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဨကဝုစ်
| colspan="2" | {pp_ms}
| colspan="2" | {pp_fs}
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဗဟုဝစ်
| colspan="2" | {pp_mp}
| colspan="2" | {pp_fp}
|-
! colspan="2" rowspan="2" class="roa-person-number-header" | ပူဂဵု
! colspan="3" class="roa-person-number-header" | ကိုန်ဨကဝုစ်
! colspan="3" class="roa-person-number-header" | ကိုန်ဗဟုဝစ်
|-
! class="roa-person-number-header" style="width:12.5%;" | ပထမ
! class="roa-person-number-header" style="width:12.5%;" | ဒုတိယ
! class="roa-person-number-header" style="width:12.5%;" | တတိယ
! class="roa-person-number-header" style="width:12.5%;" | ပထမ
! class="roa-person-number-header" style="width:12.5%;" | ဒုတိယ
! class="roa-person-number-header" style="width:12.5%;" | တတိယ
|-
! rowspan="6" class="roa-indicative-left-rail" | <span title="indicatiu">ပရေၚ်စၞောန်ထ္ၜး</span>
! class="roa-indicative-left-rail" |
! class="roa-indicative-left-rail" | <<jo>>
! class="roa-indicative-left-rail" | <<tu>>
! class="roa-indicative-left-rail" | <<ell>>/<<ella>><br /><<vostè>>
! class="roa-indicative-left-rail" | <<nosaltres>><br /><<nós>>
! class="roa-indicative-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-indicative-left-rail" | <<ells>>/<<elles>><br /><<vostès>>
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="present">ပစ္စုပ္ပန်</span>
| {pres_1s}
| {pres_2s}
| {pres_3s}
| {pres_1p}
| {pres_2p}
| {pres_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="imperfet">ဟွံဍိုက်ပေၚ်</span>
| {impf_1s}
| {impf_2s}
| {impf_3s}
| {impf_1p}
| {impf_2p}
| {impf_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="futur">အနာဂတ်</span>
| {fut_1s}
| {fut_2s}
| {fut_3s}
| {fut_1p}
| {fut_2p}
| {fut_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="passat">မပြဟ်လောန်</span>
| {pret_1s}
| {pret_2s}
| {pret_3s}
| {pret_1p}
| {pret_2p}
| {pret_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="condicional">တၚ်မကၞာတ်လဝ်စေဝ်ပၞောန်</span>
| {cond_1s}
| {cond_2s}
| {cond_3s}
| {cond_1p}
| {cond_2p}
| {cond_3p}
|-
! class="roa-subjunctive-left-rail" rowspan="3" | <span title="subjuntiu">အရေဝ်နိဒါန်</span>
! class="roa-subjunctive-left-rail" |
! class="roa-subjunctive-left-rail" | <<jo>>
! class="roa-subjunctive-left-rail" | <<tu>>
! class="roa-subjunctive-left-rail" | <<ell>>/<<ella>><br /><<vostè>>
! class="roa-subjunctive-left-rail" | <<nosaltres>><br /><<nós>>
! class="roa-subjunctive-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-subjunctive-left-rail" | <<ells>>/<<elles>><br /><<vostès>>
|-
! class="roa-subjunctive-left-rail" style="height:3em;" | <span title="present">ပစ္စုပ္ပန်</span>
| {pres_sub_1s}
| {pres_sub_2s}
| {pres_sub_3s}
| {pres_sub_1p}
| {pres_sub_2p}
| {pres_sub_3p}
|-
! class="roa-subjunctive-left-rail" style="height:3em;" rowspan="1" | <span title="imperfet">ဟွံဍိုက်ပေၚ်</span>
| {impf_sub_1s}
| {impf_sub_2s}
| {impf_sub_3s}
| {impf_sub_1p}
| {impf_sub_2p}
| {impf_sub_3p}
|-
! rowspan="3" class="roa-imperative-left-rail" style="height:3em;" | <span title="imperatiu">ပါဲဗလေတ်ဟွံဗၠး</span>
! class="roa-imperative-left-rail" |
! class="roa-imperative-left-rail" | —
! class="roa-imperative-left-rail" | <<tu>>
! class="roa-imperative-left-rail" | <<vostè>>
! class="roa-imperative-left-rail" | <<nosaltres>>
! class="roa-imperative-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-imperative-left-rail" | <<vostès>>
|-
! class="roa-imperative-left-rail" style="height:3em;" | <span title="afirmatiu">တၚ်ဂလာန်ဗိုန်ဗတ်</span>
| —
| {imp_2s}
| {imp_3s}
| {imp_1p}
| {imp_2p}
| {imp_3p}
|-
! class="roa-imperative-left-rail" style="height:3em;" | <span title="negatiu">ကယျာန်ပါဲ</span> (<<no>>)
| —
| {neg_imp_2s}
| {neg_imp_3s}
| {neg_imp_1p}
| {neg_imp_2p}
| {neg_imp_3p}
|{\cl}{notes_clause}</div></div>]=]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
forms.title = link_term(alternant_multiword_spec.lemmas[1].form, nil, "term")
local ann_parts = {}
if alternant_multiword_spec.annotation ~= "" then
table.insert(ann_parts, alternant_multiword_spec.annotation)
end
if alternant_multiword_spec.args.titlenote then
table.insert(ann_parts, alternant_multiword_spec.args.titlenote)
end
local annotation = table.concat(ann_parts, ", ")
if annotation ~= "" then
forms.title = forms.title .. " (" .. annotation .. ")"
end
forms.description = ""
-- Format the table.
forms.footnote = alternant_multiword_spec.footnote_basic
forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or ""
local table_with_pronouns = rsub(basic_table, "<<([^<>|]-)|([^<>|]-)>>", link_term)
local table_with_pronouns = rsub(table_with_pronouns, "<<(.-)>>", link_term)
return require("Module:TemplateStyles")("Module:roa-verb/style.css") ..
m_string_utilities.format(table_with_pronouns, forms)
end
-- Externally callable function to parse and conjugate a verb given user-specified arguments.
-- Return value is WORD_SPEC, an object where the conjugated forms are in `WORD_SPEC.forms`
-- for each slot. If there are no values for a slot, the slot key will be missing. The value
-- for a given slot is a list of objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(args, source_template, headword_head)
local PAGENAME = mw.loadData("Module:headword/data").pagename
local function in_template_space()
return mw.title.getCurrentTitle().nsText == "ထာမ်ပလိက်"
end
-- Determine the verb spec we're being asked to generate the conjugation of. This may be taken from the
-- current page title or the value of |pagename=; but not when called from {{ca-verb form of}}, where the
-- page title is a non-lemma form. Note that the verb spec may omit the infinitive; e.g. it may be "<i-e>".
-- For this reason, we use the value of `pagename` computed here down below, when calling normalize_all_lemmas().
local pagename = source_template ~= "ca-verb form of" and args.pagename or PAGENAME
local head = headword_head or pagename
local arg1 = args[1]
if not arg1 then
if (pagename == "ca-conj" or pagename == "ca-verb" or pagename == "ca-verb form of") and in_template_space() then
arg1 = "amar<>"
else
arg1 = "<>"
end
end
-- When called from {{ca-verb form of}}, determine the non-lemma form whose inflections we're being asked to
-- determine. This normally comes from the page title or the value of |pagename=.
local verb_form_of_form
if source_template == "ca-verb form of" then
verb_form_of_form = args.pagename
if not verb_form_of_form then
if PAGENAME == "ca-verb form of" and in_template_space() then
verb_form_of_form = "ami"
else
verb_form_of_form = PAGENAME
end
end
end
local incorporated_headword_head_into_lemma = false
if arg1:find("^<.*>$") then -- missing lemma
if head:find(" ") then
-- If multiword lemma, try to add arg spec after the first word.
-- Try to preserve the brackets in the part after the verb, but don't do it
-- if there aren't the same number of left and right brackets in the verb
-- (which means the verb was linked as part of a larger expression).
local refl_clitic_verb, post = rmatch(head, "^(.-)( .*)$")
local left_brackets = rsub(refl_clitic_verb, "[^%[]", "")
local right_brackets = rsub(refl_clitic_verb, "[^%]]", "")
if #left_brackets == #right_brackets then
arg1 = iut.remove_redundant_links(refl_clitic_verb) .. arg1 .. post
incorporated_headword_head_into_lemma = true
else
-- Try again using the form without links.
local linkless_head = m_links.remove_links(head)
if linkless_head:find(" ") then
refl_clitic_verb, post = rmatch(linkless_head, "^(.-)( .*)$")
arg1 = refl_clitic_verb .. arg1 .. post
else
error("Unable to incorporate <...> spec into explicit head due to a multiword linked verb or " ..
"unbalanced brackets; please include <> explicitly: " .. arg1)
end
end
else
-- Will be incorporated through `head` below in the call to normalize_all_lemmas().
incorporated_headword_head_into_lemma = true
end
end
local function split_bracketed_runs_into_words(bracketed_runs)
return put.split_alternating_runs(bracketed_runs, " ", "preserve splitchar")
end
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
-- Split words only on spaces, not on hyphens, because that messes up reflexive verb parsing.
split_bracketed_runs_into_words = split_bracketed_runs_into_words,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.pos = pos or "ကြိယာ"
alternant_multiword_spec.args = args
alternant_multiword_spec.source_template = source_template
alternant_multiword_spec.verb_form_of_form = verb_form_of_form
alternant_multiword_spec.incorporated_headword_head_into_lemma = incorporated_headword_head_into_lemma
normalize_all_lemmas(alternant_multiword_spec, head)
detect_all_indicator_specs(alternant_multiword_spec)
local inflect_props = {
slot_list = alternant_multiword_spec.all_verb_slots,
inflect_word_spec = conjugate_verb,
-- We add links around the generated verbal forms rather than allow the entire multiword
-- expression to be a link, so ensure that user-specified links get included as well.
include_user_specified_links = true,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- Remove redundant brackets around entire forms.
for slot, forms in pairs(alternant_multiword_spec.forms) do
for _, form in ipairs(forms) do
form.form = iut.remove_redundant_links(form.form)
end
end
compute_categories_and_annotation(alternant_multiword_spec)
if args.json and source_template == "ca-conj" then
return require("Module:JSON").toJSON(alternant_multiword_spec.forms)
end
return alternant_multiword_spec
end
-- Entry point for {{ca-conj}}. Template-callable function to parse and conjugate a verb given
-- user-specified arguments and generate a displayable table of the conjugated forms.
function export.show(frame)
local parent_args = frame:getParent().args
local params = {
[1] = {},
["titlenote"] = {},
["noautolinktext"] = {type = "boolean"},
["noautolinkverb"] = {type = "boolean"},
["pagename"] = {}, -- for testing/documentation pages
["json"] = {type = "boolean"}, -- for bot use
}
local args = require("Module:parameters").process(parent_args, params)
local alternant_multiword_spec = export.do_generate_forms(args, "ca-conj")
if type(alternant_multiword_spec) == "string" then
-- JSON return value
return alternant_multiword_spec
end
show_forms(alternant_multiword_spec)
return make_table(alternant_multiword_spec) ..
require("Module:utilities").format_categories(alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
return export
qto1t31h2a5f1o8d6u8i80to94dmplx
397726
397723
2026-06-30T14:33:44Z
咽頭べさ
33
397726
Scribunto
text/plain
--[=[
This module implements {{ca-conj}} and provides the underlying conjugation functions for {{ca-verb}}
(whose actual formatting is done in [[Module:ca-headword]]).
Authorship: Ben Wing <benwing2>
]=]
local export = {}
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of tense/mood/person/number/etc.
Example slot names for verbs are "pres_1s" (present indicative first-person singular), "pres_sub_2s" (present
subjunctive second-person singular) "impf_sub_3p" (imperfect subjunctive third-person plural).
Each slot is filled with zero or more forms.
-- "form" = The conjugated Catalan form representing the value of a given slot.
-- "lemma" = The dictionary form of a given Catalan term. For Catalan, always the infinitive.
]=]
--[=[
FIXME:
--]=]
local lang = require("Module:languages").getByCode("ca")
local m_string_utilities = require("Module:string utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:ca-common")
local force_cat = false -- set to true for debugging
local check_for_red_links = false -- set to false for debugging
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local rsubn = mw.ustring.gsub
local rsub = com.rsub
local u = mw.ustring.char
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
-- version of rsubn() that returns a 2nd argument boolean indicating whether a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
local function link_term(term, display, face)
return m_links.full_link({ lang = lang, term = term, alt = display }, face)
end
local front_vowel = "eèéiíï"
local front_vowel_c = "[" .. front_vowel .. "]"
local V = com.V -- vowel regex class
local C = com.C -- consonant regex class
-- IS_USER_STEM_OVERRIDE is prepended to user-supplied stem overrides to prevent `base.prefix` from being prepended.
-- IS_USER_FORM_OVERRIDE is similar but also prevents final devoicing (cf. Balearic pres_1s 'trob' of [[trobar]]).
-- Don't use 0xFFF0 in case we call a [[Module:parse-utilities]] function that uses it temporarily.
local IS_USER_STEM_OVERRIDE = u(0xFFF1)
local IS_USER_FORM_OVERRIDE = u(0xFFF2)
--[=[
Irregular verbs:
-ldre/-ndre verbs:
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
caldre - cal [calent] calia caldrà calgué calgui - calgut,-
coldre colc col colem colia coldré colguí colgui colguem colt,colta
doldre dolc dol dolem dolia doldré dolguí dolgui dolguem dolgut,dolguda
moldre molc mol molem molia moldré molguí molgui molguem molt,molta
oldre olc ol olem olia oldré olguí olgui olguem olgut,olguda
-soldre -solc -sol -solem -solia -soldré -solguí -solgui -solguem -solt,-solta
(absoldre, dissoldre, resoldre)
toldre tolc tol tolem tolia toldré tolguí tolgui tolguem tolt,tolta
romandre romanc roman romanem romania romandré romanguí romangui romanguem romàs,romasa,romasos
encendre encenc encén encenem encenia encendré encenguí encengui encenguem encès,encesa,encesos
fendre fenc fen/-fèn fenem fenia fendré fenguí fengui fenguem fes/-fès,fesa,fesos
(defendre, ofendre)
-pendre -depenc -pèn -penem -penia -pendré -penguí -pengui -penguem -pès,-pesa,-pesos
(dependre,despendre,expendre,suspendre)
prendre prenc pren/-prèn prenem prenia prendré prenguí prengui prenguem pres/-près,presa,presos
(aprendre, comprendre, desprendre, emprendre, reprendre, sorprendre)
-tendre -tenc -tén -tenem -tenia -tendré -tenguí -tengui -tenguem -tès,-tesa,-tesos
(pres2s: atens, pres3p: atenen)
(atendre, contendre, distendre, entendre, estendre, pretendre)
vendre venc ven venem venia vendré venguí vengui venguem venut,venuda
(malvendre, revendre)
fondre fonc fon fonem fonia fondré fonguí fongui fonguem fos/-fós,fosa,fosos
(confondre, difondre, infondre, refondre)
enfondre enfonc enfon enfonem enfonia enfondré enfonguí enfongui enfonguem enfús,enfusa,enfusos
pondre ponc pon ponem ponia pondré ponguí pongui ponguem post,posta,postos
(compondre, correspondre, descompondre, respondre)
tondre tonc ton tonem tonia tondré tonguí tongui tonguem tos,tosa,tosos
cerndre cerno cern cernem cernia cerndré cerní cerni cernem cernut,cernuda
-ler verbs (mostly like -ldre verbs):
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
caler (var. of caldre)
doler (var. of doldre)
soler solc sol solem solia soldré solguí solgui solguem solgut,solguda
valer/valdre valc val valem valia valdré valguí valgui valguem valgut,valguda
(prevaler, equivaler)
other -dre/-tre verbs (regular except sometimes pp):
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
batre bato bat batem batia batré batí bati batem batut,batuda
-metre -meto -met -metem -metia -metré -metí -meti -metem -mès,-mesa,-mesos
(ad-, co-, compro-, e-, entremetre's, mal-, o-, per-, pro-, read-, re-, retrans-, sot-, tra-, trans-)
perdre perdo perd perdem perdia perdré perdí perdi perdem perdut,perduda
-ure verbs
infinitive pres1s pres3s pres1p impf1s impf1p fut1s pret1s sub1s sub1p pp
caure caic cau caiem queia quèiem cauré caiguí caigui caiguem caigut,caiguda
(decaure, recaure)
plaure plac plau plaem plaïa plaíem plauré plaguí plagui plaguem plagut,plaguda
(complaure)
raure rac rau raem raïa raíem rauré raguí ragui raguem ragut,raguda
beure bec beu bevem bevia bevíem beuré beguí begui beguem begut,beguda
(embeure)
creure crec creu creiem creia crèiem creuré creguí cregui creguem cregut,creguda
deure dec deu devem devia devíem deuré deguí degui deguem degut,deguda
jeure jec jeu jaiem jeia jèiem jauré jaguí jegui jaguem jagut,jaguda
(ajeure)
lleure - lleu [-] llevia - lleurà llegué llegui - llegut,-
seure sec seu seiem seia sèiem seuré seguí segui seguem segut,seguda
(asseure)
treure trec treu traiem treia trèiem trauré traguí tregui traguem tret,treta
(abstreure, atreure, contreure, distreure, extreure, retreure, sostreure)
veure veig veu veiem veia vèiem veuré viu,veieres/veres, vegi vegem vist,vista,vists/vistos
(entreveure, preveure, reveure) veié/veu,veiérem/vérem
riure ric riu riem reia rèiem riuré riguí rigui riguem rigut,riguda
(somriure)
(e)scriure escric escriu escrivim escrivia escrivíem escriuré escriví/escriguí escrigui escriguem escrit,escrita
(circumscriure, descriure, inscriure, prescriure, proscriure, subscriure, transcriure)
viure visc viu vivim vivia vivíem viuré visquí visqui visquem viscut,viscuda
(conviure, sobreviure)
cloure cloc clou cloem cloïa cloíem clouré cloguí clogui cloguem clos,closa,closos
(concloure, descloure, encloure, excloure, incloure, recloure)
encloure encloc enclou encloem encloïa encloíem enclouré encloguí enclogui encloguem enclòs,enclosa,enclosos
coure coc cou coem coïa coíem couré coguí cogui coguem cuit/cogut,cuita/coguda
moure moc mou movem movia movíem mouré moguí mogui moguem mogut,moguda
(promoure)
noure noc nou noem noïa noíem nouré noguí nogui noguem nogut,noguda
ploure - plou [plovent] plovia - plourà plogué plogui - plogut,ploguda
-nyer verbs (regular except pp)
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
atènyer atenyo ateny atenyem atenyia atenyeré atenyí atenyi atenyem atès,atesa,atesos
empènyer empenyo empeny empenyem empenyia empenyeré empenyí empenyi empenyem empès,empesa,empesos
estrènyer estrenyo estreny estrenyem estrenyia estrenyeré estrenyí estrenyi estrenyem estret,estreta
estrènyer
(constrènyer,restrènyer)
fènyer fenyo feny fenyem fenyia fenyeré fenyí/fenguí fenyi fenyem fenyut/fengut,fenyuda/fenguda
pertànyer pertanyo pertany pertanyem pertanyia pertanyeré pertanyí/pertanguí pertanyi pertanyem pertanyut/pertangut,pertanyuda/pertanguda
plànyer planyo plany planyem planyia planyeré planyí/planguí planyi planyem plangut/planyut,planguda/planyuda
-xer verbs (NOTE: pres2s in -xes)
infinitive pres1s pres3s pres1p impf1s fut1s pret1s sub1s sub1p pp
créixer creixo creix creixem creixia creixeré creixí/cresquí creixi creixem crescut,crescuda
(acréixer,decréixer)
conèixer conec coneix coneixem coneixia coneixeré coneguí conegui coneguem conegut,coneguda
(desconèixer,reconèixer)
merèixer mereixo mereix mereixem mereixia mereixeré mereixí/meresquí mereixi mereixem merescut,merescuda
néixer/ neixo/ neix/ naixem naixia naixeré naixí/nasquí neixi/ naixem/nasquem nascut,nascuda
nàixer naixo naix naixi
(renéixer)
parèixer parec pareix pareixem pareixia pareixeré pareguí paregui pareguem paregut,pareguda
(aparèixer,comparèixer,desaparèixer,reaparèixer)
péixer peixo peix paixem paixia paixeré paixí peixi paixem pascut,pascuda
misc. -er verbs
infinitive pres1s pres3s pres1p impf1s impf1p fut1s pret1s sub1s sub1p pp
córrer corro corre correm corria corríem correré correguí corri correm corregut,correguda
fúmer fumo fum fumem fumia fumíem fumeré fumí fumi fumem fumut,fumuda
prémer premo prem premem premia premíem premeré premí premi premem premut,premuda
(es-, re-)
témer temo tem temem temia temíem temeré temí temi temem temut,temuda
trémer [regular]
tòrcer torço torç torcem torcia torcíem torceré torcí torci torcem torçut,torçuda
(des-) [pres2s torces]
vèncer venço venç vencem vencia vencíem venceré vencí venci vencem vençut,vençuda
(con-, re-) [pres2s vences]
cabre/caber cabo cap cabem cabia cabíem cabré cabí càpiga capiguem cabut,cabuda
[sub2s càpigues]
haver he/haig ha havem/hem havia havíem hauré haguí hagi hàgim/haguem hagut,haguda
[noimp] [cond1s hauria/haguera; impsub2s haguessis/haguesses]
poder puc pot podem podia podíem podré poguí pugui puguem pogut,poguda
saber sé sap sabem sabia sabíem sabré sabí sàpiga sapiguem sabut,sabuda
[imp2s sàpigues, imp2p sapigueu]
voler vull vol volem volia volíem voldré volguí vulgui vulguem volgut,volguda
ser/ésser soc és som era érem seré fui sigui siguem estat/sigut,estada/siguda
[ger sent/essent] [cond1s seria/fora]
[pres: soc,ets,éts,som,sou,són; pret: fui,fores,fou,fórem,fóreu,foren; impsub: fos,fossis,fos,fóssim,fóssiu,fossin]
[imp: sigues,sigueu]
fer faig fa fem feia fèiem faré fiu faci fem fet,feta
[pres3p fan]
[pret: fiu,feres,feu,férem,féreu,feren]
]=]
local all_persons_numbers = {
["1s"] = "1|s",
["2s"] = "2|s",
["3s"] = "3|s",
["1p"] = "1|p",
["2p"] = "2|p",
["3p"] = "3|p",
}
local person_number_list = {"1s", "2s", "3s", "1p", "2p", "3p"}
local imp_person_number_list = {"2s", "3s", "1p", "2p", "3p"}
local neg_imp_person_number_list = {"2s", "3s", "1p", "2p", "3p"}
proclitic_non_elided_person_number_to_reflexive_pronoun = {
["1s"] = "em ",
["2s"] = "et ",
["3s"] = "es ",
["1p"] = "ens ",
["2p"] = "us ",
["3p"] = "es ",
}
proclitic_elided_person_number_to_reflexive_pronoun = {
["1s"] = "m'",
["2s"] = "t'",
["3s"] = "s'",
["1p"] = "ens ",
["2p"] = "us ",
["3p"] = "s'",
}
enclitic_non_elided_person_number_to_reflexive_pronoun = {
["1s"] = "-me",
["2s"] = "-te",
["3s"] = "-se",
["1p"] = "-nos",
["2p"] = "-vos",
["3p"] = "-se",
}
enclitic_elided_person_number_to_reflexive_pronoun = {
["1s"] = "'m",
["2s"] = "'t",
["3s"] = "'s",
["1p"] = "'ns",
["2p"] = "-us",
["3p"] = "'s",
}
local indicator_flags = m_table.listToSet {
"no_pres_stressed",
"only3s", "only3sp", "only3p", "noimp",
"pp_inv", "irreg", "no_built_in",
}
-- Initialize all the slots for which we generate forms.
local function add_slots(alternant_multiword_spec)
-- "Basic" slots: All slots that go into the regular table (not the reflexive form-of table).
alternant_multiword_spec.verb_slots_basic = {
{"infinitive", "inf"},
{"infinitive_linked", "inf"},
{"gerund", "ger"},
{"pp_ms", "m|s|past|part"},
{"pp_fs", "f|s|past|part"},
{"pp_mp", "m|p|past|part"},
{"pp_fp", "f|p|past|part"},
}
-- Special slots used to handle non-reflexive parts of reflexive verbs in {{ca-verb form of}}. For example, for a
-- reflexive-only verb like [[arrepentirse]], we want to be able to use {{ca-verb form of}} on [[arrepinta]] (which
-- should mention that it is a part of 'me arrepinta', first-person singular present subjunctive, and
-- 'se arrepinta', third-person singular present subjunctive) or on [[arrepentimos]] (which should mention that it
-- is a part of 'arrepentímonos', first-person plural present indicative or preterite). Similarly, we want to use
-- {{ca-verb form of}} on [[arrepentindo]] (which should mention that it is a part of 'se ... arrepentindo',
-- syntactic variant of [[arrepentíndose]], which is the gerund of [[arrepentirse]]). To do this, we need to be
-- able to map non-reflexive parts like [[arrepinta]], [[arrepentimos]], [[arrepentindo]], etc. to their reflexive
-- equivalent(s), to the tag(s) of the equivalent(s), and, in the case of forms like [[arrepentindo]],
-- [[arrepentir]] and imperatives, to the separated syntactic variant of the verb+clitic combination. We do this by
-- creating slots for the non-reflexive part equivalent of each basic reflexive slot, and for the separated
-- syntactic-variant equivalent of each basic reflexive slot that is formed of verb+clitic. We use slots in this
-- way to deal with multiword lemmas. Note that we run into difficulties mapping between reflexive verbs,
-- non-reflexive part equivalents, and separated syntactic variants if a slot contains more than one form. To
-- handle this, if there are the same number of forms in two slots we're trying to match up, we assume the forms
-- match one-to-one; otherwise we don't match up the two slots (which means {{ca-verb form of}} won't work in this
-- case, but such a case is extremely rare and not worth worrying about). Alternatives that handle this "properly"
-- are significantly more complicated and require non-trivial modifications to [[Module:inflection utilities]].
local need_special_verb_form_of_slots = alternant_multiword_spec.source_template == "ca-verb form of" and
alternant_multiword_spec.refl
if need_special_verb_form_of_slots then
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {
{"infinitive_non_reflexive", "-"},
{"infinitive_variant", "-"},
{"gerund_non_reflexive", "-"},
{"gerund_variant", "-"},
}
else
alternant_multiword_spec.verb_slots_reflexive_verb_form_of = {}
end
-- Add entries for a slot with person/number variants.
-- `verb_slots` is the table to add to.
-- `slot_prefix` is the prefix of the slot, typically specifying the tense/aspect.
-- `tag_suffix` is a string listing the set of inflection tags to add after the person/number tags.
-- `person_number_list` is a list of the person/number slot suffixes to add to `slot_prefix`.
local function add_personal_slot(verb_slots, slot_prefix, tag_suffix, person_number_list)
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(verb_slots, {slot, accel})
end
end
-- Add a personal slot (i.e. a slot with person/number variants) to `verb_slots_basic`.
local function add_basic_personal_slot(slot_prefix, tag_suffix, person_number_list, no_special_verb_form_of_slot)
add_personal_slot(alternant_multiword_spec.verb_slots_basic, slot_prefix, tag_suffix, person_number_list)
-- Add special slots for handling non-reflexive parts of reflexive verbs in {{ca-verb form of}}.
-- See comment above in `need_special_verb_form_of_slots`.
if need_special_verb_form_of_slots and not no_special_verb_form_of_slot then
for _, persnum in ipairs(person_number_list) do
local persnum_tag = all_persons_numbers[persnum]
local basic_slot = slot_prefix .. "_" .. persnum
local accel = persnum_tag .. "|" .. tag_suffix
table.insert(alternant_multiword_spec.verb_slots_reflexive_verb_form_of, {basic_slot .. "_non_reflexive", "-"})
end
end
end
add_basic_personal_slot("pres", "pres|ind", person_number_list)
add_basic_personal_slot("impf", "impf|ind", person_number_list)
add_basic_personal_slot("pret", "pret|ind", person_number_list)
add_basic_personal_slot("fut", "fut|ind", person_number_list)
add_basic_personal_slot("cond", "cond", person_number_list)
add_basic_personal_slot("pres_sub", "pres|sub", person_number_list)
add_basic_personal_slot("impf_sub", "impf|sub", person_number_list)
add_basic_personal_slot("imp", "imp", imp_person_number_list)
-- Don't need special non-reflexive-part slots because the negative imperative is multiword, of which the
-- individual words are 'no' + subjunctive.
add_basic_personal_slot("neg_imp", "neg|imp", neg_imp_person_number_list, "no special verb form of")
-- Don't need special non-reflexive-part slots because we don't want [[arrependendo]] mapping to [[arrependendo-me]]
-- (only [[arrependendo-se]]) or [[arrepender]] mapping to [[arrepender-me]] (only [[arrepender-se]]).
add_basic_personal_slot("infinitive", "inf", person_number_list, "no special verb form of")
add_basic_personal_slot("gerund", "ger", person_number_list, "no special verb form of")
-- Generate the list of all slots.
alternant_multiword_spec.all_verb_slots = {}
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_basic) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
for _, slot_and_accel in ipairs(alternant_multiword_spec.verb_slots_reflexive_verb_form_of) do
table.insert(alternant_multiword_spec.all_verb_slots, slot_and_accel)
end
alternant_multiword_spec.verb_slots_basic_map = {}
for _, slotaccel in ipairs(alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
alternant_multiword_spec.verb_slots_basic_map[slot] = accel
end
end
local overridable_stems = {}
local function allow_multiple_values_for_override(separated_groups, data, is_form_override)
local retvals = {}
for _, separated_group in ipairs(separated_groups) do
local footnotes = data.fetch_footnotes(separated_group)
local form = separated_group[1]
-- Prepend marker to prevent prefixing with `base.prefix`, and (in the case of form overrides) prevent
-- final devoicing.
if is_form_override then
form = IS_USER_FORM_OVERRIDE .. form
else
form = IS_USER_STEM_OVERRIDE .. form
end
local retval = {form = form, footnotes = footnotes}
table.insert(retvals, retval)
end
return retvals
end
for _, overridable_stem in ipairs {
"stem",
"stressed_stem",
"unstressed_stem",
"pres_unstressed",
"pres_stressed",
"pres3s", -- overrides just pres_2s and pres_3s
-- Don't include pres1s, pres3p; use pres_1s etc. if you need to override just those forms
"impf1",
"impf2",
"pret",
"fut",
"cond",
"pres_sub_stressed",
"pres_sub_unstressed",
"impf_sub",
"pp",
"g_infix",
"eix_infix",
} do
-- Written so we can substitute a different validator; parallel code in [[Module:es-verb]] and [[Module:pt-verb]]
-- has simple_choice validators.
overridable_stems[overridable_stem] = allow_multiple_values_for_override
end
-- Useful as the value of the `match` property of a built-in verb. `main_verb_spec` is a Lua pattern that should match
-- the non-prefixed part of a verb, and `prefix_specs` is a list of Lua patterns that should match the prefixed part of
-- a verb. If a prefix spec is preceded by ^, it must match exactly at the beginning of the verb; otherwise, additional
-- prefixes (e.g. re-, des-) may precede. Return the prefix and main verb.
local function match_against_verbs(main_verb_spec, prefix_specs)
return function(verb)
for _, prefix_spec in ipairs(prefix_specs) do
if prefix_spec:find("^%^") then
-- must match exactly
prefix_spec = prefix_spec:gsub("^%^", "")
if prefix_spec == "" then
-- We can't use the second branch of the if-else statement because an empty () returns the current position
-- in rmatch().
local main_verb = rmatch(verb, "^(" .. main_verb_spec .. ")$")
if main_verb then
return "", main_verb
end
else
local prefix, main_verb = rmatch(verb, "^(" .. prefix_spec .. ")(" .. main_verb_spec .. ")$")
if prefix then
return prefix, main_verb
end
end
else
local prefix, main_verb = rmatch(verb, "^(.*" .. prefix_spec .. ")(" .. main_verb_spec .. ")$")
if prefix then
return prefix, main_verb
end
end
end
return nil
end
end
--[=[
Built-in (usually irregular) conjugations.
Each entry is processed in turn and consists of an object with two fields:
1. match=: Specifies the built-in verbs that match this object.
2. forms=: Specifies the built-in stems and forms for these verbs.
The value of match= is either a string beginning with "^" (match only the specified verb), a string not beginning
with "^" (match any verb ending in that string), or a function that is passed in the verb and should return the prefix
of the verb if it matches, otherwise nil. The function match_against_verbs() is provided to facilitate matching a set
of verbs with a common ending and specific prefixes (e.g. [[ter]] and [[ater]] but not [[abater]], etc.).
The value of forms= is a table specifying stems and individual override forms. Each key of the table names either a
stem (e.g. `pres_stressed`), a stem property (e.g. `g_infix`) or an individual override form (e.g. `pres_1s`).
Each value of a stem can either be a string (a single stem), a list of strings, or a list of objects of the form
{form = STEM, footnotes = {FOONOTES}}. Each value of an individual override should be of exactly the same form except
that the strings specify full forms rather than stems. The values of a stem property depend on the specific property
but are generally strings or booleans.
In order to understand how the stem specifications work, it's important to understand the phonetic modifications done
by combine_stem_ending(). In general, the complexities of predictable prefix, stem and ending modifications are all
handled in this function. In particular:
1. Spelling-based modifications (c/qu, ç/c, g/gu, j/g, gu/gü, qu/qü) occur automatically as appropriate for the ending.
2. If the ending begins with an asterisk, this is a signal to delete the accent on the last syllable of the stem, e.g.
veié -> veierem.
3. If ending begins with i, it may turn into í or ï after an unstressed vowel (in some but not all cases) to prevent the
two merging into a diphthong. See combine_stem_ending() for specifics.
The following stems are recognized [FIXME: This is not correct for Catalan, needs rewriting]:
-- pres_unstressed: The present indicative unstressed stem (1p, 2p). Also controls the imperative 2p
and gerund. Defaults to the infinitive stem (minus the ending -ar/-er/-ir/-or).
-- pres_stressed: The present indicative stressed stem (1s, 2s, 3s, 3p). Also controls the imperative 2s.
Default is empty if indicator `no_pres_stressed`, else a vowel alternation if such an indicator is given
(e.g. `ue`, `ì`), else the infinitive stem.
-- pres1: Special stem for 1s present indicative. Normally, do not set this explicitly. If you need to specify an
irregular 1s present indicative, use the form override pres_1s= to specify the entire form. Defaults to
pres_stressed.
-- pres_sub_unstressed: The present subjunctive unstressed stem (1p, 2p). Defaults to the infinitive stem.
-- pres_sub_stressed: The present subjunctive stressed stem (1s, 2s, 3s, 1p). Defaults to pres1.
-- impf: The imperfect stem (not including the -av-/-i- stem suffix, which is determined by the conjugation). Defaults
to the infinitive stem.
-- pret: The full preterite stem missing only the endings (-ste, -mos, etc.), e.g. 'fige', 'fo'. Only used for verbs
with irregular preterites (pret_conj == "irreg") such as [[facer]], [[poder]], [[traer]], etc. Defaults to
`pret_base` + the conjugation vowel.
-- fut: The future stem. Defaults to the infinitive stem + the conjugation vowel.
-- cond: The conditional stem. Defaults to `fut`.
-- impf_sub: The imperfect subjunctive stem. Defaults to `pret`.
-- pp: The masculine singular past participle. Default is based on the verb conjugation: infinitive stem + '-ado' for
-ar verbs, otherwise infinitive stem + '-ido'.
-- pp_inv: `true` if the past participle exists only in the masculine singular.
]=]
local built_in_conjugations = {
--------------------------------------------------------------------------------------------
-- -ar --
--------------------------------------------------------------------------------------------
-- Orthographic consonant alternations in endings are handled automatically in combine_stem_ending().
{
-- [[aguar]]:
-- pres agúo, agúes, agúa, agüem, agüeu, agúen
-- pres_sub aguï, aguïs, aguï, agüem, agüeu, aguïn
-- contrast a more typical verb in -guar, [[enaiguar]]:
-- pres enaiguo, enaigües, enaigua, enaigüem, enaigüeu, enaigüen
-- pres_sub enaigüi, enaigüis, enaigüi, enaigüem, enaigüeu, enaigüin
match = "^aguar",
forms = {
pres_stressed = "agú",
pres_sub_stressed = "aguï",
irreg = true,
}
},
{
-- [[anar]] (full verb); highly irregular
match = "^anar",
var = "full",
forms = {
fut = "anir",
pres_1s = "vaj", -- will be converted to 'vaig'; 'vaig' gets converted to 'vaic'
pres_2s = "vas",
pres_3s = "va",
pres_3p = "van",
pres_sub_stressed = "vagi",
imp_2s = "ves",
irreg = true,
}
},
{
-- [[anar]] (auxiliary); highly irregular
match = "^anar",
var = "aux",
forms = {
pres_1s = "vaj", -- will be converted to 'vaig'; 'vaig' gets converted to 'vaic'
pres_2s = {"vas", "vares"},
pres_3s = "va",
pres_1p = {"vam", "vàrem"},
pres_2p = {"vau", "vàreu"},
pres_3p = {"van", "varen"},
pres_sub_stressed = "vagi",
pres_sub_unstressed = "vàgi",
impf1 = {},
impf2 = {},
fut = {},
pret = {},
pp = {},
gerund = {},
noimp = true,
irreg = true,
}
},
{
-- [[dar]]
match = "^dar",
forms = {
pres_1s = {form = "do", footnotes = {"[obsolete]"}},
pres_2s = {form = "das", footnotes = {"[obsolete]"}},
pres_3s = {form = "da", footnotes = {"[obsolete]"}},
pres_3p = {form = "dan", footnotes = {"[obsolete]"}},
pres_sub_1s = {form = "de", footnotes = {"[obsolete]"}},
pres_sub_2s = {form = "des", footnotes = {"[obsolete]"}},
pres_sub_3s = {form = "de", footnotes = {"[obsolete]"}},
pres_sub_3p = {form = "den", footnotes = {"[obsolete]"}},
pret_1s = "di", -- regular except for lack of accent
pret_3s = "da", -- regular except for lack of accent
impf_sub_1s = "des", -- regular except for lack of accent
impf_sub_3s = "des", -- regular except for lack of accent
irreg = true,
}
},
{
-- [[estar]]; highly irregular
match = "^estar",
forms = {
pres_2s = "estàs",
pres_3s = "està",
pres_3p = "estan",
g_infix = "estig",
imp_2s = "estigues",
imp_2p = "estigueu",
pp = "estad",
}
},
--------------------------------------------------------------------------------------------
-- -er/-re --
--------------------------------------------------------------------------------------------
-- Regular verbs not needing entries here:
--
-- [[rebre]], [[concebre]], [[decebre]], [[percebre]]
-- [[rompre]]
-- [[fúmer]], [[prémer]], [[témer]], [[trémer]]
-- [[perdre]], [[batre]], [[botre]], [[fotre]], [[retre]]
-- [[tòrcer]], [[vèncer]]
-- etc.
------------------------------------------- -ldre/-ler/-lre --------------------------------------
{
-- [[caldre]], [[doldre]], [[condoldre's]], [[oldre]]
match = match_against_verbs("ldre", {"ca", "do", "^o"}),
forms = {
-- g_infix implies irreg = true
-- g_infix adds -g to pres_1s, sub, pret and pp stems; combine_stem_ending() changes final -g to -c
g_infix = "+",
}
},
{
-- [[caler]]
match = "caler",
like = "caldre",
},
{
-- [[doler]] and compounds
match = "doler",
like = "doldre",
},
{
-- [[dolre]]
match = "dolre",
forms = {
-- see above for g_infix effects
g_infix = "+",
}
},
{
-- [[valer]], [[equivaler]], [[prevaler]], [[sobrevaler]]
match = "valer",
forms = {
-- see above for g_infix effects
fut = "valdr",
g_infix = "+",
}
},
{
-- [[valdre]] and compounds
match = "valdre",
like = "valer",
},
{
-- [[soler]]
match = "^soler", -- this must precede -oldre rule below for alt form [[soldre]]
forms = {
-- see above for g_infix effects
fut = {},
pret = {},
impf_sub = "solgué", -- regular, but we disabled the preterite, which would normally disable impf_sub too
g_infix = "+",
pp = {},
noimp = true,
}
},
{
-- [[soldre]]
match = "^soldre", -- this must precede -oldre rule below
like = "soler",
},
{
-- [[coldre]], [[moldre]], [[absoldre]], [[dissoldre]], [[resoldre]], [[toldre]]
match = "oldre", -- this must follow [[doldre]]/[[oldre]] rule above
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "olt",
}
},
{
-- [[voler]], [[malvoler]]
match = "voler",
forms = {
fut = "voldr",
pres_1s = "vull",
pres_sub_stressed = "vulgui",
pres_sub_unstressed = "vulgue",
g_infix = "+",
imp_2s = "vulgues",
imp_2p = "vulgueu",
}
},
--------------------------------------------- -ndre ----------------------------------------
{
-- [[romandre]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("mandre", {"^ro"}),
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "màs#",
}
},
{
-- [[encendre]], [[atendre]], [[contendre]], [[desentendre's]], [[distendre]], [[entendre]], [[estendre]],
-- [[pretendre]]
match = match_against_verbs("endre", {"enc", "t"}),
forms = {
pres_3s = "én#", -- remove final accent without prefix with vowel; also removed when adding a suffix
-- see above for g_infix effects
g_infix = "+",
pp = "ès#", -- see above for effect of final #
}
},
{
-- [[vendre]], [[malvendre]], [[revendre]]
match = "vendre",
forms = {
pres_3s = "vèn#", -- see above for effect of final #
-- see above for g_infix effects
g_infix = "+",
pp = "venud", -- g_infix would normally make it vengud
}
},
{
-- [[fendre]], [[defendre]], [[ofendre]], [[dependre]], [[despendre]], [[expendre]], [[suspendre]], [[prendre]],
-- [[aprendre]], [[comprendre]], [[desprendre]], [[emprendre]], [[reprendre]], [[sorprendre]]
match = "endre", -- this must follow previous -endre rules above
forms = {
pres_3s = "èn#", -- see above for effect of final #
-- see above for g_infix effects
g_infix = "+",
pp = "ès#", -- see above for effect of final #
}
},
{
-- [[enfondre]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("fondre", {"^en"}),
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "fús#",
}
},
{
-- [[pondre]], [[compondre]], [[correspondre]], [[descompondre]], [[despondre's]], [[respondre]]
match = "pondre",
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "post",
}
},
{
-- [[fondre]], [[confondre]], [[difondre]], [[infondre]], [[refondre]], [[tondre]]
match = "ondre", -- this must follow previous -ondre rules above
forms = {
-- see above for g_infix effects
g_infix = "+",
pp = "ós#", -- see above for effect of final #
}
},
--------------------------------------------- -nyer ----------------------------------------
{
-- [[atènyer]]; write it this way so there's a prefix with a vowel to prevent against the accent in the pp
-- from being removed while still removing it in the feminine.
match = match_against_verbs("tènyer", {"^a"}),
forms = {
pp = "tès#",
irreg = true,
}
},
{
-- [[empènyer]], [[espènyer]]
match = match_against_verbs("pènyer", {"^em", "^es"}),
forms = {
pp = "pès#",
irreg = true,
}
},
{
-- [[estrènyer]], [[constrènyer]], [[destrènyer]], [[restrènyer]]
match = match_against_verbs("strènyer", {"^e", "con", "^de", "^re"}),
forms = {
pp = "stret",
irreg = true,
}
},
{
-- [[fènyer]]
match = "fènyer",
forms = {
pp = {"fengud", "fenyud"},
irreg = true,
}
},
{
-- [[júnyer]]
match = "júnyer",
like = "junyir",
},
{
-- [[plànyer]], [[complànyer]], [[pertànyer]]
match = match_against_verbs("ànyer", {"pl", "pert"}),
forms = {
pp = {"angud", "anyud"},
irreg = true,
}
},
--------------------------------------------- -aure ----------------------------------------
{
-- [[caure]], [[decaure]], [[recaure]]
match = "caure",
forms = {
-- stem ending in -ai and imperfect in -ia causes special stressed imperfect logic to take effect; we get
-- impf1s queia, impf1p quèiem (preceding vowel changed to è and attached to initial consonant using
-- combine_stem_ending(), which changes c- to qu-)
stem = "caie", -- i dropped by g_infix before u
-- g_infix implies irreg = true
-- g_infix adds -g to pres_1s, sub, pret and pp stems; combine_stem_ending() changes final -g to -c
-- g_infix sets pres_stressed to end in -u, removing a preceding -i or -v
g_infix = "+",
}
},
{
-- [[plaure]], [[complaure]]
match = "plaure",
forms = {
stem = "plae", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
}
},
{
-- [[raure]]
match = "^raure",
forms = {
stem = "rae", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = {"ragud", "ras"},
}
},
--------------------------------------------- -eure ----------------------------------------
{
-- [[beure]], [[embeure]], [[deure]], [[lleure]]
match = match_against_verbs("eure", {"b", "d", "ll"}),
forms = {
stem = "eve", -- v dropped by g_infix before g and u
g_infix = "+",
}
},
{
-- [[creure]], [[seure]], [[asseure]]
match = match_against_verbs("eure", {"cr", "s"}),
forms = {
stem = "ee",
pres_unstressed = "eie", -- affects pres_1p, pres_2p, gerund, imperfect (see [[caure]])
g_infix = "+",
}
},
{
-- [[jeure]], [[ajeure]]
match = "jeure",
forms = {
fut = "jaur", -- affects future and cond
stressed_stem = "jee", -- affects stressed forms, which get g added by g_infix by added except for
-- pres_stressed, which gets u added (controls pres_3s, pres_2s, pres_3p)
unstressed_stem = "jae", -- affects unstressed_stem, which get g added by g_infix
pres_stressed = {"jeu", "jau"},
pres_unstressed = "jaie", -- affects pres_1p, pres_2p, gerund, imperfect (see [[caure]])
pres_1s = {"jec", "jac"},
impf1 = "jei", -- otherwise we'd get impf_1s '#geia' etc.
impf2 = "jèi",
g_infix = "+",
}
},
{
match = "jaure",
like = "jeure",
},
{
-- [[treure]], [[abstreure]], [[atreure]], [[bestreure]], [[contreure]], [[detreure]], [[distreure]],
-- [[extreure]], [[retreure], [[retrotreure]], [[sostreure]]
match = "treure",
forms = {
-- like [[jeure]] except for irregular pp
fut = "traur",
stressed_stem = "tree",
unstressed_stem = "trae",
pres_stressed = {"treu", "trau"},
pres_unstressed = "traie",
pres_1s = {"trec", "trac"},
g_infix = "+",
pp = "tret",
}
},
{
match = "traure",
like = "treure",
},
{
-- [[veure]], [[entreveure]], [[preveure]], [[reveure]]
match = "veure",
forms = {
stem = "veie",
-- impf1s veia, impf1p vèiem (preceding vowel changed to è)
pres_stressed = "veu",
pres_1s = "vej", -- will be converted to 'veig'; 'veig' gets converted to 'veic'
pres_sub_stressed = "vegi",
pres_sub_unstressed = "vege",
pret = {"veié", "vé"},
pret_1s = "viu",
pret_3s = {"veié", "veu"},
impf_sub = "veié",
pp = "vist",
imp_2s = "veges",
imp_2p = {"vegeu", "veieu"},
irreg = true,
}
},
--------------------------------------------- -iure ----------------------------------------
{
-- [[escriure]], [[circumscriure]], [[descriure]], [[inscriure]], [[prescriure]], [[proscriure]],
-- [[subscriure]], [[transcriure]]
match = "scriure",
forms = {
stem = "scrivi", -- v dropped by g_infix before g and u; pres_1p/pres_2p have -ir endings
g_infix = "+",
pret = {"scriví", "scrigué"},
pp = "scrit",
}
},
{
-- [[riure]], [[somriure]]
match = "riure", -- must follow rule for 'scriure'
forms = {
stem = "rie",
-- impf1s reia, impf1p rèiem (preceding vowel changed to è)
g_infix = "+",
}
},
{
-- [[viure]], [[conviure]], [[desviure's]], [[sobreviure]]
match = "viure",
forms = {
stem = "vivi", -- v dropped by g_infix before g and u; pres_1p/pres_2p have -ir endings
g_infix = "visc", -- applies to pres1s, sub, pret, pp
}
},
--------------------------------------------- -oure ----------------------------------------
{
-- [[cloure]], [[concloure]], [[descloure]], [[encloure]], [[excloure]], [[incloure]], [[recloure]]
match = "cloure",
forms = {
stem = "cloe", -- ï in impf1s cloïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = "clòs#", -- remove final accent without prefix with vowel; also removed when adding a suffix
}
},
{
-- [[coure]] "to cook"
match = "coure",
var = "cook",
forms = {
stem = "coe", -- ï in impf1s coïa gets generated automatically by combine_stem_ending()
g_infix = "+",
pp = "cuit",
}
},
{
-- [[coure]] "to sting"
match = "coure",
var = "sting",
forms = {
stem = "coe", -- ï in impf1s coïa gets generated automatically by combine_stem_ending()
g_infix = "+",
-- pp regular 'cogud'
}
},
{
-- [[moure]], [[promoure]], [[remoure]], [[somoure]], [[ploure]]
match = match_against_verbs("oure", {"m", "pl"}),
forms = {
stem = "ove", -- v dropped by g_infix before g and u
g_infix = "+",
}
},
{
-- [[noure]]
match = "noure",
forms = {
stem = "noe", -- ï in impf1s -aïa gets generated automatically by combine_stem_ending()
g_infix = "+",
}
},
--------------------------------------------- -xer ----------------------------------------
{
-- [[conèixer]], [[desconèixer]], [[reconèixer]]
match = "conèixer",
forms = {
g_infix = "coneg",
}
},
{
-- [[créixer]], [[acréixer]], [[decréixer]], [[recréixer]], [[sobrecréixer]]
match = "créixer",
forms = {
pret = {"creixé", "cresqué"},
pres_sub_unstressed = {"creixe", "cresque"},
pp = "crescud",
irreg = true,
}
},
{
-- [[merèixer]], [[desmerèixer]], [[irèixer-se]]
match = match_against_verbs("rèixer", {"me", "^i"}),
forms = {
pret = {"reixé", "resqué"},
pres_sub_unstressed = {"reixe", "resque"},
pp = "rescud",
irreg = true,
}
},
{
-- [[néixer]]/[[nàixer]], [[renéixer]]/[[renàixer]], [[sobrenéixer]]/[[sobrenàixer]], [[péixer]]/[[pàixer]]
match = match_against_verbs("éixer", {"n", "p"}),
forms = {
stem = "aixe",
fut = "aixer",
pres_stressed = {"eix", "aix"},
pres_1s = "eixo",
pret = {"aixé", "asqué"},
pres_sub_stressed = "eixi",
pres_sub_unstressed = {"aixe", "asque"},
pp = "ascud",
irreg = true,
}
},
{
match = "àixer",
like = "éixer",
},
{
-- [[parèixer]], [[aparèixer]], [[comparèixer]], [[desaparèixer]], [[reaparèixer]]
match = "parèixer",
forms = {
g_infix = "pareg",
}
},
--------------------------------------------- misc ----------------------------------------
{
-- [[cabre]]
match = "cabre",
forms = {
pres_sub_stressed = "càpiga",
pres_sub_unstressed = "capigue",
irreg = true,
}
},
{
-- [[caber]]
match = "caber",
like = "cabre",
},
{
-- [[saber]]
match = "saber",
forms = {
fut = "sabr",
pres_1s = "sé",
pres_sub_stressed = "sàpiga",
pres_sub_unstressed = "sapigue",
imp_2s = "sàpiga",
imp_2p = "sapigueu",
irreg = true,
}
},
{
-- [[poder]]
match = "poder",
forms = {
fut = "podr",
pres_1s = "puc",
pres_sub_stressed = "pugui",
pres_sub_unstressed = "pugue",
g_infix = "pog",
imp_2s = "pugues",
imp_2p = "pugueu",
irreg = true,
}
},
{
-- [[córrer]], [[acórrer]], [[concórrer]], [[decórrer]], [[descórrer]], [[discórrer]], [[encórrer]],
-- [[escórrer]], [[incórrer]], [[ocórrer]], [[recórrer]], [[socórrer]], [[transcórrer]]
match = "córrer",
forms = {
pret = "corregué",
pres_sub_unstressed = {"corre", "corregue"},
pp = "corregud",
irreg = true,
}
},
{
-- [[metre]], [[admetre]], [[arremetre]], [[cometre]], [[comprometre]], [[demetre]], [[descomprometre]],
-- [[emetre]], [[entremetre's]], [[escometre]], [[malmetre]], [[manumetre]], [[ometre]], [[permetre]],
-- [[prometre]], [[readmetre]], [[remetre]], [[retransmetre]], [[sotmetre]], [[trametre]], [[transmetre]]
match = "metre",
forms = {
pp = "mès#",
irreg = true,
}
},
--------------------------------------------------------------------------------------------
-- -ir --
--------------------------------------------------------------------------------------------
{
-- [[acudir]]; NOTE: Separation by meaning does not occur in DCC, DIEC, DEIEC, and DCVB says the distinction
-- is geographical and makes no mention of distinction by meaning. OTOH ca.wikt does say that the pronominal
-- sense "to occur" tends to conjugate non-inchoative.
match = "acudir",
forms = {
eix_infix = {{
form = "+",
footnotes = {'[especially in the sense "to turn up, to be present"]'}
}, {
form = "-",
footnotes = {'[especially in the pronominal sense "to occur"]'}
}}
}
},
-- [[afegir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[ajupir]]
-- [[buixir]]
-- [[bullir]], [[rebullir]]
-- [[cruixir]], [[escruixir]] (Routledge says this is inchoative but DIEC, DEIEC and DCC all disagree; note
-- pres_2s 'cruixes', handled automatically)
-- [[dormir]], [[adormir]]
-- [[funyir]]
-- [[grunyir]]
-- [[munyir]], [[esmunyir]]
-- [[pudir]]
-- [[punyir]]
-- [[retrunyir]]
-- [[sentir]], [[pressentir]], [[ressentir-se]]; not [[consentir]], with can be either non-inchoative or
-- inchoative, and not [[assentir]] or [[dissentir]], which are only inchoative
match = match_against_verbs("ir", {"ajup", "buix", "bull", "cruix", "dorm", "funy", "gruny", "muny", "pud",
"puny", "retruny", "^sent", "pressent", "^ressent"}),
forms = {
eix_infix = "-",
}
},
{
-- [[arrupir-se]];
-- [[brumir]];
-- [[brunzir]];
-- [[consumir]], [[resumir]], [[presumir]] (not [[sumir]], [[assumir]], [[subsumir]], which are regular)
-- [[mentir]], [[desmentir]]
-- [[percudir]]; cf. also [[acudir]], which to some extent has separate conjugations per meaning
-- [[consentir]]
match = match_against_verbs("ir", {"arrup", "brum", "brunz", "consum", "^resum", "presum", "ment", "percud",
"consent"}),
forms = {
eix_infix = {"+", "-"},
}
},
-- [[cenyir]]: -- non-inchoative or inchoative in Balearics, inchoative elsewhere
{
-- [[cobrir]], [[descobrir]], [[encobrir]], [[recobrir]], [[redescobrir]]
match = "cobrir",
forms = {
pp = "cobert",
irreg = true,
}
},
{
-- [[collir]], [[acollir]], [[escollir]], [[recollir]]
match = "collir",
forms = {
stressed_stem = "culli",
eix_infix = "-",
irreg = true,
}
},
{
-- [[complir]], [[acomplir]], [[incomplir]]
match = "complir",
forms = {
pp = {"complert", "complid"},
irreg = true,
}
},
{
-- [[cosir]], [[descosir]], [[recosir]]
match = "cosir",
forms = {
stressed_stem = "cusi",
pres_3s = "cús#",
eix_infix = "-",
irreg = true,
}
},
{
-- [[eixir]], [[deseixir-se]]; not [[teixir]] or [[entreteixir]], and not [[reeixir]] or [[sobreeixir]],
-- which have an ï in the stem-stressed forms
match = match_against_verbs("eixir", {"^", "des"}),
forms = {
stressed_stem = "ixi",
eix_infix = "-",
irreg = true,
}
},
{
-- [[reeixir]], [[sobreeixir]]
match = match_against_verbs("eixir", {"^re", "sobre"}),
forms = {
stressed_stem = "ïxi",
eix_infix = "-",
irreg = true,
}
},
-- [[engolir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[escopir]]
match = "escopir",
forms = {
stressed_stem = "escupi",
eix_infix = "-",
irreg = true,
}
},
{
-- [[establir]], [[preestablir]], [[restablir]]
match = "establir",
forms = {
pp = {"establert", "establid"},
irreg = true,
}
},
-- [[ferir]]: -- non-inchoative in Balearics, inchoative elsewhere
-- [[fregir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[fugir]], [[confugir]], [[defugir]], [[enfugir-se]]; pres sing ''fujo, fuges, fuig'' handled by
-- combine_stem_ending(); can't be handled by rule above that lists many non-inchoative verbs because the
-- prefix would be 'fug' and the front-back alternation code doesn't apply to prefixes.
match = "fugir",
forms = {
eix_infix = "-",
}
},
{
-- [[imprimir]], [[reimprimir]], [[sobreimprimir]]; not any other verbs in -primir; write it this way so
-- there's a prefix with a vowel to prevent against the accent in the pp from being removed while still
-- removing it in the feminine.
match = match_against_verbs("primir", {"im"}),
forms = {
pp = "près#",
irreg = true,
}
},
-- [[llegir]]: -- non-inchoative in Valencia and Minorca, inchoative elsewhere
{
-- [[lluir]]: regular inchoative in the figurative meaning "to display (something), to be showy" also in the
-- legal meaning "free from a pecuniary obligation, such as a land-based tax (emphyteusis)"; irregular in the
-- literal meaning "to shine"; use <no_built_in> to get regular conjugation. In the regular conjugation,
-- umlauts appear in the following forms: pres_1p/pres_sub_1p/imp_1p lluïm, pres_2p/pres_sub_2p/imp_2p lluïu,
-- impf_1s/impf_3s lluïa, impf_2s lluïes, impf_3p lluïen, pret_2s lluïres, pret_3p lluïren,
-- impf_sub_2s lluïssis, impf_sub_3p lluïssin, throughout the pp: lluït, lluïda, lluïts, lluïdes. IN the
-- irregular conjugation, umlauts appear in the same places as well as elsewhere in the present subjunctive:
-- pres_sub_1s/pres_sub_3s/imp_3s lluï, pres_sub_2s lluïs, pres_sub_3p/imp_3p lluïn. Notably, they do *NOT*
-- appear in the gerund lluint, the infinitive lluir, or anywhere in the future or conditional. Note that
-- verbs.cat [https://www.verbs.cat/en/conjugation/899-lluir.html] lists additional irregular forms pres_1s
-- lluu, and alternative impf_sub forms in -e- instead of -i- (lluïsses, lluíssem, lluísseu, lluïssen), but
-- these are nonstandard or dialectal per both Routledge and DEIEC.
match = "^lluir",
forms = {
eix_infix = "-",
pres3s = {"lluu", "llu"}, -- generates pres_2s, imp_2s
irreg = true,
}
},
{
-- [[entrelluir]] "to be half-seen", [[relluir]] "to shine", [[traslluir-se]] "to be translucent"; either
-- inchoative or non-inchoative, not distinguished by meaning; note, [[deslluir]] and [[enlluir]] are regular
-- inchoative verbs.
match = match_against_verbs("lluir", {"entre", "^re", "tras"}),
forms = {
eix_infix = {"+", "-"},
pres3s = {"llueix", "lluu", "llú"}, -- generates pres_2s, imp_2s; note, pres_2s will end in -es due to
-- combine_stem_ending()
irreg = true,
}
},
{
-- [[morir]], [[premorir]]; but not [[atemorir]]
match = match_against_verbs("morir", {"^", "pre"}),
forms = {
eix_infix = "-",
pp = "mort",
irreg = true,
}
},
{
-- [[obrir]], [[entreobrir]], [[reobrir]]; not [[cobrir]] and derivatives, not [[empobrir]], so we have to list
-- them individually
match = match_against_verbs("obrir", {"^", "entre", "^re"}),
forms = {
eix_infix = "-",
pp = "obert",
irreg = true,
}
},
{
-- [[oferir]]; but not [[proferir]]
match = "^oferir",
forms = {
pp = {"ofert", "oferid"},
irreg = true,
}
},
-- [[oir]], [[desoir]], [[entreoir]]: -- per Routledge, non-inchoative or inchoative normally but only
-- non-inchoative in Valencian; but all dictionaries disagree and say it is a regular inchoative-only verb.
-- It has the same umlauts as lluir (and [[corroir]], another regular inchoative verb).
{
-- [[omplir]], [[desomplir-se]], [[reomplir]]; not [[complir]] and derivatives, so we have to list them
-- individually
match = match_against_verbs("omplir", {"^", "des", "^re"}),
forms = {
eix_infix = "-",
pp = {"omplert", "omplid"},
irreg = true,
}
},
-- [[penedir-se]]: -- non-inchoative in Balearics, inchoative elsewhere
{
-- [[pruir]] "to itch": same umlauts as in [[lluir]].
match = "^pruir",
forms = {
eix_infix = "-",
pres3s = {"pruu", "pru"}, -- generates pres_2s, imp_2s
irreg = true,
}
},
{
-- [[reblir]]
match = "^reblir",
forms = {
pp = {"reblert", "reblid"},
irreg = true,
}
},
-- [[renyir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[sofrir]]
match = "^sofrir",
forms = {
pp = {"sofert", "sofrid"},
irreg = true,
}
},
{
-- [[sortir]], [[ressortir]], [[sobresortir]]; but not [[assortir]], which is regular inchoative
match = match_against_verbs("sortir", {"^", "^res", "sobre"}),
forms = {
stressed_stem = "surti",
eix_infix = "-",
irreg = true,
}
},
{
-- [[suplir]]
match = "^suplir",
forms = {
pp = {"suplert", "suplid"},
irreg = true,
}
},
-- [[teixir]], [[entreteixir]]: -- non-inchoative in Valencia, inchoative elsewhere
{
-- [[tenir]] but not any compounds; highly irregular
match = "^tenir",
forms = {
fut = "tindr",
pres_stressed = "ten",
pres_3s = "té",
imp_2s = {"té", "ten", "tingues"},
imp_2p = {"teniu", "tingueu"},
g_infix = "ting",
}
},
{
-- [[abstenir-se]], [[atenir-se]], [[captenir-se]], [[cartenir]], [[contenir]], [[detenir]], [[entretenir]],
-- [[mantenir]], [[menystenir]], [[obtenir]], [[retenir]], [[sostenir]], [[viltenir]]; highly irregular
match = "tenir",
forms = {
fut = "tindr",
pres_stressed = "ten",
pres_3s = "té",
imp_2s = {"tén", "tingues"},
imp_2p = {"teniu", "tingueu"},
g_infix = "ting",
}
},
{
-- [[tindre]]: variant of [[tenir]]
match = "tindre",
like = "tenir",
},
-- [[tenyir]], [[destenyir]]: -- non-inchoative in Valencia, but [[retenyir]] inchoative or non-inchoative in
-- Valencia? (per Routledge); regular inchoative elsewhere
{
-- [[tossir]] "to cough"
match = "^tossir",
forms = {
stressed_stem = "tussi", -- pres_2s gets 'tusses'
pres_3s = "tus", -- note, pres_3s (a single form override) not pres3s (a stem override, which also affects
-- pres_2s; but imp_2s is physically copied from pres_3s, so imp_2s correctly gets 'tus')
eix_infix = "-",
irreg = true,
}
},
{
-- [[venir]] but not any compounds; highly irregular
match = "^venir",
forms = {
fut = "vindr",
pres_stressed = "ven",
pres_3s = "ve",
imp_2s = "vine",
g_infix = "ving",
}
},
{
-- compounds of [[venir]]: [[advenir]], [[avenir]], [[contravenir]], [[convenir]], [[desavenir-se]],
-- [[desconvenir]], [[entrevenir]], [[esdevenir]], [[intervenir]], [[obvenir]], [[pervenir]], [[prevenir]],
-- [[provenir]], [[reconvenir]], [[revenir]], [[sobrevenir]], [[subvenir]]; but not [[enjovenir]] or
-- [[rejovenir]]; highly irregular
match = match_against_verbs("venir", {"^ad", "^a", "contra", "con", "desa", "entre", "esde", "inter", "ob",
"per", "pre", "pro", "^re", "sobre", "sub"}),
forms = {
fut = "vindr",
pres_stressed = "ven",
pres_3s = "vé",
imp_2s = "vén",
g_infix = "ving",
}
},
{
-- [[vindre]]: variant of [[venir]]
match = "vindre",
like = "venir",
},
-- [[vestir]], [[desvestir]], [[revestir]], maybe [[transvestir]]: non-inchoative in Valencia, inchoative or
-- non-inchoative in the Balearics; regular inchoative elsewhere; but not [[envestir]] or [[investir]], which are
-- regular inchoative everywhere
{
-- [[fer]], [[contrafer]], [[desfer]], [[estrafer]], [[perfer]], [[refer]], [[satisfer]]; highly irregular
match = "fer",
forms = {
fut = "far",
pres_1s = "faj", -- will be converted to 'faig'; 'faig' gets converted to 'faic'
pres_2s = "fàs#",
pres_3s = "fà#",
pres_3p = "fan",
pres_unstressed = "fe",
impf1 = "fei",
impf2 = "fèi",
pres_sub_stressed = "faci",
pres_sub_unstressed = "fe",
pret = "fé",
pret_1s = "fiu",
pret_3s = "feu",
impf_sub_1s = "fés#", -- regular except for base form [[fes]], lacking an accent
impf_sub_3s = "fés#", -- same
imp_2s = "fés#",
pp = "fet",
irreg = true,
}
},
{
-- [[dir]], [[adir-se]], [[contradir]], [[desdir]], [[entredir]], [[interdir]], [[maldir]], [[predir]], [[redir]];
-- behaves like an -er/-re verb
match = match_against_verbs("dir", {"^", "^a", "contra", "des", "entre", "inter", "mal", "pre", "^re"}),
forms = {
stem = "die",
g_infix = "+",
imp_2s = "digues",
imp_2p = "digueu",
pp = "dit",
}
},
{
-- [[dur]], [[endur-se]]; behaves like an -er/-re verb
match = "dur",
forms = {
stem = "due",
g_infix = "+",
pres3s = {"duu", "du"}, -- generates pres_2s, imp_2s
impf1 = "dui",
impf2 = "dúi",
pp = "dut",
}
},
{
-- [[ser]]; highly irregular
match = "^ser",
forms = {
pres_1s = "soc",
pres_2s = "ets",
pres_3s = "és",
pres_1p = "som",
pres_2p = "sou",
pres_3p = "són",
impf1 = "er",
impf2 = "ér",
pres_sub_stressed = "sigui",
pres_sub_unstressed = "sigue",
pret = "fó",
pret_1s = "fui",
pret_3s = "fou",
impf_sub_1s = "fos", -- regular except for lack of accent
impf_sub_3s = "fos", -- same
cond = {"serí", "fór"},
imp_2s = "sigues",
imp_2p = "sigueu",
pp = {"estad", "sigud"},
gerund = {"sent", "essent"},
irreg = true,
}
},
{
-- [[ésser]]; variant of [[ser]]
match = "^ésser",
like = "ser",
},
{
-- [[haver]] as auxiliary; highly irregular
match = "^haver",
var = "aux",
forms = {
pres_1s = "he",
pres_2s = "has",
pres_3s = "ha",
pres_1p = "hem",
pres_2p = "heu",
pres_3p = "han",
fut = "haur",
cond = {"haurí", "haguér"},
pres_sub_stressed = "hagi",
pres_sub_unstressed = "hàgi",
noimp = true,
g_infix = "+",
}
},
{
-- [[haver]] as full verb; highly irregular
match = "^haver",
var = "full",
forms = {
pres_1s = {"hec", "hac"},
pres_stressed = {"heu", "hau"},
fut = "haur",
pres_sub_stressed = "hegui",
g_infix = "+",
}
},
{
-- [[heure]]; variant of full verb [[haver]]
match = "^heure",
like = "haver",
likevar = "full",
},
{
-- [[haure]]; variant of full verb [[haver]]
match = "^haure",
like = "haver",
likevar = "full",
},
}
local function skip_slot(base, slot, allow_overrides)
if not allow_overrides and (base.basic_overrides[slot] or
base.refl and base.basic_reflexive_only_overrides[slot]) then
-- Skip any slots for which there are overrides.
return true
end
if base.only3s and (slot:find("^pp_f") or slot:find("^pp_mp")) then
-- diluviar, atardecer, neviscar; impersonal verbs have only masc sing pp
return true
end
if not slot:find("[123]") then
-- Don't skip non-personal slots.
return false
end
if base.nofinite then
return true
end
if (base.only3s or base.only3sp or base.only3p) and (slot:find("^imp_") or slot:find("^neg_imp_")) then
return true
end
if base.only3s and not slot:find("3s") then
-- diluviar, atardecer, neviscar
return true
end
if base.only3sp and not slot:find("3[sp]") then
-- atañer, concernir
return true
end
if base.only3p and not slot:find("3p") then
-- [[caer cuatro gotas]], [[caer chuzos de punta]], [[entrarle los siete males]]
return true
end
return false
end
local function add_stem_ending(stem, ending)
if ending == "" then
return stem
end
if stem:find("#$") then -- remove final accent when adding a suffix
stem = com.remove_accents((stem:gsub("#$", "")), "final syllable only")
end
return stem .. ending
end
local function process_stem(stem, fn)
if stem:find("#$") then
local stem_no_pound_sign = stem:match("^(.*)#$")
return fn(stem_no_pound_sign) .. "#"
else
return fn(stem)
end
end
-- Add the `stem` to the `ending` and apply any phonetic modifications. `is_full_word` indicates that we're creating
-- a "full word" not a stem, and turns on devoicing of final consonants. `dont_include_prefix` is used when creating
-- stems and indicates not to prepend the prefix in `base.prefix` to the result. `is_pres_sub_stressed` is used when
-- creating the pres_sub_stressed stem, to correctly handle both [[desaiguar]] and [[argüir]], whose respective
-- interactions between ü and i/ï are very tricky.
--
-- WARNING: This function is written very carefully; changes to it can easily have unintended consequences.
local function combine_stem_ending(base, stem, ending, is_full_word, dont_include_prefix, is_pres_sub_stressed)
-- Include the prefix in the stem unless dont_include_prefix is given (used in construct_stems()), or the value of
-- `stem` comes from a user-specified stem or form override.
if not dont_include_prefix and not stem:find(IS_USER_STEM_OVERRIDE) and not stem:find(IS_USER_FORM_OVERRIDE) then
stem = base.prefix .. stem
end
-- A * at the beginning of the ending is a signal to remove a stressed accent from the stem. This may feed any of
-- the following rules.
if ending:find("^%*") then
ending = ending:gsub("^%*", "")
stem = com.remove_accents(stem, "final syllable only")
end
-- If ending begins with s and stem ends in a sibilant, we need an e in between; cf. pres_2s 'apareixes' of
-- [[aparèixer]], pres_2s 'torces' of [[tòrcer]], pres_2s 'fuges' of [[fugir]], pres_2s 'brunzes' of [[brunzir]].
-- This may feed the next rule.
if ending:find("^s") and rfind(stem, "[çjsxz]$") then
ending = "e" .. ending
end
-- By default, stems are in their "back" (standalone) form. Before a front vowel, convert the final consonant to
-- its "front" form so the pronunciation doesn't change.
if rfind(ending, "^" .. front_vowel_c) then
-- adequar -> adeqües
-- enaiguar -> enaigües
-- pegar -> pegues
-- arranjar -> arranges
-- marcar -> marques
-- abraçar -> abraces
stem = com.back_to_front(stem)
end
-- Ending beginning in -i after diphthong ending in V + i compresses the two i's into one (cf. pret_1s 'desmaí' and
-- pres_sub_1s 'desmaï' of [[desmaiar]]). This rule doesn't apply after pseudo-vowel u in gu/qu; cf. pret_1s 'guií'
-- of [[guiar]] and contrast pret_1s 'cruí' of [[cruiar]]. This may feed the next rule.
if rfind(ending, "^[iíï]") and rfind(stem, V .. "i$") and not rfind(stem, "[gq][uü]i$") then
stem = stem:gsub("i$", "")
end
-- If ending begins with i (not í), it must get a diaeresis after a true vowel (not gu/qu, cf. pres_1p 'delinquim'
-- of [[delinquir]], not '#delinquïm'; also not a diphthong ending in u, cf. pres_sub_1s 'apreui' of [[apreuar]]
-- not '#apreuï') to prevent the two merging into a diphthong. Note that ü -> u before ï, but to simplify things
-- we leave the double umlauts in place and remove the first one during postprocessing, in fix_double_umlauts().
-- Cf.:
-- * impf_1s 'raïa' of [[raure]];
-- * pres_sub_1s 'creï' of [[crear]];
-- * pres_sub_1s 'associï' of [[associar]];
-- * impf_1s 'cloïa' of [[cloure]];
-- * pres_1p 'lluïm' of [[lluir]];
-- * pres_1p 'arguïm' of [[argüir]].
if ending:find("^i") and rfind(stem, "[aeiouü]$") and not stem:find("[aeiogq]u$") and
-- Unstressed subjunctive endings of [[enaiguar]] remain without umlaut: enaigüi/enaigüis/enaigüin;
-- but stressed endings of [[argüir]] that begin with 'i' do get an umlaut: arguït, impf. arguïa, including
-- stressed subjunctive endings arguïm/arguïu. In both cases the ending is '-i' as part of the creation of
-- the respective stems. There seems no way of distinguishing the two cases other than with a special flag.
not (rfind(stem, "[gq]ü$") and ending == "i" and is_pres_sub_stressed) then
ending = ending:gsub("^i", "ï")
end
local retval = add_stem_ending(stem, ending)
if retval:find("#$") then -- remove final accent if no vowels in prefix
retval = retval:gsub("#$", "")
if not rfind(base.prefix, V) then
retval = com.remove_accents(retval, "final syllable only")
end
end
if is_full_word then
local saw_is_user_form_override
retval, saw_is_user_form_override = rsubb(retval, IS_USER_FORM_OVERRIDE, "")
retval = retval:gsub(IS_USER_STEM_OVERRIDE, "")
if not saw_is_user_form_override then
-- Devoice final voiced obstruent (cf. pres_2s 'caps', pres_3s 'cap' of [[cabre]]). But not after a
-- consonant (cf. pres_2s 'perds', pres_3s 'perd' of [[perdre]]), except for g -> c, which operates
-- even after a consonant (pres_1s 'resolc' of [[resoldre]], pres_1s 'tinc' of [[tenir]]).
retval = retval:gsub("g(s?)$", "c%1")
retval = rsub(retval, "(" .. V .. ")([bdj])(s?)$", function(before, voiced, after)
local devoice = {
b = "p",
d = "t",
j = "ig", -- pres_3s 'fuj' of [[fugir]] -> 'fuig'
}
return before .. devoice[voiced] .. after
end)
end
end
return retval
end
local function add3(base, slot, stems, endings, footnotes, allow_overrides)
if skip_slot(base, slot, allow_overrides) then
return
end
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(base, stem, ending, "is full word")
end
iut.add_forms(base.forms, slot, stems, endings, do_combine_stem_ending, nil, nil, footnotes)
end
local function insert_form(base, slot, form)
if not skip_slot(base, slot) then
iut.insert_form(base.forms, slot, form)
end
end
local function insert_forms(base, slot, forms)
if not skip_slot(base, slot) then
iut.insert_forms(base.forms, slot, forms)
end
end
local function add_single_stem_tense(base, slot_pref, stems, s1, s2, s3, p1, p2, p3)
local function addit(slot, ending)
add3(base, slot_pref .. "_" .. slot, stems, ending)
end
addit("1s", s1)
addit("2s", s2)
addit("3s", s3)
addit("1p", p1)
addit("2p", p2)
addit("3p", p3)
end
local function map_general(stemforms, fn)
return iut.map_forms(iut.convert_to_general_list_form(stemforms), fn)
end
local function flatmap_general(stemforms, fn)
return iut.flatmap_forms(iut.convert_to_general_list_form(stemforms), fn)
end
-- Given a stem ending in a conjugation vowel -a/-e/-i/-ï, split into stem base and conjugation vowel, converting the
-- stem base to "back" form if the conjugation vowel is front (hence 'torce' of [[tòrcer]] splits into 'torç' and 'e',
-- and 'fugi' of [[fugir]] splits into 'fuj' and 'i').
local function split_conj_vowel(stem)
local stem_base, conj_vowel = rmatch(stem, "^(.*)([aeiï])$")
if not stem_base then
error(("Internal error: Stem '%s' doesn't end in conjugation vowel a/e/i"):format(stem))
end
if conj_vowel == "ï" then
-- To simplify handling of ï, convert to i. It will be converted back to ï as necessary in
-- combine_stem_ending().
conj_vowel = "i"
end
if rfind(conj_vowel, front_vowel_c) then
stem_base = com.front_to_back(stem_base)
end
return stem_base, conj_vowel
end
local function construct_stems(base)
base.output_stems = {}
local stems = base.output_stems
local bst = base.input_stems
-- YUCK, see combine_stem_ending() for the necessity of is_pres_sub_stressed.
local function combine(stem, ending, is_pres_sub_stressed)
return combine_stem_ending(base, stem, ending, false, "dont include prefix", is_pres_sub_stressed)
end
stems.irreg = bst.irreg or bst.g_infix
-- NOTE: Some stems end in a conjugation or similar vowel, specifically:
-- * `stem` (ends in conjugation vowel -a/-e/-i);
-- * `stressed_stem` (likewise);
-- * `unstressed_stem` (likewise);
-- * `pres_unstressed` (which assumes the form of the gerund minus the -nt; note that `pres_stressed` does *NOT*
-- end in a conjugation vowel, but assumes the stem form; the value of pres_3s will be derived by adding -a for
-- -ar verbs and otherwise adding an -e prop vowel when required, as in [[cobrir]], and otherwise adding no
-- vowel);
-- * `pres_sub_stressed` (which assumes the form of pres_sub_3s and hence usually ends in -i, occasionally -a);
-- * `pres_sub_unstressed` (which assumes the form of pres_sub_1p minus the -m, hence ends in -e or -i).
-- Save stem for use in add_categories_and_annotation() for determining the conjugation class.
stems.stem = bst.stem or base.stem
local eix_infix_stem
if base.conj_vowel == "i" then
-- Save eix_infix value for use in add_categories_and_annotation() for determining whether consonant
-- alternations exist.
stems.eix_infix = bst.eix_infix or bst.g_infix and "-" or "+"
eix_infix_stem = flatmap_general(stems.eix_infix, function(form)
if form == "+" then
return map_general(stems.stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, "eixe")
end)
elseif form == "-" then
return stems.stem
else
return form
end
end)
end
local stressed_stem = bst.stressed_stem or eix_infix_stem or stems.stem
local unstressed_stem = bst.unstressed_stem or stems.stem
-- Add the 'g' that is characteristic of g-infix verbs. We remove a stem-final v, e.g. [[beure]] with stem 'beve'
-- becomes 'beg'.
local function add_g(stemforms)
return map_general(stemforms, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
stem_base = stem_base:gsub("v$", "")
return combine(stem_base, "g")
end)
end
-- Add the 'u' of the pres_3s that is characteristic of g-infix verbs (and conjugation vowel 'e', later removed).
-- We remove a stem-final v, as well as i as part of a diphthong, e.g. [[beure]] with stem 'beve' becomes 'beue'
-- and [[veure]] with stem 'veie' becomes 'veue' (but [[riure]] with stem 'rie' becomes 'riue' not '#rue'). We
-- don't add -u after a consonant, e.g. [[doldre]] with stem 'dole' becomes 'dole' not '#dolue'.
local function add_u(stemforms)
return map_general(stemforms, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
if stem_base:find("v$") then
stem_base = stem_base:gsub("v$", "")
else
stem_base = rsub(stem_base, "(" .. V .. ")i$", "%1")
end
-- Add u after vowel but not after another u, so we get pres_3p 'duen' of [[dur]] not '#duuen'.
if rfind(stem_base, V .. "$") and not stem_base:find("u$") then
return combine(stem_base, "u")
else
return stem_base
end
end)
end
local stressed_g_infix, unstressed_g_infix, g_infix_pres_stressed
if bst.g_infix then
local function flatmap_g_infix(default)
return flatmap_general(bst.g_infix, function(form)
if form == "+" then
return default
else
return form
end
end)
end
stressed_g_infix = flatmap_g_infix(add_g(stressed_stem))
unstressed_g_infix = flatmap_g_infix(add_g(unstressed_stem))
g_infix_pres_stressed = add_u(stressed_stem)
end
stems.pres_unstressed = bst.pres_unstressed or unstressed_stem
stems.pres_stressed =
-- If no_pres_stressed given, pres_stressed stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
bst.pres_stressed or
g_infix_pres_stressed or
map_general(stressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return stem_base
end)
stems.pres1s =
-- If no_pres_stressed given, pres1s stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
stressed_g_infix or
map_general(stems.pres_stressed, function(form)
return combine(form, "o")
end)
stems.pres3s =
-- If no_pres_stressed given, pres3s stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
bst.pres3s or
map_general(stems.pres_stressed, function(form)
if base.conj_vowel == "a" then
return combine(form, "a")
elseif rfind(form, C .. "[lr]$") and not rfind(form, V .. "ll$") then
return combine(form, "e")
else
return form
end
end)
stems.pres3p =
-- If no_pres_stressed given, pres3p stem should be empty so no forms are generated.
base.no_pres_stressed and {} or
map_general(stems.pres_stressed, function(form)
return combine(form, "en")
end)
local function compute_impf_stem(with_accent)
return map_general(stems.pres_unstressed, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
if conj_vowel == "a" then
return combine(stem_base, with_accent and "àv" or "av")
elseif stem_base:find("i#?$") then
form = form:gsub("i#?$", "")
return combine(rmatch(stem_base, "^(.-)" .. V .. "*$"), with_accent and "èi" or "ei")
else
return combine(stem_base, with_accent and "í" or "i") -- i -> ï after a vowel
end
end)
end
stems.impf1 = bst.impf1 or compute_impf_stem(false)
stems.impf2 = bst.impf2 or compute_impf_stem(true)
stems.pret = bst.pret or
unstressed_g_infix and map_general(unstressed_g_infix,
function(form) return combine(form, "é") end
) or
map_general(unstressed_stem, function(form)
local accent_conj_vowel = {
a = "à",
e = "é",
i = "í",
}
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, accent_conj_vowel[conj_vowel])
end)
stems.fut = bst.fut or base.inf_stem
stems.cond = bst.cond or map_general(stems.fut, function(form) return combine(form, "í") end)
stems.pres_sub_stressed = bst.pres_sub_stressed or
stressed_g_infix and map_general(stressed_g_infix, function(form) return combine(form, "i") end) or
map_general(stressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, "i", "is pres_sub_stressed")
end)
stems.pres_sub_unstressed = bst.pres_sub_unstressed or
unstressed_g_infix and map_general(unstressed_g_infix, function(form) return combine(form, "e") end) or
map_general(unstressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
return combine(stem_base, conj_vowel == "i" and conj_vowel or "e")
end)
stems.impf_sub = bst.impf_sub or map_general(stems.pret, function(form)
local stem_base = rmatch(form, "^(.*)à$") -- already in "back" form, no need to convert
if stem_base then
return combine(stem_base, "é")
else
return form
end
end)
stems.pp = bst.pp or
unstressed_g_infix and map_general(unstressed_g_infix,
function(form) return combine(form, "ud") end
) or
map_general(unstressed_stem, function(form)
local stem_base, conj_vowel = split_conj_vowel(form)
-- use combine() so we get 'abduïd' from 'abdu-' of [[abduir]], 'seguid' from 'seg-' from [[seguir]], etc.
return combine(stem_base, (conj_vowel == "e" and "u" or conj_vowel) .. "d")
end)
end
local function a_to_e(base, stems, suffix)
return map_general(stems, function(form)
local stem_base = form:match("^(.-)a$")
if stem_base then
suffix = "e" .. suffix
else
stem_base = form
end
return combine_stem_ending(base, stem_base, suffix, "is full word")
end)
end
local function add_present_indic(base)
local stems = base.output_stems
local function addit(slot, stems, ending)
add3(base, "pres_" .. slot, stems, ending)
end
addit("1s", stems.pres1s, "")
insert_forms(base, "pres_2s", a_to_e(base, stems.pres3s, "s"))
addit("3s", stems.pres3s, "")
insert_forms(base, "pres_1p", a_to_e(base, stems.pres_unstressed, "m"))
insert_forms(base, "pres_2p", a_to_e(base, stems.pres_unstressed, "u"))
addit("3p", stems.pres3p, "")
end
local function add_present_subj(base)
local stems = base.output_stems
local function addit(slot, stems, ending)
add3(base, "pres_sub_" .. slot, stems, ending)
end
-- Regular -ar verb: [[amar]]: ami, amis, ami, amem, ameu, amin
-- Regular -re verb: [[batre]]: bati, batis, bati, batem, bateu, batin (same as -ar verb)
-- Regular -ir verb, no -eix- infix: [[dormir]]: dormi, dormis, dormi, dormim, dormiu, dormin
-- Regular -ir verb, -eix- infix: [[imprimir]]: imprimeixi, imprimeixis, imprimeixi, imprimim, imprimiu, imprimeixin
-- Stem changing in 123s/3p vs. 12p:
-- * -eix- infix (-eix- in all stressed forms: 123s/3p of pres ind/sub, 2s imp)
-- * [[collir]]: culli, cullis, culli, collim, colliu, cullin (cull- in all stressed forms)
-- * [[cabre]]: càpiga, càpigues, càpiga, capiguem, capigueu, càpiguen (also different endings)
addit("1s", stems.pres_sub_stressed, "")
insert_forms(base, "pres_sub_2s", a_to_e(base, stems.pres_sub_stressed, "s"))
addit("3s", stems.pres_sub_stressed, "")
addit("1p", stems.pres_sub_unstressed, "m")
addit("2p", stems.pres_sub_unstressed, "u")
insert_forms(base, "pres_sub_3p", a_to_e(base, stems.pres_sub_stressed, "n"))
end
local function add_finite_non_present(base)
local stems = base.output_stems
local function add_tense(slot, stem, s1, s2, s3, p1, p2, p3)
add_single_stem_tense(base, slot, stem, s1, s2, s3, p1, p2, p3)
end
add_tense("impf", stems.impf1, "a", "es", "a", nil, nil, "en")
add_tense("impf", stems.impf2, nil, nil, nil, "em", "eu", nil)
-- pret_1s ends in -í regardless of the normal vowel of the stem.
insert_forms(base, "pret_1s", map_general(stems.pret, function(form)
local stem_base, conj_vowel = rmatch(form, "^(.*)(" .. V .. ")$")
if not stem_base then
error(("Internal error: Preterite stem '%s' doesn't end in vowel"):format(form))
end
if rfind(conj_vowel, front_vowel_c) then
stem_base = com.front_to_back(stem_base)
end
-- Use combine_stem_ending() to handle back-to-front conversions, e.g. pegà -> peguí for [[pegar]] and ensure
-- that the prefix gets added.
return combine_stem_ending(base, stem_base, "í", "is full word") end))
-- * at the beginning of the ending means to remove an accent from the last vowel of the preterite stem.
add_tense("pret", stems.pret, nil, "*res", "", "rem", "reu", "*ren")
-- * at the beginning of the ending means to remove an accent from the last vowel of the imperfect subjunctive stem.
add_tense("impf_sub", stems.impf_sub, "s", "*ssis", "s", "ssim", "ssiu", "*ssin")
add_tense("fut", stems.fut, "é", "às", "à", "em", "eu", "an")
add_tense("cond", stems.cond, "*a", "*es", "*a", "em", "eu", "*en")
end
local function add_non_finite_forms(base)
local stems = base.output_stems
local function addit(slot, stems, ending, footnotes)
add3(base, slot, stems, ending, footnotes)
end
insert_form(base, "infinitive", {form = base.orig_verb})
-- Also insert "infinitive + reflexive pronoun" combinations if we're handling a reflexive verb. See comment below
-- for "gerund + reflexive pronoun" combinations.
if base.refl then
for _, persnum in ipairs(person_number_list) do
insert_form(base, "infinitive_" .. persnum, {form = base.orig_verb})
end
end
-- Gerunds don't have an umlaut over the i in cases like 'abduint' of 'abduir' (not '#abduïnt').
local pres_unstressed_no_umlaut = map_general(stems.pres_unstressed, function(form)
return rsub(form, "ï$", "i")
end)
addit("gerund", pres_unstressed_no_umlaut, "nt")
-- Also insert "gerund + reflexive pronoun" combinations if we're handling a reflexive verb. We insert exactly the
-- same form as for the bare gerund; later on in add_reflexive_or_fixed_clitic_to_forms(), we add the appropriate
-- clitic pronouns. It's important not to do this for non-reflexive verbs, because in that case, the clitic
-- pronouns won't be added, and {{ca-verb form of}} will wrongly consider all these combinations as possible
-- inflections of the bare gerund. Thanks to [[User:JeffDoozan]] for this bug fix.
if base.refl then
for _, persnum in ipairs(person_number_list) do
addit("gerund_" .. persnum, pres_unstressed_no_umlaut, "nt")
end
end
addit("pp_ms", stems.pp, "")
if not base.pp_inv then
addit("pp_fs", stems.pp, "a")
-- make_plural() handles the complexities of e.g. 'vist' of [[veure]] -> 'vistos'/'vists' and 'romàs' of
-- [[romandre]] -> 'romasos'. We need to use flatmap_general() because make_plural() may return more than one
-- plural, and we need to use map_general() on the result, applying combine_stem_ending(), to ensure that
-- prefixes get properly added and plurals like 'amads' of stem 'amad' of [[amar]] get converted to 'amats'.
insert_forms(base, "pp_mp", map_general(flatmap_general(stems.pp, function(form)
-- Remove any # indicating that an accent will be dropped; it will be dropped in any case by make_plural().
form = form:gsub("#$", "")
return com.make_plural(form, "m")
end), function(form)
return combine_stem_ending(base, form, "", "is full word")
end))
addit("pp_fp", stems.pp, "es")
end
end
local function add_imperatives(base)
if base.noimp then
return
end
-- Copy pres3s to imperative since they are almost always the same.
insert_forms(base, "imp_2s", iut.map_forms(base.forms.pres_3s, function(form) return form end))
-- Copy pres2p to imperative plural since they are almost always the same.
insert_forms(base, "imp_2p", iut.map_forms(base.forms.pres_2p, function(form) return form end))
-- Copy subjunctives to imperatives.
for _, persnum in ipairs({"3s", "1p", "3p"}) do
local from = "pres_sub_" .. persnum
local to = "imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form) return form end))
end
end
local function fix_double_umlauts(base)
for slot, forms in pairs(base.forms) do
for _, form in ipairs(forms) do
form.form = form.form:gsub("üï", "uï")
end
end
end
local function process_slot_overrides(base, filter_slot, reflexive_only)
local overrides = reflexive_only and base.basic_reflexive_only_overrides or base.basic_overrides
for slot, forms in pairs(overrides) do
if not filter_slot or filter_slot(slot) then
add3(base, slot, forms, "", nil, "allow overrides")
end
end
end
local function link_clitic(clitic)
return (clitic:gsub("([^ %-]+)", "[[%1]]"))
end
-- Prefix `form` with `clitic`, adding fixed text `between` between them. Add links as appropriate unless the user
-- requested no links. Check whether form already has brackets (as will be the case if the form has a fixed clitic).
local function prefix_clitic_to_form(base, clitic, between, form)
if base.alternant_multiword_spec.args.noautolinkverb then
return clitic .. between .. form
else
local clitic_pref = link_clitic(clitic) .. between
if form:find("%[%[") then
return clitic_pref .. form
else
return clitic_pref .. "[[" .. form .. "]]"
end
end
end
-- Suffix `form` with `clitic`. Add links as appropriate unless the user requested no links. Check whether form already
-- has brackets (as will be the case if the form has a fixed clitic).
local function suffix_clitic_to_form(base, clitic, form)
local autolink = not base.alternant_multiword_spec.args.noautolinkverb
if base.alternant_multiword_spec.args.noautolinkverb then
return form .. clitic
else
local clitic_suf = link_clitic(clitic)
if form:find("%[%[") then
return form .. clitic_suf
else
return "[[" .. form .. "]]" .. clitic_suf
end
end
end
-- Add a reflexive pronoun or fixed clitic (FIXME: not working), as appropriate to the base forms that were generated.
-- `do_joined` means to do only the forms where the pronoun is joined to the end of the form; otherwise, do only the
-- forms where it is not joined and precedes the form.
local function add_reflexive_or_fixed_clitic_to_forms(base, do_reflexive, do_joined)
for _, slotaccel in ipairs(base.alternant_multiword_spec.verb_slots_basic) do
local slot, accel = unpack(slotaccel)
local persnum
if slot:find("[123]") then
persnum = slot:match("^.*_(.-)$")
else
persnum = "3s"
end
local function get_proclitic(form)
--if not do_reflexive then
-- return base.clitic
if form:find("^[aeiouh]") then
return proclitic_elided_person_number_to_reflexive_pronoun[persnum]
else
return proclitic_non_elided_person_number_to_reflexive_pronoun[persnum]
end
end
local function get_enclitic(form)
--if not do_reflexive then
-- return base.clitic
if rfind(form, C .. "$") or rfind(form, V .. "[iu]$") and not form:find("[gq]ui$") then
return enclitic_non_elided_person_number_to_reflexive_pronoun[persnum]
else
return enclitic_elided_person_number_to_reflexive_pronoun[persnum]
end
end
if base.forms[slot] then
if do_reflexive and slot:find("^pp_") or slot == "infinitive_linked" then
-- do nothing with reflexive past participles or with infinitive linked (handled at the end)
elseif slot:find("^neg_imp_") then
error("Internal error: Should not have forms set for negative imperative at this stage")
else
local slot_has_suffixed_clitic = slot:find("infinitive") or slot:find("gerund") or slot:find("^imp_")
-- Maybe generate non-reflexive parts and separated syntactic variants for use in
-- {{ca-verb form of}}. See comment in add_slots() above `need_special_verb_form_of_slots`.
-- Check for do_joined so we only run this code once.
if do_reflexive and do_joined and base.alternant_multiword_spec.source_template == "ca-verb form of" and
-- Skip personal variants of infinitives and gerunds so we don't think [[arrependendo]] is a
-- non-reflexive equivalent of [[arrependendo-me]].
not slot:find("infinitive_") and not slot:find("gerund_") then
-- Clone the forms because we will be destructively modifying them just below, adding the reflexive
-- pronoun.
insert_forms(base, slot .. "_non_reflexive", mw.clone(base.forms[slot]))
if slot_has_suffixed_clitic then
insert_forms(base, slot .. "_variant", iut.map_forms(base.forms[slot], function(form)
return prefix_clitic_to_form(base, get_proclitic(form), "... ", form)
end))
end
end
if slot_has_suffixed_clitic then
if do_joined then
-- Add clitic after form.
for _, form in ipairs(base.forms[slot]) do
form.form = suffix_clitic_to_form(base, get_enclitic(form.form), form.form)
end
end
elseif not do_joined then
-- Add clitic before form.
for _, form in ipairs(base.forms[slot]) do
form.form = prefix_clitic_to_form(base, get_proclitic(form.form), "", form.form)
end
end
end
end
end
end
local function handle_infinitive_linked(base)
-- Compute linked versions of potential lemma slots, for use in {{ca-verb}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs({"infinitive"}) do
insert_forms(base, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.lemma and rfind(base.linked_lemma, "%[%[") then
return base.linked_lemma
else
return form
end
end))
end
end
local function generate_negative_imperatives(base)
if base.noimp then
return
end
-- Copy subjunctives to negative imperatives, preceded by "no".
for _, persnum in ipairs(neg_imp_person_number_list) do
local from = "pres_sub_" .. persnum
local to = "neg_imp_" .. persnum
insert_forms(base, to, iut.map_forms(base.forms[from], function(form)
if base.alternant_multiword_spec.args.noautolinkverb then
return "no " .. form
elseif form:find("%[%[") then
-- already linked, e.g. when reflexive
return "[[no]] " .. form
else
return "[[no]] [[" .. form .. "]]"
end
end))
end
end
-- Process specs given by the user using 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'.
local function process_addnote_specs(base)
for _, spec in ipairs(base.addnote_specs) do
for _, slot_spec in ipairs(spec.slot_specs) do
slot_spec = "^" .. slot_spec .. "$"
for slot, forms in pairs(base.forms) do
if rfind(slot, slot_spec) then
-- To save on memory, side-effect the existing forms.
for _, form in ipairs(forms) do
form.footnotes = iut.combine_footnotes(form.footnotes, spec.footnotes)
end
end
end
end
end
end
local function add_missing_links_to_forms(base)
-- Any forms without links should get them now. Redundant ones will be stripped later.
for slot, forms in pairs(base.forms) do
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
form.form = "[[" .. form.form .. "]]"
end
end
end
end
local function conjugate_verb(base)
construct_stems(base)
add_present_indic(base)
add_present_subj(base)
add_finite_non_present(base)
add_non_finite_forms(base)
fix_double_umlauts(base)
-- do non-reflexive non-imperative slot overrides
process_slot_overrides(base, function(slot)
return not slot:find("^imp_") and not slot:find("^neg_imp_")
end)
-- This should happen after process_slot_overrides() in case a derived slot is based on an override
-- (as with the imp_3s of [[dar]], [[estar]]).
add_imperatives(base)
-- do non-reflexive positive imperative slot overrides
process_slot_overrides(base, function(slot)
return slot:find("^imp_")
end)
-- We need to add joined reflexives, then joined and non-joined clitics, then non-joined reflexives, so we get
-- [[arrepéndete]] but [[no]] [[te]] [[arrependas]].
if base.refl then
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", "do joined")
process_slot_overrides(base, nil, "do reflexive") -- do reflexive-only slot overrides
add_reflexive_or_fixed_clitic_to_forms(base, "do reflexive", false)
end
-- This should happen after add_reflexive_or_fixed_clitic_to_forms() so negative imperatives get the reflexive pronoun
-- and clitic in them.
generate_negative_imperatives(base)
-- do non-reflexive negative imperative slot overrides
-- FIXME: What about reflexive negative imperatives?
process_slot_overrides(base, function(slot)
return slot:find("^neg_imp_")
end)
-- This should happen before add_missing_links_to_forms() so that the comparison `form == base.lemma`
-- in handle_infinitive_linked() works correctly and compares unlinked forms to unlinked forms.
handle_infinitive_linked(base)
process_addnote_specs(base)
if not base.alternant_multiword_spec.args.noautolinkverb then
add_missing_links_to_forms(base)
end
end
local function parse_indicator_spec(angle_bracket_spec)
-- Store the original angle bracket spec so we can reconstruct the overall conj spec with the lemma(s) in them.
local base = {
angle_bracket_spec = angle_bracket_spec,
user_basic_overrides = {},
user_stems = {},
addnote_specs = {},
}
local function parse_err(msg)
error(msg .. ": " .. angle_bracket_spec)
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
parse_err("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
table.insert(footnotes, separated_group[j])
end
return footnotes
end
local inside = angle_bracket_spec:match("^<(.*)>$")
assert(inside)
if inside == "" then
return base
end
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = put.split_alternating_runs(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local first_element = dot_separated_group[1]
if first_element == "addnote" then
local spec_and_footnotes = fetch_footnotes(dot_separated_group)
if #spec_and_footnotes < 2 then
parse_err("Spec with 'addnote' should be of the form 'addnote[SLOTSPEC][FOOTNOTE][FOOTNOTE][...]'")
end
local slot_spec = table.remove(spec_and_footnotes, 1)
local slot_spec_inside = rmatch(slot_spec, "^%[(.*)%]$")
if not slot_spec_inside then
parse_err("Internal error: slot_spec " .. slot_spec .. " should be surrounded with brackets")
end
local slot_specs = rsplit(slot_spec_inside, ",")
-- FIXME: Here, [[Module:it-verb]] called strip_spaces(). Generally we don't do this. Should we?
table.insert(base.addnote_specs, {slot_specs = slot_specs, footnotes = spec_and_footnotes})
elseif indicator_flags[first_element] then
if #dot_separated_group > 1 then
parse_err("No footnotes allowed with '" .. first_element .. "' spec")
end
if base[first_element] then
parse_err("Spec '" .. first_element .. "' specified twice")
end
base[first_element] = true
elseif first_element:find("^var:") then
if #dot_separated_group > 1 then
parse_err(("Can't attach footnotes to 'var:' spec '%s'"):format(first_element))
end
base.var = first_element:match("^var:(.*)$")
elseif first_element:find(":") then
local colon_separated_groups = put.split_alternating_runs(dot_separated_group, "%s*:%s*")
local first_element = colon_separated_groups[1][1]
if #colon_separated_groups[1] > 1 then
parse_err("Can't attach footnotes directly to '" .. first_element .. "' spec; attach them to the " ..
"colon-separated values following the initial colon")
end
if overridable_stems[first_element] then
if base.user_stems[first_element] then
parse_err("Overridable stem '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_stems[first_element] = overridable_stems[first_element](colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes})
else -- assume a basic override; we validate further later when the possible slots are available
if base.user_basic_overrides[first_element] then
parse_err("Basic override '" .. first_element .. "' specified twice")
end
table.remove(colon_separated_groups, 1)
base.user_basic_overrides[first_element] = allow_multiple_values_for_override(colon_separated_groups,
{prefix = first_element, base = base, parse_err = parse_err, fetch_footnotes = fetch_footnotes},
"is form override")
end
else
parse_err("Unrecognized spec '" .. first_element .. "'")
end
end
return base
end
-- Normalize all lemmas, substituting the pagename for blank lemmas and adding links to multiword lemmas.
local function normalize_all_lemmas(alternant_multiword_spec, head)
-- (1) Add links to all before and after text. Remember the original text so we can reconstruct the verb spec later.
if not alternant_multiword_spec.args.noautolinktext then
iut.add_links_to_before_and_after_text(alternant_multiword_spec, "remember original")
end
-- (2) Remove any links from the lemma, but remember the original form so we can use it below in the 'lemma_linked'
-- form.
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.lemma == "" then
base.lemma = head
end
base.user_specified_lemma = base.lemma
base.lemma = m_links.remove_links(base.lemma)
local refl_verb = base.lemma
local verb, refl = rmatch(refl_verb, "^(.-)%-(se)$")
if not verb then
verb, refl = rmatch(refl_verb, "^(.-)('s)$")
end
if not verb then
verb, refl = refl_verb, nil
end
base.user_specified_verb = verb
base.refl = refl
base.verb = base.user_specified_verb
local linked_lemma
if alternant_multiword_spec.args.noautolinkverb or base.user_specified_lemma:find("%[%[") then
linked_lemma = base.user_specified_lemma
elseif base.refl then
-- Reconstruct the linked lemma with separate links around base verb, reflexive pronoun and clitic.
linked_lemma = base.user_specified_verb == base.verb and "[[" .. base.user_specified_verb .. "]]" or
"[[" .. base.verb .. "|" .. base.user_specified_verb .. "]]"
linked_lemma = linked_lemma .. (refl and "-[[" .. refl .. "]]" or "")
else
-- Add links to the lemma so the user doesn't specifically need to, since we preserve links in multiword
-- lemmas and include links in non-lemma forms rather than allowing the entire form to be a link.
linked_lemma = iut.add_links(base.user_specified_lemma)
end
base.linked_lemma = linked_lemma
end)
end
local function detect_indicator_spec(base)
if (base.only3s and 1 or 0) + (base.only3sp and 1 or 0) + (base.only3p and 1 or 0) > 1 then
error("Only one of 'only3s', 'only3sp' and 'only3p' can be specified")
end
base.forms = {}
base.input_stems = {}
base.basic_overrides = {}
base.basic_reflexive_only_overrides = {}
base.orig_verb = base.verb -- in case of a 'like = "..."' redirect
if not base.no_built_in then
local function match_built_in_spec(verb, built_in_spec)
local prefix, non_prefixed_verb
if type(built_in_spec.match) == "function" then
prefix, non_prefixed_verb = built_in_spec.match(verb)
elseif built_in_spec.match:find("^%^") and rsub(built_in_spec.match, "^%^", "") == verb then
-- begins with ^, for exact match, and matches
prefix, non_prefixed_verb = "", verb
else
prefix, non_prefixed_verb = rmatch(verb, "^(.*)(" .. built_in_spec.match .. ")$")
end
return prefix, non_prefixed_verb
end
local function find_built_in(verb, var)
for _, built_in_spec in ipairs(built_in_conjugations) do
local prefix, non_prefixed_verb = match_built_in_spec(verb, built_in_spec)
if prefix then
if not built_in_spec.var then
if var then
error(("Can't specify a variant spec 'var:%s' with verb '%s'"):format(var, verb))
end
return prefix, non_prefixed_verb, built_in_spec
elseif not var then
local possible_vars = {}
for _, built_in_spec in ipairs(built_in_conjugations) do
local prefix, non_prefixed_verb = match_built_in_spec(verb, built_in_spec)
if prefix then
table.insert(possible_vars, built_in_spec.var)
end
end
error(("For verb '%s', must specify a variant using 'var:...'; possible values are %s"):format(
verb, table.concat(possible_vars, ", ")))
elseif built_in_spec.var == var then
return prefix, non_prefixed_verb, built_in_spec
end
end
end
return nil
end
local prefix, non_prefixed_verb, built_in_spec = find_built_in(base.verb, base.var)
if prefix then
-- we found a built-in verb
if built_in_spec.like then
-- we found a redirect to another verb that has the same conjugation, just a different infinitive
base.verb = prefix .. built_in_spec.like
local new_prefix, new_non_prefixed_verb, new_built_in_spec = find_built_in(base.verb, built_in_spec.likevar)
if new_prefix then
-- redirected to another built-in verb
base.prefix = new_prefix
base.non_prefixed_verb = new_non_prefixed_verb
built_in_spec = new_built_in_spec
else
built_in_spec = nil
end
else
base.prefix = prefix
base.non_prefixed_verb = non_prefixed_verb
end
end
if built_in_spec then
-- we found a built-in verb, possibly redirecting to another built-in verb
for stem, forms in pairs(built_in_spec.forms) do
if type(forms) == "function" then
forms = forms(base, base.prefix)
end
if stem:find("^refl_") then
stem = stem:gsub("^refl_", "")
if not base.alternant_multiword_spec.verb_slots_basic_map[stem] then
error("Internal error: setting for 'refl_" .. stem .. "' does not refer to a basic verb slot")
end
base.basic_reflexive_only_overrides[stem] = forms
elseif base.alternant_multiword_spec.verb_slots_basic_map[stem] then
-- an individual form override of a basic form
base.basic_overrides[stem] = forms
else
base.input_stems[stem] = forms
end
end
end
end
-- Override built-in-verb stems and overrides with user-specified ones.
for stem, values in pairs(base.user_stems) do
base.input_stems[stem] = values
end
for override, values in pairs(base.user_basic_overrides) do
if not base.alternant_multiword_spec.verb_slots_basic_map[override] then
error("Unrecognized override '" .. override .. "': " .. base.angle_bracket_spec)
end
base.basic_overrides[override] = values
end
base.prefix = base.prefix or ""
base.non_prefixed_verb = base.non_prefixed_verb or base.verb
local inf_stem, suffix = rmatch(base.non_prefixed_verb, "^(.*)(re)$")
if not inf_stem then
inf_stem, suffix = rmatch(base.non_prefixed_verb, "^(.*)([aeiu]r)$")
end
if not inf_stem then
error("Unrecognized infinitive: " .. base.verb)
end
-- Remove accents from e.g. [[parèixer]], [[córrer]].
inf_stem = com.remove_accents(inf_stem)
-- Save full infinitive stem for use in future and conditional.
base.inf_stem = (inf_stem .. suffix):gsub("e$", "")
local stem = inf_stem
if suffix == "re" then
-- verbs in -ldre, -ndre have stem without the d
stem = stem:gsub("([ln])d$", "%1")
elseif suffix == "ur" then
stem = stem .. "u"
end
base.conj_vowel = (suffix == "re" or suffix == "ur") and "e" or suffix:gsub("r$", "")
-- If the stem is followed by a front vowel, convert it to its "back" form before calling combine_stem_ending(),
-- which expects the "back" form of the stem and may convert it back to the "front" form. Don't do this conversion
-- for ï so we leave [[arguïr]] (underlyingly 'argüïr') as 'argu' ("back" form), which becomes 'argü' ("front" form)
-- before front vowel ï and we end up with base.stem containing the underlying form 'argüï'. We remove the first of
-- two umlauts in a row in a postprocessing step (fix_double_umlauts()).
if rfind(suffix, "^[ei]") then
stem = com.front_to_back(stem)
end
-- Use combine_stem_ending() so we get ï if necessary.
base.stem = combine_stem_ending(base, stem, base.conj_vowel, false, "dont include prefix")
-- Propagate built-in-verb indicator flags to `base` and combine with user-specified flags.
for indicator_flag, _ in pairs(indicator_flags) do
base[indicator_flag] = base[indicator_flag] or base.input_stems[indicator_flag]
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
-- Propagate some settings up; some are used internally, others by [[Module:pt-headword]].
iut.map_word_specs(alternant_multiword_spec, function(base)
-- Internal indicator flags. Do these before calling detect_indicator_spec() because add_slots() uses them.
for _, prop in ipairs { "refl", "clitic" } do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
base.alternant_multiword_spec = alternant_multiword_spec
end)
add_slots(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(base)
-- User-specified indicator flags. Do these after calling detect_indicator_spec() because the latter may set these
-- indicators for built-in verbs.
for prop, _ in pairs(indicator_flags) do
if base[prop] then
alternant_multiword_spec[prop] = true
end
end
end)
end
local function add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
local function insert_ann(anntype, value)
m_table.insertIfNot(alternant_multiword_spec.annotation[anntype], value)
end
local function insert_cat(cat, also_when_multiword)
-- Don't place multiword terms in categories like 'Catalan verbs ending in -ar' to avoid spamming the
-- categories with such terms.
if also_when_multiword or not multiword_lemma then
-- m_table.insertIfNot(alternant_multiword_spec.categories, "Catalan " .. cat)
end
end
if check_for_red_links and alternant_multiword_spec.source_template == "ca-conj" and multiword_lemma then
for _, slot_and_accel in ipairs(alternant_multiword_spec.all_verb_slots) do
local slot = slot_and_accel[1]
local forms = base.forms[slot]
local must_break = false
if forms then
for _, form in ipairs(forms) do
if not form.form:find("%[%[") then
local title = mw.title.new(form.form)
if title and not title.exists then
-- insert_cat("verbs with red links in their inflection tables")
must_break = true
break
end
end
end
end
if must_break then
break
end
end
end
map_general(base.output_stems.stem, function(stem)
local stem_base, conj_vowel = split_conj_vowel(stem)
local need_no_eix_infix = true
if conj_vowel ~= base.conj_vowel then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Irregular verbs|သမ္ဗန္ဓပံၚ်ဖနှဴ]]")
-- insert_cat("mixed conjugation verbs")
elseif conj_vowel == "a" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#First conjugation|သမ္ဗန္ဓပထမ]]")
-- insert_cat("first conjugation verbs")
elseif conj_vowel == "e" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Second conjugation|သမ္ဗန္ဓဒုတိယ]]")
-- insert_cat("second conjugation verbs")
elseif conj_vowel == "i" then
insert_ann("conj", "[[en:Appendix:Catalan verbs#Third conjugation|သမ္ဗန္ဓတတိယ]]")
-- insert_cat("third conjugation verbs")
need_no_eix_infix = false
map_general(base.output_stems.eix_infix, function(form)
if form == "+" then
insert_ann("eix_infix", "with ''-eix-''")
-- insert_cat("third conjugation verbs with -eix-")
elseif form == "-" then
insert_ann("eix_infix", "without ''-eix-''")
-- insert_cat("third conjugation verbs without -eix-")
end
end)
else
error(("Internal error: Stem '%s' doesn't end in conjugation vowel a/e/i and split_conj_vowel() didn't catch it"
):format(stem))
end
if need_no_eix_infix then
insert_ann("eix_infix", "no infix")
end
end)
if base.input_stems.g_infix then
insert_ann("g_infix", "with velar infix")
-- insert_cat("verbs with velar infix")
else
insert_ann("g_infix", "no infix")
end
if base.output_stems.irreg then
insert_ann("irreg", "irregular")
-- insert_cat("irregular verbs")
else
insert_ann("irreg", "regular")
end
if base.only3s then
insert_ann("defective", "impersonal")
-- insert_cat("impersonal verbs")
elseif base.only3sp then
insert_ann("defective", "third-person only")
-- insert_cat("third-person-only verbs")
elseif base.only3p then
insert_ann("defective", "third-person plural only")
-- insert_cat("third-person-plural-only verbs")
elseif base.no_pres_stressed then
insert_ann("defective", "defective")
-- insert_cat("defective verbs")
else
insert_ann("defective", "regular")
end
--if base.clitic then
-- insert_cat("verbs with lexical clitics")
--end
if base.refl then
-- insert_cat("reflexive verbs")
end
local stem_base, conj_vowel = split_conj_vowel(base.stem)
local cons_alt
if conj_vowel == "i" and base.output_stems.eix_infix == "+" then
-- no alternations in verbs like [[afligir]] because all endings are front
elseif stem_base:find("ç$") then
cons_alt = "ç-c"
elseif stem_base:find("c$") then
cons_alt = "c-qu"
elseif stem_base:find("g$") then
cons_alt = "g-gu"
elseif stem_base:find("gu$") then
cons_alt = "gu-gü"
elseif stem_base:find("j$") then
cons_alt = "j-g"
elseif stem_base:find("qu$") then
cons_alt = "qu-qü"
end
if cons_alt then
local desc = cons_alt .. " alternation"
insert_ann("cons_alt", desc)
-- insert_cat("verbs with " .. desc)
else
insert_ann("cons_alt", "non-alternating")
end
end
-- Compute the categories to add the verb to, as well as the annotation to display in the
-- conjugation title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
local ann = {}
alternant_multiword_spec.annotation = ann
ann.conj = {}
ann.g_infix = {}
ann.eix_infix = {}
ann.irreg = {}
ann.defective = {}
ann.cons_alt = {}
local multiword_lemma = false
for _, form in ipairs(alternant_multiword_spec.forms.infinitive) do
if form.form:find(" ") then
multiword_lemma = true
break
end
end
iut.map_word_specs(alternant_multiword_spec, function(base)
add_categories_and_annotation(alternant_multiword_spec, base, multiword_lemma)
end)
local ann_parts = {}
local conj = table.concat(ann.conj, " or ")
if conj ~= "" then
table.insert(ann_parts, conj)
end
local eix_infix = table.concat(ann.eix_infix, " or ")
if eix_infix ~= "" and eix_infix ~= "no infix" then
table.insert(ann_parts, eix_infix)
end
local irreg = table.concat(ann.irreg, " or ")
if irreg ~= "" and irreg ~= "regular" then
table.insert(ann_parts, irreg)
end
local g_infix = table.concat(ann.g_infix, " or ")
if g_infix ~= "" and g_infix ~= "no infix" then
table.insert(ann_parts, g_infix)
end
local defective = table.concat(ann.defective, " or ")
if defective ~= "" and defective ~= "regular" then
table.insert(ann_parts, defective)
end
local cons_alt = table.concat(ann.cons_alt, " or ")
if cons_alt ~= "" and cons_alt ~= "non-alternating" then
table.insert(ann_parts, cons_alt)
end
alternant_multiword_spec.annotation = table.concat(ann_parts, ", ")
end
local function show_forms(alternant_multiword_spec)
local lemmas = alternant_multiword_spec.forms.infinitive
alternant_multiword_spec.lemmas = lemmas -- save for later use in make_table()
local reconstructed_verb_spec = iut.reconstruct_original_spec(alternant_multiword_spec)
local function transform_accel_obj(slot, formobj, accel_obj)
-- No accelerators for negative imperatives, which are always multiword and derived directly from the
-- present subjunctive.
if slot:find("^neg_imp") then
return nil
end
if accel_obj then
accel_obj.form = "verb-form-" .. reconstructed_verb_spec
end
return accel_obj
end
local props = {
lang = lang,
lemmas = lemmas,
transform_accel_obj = transform_accel_obj,
slot_list = alternant_multiword_spec.verb_slots_basic,
}
iut.show_forms(alternant_multiword_spec.forms, props)
alternant_multiword_spec.footnote_basic = alternant_multiword_spec.forms.footnote
end
local notes_template = [=[
<div class="roa-footnote-outer-div" style="width:100%;">
<div class="roa-footnote-inner-div">
{footnote}
</div></div>
]=]
local basic_table = [=[
{description}<div class="NavFrame">
<div class="NavHead"> သမ္ဗန္ဓကာတ်တလာန်မဇ္ဇျိမဆေၚ်စပ်ကဵု {title}</div>
<div class="NavContent">
{\op}| class="roa-inflection-table" data-toggle-category="inflection"
|-
! colspan="3" class="roa-nonfinite-header" | <span title="infinitiu">ကြိယာဟွံကၠောံ</span>
| colspan="5" | {infinitive}
|-
! colspan="3" class="roa-nonfinite-header" | <span title="gerundi">ကြိယာစၞး</span>
| colspan="5" | {gerund}
|-
! rowspan="3" colspan="2" class="roa-nonfinite-header" | <span title="participi passat">လုပ်ကၠောန်စွံလဝ်နကဵုအတိက်</span>
| colspan="2" class="roa-nonfinite-header" |
! colspan="2" class="roa-nonfinite-header" | ပုလ္လိၚ်
! colspan="2" class="roa-nonfinite-header" | ဣတ္တိလိၚ်
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဨကဝုစ်
| colspan="2" | {pp_ms}
| colspan="2" | {pp_fs}
|-
! colspan="2" class="roa-nonfinite-header" | ကိုန်ဗဟုဝစ်
| colspan="2" | {pp_mp}
| colspan="2" | {pp_fp}
|-
! colspan="2" rowspan="2" class="roa-person-number-header" | ပူဂဵု
! colspan="3" class="roa-person-number-header" | ကိုန်ဨကဝုစ်
! colspan="3" class="roa-person-number-header" | ကိုန်ဗဟုဝစ်
|-
! class="roa-person-number-header" style="width:12.5%;" | ပထမ
! class="roa-person-number-header" style="width:12.5%;" | ဒုတိယ
! class="roa-person-number-header" style="width:12.5%;" | တတိယ
! class="roa-person-number-header" style="width:12.5%;" | ပထမ
! class="roa-person-number-header" style="width:12.5%;" | ဒုတိယ
! class="roa-person-number-header" style="width:12.5%;" | တတိယ
|-
! rowspan="6" class="roa-indicative-left-rail" | <span title="indicatiu">ပရေၚ်စၞောန်ထ္ၜး</span>
! class="roa-indicative-left-rail" |
! class="roa-indicative-left-rail" | <<jo>>
! class="roa-indicative-left-rail" | <<tu>>
! class="roa-indicative-left-rail" | <<ell>>/<<ella>><br /><<vostè>>
! class="roa-indicative-left-rail" | <<nosaltres>><br /><<nós>>
! class="roa-indicative-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-indicative-left-rail" | <<ells>>/<<elles>><br /><<vostès>>
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="present">ပစ္စုပ္ပန်</span>
| {pres_1s}
| {pres_2s}
| {pres_3s}
| {pres_1p}
| {pres_2p}
| {pres_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="imperfet">ဟွံဍိုက်ပေၚ်</span>
| {impf_1s}
| {impf_2s}
| {impf_3s}
| {impf_1p}
| {impf_2p}
| {impf_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="futur">အနာဂတ်</span>
| {fut_1s}
| {fut_2s}
| {fut_3s}
| {fut_1p}
| {fut_2p}
| {fut_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="passat">မပြဟ်လောန်</span>
| {pret_1s}
| {pret_2s}
| {pret_3s}
| {pret_1p}
| {pret_2p}
| {pret_3p}
|-
! class="roa-indicative-left-rail" style="height:3em;" | <span title="condicional">တၚ်မကၞာတ်လဝ်စေဝ်ပၞောန်</span>
| {cond_1s}
| {cond_2s}
| {cond_3s}
| {cond_1p}
| {cond_2p}
| {cond_3p}
|-
! class="roa-subjunctive-left-rail" rowspan="3" | <span title="subjuntiu">အရေဝ်နိဒါန်</span>
! class="roa-subjunctive-left-rail" |
! class="roa-subjunctive-left-rail" | <<jo>>
! class="roa-subjunctive-left-rail" | <<tu>>
! class="roa-subjunctive-left-rail" | <<ell>>/<<ella>><br /><<vostè>>
! class="roa-subjunctive-left-rail" | <<nosaltres>><br /><<nós>>
! class="roa-subjunctive-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-subjunctive-left-rail" | <<ells>>/<<elles>><br /><<vostès>>
|-
! class="roa-subjunctive-left-rail" style="height:3em;" | <span title="present">ပစ္စုပ္ပန်</span>
| {pres_sub_1s}
| {pres_sub_2s}
| {pres_sub_3s}
| {pres_sub_1p}
| {pres_sub_2p}
| {pres_sub_3p}
|-
! class="roa-subjunctive-left-rail" style="height:3em;" rowspan="1" | <span title="imperfet">ဟွံဍိုက်ပေၚ်</span>
| {impf_sub_1s}
| {impf_sub_2s}
| {impf_sub_3s}
| {impf_sub_1p}
| {impf_sub_2p}
| {impf_sub_3p}
|-
! rowspan="3" class="roa-imperative-left-rail" style="height:3em;" | <span title="imperatiu">ပါဲဗလေတ်ဟွံဗၠး</span>
! class="roa-imperative-left-rail" |
! class="roa-imperative-left-rail" | —
! class="roa-imperative-left-rail" | <<tu>>
! class="roa-imperative-left-rail" | <<vostè>>
! class="roa-imperative-left-rail" | <<nosaltres>>
! class="roa-imperative-left-rail" | <<vosaltres>><br /><<vós>>
! class="roa-imperative-left-rail" | <<vostès>>
|-
! class="roa-imperative-left-rail" style="height:3em;" | <span title="afirmatiu">တၚ်ဂလာန်ဗိုန်ဗတ်</span>
| —
| {imp_2s}
| {imp_3s}
| {imp_1p}
| {imp_2p}
| {imp_3p}
|-
! class="roa-imperative-left-rail" style="height:3em;" | <span title="negatiu">ကယျာန်ပါဲ</span> (<<no>>)
| —
| {neg_imp_2s}
| {neg_imp_3s}
| {neg_imp_1p}
| {neg_imp_2p}
| {neg_imp_3p}
|{\cl}{notes_clause}</div></div>]=]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
forms.title = link_term(alternant_multiword_spec.lemmas[1].form, nil, "term")
local ann_parts = {}
if alternant_multiword_spec.annotation ~= "" then
table.insert(ann_parts, alternant_multiword_spec.annotation)
end
if alternant_multiword_spec.args.titlenote then
table.insert(ann_parts, alternant_multiword_spec.args.titlenote)
end
local annotation = table.concat(ann_parts, ", ")
if annotation ~= "" then
forms.title = forms.title .. " (" .. annotation .. ")"
end
forms.description = ""
-- Format the table.
forms.footnote = alternant_multiword_spec.footnote_basic
forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or ""
local table_with_pronouns = rsub(basic_table, "<<([^<>|]-)|([^<>|]-)>>", link_term)
local table_with_pronouns = rsub(table_with_pronouns, "<<(.-)>>", link_term)
return require("Module:TemplateStyles")("Module:roa-verb/style.css") ..
m_string_utilities.format(table_with_pronouns, forms)
end
-- Externally callable function to parse and conjugate a verb given user-specified arguments.
-- Return value is WORD_SPEC, an object where the conjugated forms are in `WORD_SPEC.forms`
-- for each slot. If there are no values for a slot, the slot key will be missing. The value
-- for a given slot is a list of objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(args, source_template, headword_head)
local PAGENAME = mw.loadData("Module:headword/data").pagename
local function in_template_space()
return mw.title.getCurrentTitle().nsText == "ထာမ်ပလိက်"
end
-- Determine the verb spec we're being asked to generate the conjugation of. This may be taken from the
-- current page title or the value of |pagename=; but not when called from {{ca-verb form of}}, where the
-- page title is a non-lemma form. Note that the verb spec may omit the infinitive; e.g. it may be "<i-e>".
-- For this reason, we use the value of `pagename` computed here down below, when calling normalize_all_lemmas().
local pagename = source_template ~= "ca-verb form of" and args.pagename or PAGENAME
local head = headword_head or pagename
local arg1 = args[1]
if not arg1 then
if (pagename == "ca-conj" or pagename == "ca-verb" or pagename == "ca-verb form of") and in_template_space() then
arg1 = "amar<>"
else
arg1 = "<>"
end
end
-- When called from {{ca-verb form of}}, determine the non-lemma form whose inflections we're being asked to
-- determine. This normally comes from the page title or the value of |pagename=.
local verb_form_of_form
if source_template == "ca-verb form of" then
verb_form_of_form = args.pagename
if not verb_form_of_form then
if PAGENAME == "ca-verb form of" and in_template_space() then
verb_form_of_form = "ami"
else
verb_form_of_form = PAGENAME
end
end
end
local incorporated_headword_head_into_lemma = false
if arg1:find("^<.*>$") then -- missing lemma
if head:find(" ") then
-- If multiword lemma, try to add arg spec after the first word.
-- Try to preserve the brackets in the part after the verb, but don't do it
-- if there aren't the same number of left and right brackets in the verb
-- (which means the verb was linked as part of a larger expression).
local refl_clitic_verb, post = rmatch(head, "^(.-)( .*)$")
local left_brackets = rsub(refl_clitic_verb, "[^%[]", "")
local right_brackets = rsub(refl_clitic_verb, "[^%]]", "")
if #left_brackets == #right_brackets then
arg1 = iut.remove_redundant_links(refl_clitic_verb) .. arg1 .. post
incorporated_headword_head_into_lemma = true
else
-- Try again using the form without links.
local linkless_head = m_links.remove_links(head)
if linkless_head:find(" ") then
refl_clitic_verb, post = rmatch(linkless_head, "^(.-)( .*)$")
arg1 = refl_clitic_verb .. arg1 .. post
else
error("Unable to incorporate <...> spec into explicit head due to a multiword linked verb or " ..
"unbalanced brackets; please include <> explicitly: " .. arg1)
end
end
else
-- Will be incorporated through `head` below in the call to normalize_all_lemmas().
incorporated_headword_head_into_lemma = true
end
end
local function split_bracketed_runs_into_words(bracketed_runs)
return put.split_alternating_runs(bracketed_runs, " ", "preserve splitchar")
end
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
-- Split words only on spaces, not on hyphens, because that messes up reflexive verb parsing.
split_bracketed_runs_into_words = split_bracketed_runs_into_words,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.pos = pos or "ကြိယာ"
alternant_multiword_spec.args = args
alternant_multiword_spec.source_template = source_template
alternant_multiword_spec.verb_form_of_form = verb_form_of_form
alternant_multiword_spec.incorporated_headword_head_into_lemma = incorporated_headword_head_into_lemma
normalize_all_lemmas(alternant_multiword_spec, head)
detect_all_indicator_specs(alternant_multiword_spec)
local inflect_props = {
slot_list = alternant_multiword_spec.all_verb_slots,
inflect_word_spec = conjugate_verb,
-- We add links around the generated verbal forms rather than allow the entire multiword
-- expression to be a link, so ensure that user-specified links get included as well.
include_user_specified_links = true,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- Remove redundant brackets around entire forms.
for slot, forms in pairs(alternant_multiword_spec.forms) do
for _, form in ipairs(forms) do
form.form = iut.remove_redundant_links(form.form)
end
end
compute_categories_and_annotation(alternant_multiword_spec)
if args.json and source_template == "ca-conj" then
return require("Module:JSON").toJSON(alternant_multiword_spec.forms)
end
return alternant_multiword_spec
end
-- Entry point for {{ca-conj}}. Template-callable function to parse and conjugate a verb given
-- user-specified arguments and generate a displayable table of the conjugated forms.
function export.show(frame)
local parent_args = frame:getParent().args
local params = {
[1] = {},
["titlenote"] = {},
["noautolinktext"] = {type = "boolean"},
["noautolinkverb"] = {type = "boolean"},
["pagename"] = {}, -- for testing/documentation pages
["json"] = {type = "boolean"}, -- for bot use
}
local args = require("Module:parameters").process(parent_args, params)
local alternant_multiword_spec = export.do_generate_forms(args, "ca-conj")
if type(alternant_multiword_spec) == "string" then
-- JSON return value
return alternant_multiword_spec
end
show_forms(alternant_multiword_spec)
return make_table(alternant_multiword_spec) ..
require("Module:utilities").format_categories(alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
return export
36gsvo0xywzui0tomg7djp78f96lbhb
ကဏ္ဍ:မဝ်ဂျူပွမပြံၚ်လှာဲဒါတ်တြေံဂမၠိုၚ်
14
296244
397718
397453
2026-06-30T13:29:43Z
咽頭べさ
33
397718
wikitext
text/x-wiki
[[ကဏ္ဍ:မဝ်ဂျူဒါတ်တြေံဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံအပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:မဝ်ဂျူဗီုအပြံၚ်အလှာဲဝေါဟာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|ဒ]]
51nolim3vogfifpbm5ld8ty4ul7830c
ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံအပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏနာမ်ဂမၠိုၚ်
14
296245
397716
397455
2026-06-30T13:28:14Z
咽頭べさ
33
397716
wikitext
text/x-wiki
[[ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံအပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏနာမ်ဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|ဒ]]
85y0r2dusrxjngvkgibqo0h8yrzfiov
ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံအပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်
14
296246
397717
397456
2026-06-30T13:28:58Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဒါတ်တြေံဂမၠိုၚ်]] ဇရေင် [[ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံအပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]] သီုကဵု ဟွံဂွံ ဂိုင်စွံလဝ် မကလေင်ပညုင်
397456
wikitext
text/x-wiki
[[ကဏ္ဍ:ထာမ်ပလိက်ဒါတ်တြေံဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|ဒ]]
s982fyndodyhfwthg93t1bjmjmen25w
မဝ်ဂျူ:es-verb/doc
828
296343
397714
2026-06-30T13:24:56Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "This module supports {{tl|es-conj}}. It is also used by {{tl|es-verb}} and {{tl|es-verb form of}} to generate inflected forms of verbs. <includeonly> {{module cat|es}} </includeonly>"
397714
wikitext
text/x-wiki
This module supports {{tl|es-conj}}. It is also used by {{tl|es-verb}} and {{tl|es-verb form of}} to generate inflected forms of verbs.
<includeonly>
{{module cat|es}}
</includeonly>
0emlltm9e7nbsmkcofgm5jszzad7mfe
ကဏ္ဍ:မဝ်ဂျူပွမပြံၚ်လှာဲသပုၚ်ဂမၠိုၚ်
14
296344
397715
2026-06-30T13:27:11Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:မဝ်ဂျူသပုၚ်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်သပုၚ်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:မဝ်ဂျူဗီုအပြံၚ်အလှာဲဝေါဟာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]"
397715
wikitext
text/x-wiki
[[ကဏ္ဍ:မဝ်ဂျူသပုၚ်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်သပုၚ်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:မဝ်ဂျူဗီုအပြံၚ်အလှာဲဝေါဟာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]
8a88cr1iq48q8ce9t3lm88eexzomdws
ထာမ်ပလိက်:ca-conj
10
296345
397719
2026-06-30T13:32:30Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{#invoke:ca-verb|show}}<!-- --><noinclude>{{documentation}}</noinclude>"
397719
wikitext
text/x-wiki
{{#invoke:ca-verb|show}}<!--
--><noinclude>{{documentation}}</noinclude>
8dgb6f7zq766xgsxquid4aku9jw7ssu
ထာမ်ပလိက်:ca-conj/documentation
10
296346
397720
2026-06-30T13:34:41Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{documentation subpage}} ==Usage== This template creates a conjugation table for all Catalan [[verb]]s. This template should be placed in a conjugation section, headed by a ====Conjugation==== section header. The template automatically categorizes the entry into the appropriate Catalan verb subcategory (e.g. [[:Category:Catalan first conjugation verbs]]). If the verb has consonant alternations, it will be categoriz..."
397720
wikitext
text/x-wiki
{{documentation subpage}}
==Usage==
This template creates a conjugation table for all Catalan [[verb]]s.
This template should be placed in a conjugation section, headed by a ====Conjugation==== section header. The template automatically categorizes the entry into the appropriate Catalan verb subcategory (e.g. [[:Category:Catalan first conjugation verbs]]). If the verb has consonant alternations, it will be categorized appropriately (e.g. or [[:Category:Catalan verbs with g-gu alternation]]), and if the verb is irregular, it will be categorized into [[:Category:Catalan irregular verbs]].
==Basic usage==
This template has no required parameters. For nearly all verbs, both regular and irregular, no parameters are necessary. In particular, the module knows how to conjugate all irregular verbs.
You can also specify the verb explicitly, e.g. {{temp|ca-conj|cantar<>}}, or just e.g. {{temp|ca-conj|cantar}} if no indicators need to be given. This is useful to conjugate a verb that is different from the pagename of the entry in question, e.g. to give the conjugation of the verb {{m|ca|dir-se}} on the page {{m|ca|dir}}.
==Examples==
===Regular verbs, including those with consonant alternations===
1. The verb {{m|ca|cantar||to sing}} is fully regular. Use as follows:
:{{temp|ca-conj}}
which produces
{{ca-conj|cantar}}
2. The verb {{m|ca|pagar||to pay}} is regular other than having a predictable spelling change to ''gu'' in various forms. This is handled automatically, so no parameters are needed. Use as follows:
:{{temp|ca-conj}}
which produces
{{ca-conj|pagar}}
3. The verb {{m|ca|distribuir||to distribute}} is regular other than having a predictable addition of a diaeresis over the i (i.e. ''ï'') in certain forms, such as the first-person plural present indicative ''distribuïm''. This is handled automatically, so no parameters are needed. Use as follows:
:{{temp|ca-conj}}
which produces
{{ca-conj|distribuir}}
===Irregular verbs===
The module knows how to conjugate all irregular verbs, including compounds such as {{m|ca|mantenir}} and {{m|ca|endur-se}}, and no parameters are needed for them.
1. For example, the verb {{m|ca|dir||to say}} has various irregularities: present tense {{m|ca|dic}}, preterite {{m|ca|diguí}}, past participle {{m|ca|dit}}, imperative {{m|ca|digues}}, etc. Specify simply as follows:
:{{temp|ca-conj}}
which produces
{{ca-conj|dir}}
2. The verb {{m|ca|acudir||to attend; to come to mind}} has two conjugations in the present indicative and subjunctive, e.g. third person singular ''acudeix'' or ''acut''. These tend to be used differently according to the meaning, with ''acudeix'' usually used in the sense "to attend" and ''acut'' in the sense "to come to mind". The module knows about this, so specify simply as follows:
:{{temp|ca-conj}}
which produces
{{ca-conj|acudir}}
Here, a footnote is automatically added to indicate the different usages.
===Defective verbs===
Certain verbs are ''defective'', i.e. are missing some forms. Indicators are available to specify this. For example, the verb {{m|ca|caldre||to be necessary}} is an impersonal verb, with only 3rd-person singular verbs and no imperative. Specify as follows:
:{{temp|ca-conj|<only3s>}}
which produces
{{ca-conj|caldre<only3s>}}
Here, <code><only3s></code> means "only third-person singular".
===Variant conjugations===
A few verbs can be conjugated in more than one fashion depending on the meaning. Specify as follows:
# {{m|ca|coure}} means either "to cook" (past participle ''cuit'') or "to sting" (past participle ''cogut''). Specify this using a ''variant indicator'', specifically {{tl|ca-conj|<var:cook>}} or {{tl|ca-conj|<var:sting>}}.
# {{m|ca|haver}} is either an auxiliary verb used to form perfect tenses, or a full verb with the meaning "to possess". These uses are conjugated differently; in both cases the conjugations are highly irregular. Specify this using a ''variant indicator'' as above, specifically {{tl|ca-conj|<var:aux>}} or {{tl|ca-conj|<var:full>}}.
# {{m|ca|lluir}} is conjugated either a regular inchoative ''-ir'' verb meaning "to display; to be popular/successful {{q|of a person}}", or an irregular "pure ''-ir''" verb meaning "to shine". Specify the latter with no parameters, i.e. {{tl|ca-conj}}, and the former using {{tl|ca-conj|<no_built_in>}}. Here, the {{lua|no_built_in}} indicator specifies that the special handling as an irregular ("built-in") verb should be disregarded, and the verb conjugated regularly.
==Parameters==
The allowed parameters are as follows:
; {{para|1}}
: Optional specification of the verb and/or indicators controlling unpredictable parts of the conjugation. See above.
==Multiword expressions==
For multiword expressions, place angle brackets after the verb(s) needing conjugation, with any indicators inside angle brackets as needed. This is not actually necessary if there is only a single verb that is the first word of the expression, as is common.
1. For example, for the idiom {{m|ca|fer caput||to kill, to off}}, both of the following work and are equivalent:
:{{temp|ca-conj}}
:{{temp|ca-conj|fer<> caput}}
which produce
{{ca-conj|fer<> caput}}
2. The expression {{m|ca|retallar i enganxar||to [[cut and paste]]}} has more than one conjugated verb. Place angle brackets after each:
:{{temp|ca-conj|retallar<> i enganxar<>}}
which produces
{{ca-conj|retallar<> i enganxar<>}}
3. Normally, each word (including the verb) is autolinked separately. You can override the linking behavior by explicitly specifying links, as in {{m|ca|donar voltes||to [[go round in circles]]}}, which can be written as follows:
:<code><nowiki>{{ca-conj|donar<> [[volta|voltes]]}}</nowiki></code>
which produces
{{ca-conj|donar<> [[volta|voltes]]}}
In this case, the singular of {{m|ca|voltes}} is explicitly linked. The verb does not explicitly need a link, however, because verbs and uninflected portions of the expression are autolinked separately.
<includeonly>
[[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏကြိယာဂမၠိုၚ်]]
</includeonly>
3k4oy5js482ano069jv8jxkq0n9k2xc
ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏကြိယာဂမၠိုၚ်
14
296347
397721
2026-06-30T13:36:22Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏကြိယာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]"
397721
wikitext
text/x-wiki
[[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏကြိယာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]
0i16ij8ezf9fjz3ope37p1r4c3d2pj2
ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်
14
296348
397722
2026-06-30T13:38:19Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]"
397722
wikitext
text/x-wiki
[[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]
bp9n4ryuiniqxtx6u5tw5ckz1ohmeiz
မဝ်ဂျူ:ca-verb/doc
828
296349
397724
2026-06-30T14:26:47Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "This module supports {{tl|ca-conj}}. It is also used by {{tl|ca-verb}} and {{tl|ca-verb form of}} to generate inflected forms of verbs. <includeonly> {{module cat|ca}} </includeonly>"
397724
wikitext
text/x-wiki
This module supports {{tl|ca-conj}}. It is also used by {{tl|ca-verb}} and {{tl|ca-verb form of}} to generate inflected forms of verbs.
<includeonly>
{{module cat|ca}}
</includeonly>
9l60wgftqdhvh88exnu5mmb1vedojmy
ကဏ္ဍ:မဝ်ဂျူပွမပြံၚ်လှာဲကာတ်တလာန်ဂမၠိုၚ်
14
296350
397725
2026-06-30T14:28:26Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:မဝ်ဂျူကာတ်တလာန်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:မဝ်ဂျူဗီုအပြံၚ်အလှာဲဝေါဟာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]"
397725
wikitext
text/x-wiki
[[ကဏ္ဍ:မဝ်ဂျူကာတ်တလာန်ဂမၠိုၚ်]][[ကဏ္ဍ:ထာမ်ပလိက်ကာတ်တလာန်အပြံၚ်အလှာဲပ္တဝ်ထ္ၜးပမာဏဂမၠိုၚ်]][[ကဏ္ဍ:မဝ်ဂျူဗီုအပြံၚ်အလှာဲဝေါဟာဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|က]]
kz3u8o4enbs7f3dasp9dfnyb1r0wf05
graverens
0
296351
397727
2026-07-01T03:56:22Z
Hiyuune
1535
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==ဒိန်နေတ်== ===နာမ်=== {{head|da|noun form}} # {{infl of|da|graver||def|gen|s}}"
397727
wikitext
text/x-wiki
==ဒိန်နေတ်==
===နာမ်===
{{head|da|noun form}}
# {{infl of|da|graver||def|gen|s}}
0csy2dadz5wavirbsr3ypj7qsmcewyd
gravernes
0
296352
397728
2026-07-01T03:56:51Z
Hiyuune
1535
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==ဒိန်နေတ်== ===နာမ်=== {{head|da|noun form}} # {{infl of|da|graver||def|gen|p}}"
397728
wikitext
text/x-wiki
==ဒိန်နေတ်==
===နာမ်===
{{head|da|noun form}}
# {{infl of|da|graver||def|gen|p}}
t43oe4yijue78ktbgt2j8pt9mtlzczv