This module generates tables of prepositions combined with pronoun suffixes for {{ar-prep-auto}}
.
local m_links = require("Module:links")
local m_strutils = require("Module:string utilities")
local ar_utilities = require("Module:ar-utilities")
local export = {}
local lang = require("Module:languages").getByCode("ar")
local u = mw.ustring.char
-- hamza variants
local HAMZA = u(0x0621) -- hamza on the line (stand-alone hamza) = ء
local HAMZA_ON_ALIF = u(0x0623)
local HAMZA_ON_W = u(0x0624)
local HAMZA_UNDER_ALIF = u(0x0625)
local HAMZA_ON_Y = u(0x0626)
local HAMZA_ANY = ""
local HAMZA_PH = u(0xFFF0) -- hamza placeholder
-- diacritics
local A = u(0x064E) -- fatḥa
local AN = u(0x064B) -- fatḥatān (fatḥa tanwīn)
local U = u(0x064F) -- ḍamma
local UN = u(0x064C) -- ḍammatān (ḍamma tanwīn)
local I = u(0x0650) -- kasra
local IN = u(0x064D) -- kasratān (kasra tanwīn)
local SK = u(0x0652) -- sukūn = no vowel
local SH = u(0x0651) -- šadda = gemination of consonants
local DAGGER_ALIF = u(0x0670)
local DIACRITIC_ANY_BUT_SH = ""
-- various letters and signs
local ALIF = u(0x0627) -- ʾalif = ا
local AMAQ = u(0x0649) -- ʾalif maqṣūra = ى
local AMAD = u(0x0622) -- ʾalif madda = آ
local TAM = u(0x0629) -- tāʾ marbūṭa = ة
local T = u(0x062A) -- tāʾ = ت
local HYPHEN = u(0x0640)
local N = u(0x0646) -- nūn = ن
local W = u(0x0648) -- wāw = و
local Y = u(0x064A) -- yā = ي
local LRM = u(0x200e) -- left-to-right mark
local function ine(x) -- If Not Empty
if x == "" then
return nil
else
return x
end
end
function canon_shadda_hamza(word)
if not word then
return nil
end
-- shadda+short-vowel (including tanwīn vowels, i.e. -an -in -un) gets
-- replaced with short-vowel+shadda during NFC normalisation, which
-- MediaWiki does for all Unicode strings; however, it makes various
-- processes inconvenient, so undo it.
word = mw.ustring.gsub(word, "(" .. DIACRITIC_ANY_BUT_SH .. ")" .. SH, SH .. "%1")
-- replace hamza with hamza placeholder; it will be fixed later by hamza_seat()
word = mw.ustring.gsub(word, HAMZA_ANY .. "()$", HAMZA_PH .. "%1")
return word
end
-- Supply the appropriate hamza seat(s) for a placeholder hamza.
function hamza_seat(word)
-- FIXME! Allow multiple possibilities in inflection tables
if mw.ustring.find(word, HAMZA_PH) then -- optimization to avoid many regexp substs
return ar_utilities.process_hamza(word)
end
return word
end
local forms = {
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
= true,
}
local function linkify(args)
for form in pairs(forms) do
if args == "-" or not ine(args) then
args = "—"
else
args = hamza_seat(args)
args = m_links.full_link({lang = lang, term = args, tr = ine(args) or nil})
end
end
end
local attach_1s = {}
attach_1s = function(args)
if not ine(args) then
-- if ends with -y, add -ya; else, truncate final short vowel and add -ī
if mw.ustring.find(args, "يْ?$") then
args = mw.ustring.gsub(args, SK .. "?$", SH .. A, 1)
args = args and (args .. "ya")
args = args and (mw.ustring.gsub(args, "īya$", "iyya", 1))
else
args = mw.ustring.gsub(args, "?$", I .. Y, 1)
args = args and (mw.ustring.gsub(args, "?$", "ī", 1))
end
end
end
attach_1s = function(args)
if not ine(args) then
-- if already ends in -n, double the -n then add -ī; else, add -nī
if mw.ustring.find(args, "نْ?$") then
args = mw.ustring.gsub(args, SK .. "?$", SH .. I .. Y, 1)
else
args = args .. "نِي"
end
args = args and (args .. "nī")
end
end
local function attach_1p(args)
if not ine(args) then
-- if already ends in -n, double the -n then add -ā; else, add -nā
if mw.ustring.find(args, "نْ?$") then
args = mw.ustring.gsub(args, SK .. "?$", SH .. A .. ALIF, 1)
else
args = args .. "نَا"
end
args = args and (args .. "nā")
end
end
local function attach_2(args)
local stem2 = args .. "ك"
local stem2tr = args and (args .. "k")
if not ine(args) then
args = stem2 .. A
args = args and (stem2tr .. "a")
end
if not ine(args) then
args = stem2 .. I
args = args and (stem2tr .. "i")
end
if not ine(args) then
args = stem2 .. "ُمَا"
args = args and (stem2tr .. "umā")
end
if not ine(args) then
args = stem2 .. "ُمْ"
args = args and (stem2tr .. "um")
end
if not ine(args) then
args = stem2 .. "ُنَّ"
args = args and (stem2tr .. "unna")
end
end
local function attach_3(args)
local stem3 = nil
local stem3tr = nil
if mw.ustring.find(args, "" .. SK .. "?$") then
stem3 = args .. "هِ"
stem3tr = args and (args .. "hi")
else
stem3 = args .. "هُ"
stem3tr = args and (args .. "hu")
end
if not ine(args) then
args = stem3
args = args and (stem3tr)
end
if not ine(args) then
args = stem3 .. "مَا"
args = args and (stem3tr .. "mā")
end
if not ine(args) then
args = stem3 .. "مْ"
args = args and (stem3tr .. "m")
end
if not ine(args) then
args = stem3 .. "نَّ"
args = args and (stem3tr .. "nna")
end
end
local function attach_3fs(args)
if not ine(args) then
args = args .. "هَا"
args = args and (args .. "hā")
end
end
local function base_to_stem(args)
-- replace final -ā with -ay (e.g. إِلَى becomes إِلَيْهِ)
args = mw.ustring.gsub(args, "*" .. AMAQ .. DAGGER_ALIF .. "?$", A .. Y .. SK, 1)
-- replace final tāʾ marbūṭa with regular t (e.g. حَالَةَ becomes حَالَتَهُ)
args = mw.ustring.gsub(args, TAM .. "()$", T .. "%1", 1)
if not ine(args) then
if args ~= args then
args = args and mw.ustring.gsub(args, "ā$", "ay", 1)
else
args = args
end
end
args = mw.ustring.gsub(args, "(.)" .. HYPHEN .. "$", "%1", 1)
args = args and (mw.ustring.gsub(args, "(.)%-$", "%1", 1))
end
local template = [===[
{| class="wikitable vsSwitcher vsToggleCategory-inflection autocollapsed" style="text-align:center; border: 0.5px solid #CCC;"
|-
! class="vsToggleElement" style="text-align: center; width:30em" colspan="6" | {heading}
|- class="vsHide"
! colspan="5" |Base form
| {base}
|- class="vsHide"
! rowspan="2"| Personal-pronoun-<br />including forms
! colspan="2" | Singular
! Dual
! colspan="2" | Plural
|- class="vsHide"
! Masculine
! Feminine
! Common
! Masculine
! Feminine
|- class="vsHide"
! style="text-align: right;"| First person
| colspan="2" | {1s}
| colspan="3" | {1p}
|- class="vsHide"
! style="text-align: right;"| Second person
| {2ms}
| {2fs}
| {2d}
| {2mp}
| {2fp}
|- class="vsHide"
! style="text-align: right;"| Third person
| {3ms}
| {3fs}
| {3d}
| {3mp}
| {3fp}
|{\cl}]===]
local function make_table(args)
return m_strutils.format(template, args)
end
function export.inflect(frame)
local args = frame:getParent().args or {}
local ni = frame.args
if args and args ~= "" and args ~= "-" then
ni = "ni"
elseif ni ~= "ni" then
ni = "i"
end
PAGENAME = mw.title.getCurrentTitle().text
SUBPAGENAME = mw.title.getCurrentTitle().subpageText
NAMESPACE = mw.title.getCurrentTitle().nsText
args = canon_shadda_hamza(ine(args) or ine(args) or SUBPAGENAME)
args = ine(args) or ine(args)
if NAMESPACE == "Template" and not args then
args = "ـ"
args = "-"
end
args = canon_shadda_hamza(ine(args) or ine(args))
if not args then
base_to_stem(args)
end
args = ine(args) or ine(args) or args == args and args or nil
attach_1s(args)
attach_1p(args)
attach_2(args)
attach_3(args)
attach_3fs(args)
linkify(args)
args = ine(args) or "Inflected forms"
return make_table(args)
end
return export