Ĉi tiu modulo estas multfoje bindita.
Se vi konas la eblajn sekvojn, tiam vi povas zorgeme ekredakti.
Se vi ne kuraĝas redakti tiam vi povas proponi la deziratan ŝanĝon en la diskutejo.
Memtesto disponeblas sur la dokumentaĵa subpaĝo.

--[===[

MODULE "MAVKFORMO" (avk form)

"eo.wiktionary.org/wiki/Modulo:mavkformo" <!--2021-Dec-30-->

Purpose: analyzes a quasi-base or non-base form of an -avk- verb,
         and returns selected one of 8 types of information

Utilo: analizas kvazaux-bazan aux nebazan formon de -avk- verbo,
       kaj redonas unu elektitan tipon de informo el 8 disponeblaj

Manfaat: menganalisis sebuah bentuk kvasi-dasar atau fleksi verba -avk-,
         dan memberikan kembali satu dari 8 ...

Syfte: analyserar en kvasi-grundform eller boejningsform hos ett -avk- verb,
       och levererar en utvald typ av information av 8 tillgaengliga

Used by templates / Uzata far sxablonoj:
- "avk-konjugacioj" and "avk-verba-formo" (not to be
  called from any other place)

Required submodules / Bezonataj submoduloj / Submodul yang diperlukan: none

This module is special in that it takes parameters both those sent
to itself (own frame) and those sent to the caller (caller's frame).
This module needs parameters that are additional to or different from
parameters submitted to the calling template.

The one hidden parameter can be on our own or on the caller's frame. If the
parameter is not found on our own frame, the caller's one is peeked. This
way we can avoid forwarding that does not work for non-existent parameters
(non-existent ie nil becomes empty string, not appreciated).

Parameters: * 1 anonymous obligatory parameter :
                type of information requested :
                * "R" for root without the final vowel
                * "D" for description
                * "B" for quasi-base form (1st singular present)
                * "V" for the final vowel (a,e,i,u) without decoration
                * "W" for the final vowel with decoration
                * "F" for the inflexion affix including the final vowel
                      with decoration if applicable
                * "T" for tense code "0" ... "2"
                * "Z" for root plus final vowel without decoration
                anything else is an error
            * 1 hidden named parameter :
              * "pagenameoverridetestonly="

Returned: * desired text, or empty on error

This module is unbreakable (when called with correct module name
and function name).

Cxi tiu modulo estas nerompebla (kiam vokita kun gxustaj nomo de modulo
kaj nomo de funkcio).

: ---------------------------------------

* #T00 ("R", page "platitit")
* expected result: "plat"
* actual result: "{{#invoke:mavkformo|ek|R|pagenameoverridetestonly=platitit}}"

::* #T01 ("D", page "platitit", holy vowel "i")
::* expected result: "unua persono de pluralo estonteco"
::* actual result: "{{#invoke:mavkformo|ek|D|pagenameoverridetestonly=platitit}}"

* #T02 ("B", page "platitit")
* expected result: "plati" (i with comma above)
* actual result: "{{#invoke:mavkformo|ek|B|pagenameoverridetestonly=platitit}}"

::* #T03 ("V", page "platitit")
::* expected result: "i" (without decoration)
::* actual result: "{{#invoke:mavkformo|ek|V|pagenameoverridetestonly=platitit}}"

* #T04 ("W", page "platitit")
* expected result: "i" (with comma above)
* actual result: "{{#invoke:mavkformo|ek|W|pagenameoverridetestonly=platitit}}"

::* #T05 ("F", page "platitit")
::* expected result: "itit" (without decoration)
::* actual result: "{{#invoke:mavkformo|ek|F|pagenameoverridetestonly=platitit}}"

* #T06 ("Z", page "platitit")
* expected result: "plati" (without decoration)
* actual result: "{{#invoke:mavkformo|ek|Z|pagenameoverridetestonly=platitit}}"

: ---------------------------------------

* #T10 ("D", page "dankayac", holy vowel "a")
* expected result: "dua persono de pluralo estinteco"
* actual result: "{{#invoke:mavkformo|ek|D|pagenameoverridetestonly=dankayac}}"

::* #T11 ("T", page "dankayac", holy vowel "a")
::* expected result: "1" (code for past)
::* actual result: "{{#invoke:mavkformo|ek|T|pagenameoverridetestonly=dankayac}}"

* #T12 ("R", page "gi", shortest root, nonstandard quasi-base form without decoration)
* expected result: "g"
* actual result: "{{#invoke:mavkformo|ek|R|pagenameoverridetestonly=gi}}"

::* #T13 ("R", page "i", invalid too short quasi-base form without decoration)
::* expected result: ""
::* actual result: "{{#invoke:mavkformo|ek|R|pagenameoverridetestonly=i}}"

: ---------------------------------------

]===]

local avkformo = {}

------------------------------------------------------------------------

---- CONSTANTS ----

------------------------------------------------------------------------

  local contabaffixes = {}
  contabaffixes ["l"] = 1 -- sing 2
  contabaffixes ["r"] = 2 -- sing 3
  contabaffixes ["t"] = 3 -- plur 1
  contabaffixes ["c"] = 4 -- plur 2
  contabaffixes ["d"] = 5 -- plur 3
  contabaffixes ["v"] = 6 -- plur 4

  local contabpersons = {}
  contabpersons [0] = "unua persono de singularo"
  contabpersons [1] = "dua persono de singularo"
  contabpersons [2] = "tria persono de singularo"
  contabpersons [3] = "unua persono de pluralo"
  contabpersons [4] = "dua persono de pluralo"
  contabpersons [5] = "tria persono de pluralo"
  contabpersons [6] = "kvara persono de pluralo"

  local contabtenses = {}
  contabtenses [0] = "prezenco"
  contabtenses [1] = "estinteco"
  contabtenses [2] = "estonteco"

  constrbaza = " (kvaza" .. string.char(197,173) .. "baza formo)"

------------------------------------------------------------------------

---- HIGH LEVEL FUNCTIONS ----

------------------------------------------------------------------------

local function lfisholy (numcode)
  return ((numcode==97) or (numcode==101) or (numcode==105) or (numcode==117))
end--function lfisholy

------------------------------------------------------------------------

-- Local function LFAEIU

-- Add or remove decoration (only comma above a,e,i,u) in the
-- last letter of a string.

-- "a"  97 C3 A1 161 -- "e" 101 C3 A9 169
-- "i" 105 C3 AD 173 -- "u" 117 C3 BA 186
-- $C3 = #195

local function lfaeiu (striinut,booremove)

  local numlenc = 0
  local numlast = 0
  local numprev = 0
  local numneww = 0

  numlenc = string.len(striinut)
  if (numlenc>=1) then
    numlast = string.byte (striinut,numlenc,numlenc)
  end--if

  if (booremove) then -- "true" to remove -- "false" to add decoration
    if (numlenc>=2) then
      numprev = string.byte (striinut,(numlenc-1),(numlenc-1))
    end--if
    if (numprev==195) then
      if (numlast==161) then
        numneww = 97 -- a
      end--if
      if (numlast==169) then
        numneww = 101 -- e
      end--if
      if (numlast==173) then
        numneww = 105 -- i
      end--if
      if (numlast==186) then
        numneww = 117 -- u
      end--if
    end--if
  else
    if (numlast==97) then
      numneww = 161 -- a
    end--if
    if (numlast==101) then
      numneww = 169 -- e
    end--if
    if (numlast==105) then
      numneww = 173 -- i
    end--if
    if (numlast==117) then
      numneww = 186 -- u
    end--if
  end--if (booremove) else

  if ((numneww>0) and (numneww<128)) then
    striinut = string.sub(striinut,1,(numlenc-2)) .. string.char(numneww) -- removing decoration
  end--if
  if (numneww>128) then
    striinut = string.sub(striinut,1,(numlenc-1)) .. string.char(195,numneww) -- adding decoration
  end--if

  return striinut

end--function lfaeiu

------------------------------------------------------------------------

---- MAIN EXPORTED FUNCTION ----

------------------------------------------------------------------------

function avkformo.ek (arxframent)

  -- general unknown type

  local vartmp = 0     -- variable without type

  -- special type "args" AKA "arx"

  local arxourown = 0 -- metaized "args" from our own "frame"
  local arxcaller = 0 -- metaized "args" from caller's "frame"

  -- general "str"

  local strpagename   = ""
  local strsist       = "" -- only one char
  local strholynd     = "" -- only one ASCII char
  local strholydk     = "" -- only one UTF8 char
  local strinflex     = "" -- will get filled per "ueglstr"
  local strret        = "" -- result string

  -- general "num"

  local numlopagena  = 0
  local numpersono   = 0 -- 0...6 -- 0 1 2 sing 3 4 5 6 plur
  local numtenso     = 0 -- 0...2 -- 0:present 1:past 2:future 3:invalid
  local numm0        = 0
  local numm1        = 0
  local numm2        = 0

  -- general "boo"

  local booerr      = false
  local boohaveroot = false -- "R" or "D" or "B" or "V" or "W" "F" "T" "Z"
  local boohavedeed = false
  local boohaveboob = false
  local boohavevaav = false
  local boohavewuuw = false
  local boohavefina = false
  local boohavetens = false
  local boohavezzzz = false

  ---- GET THE ARX:ES ----

  arxourown = arxframent.args or {} -- "args" fr our own "frame"
  arxcaller = arxframent:getParent().args or {} -- "args" fr caller's "frame"

  ---- PROCESS ONE HIDDEN AND ONE OBLIGATORY ANONYMOUS PARAMETER ----

  -- min length is 2 to allow 2-letter verbs in base form without decoration

  strpagename = ''
  while (true) do -- fake loop
    booerr = true -- preliminary, preassume guilt
    vartmp = arxourown['pagenameoverridetestonly']
    if (vartmp==nil) then
      vartmp = arxcaller['pagenameoverridetestonly']
    end--if
    if (type(vartmp)=="string") then
      numlopagena=string.len(vartmp)
      if ((numlopagena>=2 and numlopagena<=100)) then
        strpagename = vartmp -- no error possible here
      end--if
    end--if
    if (arxourown[2]~=nil) then -- undesirable
      break -- bad
    end--if
    vartmp = arxourown[1] -- mau "R" or "D" or "B" or "V" or "W" "F" "T" "Z"
    boohaveroot = (vartmp=="R")
    boohavedeed = (vartmp=="D")
    boohaveboob = (vartmp=="B")
    boohavevaav = (vartmp=="V")
    boohavewuuw = (vartmp=="W")
    boohavefina = (vartmp=="F")
    boohavetens = (vartmp=="T")
    boohavezzzz = (vartmp=="Z")
    booerr = ((not boohaveroot) and (not boohavedeed) and (not boohaveboob) and (not boohavevaav) and (not boohavewuuw) and (not boohavefina) and (not boohavetens) and (not boohavezzzz))
    break -- good or bad
  end--while -- fake loop

  ---- SEIZE THE PAGENAME FROM MW AND CHECK IT ----

  -- must be 2...100 octet:s keep consistent with "pagenameoverridetestonly="

  -- ignore if type not "string", but otherwise do either buy it or brew error

  if ((not booerr) and (strpagename=='')) then
    vartmp = mw.title.getCurrentTitle().text -- without namespace prefix
    if (type(vartmp)=="string") then
      numlopagena = string.len(vartmp)
      if ((numlopagena>=2) and (numlopagena<=100)) then
        strpagename = vartmp
      else
        booerr = true
      end--if
    end--if
  end--if

  booerr = booerr or (strpagename=='')

  ---- DETECT PERSON AND TENSE ----

  -- "numpersono" -- 0...6 -- 0 1 2 sing N/A l r -- 3 4 5 6 plur t c d v
  -- "numtenso"   -- 0...2 -- 0:present  1:past  2:future  3:invalid

  -- example:   present      past            future
  --            plat-i-v     plat-i-y-i-v    plat-i-t-i-v
  --            sux-a-v      sux-a-y-a-v     sux-a-t-a-v
  -- the holy final vowel (a,e,i,u) is used twice in past and future tenses

  if (not booerr) then

    strpagename = lfaeiu (strpagename,true) -- remove deco
    numlopagena = string.len(strpagename) -- 1...100 -- after removal !!!
    booerr = (numlopagena<2)-- but ONE is invalid

  end--if

  if (not booerr) then

    numpersono  = 0  -- preassume 1st any tense
    strinflex   = "" -- will get filled per "ueglstr"
    numtenso    = 3  -- preassume guilt

    strsist = string.sub (strpagename,numlopagena,numlopagena) -- detect perso
    vartmp = contabaffixes [strsist] -- 6 string indexes
    if (type(vartmp)=="number") then
      numpersono = vartmp -- default ZERO ie "sing 1"
      strinflex = strsist
      strpagename = string.sub (strpagename,1,(numlopagena-1))
      numlopagena = numlopagena - 1 -- remove ONE processed char
    end--if

    numm0 = string.byte (strpagename,numlopagena,numlopagena)
    numm1 = string.byte (strpagename,(numlopagena-1),(numlopagena-1))

    if (numlopagena>=4) then -- test for past and future
      numm2 = string.byte (strpagename,(numlopagena-2),(numlopagena-2))
      if ((numm0==numm2) and lfisholy(numm0)) then
        if (numm1==121) then
          numtenso = 1 -- "y" -> YES it was the paaast !!!
        end--if
        if (numm1==116) then
          numtenso = 2 -- "t" -> YES it will be the fuuuture !!!
        end--if
      end--if
      if (numtenso~=3) then
        strholynd = string.char (numm0) -- without decoration
        strinflex = string.sub (strpagename,(numlopagena-2),numlopagena) .. strinflex
        strpagename = string.sub (strpagename,1,(numlopagena-3))
        numlopagena = numlopagena - 3 -- remove 3 processed chars
      end--if
    end--if

    if ((numtenso==3) and (numlopagena>=2)) then -- test for present
      if (lfisholy(numm0)) then
        numtenso = 0 -- YES it is the preeesent !!!
        strholynd = string.char (numm0) -- without decoration
        if (numpersono==0) then
          strinflex = lfaeiu (strholynd,false) .. strinflex -- with deco
        else
          strinflex = strholynd .. strinflex -- without deco
        end--if
        strpagename = string.sub (strpagename,1,(numlopagena-1))
        numlopagena = numlopagena - 1 -- remove ONE processed char
      end--if
    end--if

    booerr = (numtenso==3)

  end--if

  ---- FILL ONE MORE VARIABLE ----

  if (not booerr) then
    strholydk = lfaeiu (strholynd,false) -- add deco
  end--if

  ---- SELECT DESIRED OUTPUT ----

  if (not booerr) then -- "R" or "D" or "B" or "V" or "W" "F" "T" "Z"

    if (boohaveroot) then -- "R" -- root
      strret = strpagename -- now stripped ;-)
    end--if

    if (boohavedeed) then -- "D" -- description
      strret = contabpersons[numpersono] .. " " .. contabtenses[numtenso]
      if ((numpersono==0) and (numtenso==0)) then
        strret = strret .. constrbaza
      end--if
    end--if

    if (boohaveboob) then -- "B" -- full base form
      strret = strpagename .. strholydk -- with decoration
    end--if

    if (boohavevaav) then -- "V"
      strret = strholynd
    end--if

    if (boohavewuuw) then -- "W"
      strret = strholydk
    end--if

    if (boohavefina) then -- "F" -- inflexion affix
      strret = strinflex
    end--if

    if (boohavetens) then -- "T" -- tense code "0" ... "2"
      strret = tostring (numtenso)
    end--if

    if (boohavezzzz) then -- "Z" -- undecorated base form, root + holy vowel
      strret = strpagename .. strholynd -- without decoration
    end--if

  end--if

  ---- RETURN THE JUNK STRING ----

  return strret -- can be empty

end--function

  ---- RETURN THE JUNK LUA TABLE ----

return avkformo