Here naverokê

Modul:ku-tewandin

Ji Wîkîferheng
Belgekirina modulê[nîşan bide] [biguhêre] [rojane bike]
Ev belge ji Modul:ku-tewandin/belge hatiye girtin.

Bikaranîn:

Bin-modul:

Lîsteya demên lêkeran ku vê modul çêdike:

Lîsteya nav û şablonên lêkerên kurmancî [biguhêre] 
Rawe Dem Bi îngilîzî Mînak (ketin) Şablon
Imp. Fermanî Imperative bikeve {{ku-fermanî}}
Ind. Dema niha Present ez dikevim {{ku-dema-niha}}
Raboriya sade
Dema boriya têdeyî
Simple past ez ketim {{ku-raboriya-sade}}
Raboriya berdest
Çîrokiya dema niha
Imperfect ez diketim {{ku-raboriya-berdest}}
Raboriya dûr
Çîrokiya boriya têdeyî
Pluperfect ez ketibûm {{ku-raboriya-dûr}}
Dema bê Future ez ê bikevim A {{ku-dema-bê}}
Dathatiya pêş Future perfect ez ê ketibim B {{ku-dahatiya-pêş}}
Ind.
(Infer.)
Raboriya dûdar
Dema boriya dûdar
Perfect ez ketime {{ku-raboriya-dûdar}}
Çîrokiya boriya dûdar Non-witnessed pluperfect ez ketibûme {{ku-çîrokiya-boriya-dûdar}}
Subj. Dema nihaya xwestekî
Nihaya bilaniyê
Present subjunctive (bila) ez bikevim A
Dema boriya xwestekî Preterite subjunctive (bila) ez ketibim B
Raboriya bilaniyê Imperfect subjunctive (bila) ez biketama C
Raboriya dûr a bilaniyê Pluperfect subjunctive (bila) ez ketibûma D
Cond. Çîrokiya dema nihaya mercî Present conditional ez ê biketama C {{ku-merciya-borî-I}}
Dema boriya mercî Preterite conditional ez ê ketibûma D {{ku-merciya-borî-II}}
  • Imp. (Imperative): Raweya fermanî
  • Ind. (Indicative): Raweya pêşkerî (daxuyanî)
  • Infer. (inferential mood): Moda/raweya neşahidî
  • Subj. (Subjunctive): Raweya xwestekî (bilanî, daxwazî)
  • Cond. (Conditional): Raweya mercî (hekînî)
  • Ev form tenê bi lêzêdekirina pirtikan (ê, dê, bila) ji hev cuda dibin. Tewandinên lêkeran wekhev in.

Çêkirina demeke nû [1]:

navêLêkerê = {
    name         = "navêLêkerê",
    nameKu       = , -- navê demê lêkerê bi kurdî
    nameEn       = , -- navê demê lêkerê bi îngilîzî
    mode         = , -- "imperative", "indicative", "subjunctive", "conditional", ...
    stemType     = , -- "present" an "past"
    preverb      = , -- getPreverb['bi'] an getPreverb['di'] an "nil"
    negPreverb   = , -- getPreverb['bi'] an getPreverb['di'] an "nil"
    negPrefix    = , -- getNegPrefix['na'] an getNegPrefix['ne']
    endings      = , -- getEndings['present'] an getEndings['past'], getEndings['ibim'], ...
    preverbParticle = -- "ê" an "nil" an pirtikek din (ez "ê" bikim, ez "dê" bikim)
}

preverb = : [2]

  • getPreverb['bi']: [3]
  • getPreverb['di']: [4]

negPrefix = : [5]

  • getNegPrefix['na']: [6]
  • getNegPrefix['ne']: [7]

endings = : bnr. [8]

  • getEndings['present']: [9]
  • getEndings['past']: [10]
  • getEndings['ibim']: [11]
  • getEndings['ibûm']: [12]
  • getEndings['ibûme']: [13]
  • getEndings['ibûma']: [14]
  • getEndings['ime']: [15]
  • getEndings['ama']: [16]
-- Modula tewandina lêkerên kurmancî

local export = {}

-- Load irregular forms table
-- local irreg = require('Module:ku-tewandin/nestandard')
local langKu = require("Modul:languages").getByCode("ku")
local link = require('Module:links').language_link
local shallowCopy = require("Module:table/shallowCopy")
local deepCopy = require("Module:table/deepCopy")

local gsub = mw.ustring.gsub
local find = mw.ustring.find

-- =============================================================================
-- Pronouns in Kurmanji
-- =============================================================================
export.order = {"s1", "s2", "s3", "p1", "p2", "p3"}

export.pronouns = {
    s1 = "ez",    p1 = "em",
    s2 = "tu",    p2 = "hûn",
    s3 = "ew",    p3 = "ew"
}

export.obliquePronouns = {
    s1 = "min",      p1 = "me",
    s2 = "te",       p2 = "we",
    s3 = "wê/wî",    p3 = "wan"
}

export.agents = {
    s1 = "te, wî, wê, we, wan",            p1 = "te, wî, wê, we, wan",
    s2 = "min, wî, wê, me, wan",           p2 = "min, wî, wê, me, wan",
    s3 = "min, te, wî, wê, me, we, wan",   p3 = "min, te, wî, wê, me, we, wan"
}

-- Oblique pronoun (green) 
export.obliquePronounsGreen = {
    s1 = '<span style="color:green">min</span>',
    s2 = '<span style="color:green">te</span>',
    s3 = '<span style="color:green">wê/wî</span>',
    p1 = '<span style="color:green">me</span>',
    p2 = '<span style="color:green">we</span>',
    p3 = '<span style="color:green">wan</span>'
}

-- ─────────────────────────────────────────────────────────────────────────────
-- 1) This function returns correct subject/agent pronoun, ergativity rule:
--   - Transitive verbs in past tenses → oblique pronoun (green) = agent
--   - All other cases                 → direct pronoun (no color) = subject
-- 2) Also add the subjunctive prefix "(bila)"
-- ─────────────────────────────────────────────────────────────────────────────
function export.conjPronouns(stemType, mode, isTransitive)
    local pronouns = shallowCopy(export.pronouns)

    -- Ergativity in kurdish: transitive verbs that are conjugated with the past tense stem are
    -- conjugated according to the object, not the subject.
    -- Therefore, to have an ergative construction,
    -- the verb must be transitive and its stem must be the stem of the past tense.
    local isErgative = isTransitive and (stemType == 'past')

    -- If it's ergative, we use oblique pronouns: "min", "te", ...
    -- If it's not ergative, we use normal pronouns: "ez", "tu", ...
    if isErgative then
        pronouns = shallowCopy(export.obliquePronounsGreen)
    end

    -- For the subjunctive mood, we add "(bila)" at the beginning.
    if mode == 'subjunctive' then
    	local subjPrefix = '<span style="color:gray">(bila)</span>'
        for _, pers in ipairs(export.order) do
            pronouns[pers] = subjPrefix .. ' ' .. pronouns[pers]
        end
    end
    return pronouns
end

-- =============================================================================
-- VERBAL STRUCTURE IN THE INFINITIVE:
-- Verbs in the infinitive appear in three main forms:
--  1) Simple verb (indivisible light verb):
--       - ex.:  "kirin", "çûn", "xwarin", ...
--  2) Verbs with preverbs (preverb + simple verb):
--       - ex.: "rakirin" (ra- + kirin), "çêkirin" (çê- + kirin), "vexwarin" (ve- + xwarin), ...
--       - Preverb verbs don't use the prefix "bi-" (ez ê rakim , ew ê rake , ...)
--  3) Compound verbs, construction with non-verbal element (the noun is not attached to the verb):
--       - Left of the simple verb: "hez kirin" ("hez" + "kirin"), "li dar xistin" ("li dar" + "xistin"), ...
--       - Right of the simple verb: "kirin der" ("kirin" + "der"), "girtin ser xwe" ("girtin" + "ser xwe"), ...
--       - Compound verbs use the prefix "bi-" (ez ê hez bi-kim , ew ê hez bi-ke )

-- STRUCTURE:  preSimpleVerb + spacing + simpleVerb + postSimpleVerb
-- EX.     kirin: preSimpleVerb='';    spacing=false; simpleVerb='kirin'; postSimpleVerb=''
--       rakirin: preSimpleVerb='ra';  spacing=false; simpleVerb='kirin'; postSimpleVerb=''
--     hez kirin: preSimpleVerb='hez'; spacing=true;  simpleVerb='kirin'; postSimpleVerb=''
--       pev çûn: preSimpleVerb='pev'; spacing=true;  simpleVerb='çûn';   postSimpleVerb=''
--     kirin der: preSimpleVerb='';    spacing=false; simpleVerb='kirin'; postSimpleVerb='der'

-- WARNING: Conjugation can vary depending on the type of verb.
-- For example, in the future tense,the prefix "bi" is used for compound verbs,
-- but not for preverbal verbs, see the function that manages it  "tenseRules" table.
-- This table does not yet support the mixed case: a verb composed of a noun and a preverb verb.
-- =============================================================================
function export.verbStruct(isCompoundVerb, preSimpleVerb)
    local struct

    if (preSimpleVerb and preSimpleVerb ~= '' and not isCompoundVerb) then
        struct = 'preverbVerb'
    elseif isCompoundVerb then
        struct = 'compoundVerb'
    else
        struct = 'simpleVerb'
    end

    return struct
end

-- ================================================================
-- INFLECTIONAL ENDINGS
-- Assigns verb inflectional endings (suffixes) to all tenses
-- ================================================================
local getEndings = {}

do
    -- ───────────────────────────────────────────────────────────────
    -- Ending using present stem
    -- ───────────────────────────────────────────────────────────────
    getEndings['present'] = function(self, stem, accent)
        local ends = {}
		
        if mw.ustring.match(stem, '[aeêiîouû]$') then
            ends['std'] = {s1='m', s2='yî', s3='', p1='n', p2='n', p3='n'}
            ends['rojhilatî'] = {s1='m', s2='(y)', s3='t', p1='yn', p2='n', p3='n'}
        else
            ends['std'] = {s1='im', s2='î', s3='e', p1='in', p2='in', p3='in'}
			ends['rojhilatî'] = {s1='im', s2='î', s3='<u>it</u>/ît', p1='în', p2='in', p3='in'}
        end

		-- Imperatîv wek ya standard e.
		if (accent == 'rojhilatî' and self.name ~= 'impPresent') then
			return ends['rojhilatî']
		else
			return ends['std']
		end
    end
	
    -- ───────────────────────────────────────────────────────────────
    -- Ind. preterite + ind. imperfect ending
    -- ───────────────────────────────────────────────────────────────
    getEndings['past'] = function(self, stem, accent)
        local ends = {}
		
        if mw.ustring.match(stem, '[aeêiouû]$') then
            ends['std'] = {s1='m', s2='yî', s3='', p1='n', p2='n', p3='n'}
			ends['rojhilatî'] = {s1='m', s2='y', s3='', p1='yn', p2='n', p3='n'}
        elseif mw.ustring.match(stem, 'î$') then
            ends['std'] = {s1='m', s2='', s3='', p1='n', p2='n', p3='n'}
			ends['rojhilatî'] = {s1='m', s2='y', s3='', p1='yn', p2='n', p3='n'}
        else
            ends['std'] = {s1='im', s2='î', s3='', p1='in', p2='in', p3='in'}
			ends['rojhilatî'] = {s1='im', s2='î', s3='', p1='în', p2='in', p3='in'}
        end

		if (accent == 'rojhilatî' and self.name == 'indPreterite') then
			return ends['rojhilatî']
		else
			return ends['std']
		end
		
    end

    -- ───────────────────────────────────────────────────────────────
    -- Compound endings with auxiliary "bûn"
    -- Inflectional endings are created by taking the different forms of the
    -- verb "bûn" (with present stem "-b-" and past stem "-bû-") and
    -- adding an "i-" prefix before them: "i-b-im", "i-bû-m", "i-bû-me", "i-bû-ma".
    -- This "i-" varies according to the final letter of the verb stem.
    -- ───────────────────────────────────────────────────────────────
    local function normalize_i(stem)
        local prfx_i = "i"
        if mw.ustring.match(stem, "ya$") or
           mw.ustring.match(stem, "[îû]$") then -- cf. karîn (-karî-)
           	prfx_i = ""
        elseif mw.ustring.match(stem, '[aeêiou]$') then
            prfx_i = "yi"
        end
        return prfx_i
    end

    getEndings['ibim'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local prfx_i = normalize_i(stem)
        return {
            s1 = prfx_i .. "bim",   p1 = prfx_i .. "bin",
            s2 = prfx_i .. "bî",    p2 = prfx_i .. "bin",
            s3 = prfx_i .. "be",    p3 = prfx_i .. "bin"
        }
    end

    getEndings['ibûm'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local prfx_i = normalize_i(stem)
        return {
            s1 = prfx_i .. "bûm",     p1 = prfx_i .. "bûn",
            s2 = prfx_i .. "bûyî",    p2 = prfx_i .. "bûn",
            s3 = prfx_i .. "bû",      p3 = prfx_i .. "bûn"
        }
    end

    getEndings['ibûme'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local prfx_i = normalize_i(stem)
        return {
            s1 = prfx_i .. "bûme",      p1 = prfx_i .. "bûne",
            s2 = prfx_i .. "bûyiye",    p2 = prfx_i .. "bûne",
            s3 = prfx_i .. "bûye",      p3 = prfx_i .. "bûne"
        }
    end

    getEndings['ibûma'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local prfx_i = normalize_i(stem)
        return {
            s1 = prfx_i .. "bûma",      p1 = prfx_i .. "bûna",
            s2 = prfx_i .. "bûyayî",    p2 = prfx_i .. "bûna",
            s3 = prfx_i .. "bûya",      p3 = prfx_i .. "bûna"
        }
    end
    
    -- ───────────────────────────────────────────────────────────────
    -- Ind. perfect ending.
    -- ───────────────────────────────────────────────────────────────
    getEndings['ime'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local ends

        if mw.ustring.match(stem, '[aeêiîouû]$') then
            ends = {s1="me", s2="yî", s3="ye", p1="ne", p2="ne", p3="ne"}
        else
            ends = {s1="ime", s2="iyî", s3="iye", p1="ine", p2="ine", p3="ine"}
        end

        return ends
    end

    -- ───────────────────────────────────────────────────────────────
    -- Subj. Imperfect ending.
    -- ───────────────────────────────────────────────────────────────
    getEndings['ama'] = function(self, stem)
		-- self: reserved for future use (was used before, might be needed again)
	    local _ = self -- delete the warning (unused argument)
		
        local ends

        -- The doublet in "-iyan" of verbs in -"în" (gerîn/-geriya-, kenîn/-keniya-, ...),
        -- in the conditional and subjunctive moods, a doublet "yaya" appears; it's removed.
        -- -yayayî → -yayî; -yaya → -ya
		if mw.ustring.match(stem, '(ya)$') then
            ends = {s1="ma", s2="yî", s3="", p1="na", p2="na", p3="na"}
		elseif mw.ustring.match(stem, '[aeêiîouû]$') then
            ends = {s1="ma", s2="yayî", s3="ya", p1="na", p2="na", p3="na"}
        else
            ends = {s1="ama", s2="ayî", s3="a", p1="ana", p2="ana", p3="ana"}
        end
        return ends
    end
end

-- =============================================================================
-- RULES FOR PREVERBS: "bi-" and "di-"
-- There are two preverbs: "bi-" and "di-". These preverbs can change form
-- depending on the first letters of the verb’s present stem or past stem.
-- =============================================================================
local getPreverb = {}

do
	getPreverb['bi'] = function (self, opts)
	    opts = opts or {}
	    local stem = opts.stem
	    local verbStruct = opts.verbStruct
	    local overridePreverb = opts.overridePreverb
		local accent = opts.accent

		-- Devoka rojhilatî:
		-- @Ferhengvan: Dema bêt bi lêkera alîkar "ê / dê" û bi rehê lêkerê yê
		-- dema niha û pêşgirên kesî tê çêkirin. Pêşgira "bi-" li destpêka lêkera
		-- serekî nîne: - ez ê / dê xw-im (standard: ez ê/dê bi-xw-im).
		if (self.name == 'indFuture' and (accent == 'rojhilatî' or accent == 'torî')) then
			return ''
		end

	    -- Preverb verbs don't use the preverb "bi-": ra-kirin (ez ê rakim), ve-xwarin (ez ê vexwim) , ...
	    -- But compound verb and simple verbs use it: hez kirin (ez ê hez bi-kim), lê bigirin (ez ê lê bi-girim), ...
	    if (verbStruct == 'preverbVerb') then
	        return ''
	    end
	
		-- If the preverb "bi-" is provided.
		if (self.stemType == 'present' and overridePreverb.presentBi) then
			return overridePreverb.presentBi
		elseif (self.stemType == 'past' and overridePreverb.pastBi) then
			return overridePreverb.pastBi
		elseif overridePreverb.sameBi then
			return overridePreverb.sameBi
		end
	
	    -- Irregular verb stem.
		if stem == 'ê' then return 'b' end  -- hatin : stem = -ê- // b-êm, bên

		-- Modification of the preverbe "bi-" according to the last letter of the stem.
		--if mw.ustring.match(stem, '^[iîouû]') then
	    --    return 'b'
	    --end
	
	    return 'bi'
	end
	
	-- PREVERB DI
	getPreverb['di'] = function (self, opts)
	    opts = opts or {}
	    local stem = opts.stem
	    local overridePreverb = opts.overridePreverb
	
		-- If the preverb "di" is provided.
		if (self.stemType == 'present' and overridePreverb.presentDi) then
			return overridePreverb.presentDi
		elseif (self.stemType == 'past' and overridePreverb.pastDi) then
			return overridePreverb.pastDi
		elseif overridePreverb.sameDi then
			return overridePreverb.sameDi
		end
	
	    -- Irregular verb stem.
		if stem == 'ê' then return 't' end  -- hatin : stem = -ê- // ez t-êm
		if stem == 'în' then return 't' end -- anîn : stem = -în- // ez t-înim

	    -- Modification of the preverbe "di-" according to the last letter of the stem.
	    --if mw.ustring.match(stem, '^[i]') then
	    --    return 'd'
	    --end
	
	    return 'di'
	end
end

-- =============================================================================
-- RULES FOR NEGATION PREFIXES: "na-" and "ne-"
-- There are two negation prefixes: "na-" and "ne-". These preverbs can change
-- form depending on the first letters of the verb’s present stem or past stem.
-- =============================================================================
local getNegPrefix = {}

do
	getNegPrefix['na'] = function (self, opts)
		-- self: reserved for future use
	    local _ = self -- delete the warning (unused argument)
		
	    opts = opts or {}
	    local stem = opts.stem
	    local overrideNa = opts.overrideNegPrefix.presentNa
	
	    if overrideNa then
			return '<b>' .. overrideNa .. '</b>'
		end

	    -- Irregular verb stem.
		if stem == 'kar' then return '<b>ni</b>' end  -- karîn : ez ni-karim
		if stem == 'zan' then return '<b>ni</b>' end -- zanîn : ez ni-zanim
		
	    -- Add sufix "-y" before certain vowels.
	    if mw.ustring.match(stem, '^[eêiîouû]') then
	        return '<b>nay</b>'
	    end
		
	    -- Elision before stems beginning with "a-" (removal of the final "-e").
	    if mw.ustring.match(stem, '^a') then
	        return '<b>n</b>'
	    end
	
	    return '<b>na</b>'
	end

	getNegPrefix['ne'] = function (self, opts)
	    opts = opts or {}
	    local stem = opts.stem
	    local tenseName = self.name
	    local impNegForm = opts.impNegForm -- form "1" or "2" of imp.
		local overrideNegPrefix = opts.overrideNegPrefix

        local negPrefix = 'ne'

		-- Bo neyînî: pêşgira "di-" tenê di nav dema "indImperfect" de tê bikaranîn.
		-- ji ber vê yekê 'negPrefix' hertim (?) 'ne' ye ji ber ku dikeve pêş 
		-- pêşgira "di-": wê/wî ne-di-elimand (elimandin)
	    if (tenseName == 'indImperfect') then
	         return '<b>' .. negPrefix .. '</b>'
	    end

		-- Override		
		if (overrideNegPrefix.impMe or overrideNegPrefix.presentNe
									or overrideNegPrefix.pastNe
				                    or overrideNegPrefix.sameNe) then
			-- Ovverride imp.
			if (tenseName == 'impPresent') then
				if (impNegForm == 1 and overrideNegPrefix.impMe) then
					return '<b>' .. overrideNegPrefix.impMe .. '</b>'
				elseif (impNegForm == 1 and overrideNegPrefix.presentNe and 
					find(overrideNegPrefix.presentNe, '^n')) then
					--For the "me-" form, we replace the "n" with an "m".
					return '<b>' .. gsub(overrideNegPrefix.presentNe, '^(.)', 'm') .. '</b>'	
				elseif (impNegForm == 1 and overrideNegPrefix.sameNe and 
					find(overrideNegPrefix.sameNe, '^n')) then
					--For the "me-" form, we replace the "n" with an "m".
					return '<b>' .. gsub(overrideNegPrefix.sameNe, '^(.)', 'm') .. '</b>'
				elseif (impNegForm == 2 and overrideNegPrefix.presentNe) then
					return '<b>' .. overrideNegPrefix.presentNe .. '</b>'
				elseif (impNegForm == 2 and overrideNegPrefix.sameNe) then
					return '<b>' .. overrideNegPrefix.sameNe .. '</b>'
				end
			else
				-- For other tenses besides the imperative
				if (self.stemType == 'present' and overrideNegPrefix.presentNe) then
					return '<b>' .. overrideNegPrefix.presentNe .. '</b>'
			    elseif (self.stemType == 'past' and overrideNegPrefix.pastNe) then
					return '<b>' .. overrideNegPrefix.pastNe .. '</b>'
				elseif overrideNegPrefix.sameNe then
					return '<b>' .. overrideNegPrefix.sameNe .. '</b>'
				end
			end
		end
	
	    -- There are two forms of construction of the imperative,
	    -- one with the prefix "me-" (1) and the other (2) with the prefix "ne-".
	    if (tenseName == 'impPresent') then
	        negPrefix = (impNegForm == 2) and 'ne' or 'me'
	    end
		
	    -- Add sufix "-y" before certain vowels.
	    if mw.ustring.match(stem, '^[eêiîouû]') then
	        return '<b>' .. negPrefix .. 'y</b>'
	    end
	
	    -- Elision before stems beginning with "a-" (removal of the final "-e").
	    --if mw.ustring.match(stem, '^a') then
	        --negPrefix = mw.ustring.sub(negPrefix, 1, -2)
	        --return '<b>' .. negPrefix .. '</b>'
	    --end
	
	    return '<b>' .. negPrefix .. '</b>'
	end
end

-- =============================================================================
-- Standardization of the PREVERBAL PARTICLE
-- The proverbial particle "ê" is placed after the personal pronoun.
-- =============================================================================
-- If there are no verbal preparticles, return empty table.
function export.getPreverbParticles(preverbParticle, typeStem, isTransitive)
    if not preverbParticle then
        return {s1='', s2='', s3='', p1='', p2='', p3=''}
    end

    if preverbParticle == 'ê' then
        local isErgative = isTransitive and (typeStem == 'past')

        -- When the personal pronoun ends in a vowel, a "y-" is added before "ê".
        -- If it's ergative, we use oblique pronouns: "min", "te", ...
        if isErgative then
            return {s1='ê/dê', s2='yê/dê', s3='yê/dê', p1='yê/dê', p2='yê/dê', p3='ê/dê'}
        else
            return {s1='ê/dê', s2='yê/dê', s3='ê/dê', p1='ê/dê', p2='ê/dê', p3='ê/dê'}
        end
    end

    -- If the verbal preparticle is identical for all pronouns,
    -- we create a table with the same value.
    local preverbParticles = {}
    for _, pers in ipairs(export.order) do
        preverbParticles[pers] = preverbParticle
    end

    return preverbParticles
end

-- =============================================================================
-- RULES FOR CONSTRUCTING EACH VERB TENSE
-- This table lists, for each verb tense, what elements are required to form it:
--   - Verb conjugation is built by placing either the preverb "bi-" or "di-" before
--     the verb stem (past or present), followed by a personal ending.
--   - For the negative form, one of the prefixes "na-" or "ne-" is added as well.
--   - In some cases, a preverbal particle such as /ê/ or /dê/ is added before
--     the conjugated verb as well.
-- Not: - The "negPreverb" (preverb (bi-/di-) for negative tenses) parameter has a
--         value different from "nil" only for the Imperfect tense ("negPreverb=di").
--      - The parameter "negPrefix=na" is used only for the present indicative.
--
-- Preverb "di", used in: "indPresent"(present stem), "indImperfect"(past stem)
--                        - Bo neyînî: pêşgira "di-" tenê di nav dema "IndImperfect" de tê bikaranîn.
-- Preverb "bi", used in: "indFuture"(present stem), "subPresent"(present stem),
--                         "subImperfect"(past stem) = "condPresent"(past stem)
--                        - The prefix "bi-" isn't used in negative forms.
--
-- Present stem, used in: "indPresent"(di)(na),
--                        "indFuture"(bi)(ne) = "subPresent"(bi)(ne)
--
-- Past stem, used in: "indPreterite"(-)(ne), "indImperfect"(di)(ne), "indPluperfect"(-)(ne),
--                     "indPerfect"(-)(ne), "indNwPluperfect"(-)(ne), "indFuturePerfect"(-)(ne),
--                     "subPreterite"(-)(ne),
--                     "subImperfect"(bi)(ne) = "condPresent"(bi)(ne),
--                     "subPluperfect"(-)(ne) = "condPreterite"(-)(ne)
-- =============================================================================
-- Some conjugations are identical except that they differ only in the preverbal particle (/ê/, /dê/).
-- So, to avoid repeating the same information (and thus risking errors),
-- we establish the common part shared between these verbs.
local sharedTenseRules = {
    indFuture = {
        stemType     = "present",
        preverb      = getPreverb['bi'],
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['present']
    },

    indFuturePerfect = {
        stemType     = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ibim']
    },

    subImperfect = {
        stemType     = "past",
        preverb      = getPreverb['bi'],
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ama']
    },

    subPluperfect = {
        stemType     = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ibûma']
    }
}

local mt = {
    __index = function(t, k)
        local commonRules = t._commonRules
        if commonRules then return commonRules[k] end
    end
}

-- TENSES CONJUGATION RULES
export.tenseRules = {
    -- IMPERATIVE MOOD
    impPresent = setmetatable({
        name         = "impPresent",
        nameKu       = "raweya fermanî",
        nameEn       = "present imperative",
        mode         = "imperative",
        _commonRules = sharedTenseRules.indFuture,
        preverbParticle = nil
    }, mt),

    -- INDICATIVE MOOD
    indPresent = {
        name         = "indPresent",
        nameKu       = "dema niha",
        nameEn       = "present",
        mode         = "indicative",
        stemType     = "present",
        preverb      = getPreverb['di'],
        negPreverb   = nil,
        negPrefix    = getNegPrefix['na'],
        endings      = getEndings['present'],
        preverbParticle = nil
    },

    indPreterite = {
        name         = "indPreterite",
        nameKu       = "raboriya sade",
        nameEn       = "simple past",
        mode         = "indicative",
        stemType     = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['past'],
        preverbParticle = nil
    },

    indImperfect = {
        name         = "indImperfect",
        nameKu       = "raboriya berdest",
        nameEn       = "Imperfect",
        mode         = "indicative",
        stemType     = "past",
        preverb      = getPreverb['di'],
        negPreverb   = getPreverb['di'],
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['past'],
        preverbParticle = nil
    },

    indPluperfect    = {
        name         = "indPluperfect",
        nameKu       = "raboriya dûr",
        nameEn       = "pluperfect",
        mode         = "indicative",
        stemType     = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ibûm'],
        preverbParticle = nil
    },

    indFuture = setmetatable({
        name         = "indFuture",
        nameKu       = "dema bê",
        nameEn       = "future",
        mode         = "indicative",
       _commonRules  = sharedTenseRules.indFuture,
        preverbParticle = 'ê'
    }, mt),

    indFuturePerfect = setmetatable({
        name         = "indFuturePerfect",
        nameKu       = "dahatiya pêş",
        nameEn       = "future perfect",
        mode         = "indicative",
       _commonRules  = sharedTenseRules.indFuturePerfect,
        preverbParticle = 'ê'
    }, mt),

    -- In some books, the "perfect" and "nonconfirmative pluperfect" tenses
    -- are classified in the "inferential mood" ("moda neşahidî").
    -- Currently we classify them using the indicative mood (at the end).
    indPerfect = {
        name         = "indPerfect",
        nameKu       = "raboriya dûdar",
        nameEn       = "perfect",
        mode         = "indicative",
        stemType    = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ime'],
        preverbParticle = nil
    },

    indNwPluperfect = {
        name         = "indNwPluperfect",
        nameKu       = "çîrokiya boriya dûdar",
        nameEn       = "non-witnessed pluperfect",
        mode         = "indicative",
        stemType    = "past",
        preverb      = nil,
        negPreverb   = nil,
        negPrefix    = getNegPrefix['ne'],
        endings      = getEndings['ibûme'],
        preverbParticle = nil
    },

    -- SUBJUNCTIVE MOOD
    subjPresent = setmetatable({
        name         = "subjPresent",
        nameKu       = "dema nihaya xwestekî",
        nameEn       = "present subjunctive",
        mode         = "subjunctive",
       _commonRules  = sharedTenseRules.indFuture,
        preverbParticle = nil
    }, mt),

    subjPreterite = setmetatable({
        name         = "subjPreterite",
        nameKu       = "dema boriya xwestekî",
        nameEn       = "preterite subjunctive",
        mode         = "subjunctive",
       _commonRules  = sharedTenseRules.indFuturePerfect,
        preverbParticle = nil,
    }, mt),

    subjImperfect = setmetatable({
        name         = "subjImperfect",
        nameKu       = "raboriya bilaniyê",
        nameEn       = "imperfect subjunctive",
        mode         = "subjunctive",
       _commonRules  = sharedTenseRules.subImperfect,
        preverbParticle = nil,
    }, mt),

    subjPluperfect = setmetatable({
        name         = "subjPluperfect",
        nameKu       = "raboriya dûr a bilaniyê",
        nameEn       = "pluperfect subjunctive",
        mode         = "subjunctive",
       _commonRules  = sharedTenseRules.subPluperfect,
        preverbParticle = nil
    }, mt),

    -- CONDITIONAL MOOD
    condPresent = setmetatable({
        name         = "condPresent",
        nameKu       = "çîrokiya dema nihaya mercî",
        nameEn       = "present conditional",
        mode         = "conditional",
       _commonRules  = sharedTenseRules.subImperfect,
        preverbParticle = 'ê'
    }, mt),

    condPreterite = setmetatable({
        name         = "condPreterite",
        nameKu       = "dema boriya mercî",
        nameEn       = "preterite conditional",
        mode         = "conditional",
       _commonRules  = sharedTenseRules.subPluperfect,
        preverbParticle = 'ê'
    }, mt),

}

-- =============================================================================
-- MAIN CONJUGATION FUNCTOIN
-- This function returns an array containing the conjugation table for a given
-- tense as well as other information about the conjugated verb.
-- =============================================================================
function export.conjugate(opts)
    opts = opts or {}
    -- Required parameters
    local tense          = opts.tense or error("'tense' required", 2)
    --One of the two parameters is required:
    --  - If the tense uses the present stem, indicate "presentStem".
    --  - If it uses the past stem, indicate "pastStem".
    local presentStem    = opts.presentStem
    local pastStem       = opts.pastStem
    -- Optional parameters
    local isTransitive   = opts.isTransitive or false   -- Indicate if the verb is transitive (true/false)
    local isNegative     = opts.isNegative or false     -- Indicate if it's the negative form (true/false)
    local isCompoundVerb = opts.isCompoundVerb or false -- Indicate if it's a compound verb (true/false)
    local preSimpleVerb  = opts.preSimpleVerb or ''     -- The part before the simple verb
    local postSimpleVerb = opts.postSimpleVerb or ''    -- The part after the simple verb
    -- These parameters are provided when the verb is irregular.
    -- Allows you to manually modify preverbs ("bi-"" or "di-")
    -- and negation prefixes ("na-" or "ne-")
	local overridePreverb = {
		-- Preverbs (bi-, di)
	    presentBi = opts.presentBi or nil,
	    presentDi = opts.presentDi or nil,
	    pastBi    = opts.pastBi or nil,
	    pastDi    = opts.pastDi or nil,
		-- Same preverbs ("past" and "present" stem)
	    sameBi     = opts.sameBi or nil,
	    sameDi     = opts.sameDi or nil,
	}
	local overrideNegPrefix = {
		-- Neg. prefix (na-, ne-)
	    presentNa  = opts.presentNa or nil,
	    presentNe  = opts.presentNe or nil,
	    pastNe     = opts.pastNe or nil,
		-- same neg. prefix (for past and present stem)
	    sameNe     = opts.sameNe or nil,
		impMe      = opts.impMe or nil,
	}
    -- By default, the negation of the imperative is constructed from the prefix "me-"".
    -- To obtain the second variant, the prefix with "ne-", you must specify "impNegForm=2".
    local impNegForm     = opts.impNegForm or 1
	-- Accent/ Devok
    local accent = opts.accent or 'std'
	
	-- If "tags='na'", remove links/tags
	local tags = opts.tags or 'erê'
	-- If addPreverbParticles='na', remove preverb particles (ê/dê) before
	-- the conjugated verbs.
	local addPreverbParticles = opts.addPreverbParticles or 'erê'

	
	-- We add a space to the left of the "postSimpleVerb" because it shouldn't be attached
	-- to the simple verb.
	if (postSimpleVerb ~= '' and postSimpleVerb ~=nil) then
		postSimpleVerb = ' ' .. postSimpleVerb
	end

    -- Access to the classification table and retrieval of verb tense parameters
    local infoTense = deepCopy(export.tenseRules[tense], 'copy') or false

    -- We check that this tense is indeed in table "tenseRules".
    if (not infoTense) then
        return '<span style="color:red">Unknown tense: ' .. tense ..'</span>'
    end

    -- We check that one of the two parameters of the stem is given
    if (infoTense.stemType == 'present' and not presentStem) then
        return '<span style="color:red">presentStem parameter required</span>'
    elseif (infoTense.stemType == 'past' and not pastStem) then
        return '<span style="color:red">pasttStem parameter required</span>'
    end

    -- Choice between the present stem or past stem
    local stem = (infoTense.stemType == 'present') and presentStem or pastStem

    --────────────────────────────
    -- Conjugation construction --
    -- ───────────────────────────
    local preverb = ''
    local negPrefix = ''

	-- +++++++++++++++++++++++++++
    -- Lêkerin nestandard --
    -- +++++++++++++++++++++++++++
	-- çûn
	if (stem == 'her-er-r') then
		if tense == 'indPresent' then
			if isNegative then
				stem = 'r'
			else
				stem = 'er'
				overridePreverb.presentDi = 't'
			end
		elseif ({impPresent=true, indFuture=true, subjPresent=true})[tense] then
			overridePreverb.presentBi = ''
			if isNegative then
				stem = 'r'
			else
				stem = 'her'
			end
		end
	end

	-- hatin
	if (stem == 'wer'  and pastStem == 'hat') then
		if ({impPresent=true, indFuture=true, subjPresent=true})[tense] then
			if isNegative then
				stem = 'ê'
			else
				overridePreverb.presentBi = ''
				stem = 'wer'
			end
		elseif (tense == 'indPresent') then
			stem = 'ê'
		end
	end
	-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
    -- Ruturns the verb type: "simpleVerb" or "preverbVerb" or "compoundVerb"
    local verbStruct = export.verbStruct(isCompoundVerb, preSimpleVerb)

    if isNegative then
        negPrefix = infoTense:negPrefix{stem=stem,
                                        impNegForm=impNegForm,
                                        overrideNegPrefix=overrideNegPrefix}
        if infoTense.negPreverb then
            preverb = infoTense:negPreverb{stem=stem, verbStruct=verbStruct,
                                           overridePreverb=overridePreverb}
        end
    else
        if infoTense.preverb then
            preverb = infoTense:preverb{stem=stem, verbStruct=verbStruct,
                                        overridePreverb=overridePreverb,
										accent=accent}
        end
    end

    infoTense.conj = {}
    local spacing = isCompoundVerb and ' ' or ''
    local endings = infoTense:endings(stem, accent)

	
    local preverbParticles = export.getPreverbParticles(
		infoTense.preverbParticle,
		infoTense.stemType, isTransitive
	)
	
    local isErgative = isTransitive and (infoTense.stemType == 'past')

    -- Creating the conjugation table for a given tense
    for _, pers in ipairs(export.order) do
        local ending
        local conjSimbleVerb
        local conjVerb

        if isErgative then
            ending = endings.s3
        else
            ending = endings[pers]
        end

        -- Adding space after the preverbal particle, and
		-- if "addPreverbParticles='na'": remove preverb particles (ê/dê).
		local preverbParticle = ''
		if infoTense.preverbParticle and addPreverbParticles ~= 'na' then
	            preverbParticle = preverbParticles[pers] .. ' '
		end

        conjSimbleVerb = negPrefix  .. preverb .. stem .. ending
        -- Adding prefixe and suffixe
        conjVerb =  preSimpleVerb .. spacing .. conjSimbleVerb .. postSimpleVerb
        -- Spelling correction(îy -> iy)
        conjVerb = gsub(conjVerb, 'îy', 'iy')
        -- Add a link / if tags='na' no links
		if tags ~= 'na' then
        	conjVerb = link{term=conjVerb, lang=langKu}
		end
        -- Addition of the preverbal particle
        infoTense.conj[pers] = preverbParticle .. conjVerb
    end

    -- Imperative
    if (infoTense.name == 'impPresent') then
        infoTense.conj.s1 = nil
        infoTense.conj.s2 = infoTense.conj.s3
        infoTense.conj.s3 = nil
        infoTense.conj.p1 = nil
        -- infoTense.conj.p2 = infoTense.conj.p2
        infoTense.conj.p3 = nil
    end

    return infoTense
end

-- =============================================================================
--                               END
-- =============================================================================
-- Some useful tools
-- =============================================================================
-- Returns the list of verb tenses
export.tensesList = function()
	local list = {}
    for _, tense in pairs(export.tenseRules) do
        table.insert(list, tense.name)
    end
	return list
end

-- Concatenation of pronouns and conjugated verbs
-- (for a given conjugate tense in all persons of that tense)
function export.concatPronouns(pronoms, conjVerbs)
    local concatTab = {}

    for _, pers in ipairs(export.order) do
        local pronom = pronoms[pers] or ""
        local verbe  = conjVerbs[pers] or ""

        if pronom == "" then
            concatTab[pers] = verbe
        elseif verbe == "" then
            concatTab[pers] = pronom
        else
            concatTab[pers] = pronom .. " " .. verbe
        end
    end

    return concatTab
end

-- Remove duplicates
local function removeDuplicates(list)
	local seen = {}
	local result = {}
	
	for _, value in ipairs(list) do
		if not seen[value] then
			seen[value] = true
			table.insert(result, value)
		end
	end
	
	return result
end

-- =============================================================================
-- ADDITIONAL STEM OF THE PAST AND PRESENT (pastStem2, ... and presentStem2, ...)
-- This function does nothing more than add additional parameters for verb stems
-- in the past and present tenses.
-- Conjugations for the different stems will be separated by "/"
-- =============================================================================
function export.conjugateMultiStem(baseOpts, tense, presentStems, pastStems, negation)
    local opts = deepCopy(baseOpts or {}, 'copy')
	opts.tense = tense

    if negation == 'negative' then
		opts.isNegative = true
	end

	-- We capture the true value of addPreverbParticles
	local addPreverbParticles = opts.addPreverbParticles

	-- This is so that we can delete proverbs to eliminate duplicates
	-- and keep each proverb only once, at the beginning.
	opts.addPreverbParticles = 'na'
	
    presentStems = presentStems or {}
	pastStems = pastStems or {}
    
    local infoTense = deepCopy(export.tenseRules[tense], 'copy')
    if not infoTense then
        return '<span style="color:red">Unknown tense: ' .. tostring(tense) ..'</span>'
    end

    local stems = (infoTense.stemType == 'present') and presentStems or pastStems
	
    -- For each verb stem, its conjugation table is calculated and stored in conjTabs.
    local conjTabs = {}
    for i = 1, #stems do
		local stem = stems[i]
        if stem then
            if (infoTense.stemType == 'past') then
				opts.pastStem = stem
				
			elseif (infoTense.stemType == 'present') then
				opts.presentStem = stem
				-- For the recognition of irregular verbs based on the past-stem part
				-- see: "çûn" û "hatin"
				opts.pastStem = pastStems[1]
			end

			local result = export.conjugate(opts)
			if result and result.conj then
				table.insert(conjTabs, result.conj)
			end
        end
    end

    -- We concatenate each row of the conjugation tables.
	local preverbParticles = deepCopy(export.getPreverbParticles(
		infoTense.preverbParticle, 
		infoTense.stemType, 
		opts.isTransitive
	), 'copy')

    local concatConjTabs = {}
    for _, pers in ipairs(export.order) do
        local frag = {}
        for i = 1, #conjTabs do
            local val = conjTabs[i][pers]
            if val then
				table.insert(frag, tostring(val))
			end
        end
				
		frag = removeDuplicates(frag)
		if (infoTense.preverbParticle and addPreverbParticles ~= 'na') then
	        concatConjTabs[pers] = preverbParticles[pers] .. ' '
								 .. table.concat(frag, ' — ')
		else
			concatConjTabs[pers] = table.concat(frag, ' — ')
		end
    end

    infoTense.conj = concatConjTabs
	
    return infoTense
end

-- ====================================================================================
--  VERB CONJUGATION IN ALL TENSES WITH OR WITHOUT PRONOUNS
-- ====================================================================================
function export.conjugateAllTenses(baseOpts, presentStems, pastStems, negation, concatPrs)
	-- "concatPrs=false" table without pronouns
	
    local opts = deepCopy(baseOpts or {}, 'copy')
    
    if negation == 'negative' then
		opts.isNegative = true
	end

    presentStems = presentStems or {}
    pastStems    = pastStems or {}

    -- Concatenation of pronouns and conjugated verbs
	local concatPronouns = export.concatPronouns

    local tensesList = export.tensesList()

    -- Conjugation in all tenses
    local conjTab = {}

    for _, tense in ipairs(tensesList) do
        -- Conjugations without the pronouns
        local conjData = deepCopy(
            export.conjugateMultiStem(opts, tense, presentStems, pastStems),
            'copy'
        )
		
        -- We concatenate the pronouns and the verbs if "concatPrs" is different of "false"
		-- No pronouns for the imperative mood
        if tense ~= 'impPresent' and concatPrs ~= false then
            local infoTense = deepCopy(export.tenseRules[tense], 'copy')
            
            local pronoms = deepCopy(
                export.conjPronouns(infoTense.stemType, infoTense.mode, opts.isTransitive)
            )
            
            conjData.conj = concatPronouns(pronoms, conjData.conj)
        end

        conjTab[tense] = conjData
    end
	
    return conjTab
end

-- ====================================================================================
-- Allows you to obtain a given conjugation from a model.
-- Ex. {{#invoke:ku-tewandin|tew|dem=indPresent|kes=s1}}
-- See {{ku-tewîn-lk-niha}}
-- ====================================================================================
function export.tew(frame)
   local args = frame:getParent().args

    local baseOpts = {
        isNegative     = frame.args['neyînî'] or false,
        isTransitive   = args['form'],
        isCompoundVerb = args['valahî'] or false,
        preSimpleVerb  = args['pêşgir'] or nil,
        postSimpleVerb = args['paşgir'] or nil,
		-- overridePreverb:
		presentBi = frame['nihaBi'] or nil,
		presentDi = frame['nihaDi'] or nil,
		pastBi    = frame['borîBi'] or nil,
		pastDi    = frame['borîDi'] or nil,
		sameBi    = frame['bi'] or nil,
		sameDi    = frame['di'] or nil,
		-- overrideNegPrefix:
		presentNa  = frame['na'] or nil,
		presentNe  = frame['nihaNe'] or nil,
		pastNe     = frame['borîNe'] or nil,
		sameNe     = frame['ne'] or nil,
		impMe      = frame['me'] or nil,
		
        impNegForm     = 1,
		tags           = args['lînk'] or 'erê',
		accent         = args['devok'] or 'std',
    }
	
	local tense        = frame.args['dem'] or nil
	local pers         = frame.args['kes'] or nil
    local presentStems = {args['niha'], args['niha2'], args['niha3']}
    local pastStems    = {args['borî'], args['borî2'], args['borî3']}

    -- A few checks
    if (baseOpts.isTransitive == 'gerguhêz') then
        baseOpts.isTransitive = true
    elseif (baseOpts.isTransitive == 'negerguhêz') then
        baseOpts.isTransitive = false
    else
        return '<span style="color:red">form = gerguhêz / negerguhêz</span>'
    end

    if (baseOpts.isCompoundVerb == 'erê') then
        baseOpts.isCompoundVerb = true
    else
        baseOpts.isCompoundVerb = false
    end

    if (baseOpts.isNegative == 'erê') then
        baseOpts.isNegative = true
    end

	local tabConj = export.conjugateMultiStem(baseOpts, tense, presentStems, pastStems).conj
	
    return tabConj[pers]
end

-- ====================================================================================
-- GET COMMMA SEPARED FORMS
-- Bnr. [[MediaWiki:Gadget-QQ.js]]
-- Ex. {{#invoke:ku-tewandin|get_comma_separated_forms|niha=kev|borî=ket}}
-- ====================================================================================
function export.get_comma_separated_forms(frame)
    local opts = {
        presentStem     = frame.args['niha'],
        pastStem        = frame.args['borî'],
        isTransitive    = false,
        isNegative      = false,
        isCompoundVerb  = frame['valahî'] or false,
        preSimpleVerb   = frame['pêşgir'] or '',
        postSimpleVerb  = frame['paşgir'] or '',
		-- overridePreverb:
		presentBi = frame['nihaBi'] or nil,
		presentDi = frame['nihaDi'] or nil,
		pastBi    = frame['borîBi'] or nil,
		pastDi    = frame['borîDi'] or nil,
		sameBi    = frame['bi'] or nil,
		sameDi    = frame['di'] or nil,
		-- overrideNegPrefix:
		presentNa  = frame['na'] or nil,
		presentNe  = frame['nihaNe'] or nil,
		pastNe     = frame['borîNe'] or nil,
		sameNe     = frame['ne'] or nil,
		impMe      = frame['me'] or nil,
		
        impNegForm     = 1,
		tags           = 'na', -- Remove links/tags
		addPreverbParticles = 'na' -- Remove preverb particles (ê/dê)
    }

   local function concateList(tenseList)
        local concatList = {}
        for _, pers in ipairs({"s1", "s2", "s3", "p1"}) do
        	local tense = tenseList[pers]
            table.insert(concatList, tense)
        end

        return table.concat(concatList, ",")
   end

   	local tenseList = {'indPresent','indPreterite','indImperfect',
                      'indPluperfect','indPerfect','indNwPluperfect',
                      'indFuture','indFuturePerfect',
                      'subjImperfect','subjPluperfect'
                    }
                    
    local concatAllTense = {}
    
    for  i = 1, #tenseList do
        local tense = tenseList[i]
        if export.tenseRules[tense] then
            opts.tense = tense
            local conj = shallowCopy(export.conjugate(opts).conj)
            local concatTense = concateList(conj)
            table.insert(concatAllTense, concatTense)
        end
    end
    
    return table.concat(concatAllTense, ",")
end

return export