Викиречник
mkwiktionary
https://mk.wiktionary.org/wiki/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
MediaWiki 1.45.0-wmf.8
case-sensitive
Медиум
Специјална
Разговор
Корисник
Разговор со корисник
Викиречник
Разговор за Викиречник
Податотека
Разговор за податотека
МедијаВики
Разговор за МедијаВики
Предлошка
Разговор за предлошка
Помош
Разговор за помош
Категорија
Разговор за категорија
TimedText
TimedText talk
Модул
Разговор за модул
χριστιανός
0
9032
53403
53332
2025-07-04T14:26:45Z
Steborce
2506
Откажано уредувањето [[Special:Diff/50783|50783]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53403
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
59qfzl9yr80r0g24nvq772prx6qpucn
53411
53403
2025-07-04T14:58:26Z
Steborce
2506
53411
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
[[Категорија:Грчки именки]]
jhob1vcntq5v2q4fj5swompwusy6eud
53417
53411
2025-07-04T15:43:33Z
Steborce
2506
53417
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{#invoke:el-noon-decl-tests|RunTests}}
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
[[Категорија:Грчки именки]]
dftdbdm3wuwjs911totp8a64gjx631p
53420
53417
2025-07-04T15:53:29Z
Steborce
2506
53420
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
[[Категорија:Грчки именки]]
jhob1vcntq5v2q4fj5swompwusy6eud
53425
53420
2025-07-04T21:52:06Z
Steborce
2506
53425
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl|DeclineNoun|δέντρο|debug=1}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
[[Категорија:Грчки именки]]
95iht2c320boidu33i7unua2gxvwq54
53426
53425
2025-07-04T21:52:51Z
Steborce
2506
53426
wikitext
text/x-wiki
{{-el-}}
'''χριστιανός'''
#[[христијанин]]
{{el-noon-conj|{{PAGENAME}}}}
{{#invoke:el-noon-decl|DeclineNoun|έγγραφο|debug=1}}
{{#invoke:el-noon-decl-tests|RunTests}}
[[Категорија:Грчки]]
[[Категорија:Грчки именки]]
i2gq4dzy8wnjyelmquaahz2dqx80pni
Модул:el-noon-decl
828
10052
53365
53364
2025-07-04T12:01:49Z
Steborce
2506
53365
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ω']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο, σχολείο)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο, έγγραφο)
if form_type == "gen_s_o" or form_type == "gen_p_o" then -- Genitive shifts to penultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Nom/Acc/Voc remains antepenultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.acc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.voc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_ma")) -- Apply accent for acc_s
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_ma")) -- Apply accent for voc_s
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
sn6gpdmobj14dewwanu7u0vidg2typv
53366
53365
2025-07-04T12:07:23Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53365|53365]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53366
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ω']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο, σχολείο)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο, έγγραφο)
if form_type == "gen_s_o" or form_type == "gen_p_o" then -- Genitive shifts to penultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Nom/Acc/Voc remains antepenultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.acc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.voc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- Special handling for "αίτημα" (vocative and accusative singular are unaccented)
if noun_base == "αίτημα" then
forms.acc_s = add_wikilinks(remove_accents(noun_base)) -- Unaccented
forms.voc_s = add_wikilinks(remove_accents(noun_base)) -- Unaccented
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
-- The rest (gen_s, plurals) will follow the general -μα rule below
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
else
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
end
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
7pjpi0yu3mbtfg3qrmgs1ipmaxyl0az
53367
53366
2025-07-04T12:09:47Z
Steborce
2506
53367
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ω']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο, σχολείο)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο, έγγραφο)
if form_type == "gen_s_o" or form_type == "gen_p_o" then -- Genitive shifts to penultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Nom/Acc/Voc remains antepenultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.acc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.voc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- Special handling for "αίτημα" (vocative and accusative singular are unaccented)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
hrd7a9axmsf7dp61xehnb8h9bvg3nsq
53370
53367
2025-07-04T12:20:33Z
Steborce
2506
53370
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ω']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο, σχολείο)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο, έγγραφο)
if form_type == "gen_s_o" or form_type == "gen_p_o" then -- Genitive shifts to penultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Nom/Acc/Voc remains antepenultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.acc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.voc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- Special handling for "αίτημα" (vocative and accusative singular are unaccented)
-- This block was previously here but has been removed as per your new working version.
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
c84tmq7rwah7edsui2xf6v5a7zp7976
53371
53370
2025-07-04T12:49:24Z
Steborce
2506
53371
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ω']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.voc_s = add_wikilinks(stem .. "ή") -- Suffix provides accent
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
1mzhuo1nyc8doppd9oqoru2adx6l8mb
53372
53371
2025-07-04T12:55:11Z
Steborce
2506
53372
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός)
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών") -- Fixed accent on ών
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.gen_p = add_wikilinks(stem .. "έων") -- Fixed accent on έων
forms.acc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
forms.voc_p = add_wikilinks(stem .. "είς") -- Fixed suffix
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
87b6c8ue3q40feuavaexj46xsubeqpn
53373
53372
2025-07-04T12:58:34Z
Steborce
2506
53373
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω", true) -- Find first 'ω'
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ία' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
puoeexi3q2xsnm4h3oudzkd1at3iyrj
53374
53373
2025-07-04T13:00:36Z
Steborce
2506
53374
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω") -- Corrected: Removed 'true'
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ία' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
i7ucvb6q2i7fxr6l252bdnltz7ofgf3
53375
53374
2025-07-04T13:03:47Z
Steborce
2506
53375
Scribunto
text/plain
--- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Keep the 'έ' for accent consistency in plural forms
stem = ustring.sub(noun_base, 1, -2) -- Keep 'έ'
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "gen_s_eas")) -- Remove accent from stem for singular suffixes
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "nom_p_eas")) -- Remove accent from stem for plural suffixes
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "ων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
obs1zv8irexiunmbouejtn7568tpdgd
53376
53375
2025-07-04T13:06:22Z
Steborce
2506
53376
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
5k9yo1wnh502dnvitl6scciyb4vwrvl
53377
53376
2025-07-04T13:08:45Z
Steborce
2506
53377
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs in paroxytone/proparoxytone -ος nouns
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.find(clean_new_form, "υ", -2) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.find(clean_new_form, "ι", -2) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.find(clean_new_form, "υ", -3) -- Accent on 'υ' of 'ους'
else
-- Fallback to penultimate vowel for other cases (e.g., singular accusative/vocative -ο, -ε)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
8wpg4w696qmjkgo0lhlmb16mysiahop
53378
53377
2025-07-04T13:11:08Z
Steborce
2506
53378
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable.
-- This means the accent is on the first vowel of a diphthong ending.
if ustring.match(clean_new_form, "ου$") then
-- Accent on 'ο' of 'ου'
target_accent_index = ustring.find(clean_new_form, "ο", -3)
elseif ustring.match(clean_new_form, "οι$") then
-- Accent on 'ο' of 'οι'
target_accent_index = ustring.find(clean_new_form, "ο", -3)
elseif ustring.match(clean_new_form, "ους$") then
-- Accent on 'ο' of 'ους'
target_accent_index = ustring.find(clean_new_form, "ο", -4)
else
-- For other endings (like -ο, -ε), the accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
hv7n57tcd9b89g0vcdrrusmqwonp39j
53379
53378
2025-07-04T13:13:32Z
Steborce
2506
53379
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable, which means the first vowel of a diphthong ending.
if ustring.match(clean_new_form, "ου$") then
-- Accent on 'ο' of 'ου'
target_accent_index = ustring.len(clean_new_form) - 1
elseif ustring.match(clean_new_form, "οι$") then
-- Accent on 'ο' of 'οι'
target_accent_index = ustring.len(clean_new_form) - 1
elseif ustring.match(clean_new_form, "ους$") then
-- Accent on 'ο' of 'ους'
target_accent_index = ustring.len(clean_new_form) - 2
else
-- For other endings (like -ο, -ε), the accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
3vwc3u4n5xiyonx8imdchuj1clyu3ly
53380
53379
2025-07-04T13:19:15Z
Steborce
2506
53380
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable.
-- The general rule of placing accent on the penultimate vowel (of the new form's vowels) applies here.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
8jpdzxpd7e7wagl8ew3k7uwhkbc2n5v
53381
53380
2025-07-04T13:21:54Z
Steborce
2506
53381
Scribunto
text/plain
--- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['ή']='η', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs where accent falls on the second vowel.
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.len(clean_new_form) - 1 -- Accent on 'υ' of 'ους'
else
-- Fallback for other endings (like -ο, -ε) where accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
lraruhwalk989pxmxtxeq9o7qj8s5qn
53382
53381
2025-07-04T13:30:06Z
Steborce
2506
53382
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['ή']='η', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs where accent falls on the second vowel.
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.len(clean_new_form) - 1 -- Accent on 'υ' of 'ους'
else
-- Fallback for other endings (like -ο, -ε) where accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically paroxytone (accent on penultimate of the *new* form)
if #new_vowel_indices >= 2 then -- Changed from >=3
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Changed from -2
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
fx0rqnuqh4v7j7l8r1zvakhlbcgcfp3
53383
53382
2025-07-04T13:31:23Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53382|53382]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53383
Scribunto
text/plain
--- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['ή']='η', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs where accent falls on the second vowel.
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.len(clean_new_form) - 1 -- Accent on 'υ' of 'ους'
else
-- Fallback for other endings (like -ο, -ε) where accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
lraruhwalk989pxmxtxeq9o7qj8s5qn
53384
53383
2025-07-04T13:31:38Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53381|53381]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53384
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable.
-- The general rule of placing accent on the penultimate vowel (of the new form's vowels) applies here.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
8jpdzxpd7e7wagl8ew3k7uwhkbc2n5v
53385
53384
2025-07-04T13:34:34Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53380|53380]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53385
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable, which means the first vowel of a diphthong ending.
if ustring.match(clean_new_form, "ου$") then
-- Accent on 'ο' of 'ου'
target_accent_index = ustring.len(clean_new_form) - 1
elseif ustring.match(clean_new_form, "οι$") then
-- Accent on 'ο' of 'οι'
target_accent_index = ustring.len(clean_new_form) - 1
elseif ustring.match(clean_new_form, "ους$") then
-- Accent on 'ο' of 'ους'
target_accent_index = ustring.len(clean_new_form) - 2
else
-- For other endings (like -ο, -ε), the accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
3vwc3u4n5xiyonx8imdchuj1clyu3ly
53386
53385
2025-07-04T13:34:48Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53379|53379]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53386
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- For these, the accent typically stays on the same syllable.
-- This means the accent is on the first vowel of a diphthong ending.
if ustring.match(clean_new_form, "ου$") then
-- Accent on 'ο' of 'ου'
target_accent_index = ustring.find(clean_new_form, "ο", -3)
elseif ustring.match(clean_new_form, "οι$") then
-- Accent on 'ο' of 'οι'
target_accent_index = ustring.find(clean_new_form, "ο", -3)
elseif ustring.match(clean_new_form, "ους$") then
-- Accent on 'ο' of 'ους'
target_accent_index = ustring.find(clean_new_form, "ο", -4)
else
-- For other endings (like -ο, -ε), the accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
hv7n57tcd9b89g0vcdrrusmqwonp39j
53387
53386
2025-07-04T13:35:00Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53378|53378]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53387
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs in paroxytone/proparoxytone -ος nouns
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.find(clean_new_form, "υ", -2) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.find(clean_new_form, "ι", -2) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.find(clean_new_form, "υ", -3) -- Accent on 'υ' of 'ους'
else
-- Fallback to penultimate vowel for other cases (e.g., singular accusative/vocative -ο, -ε)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
8wpg4w696qmjkgo0lhlmb16mysiahop
53388
53387
2025-07-04T13:35:17Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53377|53377]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53388
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Remove 'έας' and unaccent to get the base stem for suffixing
stem = remove_accents(ustring.sub(noun_base, 1, -4))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
5k9yo1wnh502dnvitl6scciyb4vwrvl
53389
53388
2025-07-04T13:35:42Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53376|53376]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53389
Scribunto
text/plain
--- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ια' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
-- Corrected stem: Keep the 'έ' for accent consistency in plural forms
stem = ustring.sub(noun_base, 1, -2) -- Keep 'έ'
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "gen_s_eas")) -- Remove accent from stem for singular suffixes
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "α", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "nom_p_eas")) -- Remove accent from stem for plural suffixes
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "ων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(stem) .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
obs1zv8irexiunmbouejtn7568tpdgd
53390
53389
2025-07-04T13:36:32Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53375|53375]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53390
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω") -- Corrected: Removed 'true'
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_p_ma" then
-- Genitive plural: always paroxytone (accent on penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
else -- gen_s_ma, nom_p_ma, acc_p_ma, voc_p_ma
-- These forms are typically proparoxytone (accent on antepenultimate of the *new* form)
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ία' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
i7ucvb6q2i7fxr6l252bdnltz7ofgf3
53391
53390
2025-07-04T13:40:41Z
Steborce
2506
53391
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Custom table.find implementation (since table.find is not standard Lua)
local function table_find(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return i
end
end
return nil
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ω'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Determine accent position based on noun type and form_type
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
local original_accent_vowel_idx_in_vowels = table_find(original_vowel_indices, original_accent_pos)
local original_accent_relative_to_end = #original_vowel_indices - (original_accent_vowel_idx_in_vowels or 0) + 1
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then -- Masculine -ος
if form_type == "gen_p" and original_accent_relative_to_end == 1 then -- Oxytone genitive plural (χριστιανών)
-- Accent should be on 'ω' in 'ων'
target_accent_index = ustring.find(clean_new_form, "ω")
elseif original_accent_relative_to_end == 1 then -- Oxytone (χριστιανός) for other forms
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Accent on last vowel
else -- Paroxytone/Proparoxytone (δρόμος, κήπος, θείος)
-- Specific handling for diphthongs where accent falls on the second vowel.
if ustring.match(clean_new_form, "ου$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'υ' of 'ου'
elseif ustring.match(clean_new_form, "οι$") then
target_accent_index = ustring.len(clean_new_form) -- Accent on 'ι' of 'οι'
elseif ustring.match(clean_new_form, "ους$") then
target_accent_index = ustring.len(clean_new_form) - 1 -- Accent on 'υ' of 'ους'
else
-- Fallback for other endings (like -ο, -ε) where accent is on the penultimate vowel.
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
elseif ustring.match(original_noun, "ο$") then -- Neuter -ο
if form_type == "gen_s_o" then
-- For -ου ending, accent is on 'υ'
local u_index = ustring.find(clean_new_form, "υ", ustring.len(clean_new_form) - 1)
target_accent_index = u_index
elseif form_type == "gen_p_o" then
-- For -ων ending, accent is on 'ω'
local o_index = ustring.find(clean_new_form, "ω", ustring.len(clean_new_form) - 1)
target_accent_index = o_index
elseif form_type == "nom_s_o" or form_type == "acc_s_o" or form_type == "voc_s_o" then
-- These forms retain the original noun's accent pattern
target_accent_index = original_accent_pos
elseif form_type == "nom_p_o" or form_type == "acc_p_o" or form_type == "voc_p_o" then
-- These forms end in -α and follow the original noun's accent pattern relative to end
if original_accent_relative_to_end == 2 then -- Paroxytone (βιβλίο -> βιβλία)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_to_end == 3 then -- Proparoxytone (πρόσωπο -> πρόσωπα, δάνειο -> δάνεια)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2] -- Accent on antepenultimate vowel
else -- Fallback
target_accent_index = new_vowel_indices[1]
end
end
-- Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
-- For all plural forms, accent is on the antepenultimate vowel
if form_type == "gen_p_eta" or form_type == "nom_p_eta" or form_type == "acc_p_eta" or form_type == "voc_p_eta" then
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
else -- Singular forms retain original accent pattern (typically paroxytone)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
-- Feminine -α (stressed -ία) - specifically handle accent placement
elseif ustring.match(original_noun, "ία$") then
if form_type == "gen_s_ia" or form_type == "nom_p_ia" or form_type == "acc_p_ia" or form_type == "voc_p_ia" then
-- Accent is typically on 'ι' (penultimate vowel for these forms)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1] -- Fallback
end
elseif form_type == "gen_p_ia" then
-- Genitive plural: always oxytone (accent on last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
else
-- Default for other forms, if any, or original noun form
target_accent_index = original_accent_pos
end
-- Neuter -ι / -ί (παιδί, νησί) - typically oxytone
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices]
-- For -μα nouns (general case)
elseif ustring.match(original_noun, "μα$") then
-- All forms of -μα nouns (except Nom/Acc/Voc singular which retain original accent)
-- typically have the accent on the antepenultimate vowel of the new form.
-- The genitive plural also follows this pattern for proparoxytone -μα nouns.
if #new_vowel_indices >= 3 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
else -- Fallback if not enough vowels (shouldn't happen for valid nouns)
target_accent_index = new_vowel_indices[1]
end
-- Masculine -ας (e.g., ταμίας)
elseif ustring.match(original_noun, "ας$") then
if form_type == "gen_s_as" or form_type == "acc_s_as" or form_type == "voc_s_as" then
-- Accent on 'α' of 'ία' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_as" or form_type == "acc_p_as" or form_type == "voc_p_as" then
-- Accent on 'ι' of 'ιες' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "gen_p_as" then
-- Accent on 'ω' of 'ών' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
-- Masculine -έας (e.g., διερμηνέας)
elseif ustring.match(original_noun, "έας$") then
if form_type == "gen_s_eas" or form_type == "acc_s_eas" or form_type == "voc_s_eas" then
-- Accent on 'ε' of 'έα' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
elseif form_type == "nom_p_eas" or form_type == "acc_p_eas" or form_type == "voc_p_eas" then
-- Accent on 'ι' of 'είς' (last vowel)
target_accent_index = new_vowel_indices[#new_vowel_indices]
elseif form_type == "gen_p_eas" then
-- Accent on 'ε' of 'έων' (penultimate vowel)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else
target_accent_index = new_vowel_indices[1]
end
end
else
-- Fallback: try to keep accent on same relative position from start of vowels
if original_accent_pos then
if original_accent_vowel_idx_in_vowels then
if #new_vowel_indices >= original_accent_vowel_idx_in_vowels then
target_accent_index = new_vowel_indices[original_accent_vowel_idx_in_vowels]
else
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Fallback to last vowel
end
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
if accent_map[char_to_accent] then -- Only accent if it's a non-accented vowel
local new_accented_char = accent_map[char_to_accent]
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
end
return clean_new_form -- Return as is if no accent rule applies or error
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
-- Use ustring.match for more robust ending checks
local ends_with_os = ustring.match(noun_base, "ος$") or ustring.match(noun_base, "νός$")
local ends_with_as = ustring.match(noun_base, "ας$")
local ends_with_eas = ustring.match(noun_base, "έας$")
local ends_with_is_es = ustring.match(noun_base, "ης$") or ustring.match(noun_base, "ής$")
local ends_with_eta_unstressed = ustring.match(noun_base, "η$") and not ustring.match(noun_base, "ή$")
local ends_with_eta_stressed = ustring.match(noun_base, "ή$")
local ends_with_ia = ustring.match(noun_base, "ία$")
local ends_with_ma = ustring.match(noun_base, "μα$")
local ends_with_i_ii = ustring.match(noun_base, "[ιί]$")
local ends_with_o = ustring.match(noun_base, "ο$")
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if ends_with_os then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif ends_with_as then
stem = remove_accents(ustring.sub(noun_base, 1, -3)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "gen_s_as"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "acc_s_as"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "α", "voc_s_as"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_as"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_as"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_as"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_as"))
-- Masculine -έας (e.g., διερμηνέας)
elseif ends_with_eas then
stem = remove_accents(ustring.sub(noun_base, 1, -4)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "gen_s_eas"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "acc_s_eas"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εα", "voc_s_eas"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eas"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eas"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eas"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eas"))
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif ends_with_is_es then
-- Corrected: Remove the last two characters to get the proper stem
stem = remove_accents(ustring.sub(noun_base, 1, -3))
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif ends_with_eta_unstressed then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "nom_p_eta")) -- Accent shift
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εων", "gen_p_eta")) -- Accent shift
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "acc_p_eta")) -- Accent shift
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "εις", "voc_p_eta")) -- Accent shift
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif ends_with_eta_stressed then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής") -- Suffix provides accent
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.gen_p = add_wikilinks(stem .. "ών") -- Suffix provides accent
forms.acc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
forms.voc_p = add_wikilinks(stem .. "ές") -- Suffix provides accent
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif ends_with_ia then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ας", "gen_s_ia"))
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "nom_p_ia"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p_ia"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "acc_p_ia"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ες", "voc_p_ia"))
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif ends_with_ma then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- General logic for other -μα nouns (e.g., γράμμα, ποίημα, μήνυμα, κήρυγμα, etc.)
local base_part_for_stem = ustring.sub(noun_base, 1, -3)
local declension_stem_unaccented = remove_accents(base_part_for_stem) .. "ματ"
local gen_s_form_no_accent = declension_stem_unaccented .. "ος"
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, gen_s_form_no_accent, "gen_s_ma"))
local gen_p_form_no_accent = declension_stem_unaccented .. "ων"
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, gen_p_form_no_accent, "gen_p_ma"))
local nom_acc_voc_p_form_no_accent = declension_stem_unaccented .. "α"
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, nom_acc_voc_p_form_no_accent, "voc_p_ma"))
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif ends_with_i_ii then
stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Stem should be unaccented
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ends_with_o then
local base_stem = remove_accents(ustring.sub(noun_base, 1, -2)) -- Remove 'ο' and unaccent
forms.nom_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "nom_s_o"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "acc_s_o"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, remove_accents(noun_base), "voc_s_o"))
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Воκαтив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
t8wr3t2o3vjhpanza2th6w0rlivyknw
53392
53391
2025-07-04T13:50:52Z
Steborce
2506
53392
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις. Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων. Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων. Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Specific rule for vocative and accusative singular of proparoxytone -μα nouns
-- For "αίτημα", the accusative and vocative singular are unaccented.
if accent_pos == 3 and noun == "αίτημα" then
forms.voc_s = strip_tonos(noun) -- "αιτημα"
forms.acc_s = strip_tonos(noun) -- "αιτημα"
end
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(strip_tonos(noun), 1, -3) -- Should yield "διευθυντ"
-- Nom/Acc/Voc Plural: Correct base + "ές".
local nom_p_form = unaccented_base_with_t_for_plural .. "ές"
-- Genitive Plural: Correct base + "ών".
local gen_p_form = unaccented_base_with_t_for_plural .. "ών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
local function decline_noun(noun)
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = decline_noun(noun) -- Get the declined forms.
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
rnh5b1y1f4wgfp3xmjoqhh3ultlq7z7
53393
53392
2025-07-04T14:07:30Z
Steborce
2506
53393
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις. Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων. Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων. Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Specific rule for vocative and accusative singular of proparoxytone -μα nouns
-- For "αίτημα", the accusative and vocative singular are unaccented.
if accent_pos == 3 and noun == "αίτημα" then
forms.voc_s = strip_tonos(noun) -- "αιτημα"
forms.acc_s = strip_tonos(noun) -- "αιτημα"
end
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(strip_tonos(noun), 1, -3) -- Should yield "διευθυντ"
-- Nom/Acc/Voc Plural: Correct base + "ές".
local nom_p_form = unaccented_base_with_t_for_plural .. "ές"
-- Genitive Plural: Correct base + "ών".
local gen_p_form = unaccented_base_with_t_for_plural .. "ών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
local function decline_noun(noun)
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = decline_noun(noun) -- Get the declined forms.
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export -- Add this line
dwl430loj6ysaxy0d2sxl79p0o4bm2u
53394
53393
2025-07-04T14:09:23Z
Steborce
2506
53394
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις. Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων. Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων. Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Specific rule for vocative and accusative singular of proparoxytone -μα nouns
-- For "αίτημα", the accusative and vocative singular are unaccented.
if accent_pos == 3 and noun == "αίτημα" then
forms.voc_s = strip_tonos(noun) -- "αιτημα"
forms.acc_s = strip_tonos(noun) -- "αιτημα"
end
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(strip_tonos(noun), 1, -3) -- Should yield "διευθυντ"
-- Nom/Acc/Voc Plural: Correct base + "ές".
local nom_p_form = unaccented_base_with_t_for_plural .. "ές"
-- Genitive Plural: Correct base + "ών".
local gen_p_form = unaccented_base_with_t_for_plural .. "ών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
local function decline_noun(noun)
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = decline_noun(noun) -- Get the declined forms.
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
18mo79jz5ntqwuoh4tn2duaw9xt1n3h
53404
53394
2025-07-04T14:30:22Z
Steborce
2506
53404
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις. Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων. Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων. Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Specific rule for vocative and accusative singular of proparoxytone -μα nouns
-- For "αίτημα", the accusative and vocative singular are unaccented.
if accent_pos == 3 and noun == "αίτημα" then
forms.voc_s = strip_tonos(noun) -- "αιτημα"
forms.acc_s = strip_tonos(noun) -- "αιτημα"
end
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(strip_tonos(noun), 1, -3) -- Should yield "διευθυντ"
-- Nom/Acc/Voc Plural: Correct base + "ές".
local nom_p_form = unaccented_base_with_t_for_plural .. "ές"
-- Genitive Plural: Correct base + "ών".
local gen_p_form = unaccented_base_with_t_for_plural .. "ών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
local function decline_noun(noun)
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = decline_noun(noun) -- Get the declined forms.
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
-- NEW TEST FUNCTION
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page,
-- or by invoking export.RunTests() if you have a Lua console or similar.
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αιτημα]]", voc_s = "[[αιτημα]]", -- EXPECTED "αιτημα" here (unaccented)
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected = test_case.expected
local actual = decline_noun(noun) -- Call the main declension logic
local passed = true
if not actual then
passed = false
table.insert(results, {noun = noun, case_type = "Overall", status = "FAIL", got = "Unsupported noun or pattern.", expected = "Full forms"})
else
for k, v in pairs(expected) do
if actual[k] ~= v then
passed = false
table.insert(results, {noun = noun, case_type = k, status = "FAIL", got = actual[k], expected = v})
end
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Declension Test Results\n" ..
"|-\n" ..
"! Status !! Noun !! Case !! Got !! Expected\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\"\n"
if num_failed == 0 then
output_table = output_table .. "All declension tests passed successfully!\n"
end
return output_table
end
return export
5b24b3b77ys9qu68337glw3op7nwu80
53405
53404
2025-07-04T14:34:53Z
Steborce
2506
53405
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις. Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων. Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων. Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Specific rule for vocative and accusative singular of proparoxytone -μα nouns
-- For "αίτημα", the accusative and vocative singular are unaccented.
if accent_pos == 3 and noun == "αίτημα" then
forms.voc_s = strip_tonos(noun) -- "αιτημα"
forms.acc_s = strip_tonos(noun) -- "αιτημα"
end
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(strip_tonos(noun), 1, -3) -- Should yield "διευθυντ"
-- Nom/Acc/Voc Plural: Correct base + "ές".
local nom_p_form = unaccented_base_with_t_for_plural .. "ές"
-- Genitive Plural: Correct base + "ών".
local gen_p_form = unaccented_base_with_t_for_plural .. "ών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
azbvti1z9n69vxawwouje1n5rqp69e0
53408
53405
2025-07-04T14:52:00Z
Steborce
2506
53408
Scribunto
text/plain
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 3) -- "ναύτες" (να-ύ-τες)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 3) -- "ναύτων" (να-ύ-των)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
8cfysggaj2fq8n1te8woav5fw9czziz
53409
53408
2025-07-04T14:53:33Z
Steborce
2506
53409
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 3) -- "ναύτες" (να-ύ-τες)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 3) -- "ναύτων" (να-ύ-των)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
-- The previous issue was that the `.. "τ"` was redundant, leading to `διευθυνττ`.
-- CORRECTED: The substring operation needs to result in the base ending in 'τ'.
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
kfvx3prauivyasnovgy769pncpyqvtr
53412
53409
2025-07-04T15:25:03Z
Steborce
2506
53412
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local stem_without_tonos = strip_tonos(stem_with_tonos)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else
gen_s = "[[" .. stem_with_tonos .. "ου]]" -- Use stem with tonos for consistency, e.g., "δώρου"
gen_p = "[[" .. stem_with_tonos .. "ων]]" -- Use stem with tonos, e.g., "δώρων"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "δρομ", "θει")
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
3y6g9phhj8p6ui514rafnc335tdxmn7
53413
53412
2025-07-04T15:26:56Z
Steborce
2506
53413
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
-- Defines the set of Greek vowels (both lowercase and uppercase) as a string for pattern matching.
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Pattern to split the word into approximate syllables.
-- It finds segments that start with non-vowels (0 or more),
-- followed by exactly one vowel (the nucleus of the syllable),
-- followed by non-vowels (0 or more).
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word -- Fallback: return original word if target syllable is out of bounds.
end
local syllable = syllables[target_index]
local changed = false
-- Apply tonos to the first accentable vowel found in the target syllable.
-- This approach simplifies accentuation for Modern Greek, assuming one accent per word.
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 3rd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 3) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
k792y068iwoll2mi03hksa4usbc5xef
53414
53413
2025-07-04T15:31:42Z
Steborce
2506
53414
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word
end
local syllable = syllables[target_index]
local changed = false
-- Prioritize diphthongs first for correct accent placement
if mw.ustring.find(syllable, "ου") and not changed then syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true end
if mw.ustring.find(syllable, "ει") and not changed then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if mw.ustring.find(syllable, "αι") and not changed then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if mw.ustring.find(syllable, "οι") and not changed then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if mw.ustring.find(syllable, "αυ") and not changed then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
if mw.ustring.find(syllable, "ευ") and not changed then syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true end
-- Then handle single vowels if no diphthong was accented
if not changed then
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
6tahwp2dim2hqw0z9w2tvsfykqbazmz
53415
53414
2025-07-04T15:37:32Z
Steborce
2506
53415
Scribunto
text/plain
local export = {}
-- Global tables for vowel and accent processing
local vowels = {["α"]=true, ["ε"]=true, ["η"]=true, ["ι"]=true, ["ο"]=true, ["υ"]=true, ["ω"]=true}
local accented_vowels = {["ά"]="α", ["έ"]="ε", ["ή"]="η", ["ί"]="ι", ["ό"]="ο", ["ύ"]="υ", ["ώ"]="ώ"}
local reverse_accented_vowels = {["α"]="ά", ["ε"]="έ", ["η"]="ή", ["ι"]="ί", ["ο"]="ό", ["υ"]="ύ", ["ω"]="ώ"}
-- Ordered by length (longest first for matching) to correctly identify diphthongs
local GREEK_VOWELS_DIPHTHONGS = {
"ου", "ευ", "αυ", "ει", "οι", "αι", "υι", -- Diphthongs
"α", "ε", "η", "ι", "ο", "υ", "ω" -- Single vowels
}
-- Helper function to clean string (trim)
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[ανθρώπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
local unaccented_word = word
for accented, unaccented in pairs(accented_vowels) do
unaccented_word = mw.ustring.gsub(unaccented_word, accented, unaccented)
end
return unaccented_word
end
-- Revised syllable tokenizer to correctly handle diphthongs
local function get_syllables(word_input)
local syllables = {}
local current_syllable = ""
local i = 1
local word_len = mw.ustring.len(word_input)
while i <= word_len do
local char = mw.ustring.sub(word_input, i, i)
local char2 = mw.ustring.sub(word_input, i, i+1)
local matched_vd = nil
local vd_len = 0
-- Check for diphthongs first (longest match)
for _, vd in ipairs(GREEK_VOWELS_DIPHTHONGS) do
if mw.ustring.len(vd) == 2 and char2 == vd then
matched_vd = vd
vd_len = 2
break
elseif mw.ustring.len(vd) == 1 and char == vd then
matched_vd = vd
vd_len = 1
break
end
end
if matched_vd then
-- If current_syllable already contains a vowel/diphthong,
-- then this new matched_vd starts a new syllable.
-- This is a simplified approach for accentuation purposes.
if mw.ustring.find(current_syllable, "[αεηιοωάέήίόύώ]") then
table.insert(syllables, current_syllable)
current_syllable = matched_vd
else
current_syllable = current_syllable .. matched_vd
end
i = i + vd_len
else
-- It's a consonant or an unrecognized character
current_syllable = current_syllable .. char
i = i + 1
end
end
if current_syllable ~= "" then
table.insert(syllables, current_syllable)
end
return syllables
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
-- First, remove any existing accents from the input word
local unaccented_word = strip_tonos(word)
local syllables = get_syllables(unaccented_word) -- Use the new, robust syllable splitter
local num_syllables = #syllables
local accent_syllable_index = num_syllables - target_syllable_from_end + 1
-- Ensure index is within bounds
if accent_syllable_index < 1 then accent_syllable_index = 1 end
if accent_syllable_index > num_syllables then accent_syllable_index = num_syllables end
local accented_syllables = {}
for i, syllable_content in ipairs(syllables) do
if i == accent_syllable_index then
local changed = false
-- Apply accent to diphthongs first
-- Ordered by length (longest first) to avoid partial matches
local DiphthongAccentMap = {
["ου"] = "ού", ["ευ"] = "εύ", ["αυ"] = "αύ",
["ει"] = "εί", ["οι"] = "οί", ["αι"] = "αί", ["υι"] = "υί"
}
for diphthong, accented_diphthong in pairs(DiphthongAccentMap) do
-- Use plain=true for literal string matching in mw.ustring.find
if mw.ustring.find(syllable_content, diphthong, 1, true) then
syllable_content = mw.ustring.gsub(syllable_content, diphthong, accented_diphthong, 1)
changed = true
break -- Accent applied, no need to check other diphthongs
end
end
-- If no diphthong was accented, accent the last single vowel
if not changed then
local last_vowel_pos = nil
for k = mw.ustring.len(syllable_content), 1, -1 do
local char = mw.ustring.sub(syllable_content, k, k)
if vowels[char] then
last_vowel_pos = k
break
end
end
if last_vowel_pos then
syllable_content = mw.ustring.sub(syllable_content, 1, last_vowel_pos - 1) ..
reverse_accented_vowels[mw.ustring.sub(syllable_content, last_vowel_pos, last_vowel_pos)] ..
mw.ustring.sub(syllable_content, last_vowel_pos + 1)
end
end
end
table.insert(accented_syllables, syllable_content)
end
return table.concat(accented_syllables)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function get_accented_syllable_from_end(word)
local syllables = get_syllables(word) -- Use the new, robust syllable splitter
local num_syllables = #syllables
for i, syllable_content in ipairs(syllables) do
if mw.ustring.find(syllable_content, "[άέήίόύώ]") then -- Check for any accented vowel in the syllable
return num_syllables - i + 1 -- Return position from the end
end
end
-- Fallback: if no accent is explicitly found (e.g., monosyllabic words or words where accent is not written)
-- For Greek, this is usually on the second-to-last or last, depending on the rules.
-- For base nouns, assume proparoxytone or paroxytone if no accent is marked.
-- A safe default for these cases would be to assume the original accent position if no explicit accent is found,
-- or the second-to-last syllable for general purposes if unsure.
-- Since we expect base nouns to have accents, a return of 1 here means last syllable.
-- For 'δέντρο', 'δώρο', 'έγγραφο', an accent should be present.
return 1 -- Default to last syllable from the end if no accent found (e.g., monosyllabic)
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = mw.ustring.sub(noun, 1, -2) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = mw.ustring.sub(noun, 1, -2) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = get_accented_syllable_from_end(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = mw.ustring.sub(noun, 1, -3) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Neuter nouns ending in -ο (e.g., "δέντρο", "δώρο", "έγγραφο")
local function decline_neuter_o(noun)
local forms = {}
local stem = mw.ustring.sub(noun, 1, -2) -- Remove the -ο ending
-- Determine the accent position of the base noun
local base_noun_accent_from_end = get_accented_syllable_from_end(noun)
-- Nom S is the noun itself
forms.nom_s = "[[" .. noun .. "]]"
-- Acc S same as Nom S
forms.acc_s = "[[" .. noun .. "]]"
-- Voc S same as Nom S
forms.voc_s = "[[" .. noun .. "]]"
-- Gen S: stem + "ου"
local gen_s_base = stem .. "ου"
forms.gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, base_noun_accent_from_end) .. "]]" -- Use original accent position
-- Nom P: stem + "α"
local nom_p_base = stem .. "α"
forms.nom_p = "[[" .. add_tonos_to_syllable(nom_p_base, base_noun_accent_from_end) .. "]]"
-- Acc P: same as Nom P
forms.acc_p = forms.nom_p
-- Voc P: same as Nom P
forms.voc_p = forms.nom_p
-- Gen P: stem + "ων"
local gen_p_base = stem .. "ων"
forms.gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, base_noun_accent_from_end) .. "]]"
return forms
end
-- Main function to decline a noun based on its ending
function export.decline_noun(noun)
local cleaned_noun = clean(noun)
if cleaned_noun == "" then return nil end
-- Check irregular nouns first
if irregular_nouns[cleaned_noun] then
return irregular_nouns[cleaned_noun]
end
local ending1 = mw.ustring.sub(cleaned_noun, -1)
local ending2 = mw.ustring.sub(cleaned_noun, -2)
local ending3 = mw.ustring.sub(cleaned_noun, -3)
-- Specific checks for -μα nouns (neuter)
if ending2 == "μα" then
return decline_neuter_ma(cleaned_noun)
end
-- Specific checks for -ος nouns (masculine and some feminine/neuter)
if ending2 == "ος" or ending2 == "ός" then -- Handle masculine -ος/-ός nouns
-- This part is not fully implemented in the provided snippets.
-- For the scope of the current problem, we are focusing on neuter -ο
-- and assuming other masculine/feminine patterns are handled or will be added.
return nil -- Or call a specific decline_masc_os function if available
elseif ending2 == "ας" or ending2 == "άς" then -- Handle masculine -ας/-άς nouns
-- Similarly, this would call a decline_masc_as function
return nil
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
-- Similarly, this would call a decline_masc_is function
return nil
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(cleaned_noun)
elseif ending1 == "ο" then
return decline_neuter_o(cleaned_noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
-- This would call a decline_fem_stressed_eta function
return nil
elseif ending1 == "α" then
return decline_fem_a(cleaned_noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(cleaned_noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\\n" ..
"! Падеж !! Еднина !! Множина\\n" ..
"|-\\n|'''Номинатив'''||" .. forms.nom_s .. "||" .. forms.nom_p .. "\\n" ..
"|-\\n|'''Генитив'''||" .. forms.gen_s .. "||" .. forms.gen_p .. "\\n" ..
"|-\\n|'''Ак.тив'''||" .. forms.acc_s .. "||" .. forms.acc_p .. "\\n" ..
"|-\\n|'''Вокатив'''||" .. forms.voc_s .. "||" .. forms.voc_p .. "\\n" ..
"|}"
return output
end
return export
efqcjm1ry03ql93oq9ikmvy2et08tr2
53419
53415
2025-07-04T15:53:10Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53415|53415]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53419
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word
end
local syllable = syllables[target_index]
local changed = false
-- Prioritize diphthongs first for correct accent placement
if mw.ustring.find(syllable, "ου") and not changed then syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true end
if mw.ustring.find(syllable, "ει") and not changed then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if mw.ustring.find(syllable, "αι") and not changed then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if mw.ustring.find(syllable, "οι") and not changed then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if mw.ustring.find(syllable, "αυ") and not changed then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
if mw.ustring.find(syllable, "ευ") and not changed then syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true end
-- Then handle single vowels if no diphthong was accented
if not changed then
if mw.ustring.find(syllable, "α") and not changed then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if mw.ustring.find(syllable, "ε") and not changed then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
if mw.ustring.find(syllable, "η") and not changed then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
if mw.ustring.find(syllable, "ι") and not changed then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
if mw.ustring.find(syllable, "ο") and not changed then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
if mw.ustring.find(syllable, "υ") and not changed then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
if mw.ustring.find(syllable, "ω") and not changed then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
6tahwp2dim2hqw0z9w2tvsfykqbazmz
53421
53419
2025-07-04T16:17:46Z
Steborce
2506
53421
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word
end
local syllable = syllables[target_index]
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
kdlqlzqywy51apqxl40uqgl6l6s4z01
53422
53421
2025-07-04T16:23:09Z
Steborce
2506
53422
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
-- >>> INSERT PRINT STATEMENTS HERE <<<
print("--- Debugging add_tonos_to_syllable ---")
print("Input word: " .. word .. ", target_syllable_from_end: " .. target_syllable_from_end)
print("Identified syllables:")
for i, s in ipairs(syllables) do
print(" [" .. i .. "] " .. s)
end
-----------------------------------------
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
return word
end
local syllable = syllables[target_index]
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
icftd9ovhkwg26fqq30d5lh32i916cd
53423
53422
2025-07-04T21:35:26Z
Steborce
2506
53423
Scribunto
text/plain
local export = {}
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
-- >>> Debugging statements using mw.log() <<<
mw.log("--- Debugging add_tonos_to_syllable ---")
mw.log("Input word: " .. word .. ", target_syllable_from_end: " .. target_syllable_from_end)
mw.log("Identified syllables:")
for i, s in ipairs(syllables) do
mw.log(" [" .. i .. "] " .. s)
end
-----------------------------------------
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
mw.log("Error: Target syllable index out of bounds. Returning original word.") -- Debug
return word
end
local syllable = syllables[target_index]
-- >>> Another mw.log() statement <<<
mw.log("Target index: " .. target_index .. ", Target syllable: " .. syllable)
-----------------------------------------------
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local forms = export.decline_noun(noun) -- Call the exported decline_noun function
if not forms then
return "Unsupported noun or pattern." -- Message if declension fails.
end
-- Construct the wikitable output string.
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
ip0r5hugihg0op4v1ice89q3jgp9sv0
53424
53423
2025-07-04T21:49:27Z
Steborce
2506
53424
Scribunto
text/plain
local export = {}
local debug_messages = {}
local function debug_log(message)
table.insert(debug_messages, message)
end
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
-- >>> Debugging statements using debug_log() <<<
debug_log("--- Debugging add_tonos_to_syllable ---")
debug_log("Input word: " .. word .. ", target_syllable_from_end: " .. target_syllable_from_end)
debug_log("Identified syllables:")
for i, s in ipairs(syllables) do
debug_log(" [" .. i .. "] " .. s)
end
-----------------------------------------
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
debug_log("Error: Target syllable index out of bounds. Returning original word.") -- Debug
return word
end
local syllable = syllables[target_index]
-- >>> Another debug_log() statement <<<
debug_log("Target index: " .. target_index .. ", Target syllable: " .. syllable)
-----------------------------------------------
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun) -- Changed to export.decline_noun
noun = clean(noun)
if irregular_nouns[noun] then
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
return decline_neuter_i(noun)
elseif ending1 == "ο" then
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
return decline_fem_i(noun)
else
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local debug_mode = args.debug -- Check for a 'debug' argument
-- Reset debug messages for each invocation
debug_messages = {}
local forms = export.decline_noun(noun)
if not forms then
debug_log("Unsupported noun or pattern for: " .. noun) -- Log this too
return "Unsupported noun or pattern."
end
-- If debug_mode is active, return the debug messages
if debug_mode then
return "<pre>" .. table.concat(debug_messages, "\n") .. "</pre>"
end
-- Otherwise, return the normal output
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
end
return export
ctrbftcz8o2mccu0uxjed5x5pl7l99a
53427
53424
2025-07-04T21:56:52Z
Steborce
2506
53427
Scribunto
text/plain
local export = {}
local debug_messages = {}
local function debug_log(message)
table.insert(debug_messages, message)
end
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
debug_log("--- Debugging add_tonos_to_syllable ---")
debug_log("Input word: " .. word .. ", target_syllable_from_end: " .. target_syllable_from_end)
debug_log("Identified syllables:")
for i, s in ipairs(syllables) do
debug_log(" [" .. i .. "] " .. s)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
debug_log("Error: Target syllable index out of bounds. Returning original word.") -- Debug
return word
end
local syllable = syllables[target_index]
debug_log("Target index: " .. target_index .. ", Target syllable: " .. syllable)
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 2) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant_stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun)
debug_log("decline_noun called for: " .. noun) -- Added debug
noun = clean(noun)
debug_log("Cleaned noun: " .. noun) -- Added debug
if irregular_nouns[noun] then
debug_log("Matched irregular noun: " .. noun) -- Added debug
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
debug_log("Ending1: '" .. ending1 .. "', Ending2: '" .. ending2 .. "', Ending3: '" .. ending3 .. "'") -- Added debug
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
debug_log("Matched ending: -μα")
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
debug_log("Matched ending: -ός")
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
debug_log("Matched ending: -ος")
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
debug_log("Matched ending: -έας")
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
debug_log("Matched ending: -ας")
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
debug_log("Matched ending: -ης/-ής")
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
debug_log("Matched ending: -ι/-ί")
return decline_neuter_i(noun)
elseif ending1 == "ο" then
debug_log("Matched ending: -ο") -- This is the expected path for 'έγγραφο'
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
debug_log("Matched ending: -ή")
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
debug_log("Matched ending: -α")
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
debug_log("Matched ending: -η")
return decline_fem_i(noun)
else
debug_log("No matching regular pattern found for: " .. noun) -- This message will be logged if no rule matches
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local debug_mode = args.debug -- Check for a 'debug' argument. This will be "1" if used.
-- Reset debug messages for each invocation
debug_messages = {}
debug_log("DeclineNoun function called. Noun: " .. noun .. ", Debug mode argument: " .. tostring(debug_mode))
local forms = export.decline_noun(noun)
if not forms then
-- This message is logged if the noun is not supported by decline_noun
debug_log("Final result: Unsupported noun or pattern for: " .. noun)
-- If debug mode is active, the following block will override the "Unsupported..." string.
-- If debug mode is NOT active, it will return "Unsupported..." directly.
end
-- If debug_mode is active (e.g., args.debug is "1"), return the collected debug messages.
-- Lua treats non-nil and non-false values (like the string "1") as true.
if debug_mode then
return "<pre>" .. table.concat(debug_messages, "\n") .. "</pre>"
end
-- Otherwise (if debug_mode is not active AND forms were found), return the normal output.
if forms then
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
else
-- This path is taken if forms is nil AND debug_mode is not active.
return "Unsupported noun or pattern."
end
end
return export
2y5tk2wwzkcmdiluv67z2hrr97ts6ur
53429
53427
2025-07-04T22:15:22Z
Steborce
2506
53429
Scribunto
text/plain
local export = {}
local debug_messages = {}
local function debug_log(message)
table.insert(debug_messages, message)
end
local function clean(str)
return mw.text.trim(str or "")
end
-- Irregular noun dictionary.
-- These nouns do not follow regular patterns
-- and must be defined manually.
local irregular_nouns = {
["άνθρωπος"] = { -- man, human (masculine -ος, but irregular)
nom_s = "[[άνθρωπος]]",
gen_s = "[[ανθρώπου]]",
acc_s = "[[άνθρωπο]]",
voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]",
gen_p = "[[ανθρώπων]]",
acc_p = "[[άνθρωπους]]",
voc_p = "[[άνθρωποι]]"
},
["πατέρας"] = { -- father (masculine -ας, but irregular)
nom_s = "[[πατέρας]]",
gen_s = "[[πατέρα]]",
acc_s = "[[πατέρα]]",
voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]",
gen_p = "[[πατέρων]]",
acc_p = "[[πατέρες]]",
voc_p = "[[πατέρες]]"
},
["θεός"] = { -- god (masculine -ος, highly irregular)
nom_s = "[[θεός]]",
gen_s = "[[θεού]]",
acc_s = "[[θεό]]",
voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]",
gen_p = "[[θεών]]",
acc_p = "[[θεούς]]",
voc_p = "[[θεοί]]"
},
["δίκτυο"] = { -- network (neuter -ο, irregular accent shift)
nom_s = "[[δίκτυο]]",
gen_s = "[[δικτύου]]",
acc_s = "[[δίκτυο]]",
voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]",
gen_p = "[[δικτύων]]",
acc_p = "[[δίκτυα]]",
voc_p = "[[δίκτυα]]"
}
}
-- Helper function to remove tonos (accent marks) from a word.
-- Used to get a "base" form before applying new accentuation.
local function strip_tonos(word)
word = mw.ustring.gsub(word, "ά", "α")
word = mw.ustring.gsub(word, "έ", "ε")
word = mw.ustring.gsub(word, "ή", "η")
word = mw.ustring.gsub(word, "ί", "ι")
word = mw.ustring.gsub(word, "ό", "ο")
word = mw.ustring.gsub(word, "ύ", "υ")
word = mw.ustring.gsub(word, "ώ", "ω")
return word
end
-- Helper function to add a tonos (accent mark) to a specific syllable
-- from the end of a word.
-- @param word string: The word to accent.
-- @param target_syllable_from_end number: 1 for last, 2 for second to last, etc.
-- @return string: The word with the accent applied to the target syllable.
local function add_tonos_to_syllable(word, target_syllable_from_end)
local syllables = {}
local greek_vowels_str = "αεηιουωΑΕΗΙΟΥΩ"
-- Original robust syllabification pattern from script.txt
for syll in mw.ustring.gmatch(word, "[^" .. greek_vowels_str .. "]*[" .. greek_vowels_str .. "][^" .. greek_vowels_str .. "]*") do
table.insert(syllables, syll)
end
debug_log("--- Debugging add_tonos_to_syllable ---")
debug_log("Input word: " .. word .. ", target_syllable_from_end: " .. target_syllable_from_end)
debug_log("Identified syllables:")
for i, s in ipairs(syllables) do
debug_log(" [" .. i .. "] " .. s)
end
local target_index = #syllables - target_syllable_from_end + 1
if target_index < 1 or target_index > #syllables then
debug_log("Error: Target syllable index out of bounds. Returning original word.") -- Debug
return word
end
local syllable = syllables[target_index]
debug_log("Target index: " .. target_index .. ", Target syllable: " .. syllable)
local changed = false
-- Prioritize specific diphthongs where the accent falls on the first vowel (like ου, ευ)
-- This handles cases where the target syllable itself contains 'ου' or 'ευ'
-- and it should be accented as 'ού' or 'εύ'.
if mw.ustring.find(syllable, "ού") then -- Check if already accented 'ού'
changed = true
elseif mw.ustring.find(syllable, "εύ") then -- Check if already accented 'εύ'
changed = true
elseif mw.ustring.find(syllable, "ου") and not changed then
syllable = mw.ustring.gsub(syllable, "ου", "ού", 1); changed = true
elseif mw.ustring.find(syllable, "ευ") and not changed then
syllable = mw.ustring.gsub(syllable, "ευ", "εύ", 1); changed = true
end
-- Standard diphthongs accenting on the second vowel if it's the target syllable
if not changed then
if mw.ustring.find(syllable, "ει") then syllable = mw.ustring.gsub(syllable, "ει", "εί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αι") then syllable = mw.ustring.gsub(syllable, "αι", "αί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "οι") then syllable = mw.ustring.gsub(syllable, "οι", "οί", 1); changed = true end
if not changed and mw.ustring.find(syllable, "αυ") then syllable = mw.ustring.gsub(syllable, "αυ", "αύ", 1); changed = true end
end
-- Then handle single vowels if no diphthong was accented
if not changed then
-- It's important to replace the UNACCENTED vowel.
-- Order matters here: prefer replacing the first vowel found if multiple options.
-- This sequence tries to match from left to right within the syllable.
if mw.ustring.find(syllable, "ά") then changed = true -- Already accented
elseif mw.ustring.find(syllable, "α") then syllable = mw.ustring.gsub(syllable, "α", "ά", 1); changed = true end
if not changed then
if mw.ustring.find(syllable, "έ") then changed = true
elseif mw.ustring.find(syllable, "ε") then syllable = mw.ustring.gsub(syllable, "ε", "έ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ή") then changed = true
elseif mw.ustring.find(syllable, "η") then syllable = mw.ustring.gsub(syllable, "η", "ή", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ί") then changed = true
elseif mw.ustring.find(syllable, "ι") then syllable = mw.ustring.gsub(syllable, "ι", "ί", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ό") then changed = true
elseif mw.ustring.find(syllable, "ο") then syllable = mw.ustring.gsub(syllable, "ο", "ό", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ύ") then changed = true
elseif mw.ustring.find(syllable, "υ") then syllable = mw.ustring.gsub(syllable, "υ", "ύ", 1); changed = true end
end
if not changed then
if mw.ustring.find(syllable, "ώ") then changed = true
elseif mw.ustring.find(syllable, "ω") then syllable = mw.ustring.gsub(syllable, "ω", "ώ", 1); changed = true end
end
end
syllables[target_index] = syllable
return table.concat(syllables)
end
-- Helper: removes 'length' characters from the end of a noun to get its stem.
-- Preserves existing tonos on the stem.
-- @param noun string: The full noun form.
-- @param length number: Number of characters to remove from the end.
-- @return string: The stem of the noun.
local function get_stem(noun, length)
return mw.ustring.sub(noun, 1, -length - 1)
end
-- Helper: Finds which syllable (from the end) has the accent in a word
-- Returns: syllable number (1 = last, 2 = second-to-last, etc.)
local function find_accent_position(word)
local vowels_and_stressed_vowels = "αεηιουωάέήίόύώ"
local syllables = {}
local accent_pos = nil
-- Split into syllables and find the accented one
for syll in mw.ustring.gmatch(word, "[^" .. vowels_and_stressed_vowels .. "]*[" .. vowels_and_stressed_vowels .. "][^" .. vowels_and_stressed_vowels .. "]*") do
table.insert(syllables, syll)
if mw.ustring.find(syll, "[άέήίόύώ]") then
accent_pos = #syllables -- Position from the start
end
end
-- Convert to position from the end (default to 2 if no accent found)
return accent_pos and (#syllables - accent_pos + 1) or 2
end
-- Declension function for Feminine nouns ending in -η (e.g., "διεύθυνση")
-- This function is for nouns where the singular accent is NOT on the final 'η'.
local function decline_fem_i(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'η', keeps accent (e.g., "διεύθυνσ")
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "διευθυνσ")
-- Nom/Acc/Voc Plural: base stem + εις.
-- Accent on 3rd syllable from end (common pattern).
local base_nom_acc_voc_plural = stem_without_tonos .. "εις"
local nom_acc_voc_plural = add_tonos_to_syllable(base_nom_acc_voc_plural, 3)
-- Genitive Plural: base stem + εων.
-- Accent on 3rd syllable from end (common pattern).
local base_gen_plural = stem_without_tonos .. "εων"
local gen_plural = add_tonos_to_syllable(base_gen_plural, 3)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_with_tonos .. "ης]]", -- e.g. διεύθυνσης
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_plural .. "]]",
gen_p = "[[" .. gen_plural .. "]]",
acc_p = "[[" .. nom_acc_voc_plural .. "]]",
voc_p = "[[" .. nom_acc_voc_plural .. "]]"
}
end
-- Declension function for Feminine nouns ending in -α (e.g., "αλληλογραφία")
local function decline_fem_a(noun)
local stem_with_tonos = get_stem(noun, 1) -- Removes 'α', keeps existing accent (e.g., "αλληλογραφί")
-- Corrected stem for ιών ending: remove last 2 chars (ία) and get unaccented base
local base_stem_for_ion = mw.ustring.sub(strip_tonos(noun), 1, -3) -- e.g., "αλληλογραφ" from "αλληλογραφία"
-- Singular forms
local gen_s_form = stem_with_tonos .. "ας"
-- Plural forms
-- Nom/Acc/Voc Plural: For -α nouns, often the accent remains on the same syllable as singular stem.
local nom_acc_voc_p = stem_with_tonos .. "ες" -- (e.g., "αλληλογραφί" + "ες" -> "αλληλογραφίες")
-- Genitive Plural: base stem + ων.
-- Accent *always* on the last syllable (ών).
local gen_p = base_stem_for_ion .. "ιών" -- (e.g., "αλληλογραφιών", "συνομιλιών")
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Neuter nouns ending in -μα (general pattern)
local function decline_neuter_ma(noun)
local forms = {}
forms.nom_s = noun
forms.acc_s = noun -- Default, might be overridden for specific cases
forms.voc_s = noun -- Default, might be overridden for specific cases
-- 1. Get the original stem (remove -μα) and its unaccented version
local original_stem_for_analysis = mw.ustring.sub(noun, 1, -3) -- e.g., "αιτη" from "αίτημα"
local unaccented_original_stem = strip_tonos(original_stem_for_analysis)
-- 2. Determine accent position in the nominative singular
local accent_pos = find_accent_position(noun) -- 3 for proparoxytone like αίτημα, σύστημα, etc.
-- Handle Genitive Singular
local gen_s_base_word = unaccented_original_stem .. "ματ" .. "ος" -- e.g., "αιτηματος"
if accent_pos == 3 then -- If proparoxytone (accent on 3rd from end in NOM S)
-- Accent shifts to the 2nd syllable from the start (or 3rd from end) of the GEN S word.
-- For a word like "αιτηματος" (αι-τη-μα-τος), the target is 'τη'.
forms.gen_s = add_tonos_to_syllable(gen_s_base_word, 3) -- Place accent on 3rd syllable from end
else -- Otherwise, accent stays on the original stem position (e.g. πράγμα -> πράγματος)
local stem_with_original_accent = get_stem(noun, 2) -- "πράγμ" from "πράγμα"
forms.gen_s = stem_with_original_accent .. "ματος" -- "πράγματος"
end
-- Handle Plural Forms (Nom/Acc/Voc)
local plural_stem = unaccented_original_stem .. "ματ"
forms.nom_p = add_tonos_to_syllable(plural_stem .. "α", 3)
forms.acc_p = forms.nom_p
forms.voc_p = forms.nom_p
-- Handle Genitive Plural
forms.gen_p = unaccented_original_stem .. "μάτων"
-- Add wikilinks
for k, v in pairs(forms) do
forms[k] = "[[" .. v .. "]]"
end
return forms
end
-- Declension for Neuter nouns ending in -ι / -ί (e.g., "παιδί", "νησί")
local function decline_neuter_i(noun)
-- For these nouns, the 'ι' is part of the changing ending.
-- We'll take the stem by removing just the final accented vowel,
-- and then append the correct accented endings explicitly.
local base_stem = mw.ustring.sub(noun, 1, -2) -- Gets "παιδ" from "παιδί", "νησ" from "νησί"
-- Singular Forms
local gen_s_form = base_stem .. "ιού" -- Correctly forms "παιδιού", "νησιού"
-- Plural Forms
local nom_acc_voc_p = base_stem .. "ιά" -- Correctly forms "παιδιά", "νησιά"
local gen_p = base_stem .. "ιών" -- Correctly forms "παιδιών", "νησιών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Updated decline_neuter_o function
local function decline_neuter_o(noun)
local stem_with_tonos = get_stem(noun, 1)
local unaccented_noun = strip_tonos(noun)
local is_io_ending_noun = mw.ustring.sub(unaccented_noun, -2) == "ιο"
local ends_in_eio_ending = mw.ustring.sub(unaccented_noun, -3) == "ειο"
local base_stem_for_genitive -- This will be the pure root before the 'ι' or 'ει'
if ends_in_eio_ending then -- For words like σχολείο, δάνειο, στοιχείο (unaccented ends in "ειο")
-- To get the stem (e.g., "σχολ" from "σχολειο"), remove the last 3 characters "ειο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -4)
elseif is_io_ending_noun then -- For words like βιβλίο, σενάριο (unaccented ends in "ιο" but NOT "ειο")
-- To get the stem (e.g., "βιβλ" from "βιβλιο"), remove the last 2 characters "ιο".
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -3)
else -- General -ο nouns like δώρο (unaccented ends in "ο")
base_stem_for_genitive = mw.ustring.sub(unaccented_noun, 1, -2) -- remove -ο
end
local gen_s, gen_p
if ends_in_eio_ending then
gen_s = "[[" .. base_stem_for_genitive .. "είου]]" -- e.g., "σχολ" + "είου" = "σχολείου"
gen_p = "[[" .. base_stem_for_genitive .. "είων]]" -- e.g., "σχολ" + "είων" = "σχολείων"
elseif is_io_ending_noun then
gen_s = "[[" .. base_stem_for_genitive .. "ίου]]" -- e.g., "βιβλ" + "ίου" = "βιβλίου"
gen_p = "[[" .. base_stem_for_genitive .. "ίων]]" -- e.g., "βιβλ" + "ίων" = "βιβλίων"
else -- Corrected logic for general -ο nouns like "έγγραφο", "δώρο"
local unaccented_stem = base_stem_for_genitive -- "εγγραφ" for "έγγραφο"
-- Genitive Singular: unaccented stem + "ου", accent on 2nd from end (εγγράφου)
local gen_s_base = unaccented_stem .. "ου"
gen_s = "[[" .. add_tonos_to_syllable(gen_s_base, 3) .. "]]"
-- Genitive Plural: unaccented stem + "ων", accent on 2nd from end (εγγράφων)
local gen_p_base = unaccented_stem .. "ων"
gen_p = "[[" .. add_tonos_to_syllable(gen_p_base, 2) .. "]]"
end
local nom_acc_voc_p = "[[" .. stem_with_tonos .. "α]]"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = gen_s,
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = nom_acc_voc_p,
gen_p = gen_p,
acc_p = nom_acc_voc_p,
voc_p = nom_acc_voc_p
}
end
-- Declension for Masculine nouns ending in -ος (e.g., "δρόμος", "κήπος", "θείος")
local function decline_masc_os(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ος', e.g., "δρόμ", "θεί"
-- Singular Forms
local gen_s_form = stem_with_tonos .. "ου" -- "δρόμου", "θείου"
local acc_s_form = stem_with_tonos .. "ο" -- "δρόμο", "θείο"
local voc_s_form = stem_with_tonos .. "ε" -- "δρόμε", "θείε"
-- Plural Forms
local nom_voc_p = stem_with_tonos .. "οι" -- "δρόμοι", "θείοι" (accent usually stays)
local acc_p = stem_with_tonos .. "ους" -- "δρόμους", "θείους" (accent usually stays)
local gen_p = stem_with_tonos .. "ων" -- "δρόμων", "θείων" (accent usually stays)
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in -ας (e.g., "ταμίας", "αγρότης" - though -ης, keep for this category example)
local function decline_masc_as(noun)
local stem_with_tonos = get_stem(noun, 2) -- Removes 'ας', e.g., "ταμί"
local stem_without_tonos = strip_tonos(stem_with_tonos) -- (e.g., "ταμι")
-- Singular Forms
-- Nom: noun
-- Gen/Acc/Voc: stem + α (e.g., ταμία)
local gen_acc_voc_s = stem_with_tonos .. "α"
-- Plural forms
-- Nom/Acc/Voc Plural: stem + ες (e.g., ταμίες)
local nom_acc_voc_p = stem_with_tonos .. "ες"
-- Genitive Plural: stem + ών (e.g., ταμιών)
local gen_p = stem_without_tonos .. "ών" -- Accent is typically on the 'ών' ending
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s .. "]]",
acc_s = "[[" .. gen_acc_voc_s .. "]]",
voc_s = "[[" .. gen_acc_voc_s .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Declension for Masculine nouns ending in stressed -έας (e.g., "διερμηνέας")
local function decline_masc_eas(noun)
-- Corrected base_stem derivation: remove 'νεας' (4 characters) from the unaccented noun.
local base_stem = mw.ustring.sub(strip_tonos(noun), 1, -5) -- e.g., "διερμη" from "διερμηνέας"
-- Singular Forms
local gen_acc_voc_s_form = base_stem .. "νέα" -- "διερμηνέα"
-- Plural Forms
local nom_acc_voc_p_form = base_stem .. "νείς" -- "διερμηνείς"
local gen_p_form = base_stem .. "νέων" -- "διερμηνέων"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_acc_voc_s_form .. "]]",
acc_s = "[[" .. gen_acc_voc_s_form .. "]]",
voc_s = "[[" .. gen_acc_voc_s_form .. "]]",
nom_p = "[[" .. nom_acc_voc_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_acc_voc_p_form .. "]]",
voc_p = "[[" .. nom_acc_voc_p_form .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in -ης / -ής (e.g., "διευθυντής", "καθηγητής")
local function decline_masc_is(noun)
-- Singular forms (gen_s, acc_s, voc_s are same as noun without final 'ς')
local stem_for_singular = mw.ustring.sub(noun, 1, -2) -- e.g., "διευθυντή" from "διευθυντής"
local unaccented_noun = strip_tonos(noun)
local accent_pos = find_accent_position(noun) -- Get original accent position
local nom_p_form
local gen_p_form
-- Handle -της (paroxytone) vs -τής (oxytone) plural accentuation
if accent_pos == 2 then -- Noun is paroxytone (accent on second-to-last syllable), e.g., "ναύτης"
-- Stem for plural: remove 'ης', then add 'τ' and apply accent to third-to-last syllable of full word
local base_stem_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- "ναυτ" from "ναύτης" -> "ναυτ"
nom_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ες", 2) -- Corrected for "ναύτες" (accent on 2nd from end)
gen_p_form = add_tonos_to_syllable(base_stem_for_plural .. "ων", 1) -- Corrected for "ναυτών" (accent on 1st from end)
else -- Noun is oxytone (accent on last syllable), e.g., "διευθυντής"
-- For plural forms, take the unaccented noun and remove the final 3 chars (ης/ής)
-- This gets the actual root (e.g., "διευθυ" from "διευθυντής")
local unaccented_base_with_t_for_plural = mw.ustring.sub(unaccented_noun, 1, -3) -- Should yield "διευθυντ"
nom_p_form = unaccented_base_with_t_for_plural .. "ές"
gen_p_form = unaccented_base_with_t_for_plural .. "ών"
end
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. stem_for_singular .. "]]",
acc_s = "[[" .. stem_for_singular .. "]]",
voc_s = "[[" .. stem_for_singular .. "]]",
nom_p = "[[" .. nom_p_form .. "]]",
gen_p = "[[" .. gen_p_form .. "]]",
acc_p = "[[" .. nom_p_form .. "]]",
voc_p = "[[" .. nom_p_form .. "]]"
}
end
-- Declension for Feminine nouns ending in stressed -ή (e.g., "προβολή", "ψυχή")
local function decline_fem_stressed_eta(noun)
-- Get the stem by removing the final character (ή), which will result in an unaccented stem.
local base_stem = mw.ustring.sub(noun, 1, -2) -- e.g., "προβολ" from "προβολή"
-- Singular Forms: Accent is on the final syllable.
local gen_s_form = base_stem .. "ής" -- "προβολής"
-- Plural Forms: Accent shifts to the last syllable (ές, ών).
local nom_acc_voc_p = base_stem .. "ές" -- "προβολές"
local gen_p = base_stem .. "ών" -- "προβολών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. noun .. "]]",
voc_s = "[[" .. noun .. "]]",
nom_p = "[[" .. nom_acc_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. nom_acc_voc_p .. "]]",
voc_p = "[[" .. nom_acc_voc_p .. "]]"
}
end
-- Revised Declension for Masculine nouns ending in stressed -ός (e.g., "χριστιανός")
-- Note: "θεός" is now handled as an irregular noun.
local function decline_masc_stressed_os(noun)
local base_consonant_stem -- This will be the pure consonant root (e.g., "χριστιαν")
-- For "χριστιανός", the base consonant_stem is fixed.
if noun == "χριστιανός" then
base_consonant_stem = "χριστιαν"
else
-- Fallback for other stressed -ος nouns (excluding θεός, which is now irregular).
-- This removes 'ός' to get to the base consonant stem.
base_consonant_stem = mw.ustring.sub(strip_tonos(noun), 1, -3)
end
-- Singular Forms (Direct construction with pre-accented endings)
local gen_s_form = base_consonant_stem .. "ού" -- "χριστιανού"
local acc_s_form = base_consonant_stem .. "ό" -- "χριστιανό
local voc_s_form = base_consonant_stem .. "έ" -- "χριστιανέ"
-- Plural Forms (Direct construction with pre-accented endings)
local nom_voc_p = base_consonant_stem .. "οί" -- "χριστιανοί"
local acc_p = base_consonant_stem .. "ούς" -- "χριστιανούς"
local gen_p = base_consonant_stem .. "ών" -- "χριστιανών"
return {
nom_s = "[[" .. noun .. "]]",
gen_s = "[[" .. gen_s_form .. "]]",
acc_s = "[[" .. acc_s_form .. "]]",
voc_s = "[[" .. voc_s_form .. "]]",
nom_p = "[[" .. nom_voc_p .. "]]",
gen_p = "[[" .. gen_p .. "]]",
acc_p = "[[" .. acc_p .. "]]",
voc_p = "[[" .. nom_voc_p .. "]]"
}
end
-- Dispatcher function: determines the correct declension function based on noun ending.
function export.decline_noun(noun)
debug_log("decline_noun called for: " .. noun) -- Added debug
noun = clean(noun)
debug_log("Cleaned noun: " .. noun) -- Added debug
if irregular_nouns[noun] then
debug_log("Matched irregular noun: " .. noun) -- Added debug
return irregular_nouns[noun]
end
local ending3 = mw.ustring.sub(noun, -3) -- Last three characters
local ending2 = mw.ustring.sub(noun, -2) -- Last two characters
local ending1 = mw.ustring.sub(noun, -1) -- Last character
debug_log("Ending1: '" .. ending1 .. "', Ending2: '" .. ending2 .. "', Ending3: '" .. ending3 .. "'") -- Added debug
-- Order of checks matters: check longer endings or more specific cases first.
if ending2 == "μα" then
debug_log("Matched ending: -μα")
return decline_neuter_ma(noun)
elseif ending2 == "ός" then -- Check for stressed 'ός' specifically
debug_log("Matched ending: -ός")
return decline_masc_stressed_os(noun)
elseif ending2 == "ος" then -- Unstressed 'ος'
debug_log("Matched ending: -ος")
return decline_masc_os(noun)
elseif ending3 == "έας" then -- Check for stressed -έας using 3 chars
debug_log("Matched ending: -έας")
return decline_masc_eas(noun)
elseif ending2 == "ας" then -- General -ας (like ταμίας)
debug_log("Matched ending: -ας")
return decline_masc_as(noun)
elseif ending2 == "ης" or ending2 == "ής" then -- Handle masculine -ης/-ής nouns
debug_log("Matched ending: -ης/-ής")
return decline_masc_is(noun)
elseif ending1 == "ι" or ending1 == "ί" then
debug_log("Matched ending: -ι/-ί")
return decline_neuter_i(noun)
elseif ending1 == "ο" then
debug_log("Matched ending: -ο") -- This is the expected path for 'έγγραφο'
return decline_neuter_o(noun)
elseif ending1 == "ή" then -- Check for stressed 'ή' first, specific rule
debug_log("Matched ending: -ή")
return decline_fem_stressed_eta(noun)
elseif ending1 == "α" then
debug_log("Matched ending: -α")
return decline_fem_a(noun)
elseif ending1 == "η" then -- Unstressed 'η'
debug_log("Matched ending: -η")
return decline_fem_i(noun)
else
debug_log("No matching regular pattern found for: " .. noun) -- This message will be logged if no rule matches
return nil -- No matching regular pattern found
end
end
-- Main export function called by MediaWiki templates.
function export.DeclineNoun(frame)
local args = frame:getParent().args
local noun = clean(args[1]) -- Get the noun from the template arguments.
local debug_mode = args.debug -- Check for a 'debug' argument. This will be "1" if used.
-- Reset debug messages for each invocation
debug_messages = {}
debug_log("DeclineNoun function called. Noun: " .. noun .. ", Debug mode argument: " .. tostring(debug_mode))
local forms = export.decline_noun(noun)
if not forms then
-- This message is logged if the noun is not supported by decline_noun
debug_log("Final result: Unsupported noun or pattern for: " .. noun)
-- If debug mode is active, the following block will override the "Unsupported..." string.
-- If debug mode is NOT active, it will return "Unsupported..." directly.
end
-- If debug_mode is active (e.g., args.debug is "1"), return the collected debug messages.
-- Lua treats non-nil and non-false values (like the string "1") as true.
if debug_mode then
return "<pre>" .. table.concat(debug_messages, "\n") .. "</pre>"
end
-- Otherwise (if debug_mode is not active AND forms were found), return the normal output.
if forms then
local output = "{| class=\"wikitable\"\n" ..
"! Падеж !! Еднина !! Множина\n" ..
"|-\n|'''Номинатив''' ||" .. forms.nom_s .. "||" .. forms.nom_p ..
"\n|-\n|'''Генитив''' ||" .. forms.gen_s .. "||" .. forms.gen_p ..
"\n|-\n|'''Акузатив''' ||" .. forms.acc_s .. "||" .. forms.acc_p ..
"\n|-\n|'''Вокатив''' ||" .. forms.voc_s .. "||" .. forms.voc_p ..
"\n|}"
return output
else
-- This path is taken if forms is nil AND debug_mode is not active.
return "Unsupported noun or pattern."
end
end
return export
29q23bn14k57p0z4thnzcfbstjyf5g9
Предлошка:el-noon-conj
10
10053
53428
53152
2025-07-04T22:08:11Z
Steborce
2506
53428
wikitext
text/x-wiki
{| class="wikitable"
{{#invoke:el-noon-decl|DeclineNoun|{{{1|{{PAGENAME}}}}}}|debug={{{debug|}}}}}
|}
od29w9pmxua2rw5pqkt4y8j4riybygo
Модул:el-noon-decl-tests
828
10079
53368
53336
2025-07-04T12:15:25Z
Steborce
2506
53368
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
sbczhaj2phyrb8859w5dsab3dtv9jdp
53369
53368
2025-07-04T12:17:33Z
Steborce
2506
53369
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
grwodir1qvmnnubezmd9med1ftefgzn
53395
53369
2025-07-04T14:11:27Z
Steborce
2506
53395
Scribunto
text/plain
-- Module:el-noon-decl-tests
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Create a mock frame object for testing
local mock_frame = {
getParent = function()
return {
args = {
[1] = noun -- Simulate the first argument being the noun
}
}
end
}
-- Call DeclineNoun from the main module with the mock frame
local declined_forms = el_noon_decl.DeclineNoun(mock_frame)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p
pd4ewk3mwfjb9wz4ej02pn2uye3ls5x
53396
53395
2025-07-04T14:19:16Z
Steborce
2506
53396
Scribunto
text/plain
-- Module:el-noon-decl-tests
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Create a mock frame object for testing
local mock_frame = {
getParent = function()
return {
args = {
[1] = noun -- Simulate the first argument being the noun
}
}
end
}
local declined_forms_raw = el_noon_decl.DeclineNoun(mock_frame)
local declined_forms = {}
local skip_detailed_check = false
if type(declined_forms_raw) == 'table' then
declined_forms = declined_forms_raw
elseif type(declined_forms_raw) == 'string' then
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = "Module Return (String)",
got = declined_forms_raw,
expected = "a table of forms"
})
num_failed = num_failed + 1
total_tests = total_tests + #case_keys_order
skip_detailed_check = true -- Set flag to skip detailed checks
else -- If it's neither table nor string, it's truly nil or unexpected.
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = "Module Return (Nil/Other)",
got = tostring(declined_forms_raw),
expected = "a table of forms"
})
num_failed = num_failed + 1
total_tests = total_tests + #case_keys_order
skip_detailed_check = true -- Set flag to skip detailed checks
end
if not skip_detailed_check then
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form == nil then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = "NIL (missing form)",
expected = expected_form
})
elseif got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
local display_got = tostring(result.got or "NIL_FORM")
local display_expected = tostring(result.expected or "NIL_EXPECTED")
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. display_got ..
"|| " .. display_expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p
2x12f6610xseid4pd4u65wkrd9psnd3
53397
53396
2025-07-04T14:22:32Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53396|53396]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53397
Scribunto
text/plain
-- Module:el-noon-decl-tests
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Create a mock frame object for testing
local mock_frame = {
getParent = function()
return {
args = {
[1] = noun -- Simulate the first argument being the noun
}
}
end
}
-- Call DeclineNoun from the main module with the mock frame
local declined_forms = el_noon_decl.DeclineNoun(mock_frame)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p
pd4ewk3mwfjb9wz4ej02pn2uye3ls5x
53398
53397
2025-07-04T14:22:50Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53395|53395]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53398
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
grwodir1qvmnnubezmd9med1ftefgzn
53399
53398
2025-07-04T14:23:09Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53369|53369]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53399
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
sbczhaj2phyrb8859w5dsab3dtv9jdp
53400
53399
2025-07-04T14:23:30Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53368|53368]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53400
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αιτημα]]", voc_s = "[[αιτημα]]", -- EXPECTED "αιτημα" here (unaccented)
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "σχόλιο", expected = {
nom_s = "[[σχόλιο]]", gen_s = "[[σχολίου]]", acc_s = "[[σχόλιο]]", voc_s = "[[σχόλιο]]",
nom_p = "[[σχόλια]]", gen_p = "[[σχολίων]]", acc_p = "[[σχόλια]]", voc_p = "[[σχόλια]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "σενάριο", expected = {
nom_s = "[[σενάριο]]", gen_s = "[[σεναρίου]]", acc_s = "[[σενάριο]]", voc_s = "[[σενάριο]]",
nom_p = "[[σενάρια]]", gen_p = "[[σεναρίων]]", acc_p = "[[σενάρια]]", voc_p = "[[σενάρια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "θεμέλιο", expected = {
nom_s = "[[θεμέλιο]]", gen_s = "[[θεμελίου]]", acc_s = "[[θεμέλιο]]", voc_s = "[[θεμέλιο]]",
nom_p = "[[θεμέλια]]", gen_p = "[[θεμελίων]]", acc_p = "[[θεμέλια]]", voc_p = "[[θεμέλια]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- TEST CASE FOR διερμηνέας (now corrected)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
i0pr4cbtpys7u29n88np7h75ebznevt
53401
53400
2025-07-04T14:23:52Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53336|53336]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53401
Scribunto
text/plain
-- Module:el-noon-decl-tests
--
-- This module provides test cases for the el-noon-decl module.
local p = {} -- Main table for module functions
local el_noon_decl = require("Модул:el-noon-decl") -- Require the main declension module
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- This function will run a series of tests to verify declension accuracy.
-- It can be called by adding {{#invoke:ModuleName|RunTests}} to a Wiki page.
-- @param frame object The Scribunto frame object.
-- @return string The Wikitable markup for test results.
function p.RunTests(frame)
local test_cases = {
-- Neuter -μα nouns
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αιτημα]]", -- EXPECTED "αιτημα" here (unaccented)
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύгματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυгμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείгματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειгμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "πρόσωπο", expected = {
nom_s = "[[πρόσωπο]]", gen_s = "[[προσώπου]]", acc_s = "[[πρόσωπο]]", voc_s = "[[πρόσωπο]]",
nom_p = "[[πρόσωπα]]", gen_p = "[[προσώπων]]", acc_p = "[[πρόσωπα]]", voc_p = "[[πρόσωπα]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
-- Masculine -έας
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine stressed -ή
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine stressed -ός
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιαноί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιαноί]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
local total_tests = 0
local case_keys_order = {
"nom_s", "gen_s", "acc_s", "voc_s",
"nom_p", "gen_p", "acc_p", "voc_p"
}
for _, test in ipairs(test_cases) do
local noun = test.noun
local expected_forms = test.expected
-- Call DeclineNoun from the main module
local declined_forms = el_noon_decl.DeclineNoun(noun)
local noun_passed_all_cases = true
for _, case_type in ipairs(case_keys_order) do
total_tests = total_tests + 1
local got_form = declined_forms[case_type]
local expected_form = expected_forms[case_type]
if got_form ~= expected_form then
noun_passed_all_cases = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_form,
expected = expected_form
})
end
end
if noun_passed_all_cases then
num_passed = num_passed + 1
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Резултати од тестот за деклинација\n" ..
"|-\n" ..
"! Статус !! Именка !! Падеж !! Добиено !! Очекувано\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">НЕУСПЕШНО</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Вкупно''' || '''" .. total_tests .. "''' || || ||\n" ..
"| '''Поминати''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Неуспешни''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "Сите тестови поминаа успешно!\n"
else
output_table = output_table .. "Некои тестови не успеаја. Ве молиме прегледајте ги неуспесите погоре.\n"
end
return output_table
end
return p -- Return the module table
7olsioyof3j5o7owhqj7srfagq0bx4c
53402
53401
2025-07-04T14:26:08Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53334|53334]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53402
Scribunto
text/plain
-- Module:el-noon-decl
--
-- This module provides functions to generate declension tables for Greek nouns.
-- It focuses solely on declension logic.
local p = {} -- Main table for module functions
local ustring = mw.ustring -- Use mw.ustring for Unicode-aware string operations
-- Helper function to remove accents from a Greek string (simplified for common cases)
local function remove_accents(s)
s = ustring.gsub(s, "ά", "α")
s = ustring.gsub(s, "έ", "ε")
s = ustring.gsub(s, "ή", "η")
s = ustring.gsub(s, "ί", "ι")
s = ustring.gsub(s, "ό", "ο")
s = ustring.gsub(s, "ύ", "υ")
s = ustring.gsub(s, "ώ", "ω")
-- Add more if needed, e.g., for diacritics like ϊ, ϋ
return s
end
-- Helper function to add Wikilinks
local function add_wikilinks(s)
return "[[" .. s .. "]]"
end
-- Helper function to get the position of the accented vowel in a word
local function get_accented_vowel_index(s)
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
if accented_vowels_map[ustring.sub(s, i, i)] then
return i
end
end
return nil
end
-- Helper function to get indices of all vowels in a string
local function get_vowel_indices(s)
local indices = {}
local vowels = {['α']=true, ['ε']=true, ['η']=true, ['ι']=true, ['ο']=true, ['υ']=true, ['ω']=true}
local accented_vowels_map = {['ά']='α', ['έ']='ε', ['ή']='η', ['ί']='ι', ['ό']='ο', ['ύ']='υ', ['ώ']='ώ'}
for i = 1, ustring.len(s) do
local char = ustring.sub(s, i, i)
if vowels[char] or accented_vowels_map[char] then
table.insert(indices, i)
end
end
return indices
end
-- Helper function to apply accent based on the original noun's accentuation and declension rules
local function apply_accent_for_form(original_noun, new_form_no_accent, form_type)
local accent_map = {['α']='ά', ['ε']='έ', ['η']='ή', ['ι']='ί', ['ο']='ό', ['υ']='ύ', ['ώ']='ώ'}
local clean_new_form = remove_accents(new_form_no_accent)
local original_accent_pos = get_accented_vowel_index(original_noun)
local original_vowel_indices = get_vowel_indices(original_noun)
if not original_accent_pos or #original_vowel_indices == 0 then
return clean_new_form -- No accent in original or no vowels, return as is
end
local original_accent_relative_pos = nil -- 1=oxytone (last vowel), 2=paroxytone (penultimate), 3=proparoxytone (antepenultimate)
for i = 1, #original_vowel_indices do
if original_vowel_indices[i] == original_accent_pos then
original_accent_relative_pos = #original_vowel_indices - i + 1
break
end
end
local new_vowel_indices = get_vowel_indices(clean_new_form)
local target_accent_index = nil
-- Rule for Masculine -ος nouns (δρόμος, κήπος, θείος, χριστιανός)
if ustring.match(original_noun, "ος$") or ustring.match(original_noun, "νός$") then
if original_accent_relative_pos == 1 then -- Oxytone (e.g., χριστιανός)
if form_type == "gen_p" then -- Genitive plural of oxytone -ος nouns is often oxytone
target_accent_index = new_vowel_indices[#new_vowel_indices]
else -- Other forms typically remain oxytone
target_accent_index = new_vowel_indices[#new_vowel_indices]
end
else -- Paroxytone/Proparoxytone (e.g., δρόμος, κήπος, θείος)
if form_type == "gen_p" then -- Genitive plural of paroxytone/proparoxytone -ος nouns is often paroxytone
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Other forms typically remain paroxytone
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
end
-- Rule for Neuter -ο nouns (βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif ustring.match(original_noun, "ο$") then
if original_accent_relative_pos == 2 then -- Paroxytone (e.g., βιβλίο, σχολείο)
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Accent on penultimate vowel
elseif original_accent_relative_pos == 3 then -- Proparoxytone (e.g., πρόσωπο, έγγραφο)
if form_type == "gen_s_o" or form_type == "gen_p_o" then -- Genitive singular/plural shift to penultimate
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
else -- Nom/Acc/Voc singular/plural (accent on antepenultimate)
target_accent_index = new_vowel_indices[#new_vowel_indices - 2]
end
end
-- Rule for Feminine -η (unstressed)
elseif ustring.match(original_noun, "η$") and not ustring.match(original_noun, "ή$") then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Typically paroxytone
-- Rule for Feminine stressed -ή
elseif ustring.match(original_noun, "ή$") then
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Typically oxytone
-- Rule for Feminine -α (stressed -ία)
elseif ustring.match(original_noun, "ία$") then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1] -- Typically paroxytone
-- Rule for Neuter -ι / -ί
elseif ustring.match(original_noun, "[ιί]$") then
target_accent_index = new_vowel_indices[#new_vowel_indices] -- Typically oxytone
-- Rule for -μα nouns
elseif ustring.match(original_noun, "μα$") then
if form_type == "gen_s_ma" then -- Genitive singular
local original_stem_no_accent = remove_accents(ustring.sub(original_noun, 1, -2))
local original_stem_vowel_indices = get_vowel_indices(original_stem_no_accent)
local original_accent_vowel_index_in_stem = nil
for i = 1, #original_stem_vowel_indices do
if original_stem_vowel_indices[i] == original_accent_pos then
original_accent_vowel_index_in_stem = i
break
end
end
if original_accent_vowel_index_in_stem then
target_accent_index = new_vowel_indices[original_accent_vowel_index_in_stem]
end
elseif form_type == "gen_p_ma" then -- Genitive plural (accent shifts to penultimate)
if #new_vowel_indices >= 2 then
target_accent_index = new_vowel_indices[#new_vowel_indices - 1]
end
else -- Nom/Acc/Voc plural
local original_stem_no_accent = remove_accents(ustring.sub(original_noun, 1, -2))
local original_stem_vowel_indices = get_vowel_indices(original_stem_no_accent)
local original_accent_vowel_index_in_stem = nil
for i = 1, #original_stem_vowel_indices do
if original_stem_vowel_indices[i] == original_accent_pos then
original_accent_vowel_index_in_stem = i
break
end
end
if original_accent_vowel_index_in_stem then
target_accent_index = new_vowel_indices[original_accent_vowel_index_in_stem]
end
end
end
if target_accent_index and target_accent_index > 0 and target_accent_index <= #clean_new_form then
local char_to_accent = ustring.sub(clean_new_form, target_accent_index, target_accent_index)
local new_accented_char = accent_map[char_to_accent] or char_to_accent
return ustring.sub(clean_new_form, 1, target_accent_index - 1) .. new_accented_char .. ustring.sub(clean_new_form, target_accent_index + 1)
end
return clean_new_form -- Fallback if accent cannot be placed or rule not found
end
-- Helper function to get the stem for genitive singular of -μα nouns (accent preserved)
local function get_stem_for_gen_s_ma(original_word)
local base_stem = ustring.sub(original_word, 1, -2) -- Remove 'μα'
return apply_accent_for_form(original_word, base_stem, "gen_s_ma") -- Use a specific type for accent rule
end
-- Helper function to get the stem for genitive plural of -μα nouns (accent shifts to penultimate)
local function get_stem_for_gen_p_ma(original_word)
local base_stem = ustring.sub(original_word, 1, -2) -- Remove 'μα'
return apply_accent_for_form(original_word, base_stem, "gen_p_ma") -- Use a specific type for accent rule
end
-- Function to decline a Greek noun based on its ending and inferred gender/class.
-- This function is now designed to handle both direct calls from templates (receiving a frame object)
-- and internal calls from other module functions (receiving a string noun_base).
-- @param frame_or_noun_base mixed The Scribunto frame object if called from a template,
-- or the noun string if called internally.
-- @return table A table containing the singular and plural forms for each case, with Wikilinks.
function p.DeclineNoun(frame_or_noun_base)
local noun_base
-- Check if the first argument is a frame object (common when invoked directly from a template)
if type(frame_or_noun_base) == "table" and frame_or_noun_base.args then
local args = frame_or_noun_base:getParent().args -- Get arguments from the parent template call
noun_base = args[1] or frame_or_noun_base.args[1] -- Get the noun string (first argument)
else
-- Otherwise, assume it's already the noun string (e.g., when called from p.RunTests)
noun_base = frame_or_noun_base
end
-- Basic validation for the noun string
if not noun_base or type(noun_base) ~= "string" then
return {
nom_s = "[[Грешка: Не е дадена именка]]",
gen_s = "", acc_s = "", voc_s = "",
nom_p = "", gen_p = "", acc_p = "", voc_p = ""
}
end
local forms = {}
local stem = ""
local last_char = ustring.sub(noun_base, -1)
local last_two_chars = ustring.sub(noun_base, -2)
local last_three_chars = ustring.sub(noun_base, -3)
-- Initialize forms with empty strings
local cases = {"nom_s", "gen_s", "acc_s", "voc_s", "nom_p", "gen_p", "acc_p", "voc_p"}
for _, case_key in ipairs(cases) do
forms[case_key] = ""
end
-- Masculine -ος (e.g., δρόμος, κήπος, θείος, χριστιανός)
if last_two_chars == "ος" or last_three_chars == "νός" then
stem = ustring.sub(noun_base, 1, -3) -- Remove "ος"
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ου", "gen_s"))
forms.acc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ο", "acc_s"))
forms.voc_s = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ε", "voc_s"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "nom_p"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ων", "gen_p"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "ους", "acc_p"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, stem .. "οι", "voc_p"))
-- Masculine -ας (e.g., ταμίας)
elseif last_two_chars == "ας" then
stem = ustring.sub(noun_base, 1, -3)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "α")
forms.acc_s = add_wikilinks(stem .. "α")
forms.voc_s = add_wikilinks(stem .. "α")
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Masculine -έας (e.g., διερμηνέας)
elseif last_three_chars == "έας" then
stem = ustring.sub(noun_base, 1, -4)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "έα")
forms.acc_s = add_wikilinks(stem .. "έα")
forms.voc_s = add_wikilinks(stem .. "έα")
forms.nom_p = add_wikilinks(stem .. "είς")
forms.gen_p = add_wikilinks(stem .. "έων")
forms.acc_p = add_wikilinks(stem .. "είς")
forms.voc_p = add_wikilinks(stem .. "είς")
-- Masculine -ης / -ής (e.g., διευθυντής, καθηγητής)
elseif last_two_chars == "ης" or last_two_chars == "ής" then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ή")
forms.acc_s = add_wikilinks(stem .. "ή")
forms.voc_s = add_wikilinks(stem .. "ή")
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -η (unstressed) (e.g., διεύθυνση, συνέντευξη)
elseif last_char == "η" and ustring.sub(noun_base, -2, -2) ~= "ή" then -- Check for unstressed η
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ης")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "εις")
forms.gen_p = add_wikilinks(stem .. "εων")
forms.acc_p = add_wikilinks(stem .. "εις")
forms.voc_p = add_wikilinks(stem .. "εις")
-- Feminine stressed -ή (e.g., προβολή, ψυχή)
elseif last_char == "ή" then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ής")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ές")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ές")
forms.voc_p = add_wikilinks(stem .. "ές")
-- Feminine -α (stressed -ία) (e.g., αλληλογραφία, συνομιλία, νοσηλεία)
elseif last_two_chars == "ία" then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ας")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ες")
forms.gen_p = add_wikilinks(stem .. "ών")
forms.acc_p = add_wikilinks(stem .. "ες")
forms.voc_p = add_wikilinks(stem .. "ες")
-- Neuter -μα (e.g., όνομα, γράμμα, αίτημα, ποίημα, μήνυμα, τραύμα, βάπτισμα, κήρυγμα, δείγμα, κρεύμα, σύστημα, σώμα, πράγμα)
elseif last_two_chars == "μα" then
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
-- Special handling for "όνομα" due to irregular stem change
if noun_base == "όνομα" then
forms.gen_s = add_wikilinks("ονόματος")
forms.gen_p = add_wikilinks("ονομάτων")
else
-- General logic for other -μα nouns
forms.gen_s = add_wikilinks(get_stem_for_gen_s_ma(noun_base) .. "τος")
forms.gen_p = add_wikilinks(get_stem_for_gen_p_ma(noun_base) .. "των")
end
local base_stem_for_plural = ustring.sub(noun_base, 1, -2) -- Remove 'μα' for nom/acc/voc plural
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem_for_plural .. "ματα", "nom_p_ma"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem_for_plural .. "ματα", "acc_p_ma"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem_for_plural .. "ματα", "voc_p_ma"))
-- Specific vocative singular for αίτημα (unaccented)
if noun_base == "αίτημα" then
forms.voc_s = add_wikilinks(remove_accents(noun_base))
end
-- Neuter -ι / -ί (e.g., παιδί, νησί)
elseif last_char == "ι" or last_char == "ί" then
stem = ustring.sub(noun_base, 1, -2)
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(stem .. "ιού")
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.nom_p = add_wikilinks(stem .. "ιά")
forms.gen_p = add_wikilinks(stem .. "ιών")
forms.acc_p = add_wikilinks(stem .. "ιά")
forms.voc_p = add_wikilinks(stem .. "ιά")
-- Neuter -ο (e.g., βιβλίο, σχολείο, πρόσωπο, έγγραφο)
elseif last_char == "ο" then
local base_stem = ustring.sub(noun_base, 1, -2) -- Remove 'ο'
forms.nom_s = add_wikilinks(noun_base)
forms.acc_s = add_wikilinks(noun_base)
forms.voc_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ου", "gen_s_o"))
forms.gen_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "ων", "gen_p_o"))
forms.nom_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "nom_p_o"))
forms.acc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "acc_p_o"))
forms.voc_p = add_wikilinks(apply_accent_for_form(noun_base, base_stem .. "α", "voc_p_o"))
else
-- Fallback for unsupported noun types.
forms.nom_s = add_wikilinks(noun_base)
forms.gen_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_s = add_wikilinks(noun_base .. " (неподдржано)")
forms.nom_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.gen_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.acc_p = add_wikilinks(noun_base .. " (неподдржано)")
forms.voc_p = add_wikilinks(noun_base .. " (неподдржано)")
end
return forms
end
-- Function to generate the Wikitable for noun declension.
-- This function takes the noun forms and formats them into a Wikitable string.
-- @param forms table A table containing the singular and plural forms for each case.
-- @return string A string containing the Wikitable markup.
function p.generate_wikitable(forms)
local table_string = '{| class="wikitable"\n'
table_string = table_string .. '|-\n'
table_string = table_string .. '! Падеж\n'
table_string = table_string .. '! Еднина\n'
table_string = table_string .. '! Множина\n'
local case_map = {
nom_s = "Номинатив",
gen_s = "Генитив",
acc_s = "Акузатив",
voc_s = "Вокатив"
}
local singular_cases = {"nom_s", "gen_s", "acc_s", "voc_s"}
local plural_cases = {"nom_p", "gen_p", "acc_p", "voc_p"}
for i, s_case_key in ipairs(singular_cases) do
local p_case_key = plural_cases[i]
table_string = table_string .. '|-\n'
table_string = table_string .. '| ' .. case_map[s_case_key] .. '\n'
table_string = table_string .. '| ' .. (forms[s_case_key] or "") .. '\n'
table_string = table_string .. '| ' .. (forms[p_case_key] or "") .. '\n'
end
table_string = table_string .. '|}'
return table_string
end
return p -- Return the module table
on8r1iltb069ukuhpe2y6dj66hx5iaw
53406
53402
2025-07-04T14:35:38Z
Steborce
2506
53406
Scribunto
text/plain
local export = {}
local el_noon_decl = require('Модул:el-noon-decl') -- Load the main declension module
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αιτημα]]", voc_s = "[[αιτημα]]", -- EXPECTED "αιτημα" here (unaccented)
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "κρεύμα", expected = {
nom_s = "[[κρεύμα]]", gen_s = "[[κρεύματος]]", acc_s = "[[κρεύμα]]", voc_s = "[[κρεύμα]]",
nom_p = "[[κρεύματα]]", gen_p = "[[κρευμάτων]]", acc_p = "[[κρεύματα]]", voc_p = "[[κρεύματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "δέντρο", expected = {
nom_s = "[[δέντρο]]", gen_s = "[[δέντρου]]", acc_s = "[[δέντρο]]", voc_s = "[[δέντρο]]",
nom_p = "[[δέντρα]]", gen_p = "[[δέντρων]]", acc_p = "[[δέντρα]]", voc_p = "[[δέντρα]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας (unstressed, like ταμίας)
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
{ noun = "ναύτης", expected = { -- This ends in -ης, but acts like -ας for declension.
nom_s = "[[ναύτης]]", gen_s = "[[ναύτη]]", acc_s = "[[ναύτη]]", voc_s = "[[ναύτη]]",
nom_p = "[[ναύτες]]", gen_p = "[[ναυτών]]", acc_p = "[[ναύτες]]", voc_p = "[[ναύτες]]"
}},
-- Masculine -έας (stressed)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής (stressed)
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine -ή (stressed)
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine -ός (stressed) - excluding θεός, which is irregular
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
{ noun = "διευθυντής", expected = { -- Example of a new test for masculine -ης/-ής
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
-- Irregular nouns (re-tests from the top, ensuring they're still handled)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected_forms = test_case.expected
local got_forms = el_noon_decl.decline_noun(noun) -- Call the function from the other module
local passed = true
for case_type, expected_value in pairs(expected_forms) do
local got_value = got_forms[case_type]
if got_value ~= expected_value then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_value or "nil",
expected = expected_value
})
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Declension Test Results\n" ..
"|-\n" ..
"! Status !! Noun !! Case !! Got !! Expected\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "<p style=\"color:green;\">All " .. #test_cases .. " tests passed!</p>"
else
output_table = output_table .. "<p style=\"color:red;\">" .. num_failed .. " of " .. #test_cases .. " tests failed.</p>"
end
return output_table
end
return export
c1ia1anxdgbezyycoqfr0fhpfnx459h
53407
53406
2025-07-04T14:41:19Z
Steborce
2506
53407
Scribunto
text/plain
local export = {}
local el_noon_decl = require('Модул:el-noon-decl') -- Load the main declension module
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = { nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]", nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]" }},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "δέντρο", expected = {
nom_s = "[[δέντρο]]", gen_s = "[[δέντρου]]", acc_s = "[[δέντρο]]", voc_s = "[[δέντρο]]",
nom_p = "[[δέντρα]]", gen_p = "[[δέντρων]]", acc_p = "[[δέντρα]]", voc_p = "[[δέντρα]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας (unstressed, like ταμίας)
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
{ noun = "ναύτης", expected = { -- This ends in -ης, but acts like -ας for declension.
nom_s = "[[ναύτης]]", gen_s = "[[ναύτη]]", acc_s = "[[ναύτη]]", voc_s = "[[ναύτη]]",
nom_p = "[[ναύτες]]", gen_p = "[[ναυτών]]", acc_p = "[[ναύτες]]", voc_p = "[[ναύτες]]"
}},
-- Masculine -έας (stressed)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής (stressed)
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine -ή (stressed)
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine -ός (stressed) - excluding θεός, which is irregular
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
{ noun = "διευθυντής", expected = { -- Example of a new test for masculine -ης/-ής
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
-- Irregular nouns (re-tests from the top, ensuring they're still handled)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected_forms = test_case.expected
local got_forms = el_noon_decl.decline_noun(noun) -- Call the function from the other module
local passed = true
for case_type, expected_value in pairs(expected_forms) do
local got_value = got_forms[case_type]
if got_value ~= expected_value then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_value or "nil",
expected = expected_value
})
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Declension Test Results\n" ..
"|-\n" ..
"! Status !! Noun !! Case !! Got !! Expected\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "<p style=\"color:green;\">All " .. #test_cases .. " tests passed!</p>"
else
output_table = output_table .. "<p style=\"color:red;\">" .. num_failed .. " of " .. #test_cases .. " tests failed.</p>"
end
return output_table
end
return export
fecsdjviof1kuwz74w71uyhly05sdnp
53410
53407
2025-07-04T14:57:02Z
Steborce
2506
53410
Scribunto
text/plain
local export = {}
local el_noon_decl = require('Модул:el-noon-decl') -- Load the main declension module
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = { nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]", nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]" }},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "δέντρο", expected = {
nom_s = "[[δέντρο]]", gen_s = "[[δέντρου]]", acc_s = "[[δέντρο]]", voc_s = "[[δέντρο]]",
nom_p = "[[δέντρα]]", gen_p = "[[δέντρων]]", acc_p = "[[δέντρα]]", voc_p = "[[δέντρα]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας (unstressed, like ταμίας)
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
{ noun = "ναύτης", expected = { -- This ends in -ης, but acts like -ας for declension.
nom_s = "[[ναύτης]]", gen_s = "[[ναύτη]]", acc_s = "[[ναύτη]]", voc_s = "[[ναύτη]]",
nom_p = "[[ναύτες]]", gen_p = "[[ναυτών]]", acc_p = "[[ναύτες]]", voc_p = "[[ναύτες]]"
}},
-- Masculine -έας (stressed)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής (stressed)
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine -ή (stressed)
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine -ός (stressed) - excluding θεός, which is irregular
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
{ noun = "διευθυντής", expected = { -- Example of a new test for masculine -ης/-ής
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
-- Irregular nouns (re-tests from the top, ensuring they're still handled)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected_forms = test_case.expected
local got_forms = el_noon_decl.decline_noun(noun) -- Call the function from the other module
local passed = true
for case_type, expected_value in pairs(expected_forms) do
local got_value = got_forms[case_type]
if got_value ~= expected_value then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_value or "nil",
expected = expected_value
})
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Declension Test Results\n" ..
"|-\n" ..
"! Status !! Noun !! Case !! Got !! Expected\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "<p style=\"color:green;\">All " .. #test_cases .. " tests passed!</p>"
else
output_table = output_table .. "<p style=\"color:red;\">" .. num_failed .. " of " .. #test_cases .. " tests failed.</p>"
end
return output_table
end
return export
30xiix0jzbf280szrnugb26fyyv2hw1
53416
53410
2025-07-04T15:42:28Z
Steborce
2506
53416
Scribunto
text/plain
local export = {}
local el_noon_decl = require('Модул:el-noon-decl') -- Load the main declension module
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = {
nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]",
nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]"
}},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "δέντρο", expected = {
nom_s = "[[δέντρο]]", gen_s = "[[δέντρου]]", acc_s = "[[δέντρο]]", voc_s = "[[δέντρο]]",
nom_p = "[[δέντρα]]", gen_p = "[[δέντρων]]", acc_p = "[[δέντρα]]", voc_p = "[[δέντρα]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας (unstressed, like ταμίας)
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
{ noun = "ναύτης", expected = { -- This ends in -ης, but acts like -ας for declension.
nom_s = "[[ναύτης]]", gen_s = "[[ναύτη]]", acc_s = "[[ναύτη]]", voc_s = "[[ναύτη]]",
nom_p = "[[ναύτες]]", gen_p = "[[ναυτών]]", acc_p = "[[ναύτες]]", voc_p = "[[ναύτες]]"
}},
-- Masculine -έας (stressed)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής (stressed)
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine -ή (stressed)
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine -ός (stressed) - excluding θεός, which is irregular
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
{ noun = "διευθυντής", expected = { -- Example of a new test for masculine -ης/-ής
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
-- Irregular nouns (re-tests from the top, ensuring they're still handled)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected_forms = test_case.expected
local got_forms = el_noon_decl.decline_noun(noun) -- Call the function from the other module
local passed = true
-- Check if got_forms is nil (meaning the noun type is not yet supported)
if got_forms == nil then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = "ALL", -- Mark all cases as failed for this noun
got = "Unsupported noun type (returned nil)",
expected = "Expected forms for " .. noun
})
else
for case_type, expected_value in pairs(expected_forms) do
local got_value = got_forms[case_type]
if got_value ~= expected_value then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_value or "nil", -- Ensure "nil" is shown if value is truly nil
expected = expected_value
})
end
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\\n" ..
"|+ Declension Test Results\\n" ..
"|-\\n" ..
"! Status !! Noun !! Case !! Got !! Expected\\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\\n"
end
end
output_table = output_table .. "|-\\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\\n" ..
"|}\\n"
if num_failed == 0 then
output_table = output_table .. "<p style=\"color:green;\">All " .. #test_cases .. " tests passed!</p>"
else
output_table = output_table .. "<p style=\"color:red;\">" .. num_failed .. " of " .. #test_cases .. " tests failed.</p>"
end
return output_table
end
return export
k1sekff9hg3jjuu74c558ujo2a6avlk
53418
53416
2025-07-04T15:52:19Z
Steborce
2506
Откажано уредувањето [[Special:Diff/53416|53416]] на [[Special:Contributions/Steborce|Steborce]] ([[User talk:Steborce|разговор]])
53418
Scribunto
text/plain
local export = {}
local el_noon_decl = require('Модул:el-noon-decl') -- Load the main declension module
function export.RunTests()
local test_cases = {
-- Irregular nouns (expected to pass)
-- Neuter -μα (All should now pass with the improved gen_s logic)
{ noun = "όνομα", expected = {
nom_s = "[[όνομα]]", gen_s = "[[ονόματος]]", acc_s = "[[όνομα]]", voc_s = "[[όνομα]]",
nom_p = "[[ονόματα]]", gen_p = "[[ονομάτων]]", acc_p = "[[ονόματα]]", voc_p = "[[ονόματα]]"
}},
{ noun = "γράμμα", expected = {
nom_s = "[[γράμμα]]", gen_s = "[[γράμματος]]", acc_s = "[[γράμμα]]", voc_s = "[[γράμμα]]",
nom_p = "[[γράμματα]]", gen_p = "[[γραμμάτων]]", acc_p = "[[γράμματα]]", voc_p = "[[γράμματα]]"
}},
{ noun = "αίτημα", expected = { nom_s = "[[αίτημα]]", gen_s = "[[αιτήματος]]", acc_s = "[[αίτημα]]", voc_s = "[[αίτημα]]", nom_p = "[[αιτήματα]]", gen_p = "[[αιτημάτων]]", acc_p = "[[αιτήματα]]", voc_p = "[[αιτήματα]]" }},
{ noun = "ποίημα", expected = {
nom_s = "[[ποίημα]]", gen_s = "[[ποιήματος]]", acc_s = "[[ποίημα]]", voc_s = "[[ποίημα]]",
nom_p = "[[ποιήματα]]", gen_p = "[[ποιημάτων]]", acc_p = "[[ποιήματα]]", voc_p = "[[ποιήματα]]"
}},
{ noun = "μήνυμα", expected = {
nom_s = "[[μήνυμα]]", gen_s = "[[μηνύματος]]", acc_s = "[[μήνυμα]]", voc_s = "[[μήνυμα]]",
nom_p = "[[μηνύματα]]", gen_p = "[[μηνυμάτων]]", acc_p = "[[μηνύματα]]", voc_p = "[[μηνύματα]]"
}},
{ noun = "τραύμα", expected = {
nom_s = "[[τραύμα]]", gen_s = "[[τραύματος]]", acc_s = "[[τραύμα]]", voc_s = "[[τραύμα]]",
nom_p = "[[τραύματα]]", gen_p = "[[τραυμάτων]]", acc_p = "[[τραύματα]]", voc_p = "[[τραύματα]]"
}},
{ noun = "βάπτισμα", expected = {
nom_s = "[[βάπτισμα]]", gen_s = "[[βαπτίσματος]]", acc_s = "[[βάπτισμα]]", voc_s = "[[βάπτισμα]]",
nom_p = "[[βαπτίσματα]]", gen_p = "[[βαπτισμάτων]]", acc_p = "[[βαπτίσματα]]", voc_p = "[[βαπτίσματα]]"
}},
{ noun = "κήρυγμα", expected = {
nom_s = "[[κήρυγμα]]", gen_s = "[[κηρύγματος]]", acc_s = "[[κήρυγμα]]", voc_s = "[[κήρυγμα]]",
nom_p = "[[κηρύγματα]]", gen_p = "[[κηρυγμάτων]]", acc_p = "[[κηρύγματα]]", voc_p = "[[κηρύγματα]]"
}},
{ noun = "δείγμα", expected = {
nom_s = "[[δείγμα]]", gen_s = "[[δείγματος]]", acc_s = "[[δείγμα]]", voc_s = "[[δείγμα]]",
nom_p = "[[δείγματα]]", gen_p = "[[δειγμάτων]]", acc_p = "[[δείγματα]]", voc_p = "[[δείγματα]]"
}},
{ noun = "σύστημα", expected = {
nom_s = "[[σύστημα]]", gen_s = "[[συστήματος]]", acc_s = "[[σύστημα]]", voc_s = "[[σύστημα]]",
nom_p = "[[συστήματα]]", gen_p = "[[συστημάτων]]", acc_p = "[[συστήματα]]", voc_p = "[[συστήματα]]"
}},
{ noun = "σώμα", expected = {
nom_s = "[[σώμα]]", gen_s = "[[σώματος]]", acc_s = "[[σώμα]]", voc_s = "[[σώμα]]",
nom_p = "[[σώματα]]", gen_p = "[[σωμάτων]]", acc_p = "[[σώματα]]", voc_p = "[[σώματα]]"
}},
{ noun = "πράγμα", expected = {
nom_s = "[[πράγμα]]", gen_s = "[[πράγματος]]", acc_s = "[[πράγμα]]", voc_s = "[[πράγμα]]",
nom_p = "[[πράγματα]]", gen_p = "[[πραγμάτων]]", acc_p = "[[πράγματα]]", voc_p = "[[πράγματα]]"
}},
-- Feminine -η (unstressed)
{ noun = "διεύθυνση", expected = {
nom_s = "[[διεύθυνση]]", gen_s = "[[διεύθυνσης]]", acc_s = "[[διεύθυνση]]", voc_s = "[[διεύθυνση]]",
nom_p = "[[διευθύνσεις]]", gen_p = "[[διευθύνσεων]]", acc_p = "[[διευθύνσεις]]", voc_p = "[[διευθύνσεις]]"
}},
{ noun = "συνέντευξη", expected = {
nom_s = "[[συνέντευξη]]", gen_s = "[[συνέντευξης]]", acc_s = "[[συνέντευξη]]", voc_s = "[[συνέντευξη]]",
nom_p = "[[συνεντεύξεις]]", gen_p = "[[συνεντεύξεων]]", acc_p = "[[συνεντεύξεις]]", voc_p = "[[συνεντεύξεις]]"
}},
-- Feminine -α (stressed -ία)
{ noun = "αλληλογραφία", expected = {
nom_s = "[[αλληλογραφία]]", gen_s = "[[αλληλογραφίας]]", acc_s = "[[αλληλογραφία]]", voc_s = "[[αλληλογραφία]]",
nom_p = "[[αλληλογραφίες]]", gen_p = "[[αλληλογραφιών]]", acc_p = "[[αλληλογραφίες]]", voc_p = "[[αλληλογραφίες]]"
}},
{ noun = "συνομιλία", expected = {
nom_s = "[[συνομιλία]]", gen_s = "[[συνομιλίας]]", acc_s = "[[συνομιλία]]", voc_s = "[[συνομιλία]]",
nom_p = "[[συνομιλίες]]", gen_p = "[[συνομιλιών]]", acc_p = "[[συνομιλίες]]", voc_p = "[[συνομιλίες]]"
}},
{ noun = "νοσηλεία", expected = {
nom_s = "[[νοσηλεία]]", gen_s = "[[νοσηλείας]]", acc_s = "[[νοσηλεία]]", voc_s = "[[νοσηλεία]]",
nom_p = "[[νοσηλείες]]", gen_p = "[[νοσηλειών]]", acc_p = "[[νοσηλείες]]", voc_p = "[[νοσηλείες]]"
}},
-- Neuter -ι / -ί
{ noun = "παιδί", expected = {
nom_s = "[[παιδί]]", gen_s = "[[παιδιού]]", acc_s = "[[παιδί]]", voc_s = "[[παιδί]]",
nom_p = "[[παιδιά]]", gen_p = "[[παιδιών]]", acc_p = "[[παιδιά]]", voc_p = "[[παιδιά]]"
}},
{ noun = "νησί", expected = {
nom_s = "[[νησί]]", gen_s = "[[νησιού]]", acc_s = "[[νησί]]", voc_s = "[[νησί]]",
nom_p = "[[νησιά]]", gen_p = "[[νησιών]]", acc_p = "[[νησιά]]", voc_p = "[[νησιά]]"
}},
-- Neuter -ο
{ noun = "βιβλίο", expected = {
nom_s = "[[βιβλίο]]", gen_s = "[[βιβλίου]]", acc_s = "[[βιβλίο]]", voc_s = "[[βιβλίο]]",
nom_p = "[[βιβλία]]", gen_p = "[[βιβλίων]]", acc_p = "[[βιβλία]]", voc_p = "[[βιβλία]]"
}},
{ noun = "σχολείο", expected = {
nom_s = "[[σχολείο]]", gen_s = "[[σχολείου]]", acc_s = "[[σχολείο]]", voc_s = "[[σχολείο]]",
nom_p = "[[σχολεία]]", gen_p = "[[σχολείων]]", acc_p = "[[σχολεία]]", voc_p = "[[σχολεία]]"
}},
{ noun = "δάνειο", expected = {
nom_s = "[[δάνειο]]", gen_s = "[[δανείου]]", acc_s = "[[δάνειο]]", voc_s = "[[δάνειο]]",
nom_p = "[[δάνεια]]", gen_p = "[[δανείων]]", acc_p = "[[δάνεια]]", voc_p = "[[δάνεια]]"
}},
{ noun = "στοιχείο", expected = {
nom_s = "[[στοιχείο]]", gen_s = "[[στοιχείου]]", acc_s = "[[στοιχείο]]", voc_s = "[[στοιχείο]]",
nom_p = "[[στοιχεία]]", gen_p = "[[στοιχείων]]", acc_p = "[[στοιχεία]]", voc_p = "[[στοιχεία]]"
}},
{ noun = "δέντρο", expected = {
nom_s = "[[δέντρο]]", gen_s = "[[δέντρου]]", acc_s = "[[δέντρο]]", voc_s = "[[δέντρο]]",
nom_p = "[[δέντρα]]", gen_p = "[[δέντρων]]", acc_p = "[[δέντρα]]", voc_p = "[[δέντρα]]"
}},
{ noun = "δώρο", expected = {
nom_s = "[[δώρο]]", gen_s = "[[δώρου]]", acc_s = "[[δώρο]]", voc_s = "[[δώρο]]",
nom_p = "[[δώρα]]", gen_p = "[[δώρων]]", acc_p = "[[δώρα]]", voc_p = "[[δώρα]]"
}},
{ noun = "έγγραφο", expected = {
nom_s = "[[έγγραφο]]", gen_s = "[[εγγράφου]]", acc_s = "[[έγγραφο]]", voc_s = "[[έγγραφο]]",
nom_p = "[[έγγραφα]]", gen_p = "[[εγγράφων]]", acc_p = "[[έγγραφα]]", voc_p = "[[έγγραφα]]"
}},
-- Masculine -ος (unstressed)
{ noun = "δρόμος", expected = {
nom_s = "[[δρόμος]]", gen_s = "[[δρόμου]]", acc_s = "[[δρόμο]]", voc_s = "[[δρόμε]]",
nom_p = "[[δρόμοι]]", gen_p = "[[δρόμων]]", acc_p = "[[δρόμους]]", voc_p = "[[δρόμοι]]"
}},
{ noun = "κήπος", expected = {
nom_s = "[[κήπος]]", gen_s = "[[κήπου]]", acc_s = "[[κήπο]]", voc_s = "[[κήπε]]",
nom_p = "[[κήποι]]", gen_p = "[[κήπων]]", acc_p = "[[κήπους]]", voc_p = "[[κήποι]]"
}},
{ noun = "θείος", expected = {
nom_s = "[[θείος]]", gen_s = "[[θείου]]", acc_s = "[[θείο]]", voc_s = "[[θείε]]",
nom_p = "[[θείοι]]", gen_p = "[[θείων]]", acc_p = "[[θείους]]", voc_p = "[[θείοι]]"
}},
-- Masculine -ας (unstressed, like ταμίας)
{ noun = "ταμίας", expected = {
nom_s = "[[ταμίας]]", gen_s = "[[ταμία]]", acc_s = "[[ταμία]]", voc_s = "[[ταμία]]",
nom_p = "[[ταμίες]]", gen_p = "[[ταμιών]]", acc_p = "[[ταμίες]]", voc_p = "[[ταμίες]]"
}},
{ noun = "ναύτης", expected = { -- This ends in -ης, but acts like -ας for declension.
nom_s = "[[ναύτης]]", gen_s = "[[ναύτη]]", acc_s = "[[ναύτη]]", voc_s = "[[ναύτη]]",
nom_p = "[[ναύτες]]", gen_p = "[[ναυτών]]", acc_p = "[[ναύτες]]", voc_p = "[[ναύτες]]"
}},
-- Masculine -έας (stressed)
{ noun = "διερμηνέας", expected = {
nom_s = "[[διερμηνέας]]", gen_s = "[[διερμηνέα]]", acc_s = "[[διερμηνέα]]", voc_s = "[[διερμηνέα]]",
nom_p = "[[διερμηνείς]]", gen_p = "[[διερμηνέων]]", acc_p = "[[διερμηνείς]]", voc_p = "[[διερμηνείς]]"
}},
-- Masculine -ης / -ής (stressed)
{ noun = "διευθυντής", expected = {
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
{ noun = "καθηγητής", expected = {
nom_s = "[[καθηγητής]]", gen_s = "[[καθηγητή]]", acc_s = "[[καθηγητή]]", voc_s = "[[καθηγητή]]",
nom_p = "[[καθηγητές]]", gen_p = "[[καθηγητών]]", acc_p = "[[καθηγητές]]", voc_p = "[[καθηγητές]]"
}},
-- Feminine -ή (stressed)
{ noun = "προβολή", expected = {
nom_s = "[[προβολή]]", gen_s = "[[προβολής]]", acc_s = "[[προβολή]]", voc_s = "[[προβολή]]",
nom_p = "[[προβολές]]", gen_p = "[[προβολών]]", acc_p = "[[προβολές]]", voc_p = "[[προβολές]]"
}},
{ noun = "ψυχή", expected = {
nom_s = "[[ψυχή]]", gen_s = "[[ψυχής]]", acc_s = "[[ψυχή]]", voc_s = "[[ψυχή]]",
nom_p = "[[ψυχές]]", gen_p = "[[ψυχών]]", acc_p = "[[ψυχές]]", voc_p = "[[ψυχές]]"
}},
-- Masculine -ός (stressed) - excluding θεός, which is irregular
{ noun = "χριστιανός", expected = {
nom_s = "[[χριστιανός]]", gen_s = "[[χριστιανού]]", acc_s = "[[χριστιανό]]", voc_s = "[[χριστιανέ]]",
nom_p = "[[χριστιανοί]]", gen_p = "[[χριστιανών]]", acc_p = "[[χριστιανούς]]", voc_p = "[[χριστιανοί]]"
}},
{ noun = "διευθυντής", expected = { -- Example of a new test for masculine -ης/-ής
nom_s = "[[διευθυντής]]", gen_s = "[[διευθυντή]]", acc_s = "[[διευθυντή]]", voc_s = "[[διευθυντή]]",
nom_p = "[[διευθυντές]]", gen_p = "[[διευθυντών]]", acc_p = "[[διευθυντές]]", voc_p = "[[διευθυντές]]"
}},
-- Irregular nouns (re-tests from the top, ensuring they're still handled)
{ noun = "άνθρωπος", expected = {
nom_s = "[[άνθρωπος]]", gen_s = "[[ανθρώπου]]", acc_s = "[[άνθρωπο]]", voc_s = "[[άνθρωπε]]",
nom_p = "[[άνθρωποι]]", gen_p = "[[ανθρώπων]]", acc_p = "[[άνθρωπους]]", voc_p = "[[άνθρωποι]]"
}},
{ noun = "πατέρας", expected = {
nom_s = "[[πατέρας]]", gen_s = "[[πατέρα]]", acc_s = "[[πατέρα]]", voc_s = "[[πατέρα]]",
nom_p = "[[πατέρες]]", gen_p = "[[πατέρων]]", acc_p = "[[πατέρες]]", voc_p = "[[πατέρες]]"
}},
{ noun = "θεός", expected = {
nom_s = "[[θεός]]", gen_s = "[[θεού]]", acc_s = "[[θεό]]", voc_s = "[[θεέ]]",
nom_p = "[[θεοί]]", gen_p = "[[θεών]]", acc_p = "[[θεούς]]", voc_p = "[[θεοί]]"
}},
{ noun = "δίκτυο", expected = {
nom_s = "[[δίκτυο]]", gen_s = "[[δικτύου]]", acc_s = "[[δίκτυο]]", voc_s = "[[δίκτυο]]",
nom_p = "[[δίκτυα]]", gen_p = "[[δικτύων]]", acc_p = "[[δίκτυα]]", voc_p = "[[δίκτυα]]"
}},
}
local results = {}
local num_passed = 0
local num_failed = 0
for _, test_case in ipairs(test_cases) do
local noun = test_case.noun
local expected_forms = test_case.expected
local got_forms = el_noon_decl.decline_noun(noun) -- Call the function from the other module
local passed = true
for case_type, expected_value in pairs(expected_forms) do
local got_value = got_forms[case_type]
if got_value ~= expected_value then
passed = false
table.insert(results, {
noun = noun,
status = "FAIL",
case_type = case_type,
got = got_value or "nil",
expected = expected_value
})
end
end
if passed then
num_passed = num_passed + 1
-- table.insert(results, {noun = noun, status = "PASS"}) -- Uncomment if you want all successful tests to be listed
else
num_failed = num_failed + 1
end
end
local output_table = "{| class=\"wikitable sortable\"\n" ..
"|+ Declension Test Results\n" ..
"|-\n" ..
"! Status !! Noun !! Case !! Got !! Expected\n"
for _, result in ipairs(results) do
if result.status == "FAIL" then
output_table = output_table .. "|-\n" ..
"| <span style=\"color:red;\">FAIL</span> " ..
"|| " .. result.noun ..
"|| " .. result.case_type ..
"|| " .. result.got ..
"|| " .. result.expected .. "\n"
end
end
output_table = output_table .. "|-\n" ..
"| '''Total''' || '''" .. #test_cases .. "''' || || ||\n" ..
"| '''Passed''' || '''" .. num_passed .. "''' || || ||\n" ..
"| '''Failed''' || '''" .. num_failed .. "''' || || ||\n" ..
"|}\n"
if num_failed == 0 then
output_table = output_table .. "<p style=\"color:green;\">All " .. #test_cases .. " tests passed!</p>"
else
output_table = output_table .. "<p style=\"color:red;\">" .. num_failed .. " of " .. #test_cases .. " tests failed.</p>"
end
return output_table
end
return export
30xiix0jzbf280szrnugb26fyyv2hw1
έγγραφος
0
10080
53430
2025-07-04T22:22:44Z
Steborce
2506
Создадена страница со: {{-el-}} ===Етимологија=== Од старогрчкиот збор '''ἔγγραφος''' („запишан, запишано“), составен од '''ἐν''' („во“) + '''γράφω''' („пишувам“). Значењето се однесува на нешто што е запишано во документ или во писмена форма. ===Изговор=== * МФА-гр: /ˈeŋ.ɣra.fos/ * Поделба н...
53430
wikitext
text/x-wiki
{{-el-}}
===Етимологија===
Од старогрчкиот збор '''ἔγγραφος''' („запишан, запишано“), составен од '''ἐν''' („во“) + '''γράφω''' („пишувам“). Значењето се однесува на нешто што е запишано во документ или во писмена форма.
===Изговор===
* МФА-гр: /ˈeŋ.ɣra.fos/
* Поделба на слогови: έγ‧γρα‧φος
===Придавка===
'''έγγραφος''' • машки род (женски род '''έγγραφη''', среден род '''έγγραφο''')
# [[писмен]], [[во писмена форма]] — што постои или се изразува преку документ, текст или официјално писмо
#: '''Απαιτείται έγγραφη συγκατάθεση του γονέα.'''
#: ''Се бара писмена согласност од родителот.''
# што е [[документиран]], [[регистриран]]
#: '''Έγγραφα στοιχεία δείχνουν την αλήθεια.'''
#: ''Документирани податоци ја покажуваат вистината.''
===Mенување на придавката по падежи===
{{el-cases-conj| {{PAGENAME}}| }}
===Синоними===
* [[γραπτός]] — [[писмен]]
* [[τεκμηριωμένος]] — [[документиран]]
* [[επίσημος]] — [[официјален]] (во одредени контексти)
===Антоними===
* [[προφορικός]] — [[усмен]]
===Сродни поими===
* [[έγγραφο]] — [[документ]] (како именка)
* [[έγγραφη συγκατάθεση]] — [[писмена согласност]]
* [[καταγράφω]] — [[запишувам]]
* [[γραφή]] — [[пишување]], [[запис]]
[[Категорија:Грчки]]
[[Категорија:Грчки придавки]]
av7668lu6jjy64cszj4cm6jx1zivxr2