local export = {}
local lang = require('Module:languages').getByCode('es')
local entry_data = require('Module:es-conj/data/entry_data')
local paradigms = require('Module:es-conj/data/paradigms')
local json = require('Module:Json')
local ulen = mw.ustring.len
local usub = mw.ustring.sub
local ufind = mw.ustring.find
local ugsub = mw.ustring.gsub
local pronouns = {[ "me"] = {7,14,20,26,32,38,45,51,57},
[ "te"] = {8,15,21,27,33,39,46,52,58,69},
[ "se"] = {9,40,64,10,13,16,19,22,25,28,31,34,37,41,44,47,50,53,56,59,62,70,73},
["nos"] = {11,17,23,29,35,42,48,54,60,71},
[ "os"] = {12,18,24,30,36,43,49,55,61,72}}
local vowels = {["a"]="á",
["e"]="é",
["i"]="í",
["o"]="ó",
["u"]="ú"}
local stressed_vowels = {
["á"]="a",
["é"]="e",
["í"]="i",
["ó"]="o",
["ú"]="u"}
local function to_boolean(val)
if type(val) == 'string' then
val = mw.text.trim(val)
end
return not (not val or val == "" or val == "0" or val == "no" or val == "n" or val == "false")
end
function unpack_args(frame)
local args = frame.args
if (not args[1]) then
args = frame:getParent().args
end
local ending = args[1]
local pattern = args[2]
local ref = to_boolean(args['ref'])
local json = to_boolean(args['json'])
local combined = to_boolean(args['combined'])
local json_combined = to_boolean(args['json_combined'])
local stems = {}
local i = 3
while args[i] do
stems[i-2] = args[i]
i = i + 1
end
return {ending, pattern, stems, ref, json, combined, json_combined}
end
function strip_accents(form)
if form then
return (mw.ustring.gsub(form, ".", stressed_vowels):gsub(",+", ","))
end
end
function create_accented_form(form, ua_disyllabic)
-- create accented stem for reflexive verbs
-- split by commas if more than 1 form is given
if form then
if string.find(form, ',') then
local result_t = {}
for term in string.gmatch(form, '[^,]+') do
table.insert(result_t, create_accented_form(term, ua_disyllabic))
end
return table.concat(result_t, ',')
end
local result = form
-- c: index of current character
local c = ulen(result)
local vowel_count = 0
while (c >= 0) do
local v1 = usub(result, c, c)
if vowels[v1] then
vowel_count = vowel_count + 1
end
-- 'ue' or 'ua' count as 1 vowel, accent goes on e or a
if c ~= ulen(result) then
local v2 = usub(result, c+1, c+1)
if (v1 == 'u' and v2 == 'e') then
vowel_count = vowel_count - 1
end
if (not ua_disyllabic) then
if (v1 == 'u' and v2 == 'a') then
vowel_count = vowel_count - 1
end
end
end
-- 'ai' or 'oi' counts as 1 vowel, accent goes on a or o
if (c ~= 1) then
local v3 = usub(result, c-1, c-1)
if (v3 == 'a' and v1 == 'i') then
vowel_count = vowel_count - 1
end
if (v3 == 'o' and v1 == 'i') then
vowel_count = vowel_count - 1
end
end
if vowel_count == 3 then
return usub(result, 1, c-1)..vowels[v1]..usub(result, c+1, ulen(result))
end
c = c - 1
end
end
return form
end
local function makeLink(term, face, allow_self_link)
local m_links = require('Module:links')
local alt, sc, id, annotations = nil, nil, nil, nil
if string.find(term, ',') then
local result = {}
local c = 1
local found = {}
for i in string.gmatch(term, '[^,]+') do
if not found[i] then
found[i] = true
result[c] = m_links.full_link({lang = lang, term = i}, face, allow_self_link)
c = c + 1
end
end
return table.concat(result, ', ')
end
return m_links.full_link({lang = lang, term = term}, face, allow_self_link)
end
function decorate_inflections(inflections, ref, defective, patterns)
local defective_t = {}
if defective then
for k1,v1 in pairs(defective) do
defective_t[v1] = true
end
end
local result = {}
for k1,v1 in pairs(inflections) do
if not defective_t[k1] then
result[k1] = makeLink(v1, nil, true)
else
result[k1] = "<div style=\"color:#aaa\">" .. v1 .. "</div>"
end
end
if ref then
for k1,v1 in pairs(pronouns) do
for k2,v2 in pairs(v1) do
if result[v2] then
if not defective_t[v2] then
result[v2] = k1.." "..result[v2]
else
result[v2] = "<div style=\"color:#aaa\">" .. k1 .. "</div> " .. result[v2]
end
end
end
end
end
return result
end
function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function export.json_raw(frame)
local args = unpack_args(frame)
local forms = export.inflect(args, {}, false)
local result = {}
for i, form in pairs(forms) do
if not result[form] then
result[form] = {}
end
for j, def in pairs(entry_data.data[i]) do
table.insert(result[form], def)
end
end
return json.jsonValueFromValue(result)
end
function export.json_wikt_forms(frame)
local args = unpack_args(frame)
local forms = export.inflect(args, {}, false)
local ending = args[1]
local pattern = args[2]
local pattern_data = deepcopy(require("Module:es-conj/data/"..ending))
if pattern ~= ending then
pattern_data = deepcopy(require("Module:es-conj/data/"..ending.."/"..pattern))
end
local defective = pattern_data["defective"]
if not defective then
defective = {}
end
local defective_t = {}
for k1,v1 in pairs(defective) do
defective_t[v1] = true
end
local infinitive = forms[1]
local ending = args[1]
local result = {}
for i, form in pairs(forms) do
if not defective_t[i] then
if (form ~= infinitive) then
for form_s in string.gmatch(form, '[^,]+') do
local form_s_t = mw.text.trim(form_s)
if not result[form_s_t] then
result[form_s_t] = {}
end
for j, def in pairs(entry_data.data[i]) do
table.insert(result[form_s_t], entry_data.make_template(def, ending, infinitive))
end
end
end
end
end
return json.jsonValueFromValue(result)
end
function export.json_paradigms(frame)
return json.jsonValueFromValue(paradigms)
end
function export.inflect(args, categories, toggle_decorate)
table.insert(categories, "[[Category:西班牙語動詞]]")
local ending = args[1]
local pattern = args[2]
local stems = args[3]
local ref = args[4]
local ending_data = deepcopy(require("Module:es-conj/data/"..ending))
local pattern_data = deepcopy(require("Module:es-conj/data/"..ending))
if pattern ~= ending then
pattern_data = deepcopy(require("Module:es-conj/data/"..ending.."/"..pattern))
end
local description = pattern_data["description"]
local defective = pattern_data["defective"]
local unstressed = pattern_data["unstressed"] or {}
if not defective then
defective = {}
else
table.insert(categories, "[[Category:缺少變位形式的西班牙語動詞]]")
end
if ref then
table.insert(categories, "[[Category:西班牙語自反動詞]]")
for k1,v1 in pairs(ending_data["ref"]) do
ending_data["patterns"][k1] = v1
end
if (pattern_data["ref"]) then
for k1,v1 in pairs(pattern_data["ref"]) do
pattern_data["patterns"][k1] = v1
end
end
end
if pattern_data["replacement"] then
for k1,v1 in pairs(pattern_data["replacement"]) do
for k2,v2 in pairs(ending_data["patterns"]) do
ending_data["patterns"][k2] = ugsub(ending_data["patterns"][k2], k1, v1)
end
end
end
for k1,v1 in pairs(pattern_data["patterns"]) do
if v1 == '-' then
ending_data["patterns"][k1] = nil
else
if ending_data["patterns"][k1] ~= v1 then
if entry_data.data[k1] then
for k2,v2 in pairs(entry_data.data[k1]) do
tense = v2.tense
mood = v2.mood
if mood ~= 'infinitive' then
if tense then
table.insert(categories, "[[Category:".. mood .. tense .. "不規則的西班牙語動詞]]")
else
table.insert(categories, "[[Category:".. mood .. "不規則的西班牙語動詞]]")
end
end
end
end
ending_data["patterns"][k1] = v1
end
end
end
for k1,v1 in pairs(ending_data["patterns"]) do
for k2,v2 in pairs(stems) do
ending_data["patterns"][k1] = ugsub(ending_data["patterns"][k1], k2, v2)
end
end
if ref then
if not unstressed[63] then
ending_data["patterns"][63] = create_accented_form(ending_data["patterns"][63], false)
end
if not unstressed[65] then
ending_data["patterns"][65] = create_accented_form(ending_data["patterns"][65], false)
end
if not unstressed[68] then
ending_data["patterns"][68] = create_accented_form(ending_data["patterns"][68], false)
end
end
for i=98,121 do
ending_data["patterns"][i] = create_accented_form(ending_data["patterns"][i], false)
end
for i=146,157 do
ending_data["patterns"][i] = create_accented_form(ending_data["patterns"][i] , false)
end
if not toggle_decorate then
return ending_data["patterns"]
end
-- detect redlinks
local defective_t = {}
for k1,v1 in pairs(defective) do
defective_t[v1] = true
end
for k1,v1 in pairs(ending_data["patterns"]) do
if (k1 <= 73) then
if not defective_t[k1] then
for form_s in string.gmatch(v1, '[^,]+') do
local form_s_t = mw.text.trim(form_s)
local link_object = mw.title.new(form_s_t) or nil
if (link_object) then
local link_id = link_object.id
if link_object.id == 0 then
table.insert(categories, "[[Category:變位表中含有紅鏈的西班牙語動詞]]")
end
end
end
end
end
end
ending_data = decorate_inflections(ending_data["patterns"], ref, defective, pattern_data["patterns"])
ending_data["description"] = description
return ending_data
end
function export.inflect_combined(forms, args, toggle_decorate, toggle_json)
local ending = args[1]
local pattern = args[2]
local ref = args[4]
local pattern_data = deepcopy(require("Module:es-conj/data/"..ending))
if pattern ~= ending then
pattern_data = deepcopy(require("Module:es-conj/data/"..ending.."/"..pattern))
end
local unstressed = pattern_data["unstressed"]
local result = {}
local aspects = {[1] = "acc", [2] = "dat"}
local combined_data = require("Module:es-conj/data/combined")
for paradigm,paradigm_data in pairs(combined_data) do
local stem = forms[paradigm_data["index"]]
if (ref) then
stem = usub(stem,1,-3)
end
if (not toggle_json) then
result[paradigm] = stem
end
for form in string.gmatch(stem, '[^,]+') do
for k1,aspect in pairs(aspects) do
for k2,pronoun_table in pairs(paradigm_data[aspect]) do
local t = {}
for k3,pronoun in pairs(pronoun_table) do
local irregular = false
local form_modified = deepcopy(form)
if paradigm_data["stem_cuts"][k2] then
if (#paradigm_data["stem_cuts"][k2] == 2) then
form_modified = usub(form_modified, paradigm_data["stem_cuts"][k2][1], paradigm_data["stem_cuts"][k2][2])
else
if (pronoun == paradigm_data["stem_cuts"][k2][1]) then
form_modified = usub(form_modified, paradigm_data["stem_cuts"][k2][2], paradigm_data["stem_cuts"][k2][3])
end
end
end
if paradigm_data["ending_irregularities"][ending] then
for k4,pattern_data in pairs(paradigm_data["ending_irregularities"][ending]) do
if (aspect == pattern_data[1]) then
if (k2 == pattern_data[2]) then
if (pronoun == pattern_data[3]) then
form_modified = pattern_data[4](form_modified)
end
end
end
end
end
if (paradigm_data["paradigm_irregularities"][pattern]) then
for k4,pattern_data in pairs(paradigm_data["paradigm_irregularities"][pattern]) do
if (aspect == pattern_data[1]) then
if (k2 == pattern_data[2]) then
if (pronoun == pattern_data[3]) then
form_modified = pattern_data[4](form_modified)
irregular = true
end
end
end
end
end
if (unstressed) then
if (unstressed[paradigm_data["index"]]) then
form_modified = strip_accents(form_modified)
end
end
if (paradigm_data["paradigm_no_accent"][pattern]) then
form_modified = strip_accents(form_modified)..pronoun
else
if (not irregular) then
if (paradigm_data["accented_stem"]) then
if paradigm_data["ua_disyllabic"][pattern] then
form_modified = create_accented_form(strip_accents(form_modified)..pronoun, true)
else
form_modified = create_accented_form(strip_accents(form_modified)..pronoun, false)
end
else
form_modified = form_modified..pronoun
end
end
end
if (not toggle_json) then
table.insert(t, form_modified)
else
result[form_modified] = {pronoun, paradigm, stem}
end
end
if (not toggle_json) then
local parameter = paradigm .. "_" .. aspect .. "_" .. k2
if (result[parameter]) then
result[parameter] = result[parameter] .. ',' .. table.concat(t, ',')
else
result[parameter] = table.concat(t, ',')
end
end
end
end
end
end
if (toggle_json) then
return json.jsonValueFromValue(result)
end
if not toggle_decorate then
return result
end
result["inf_ref"] = forms[1]
return decorate_inflections(result, false, nil, nil)
end
function export.headword_line(frame)
local args = unpack_args(frame)
local categories = {}
local forms = export.inflect(args, categories, true)
if forms then
local result = {title = "head", args = {[1] = "es",
[2] = "verb",
[3] = 'first-person singular present',
[5] = 'first-person singular preterite',
[7] = 'past participle'}}
if (forms[7]) then
result.args[4] = forms[7]
end
if (forms[20]) then
result.args[6] = forms[20]
end
if (forms[3]) then
result.args[8] = forms[3]
end
return frame:expandTemplate(result) .. table.concat(categories)
else
error("No inflection data found")
end
end
function export.verb_table(frame)
local calling_title = mw.title.getCurrentTitle()
local m_table = require("Module:es-conj/table")
local args = unpack_args(frame)
if (args[5]) then
return export.json_wikt_forms(frame)
end
categories = {}
local forms = export.inflect(args, categories, true)
if (args[7]) then
return export.inflect_combined(export.inflect(args, categories, false), args, false, true)
end
if (args[6]) then
local combined = export.inflect_combined(export.inflect(args, categories, false), args, true)
if calling_title.namespace == 0 then
return m_table.create(frame, args, forms, combined) .. table.concat(categories)
else
return m_table.create(frame, args, forms, combined)
end
end
if forms then
if calling_title.namespace == 0 then
return m_table.create(frame, args, forms) .. table.concat(categories)
else
return m_table.create(frame, args, forms)
end
else
error("No inflection data found")
end
end
function export.boiler(frame)
local args = frame:getParent().args
local ending = args[1]
local pattern = args[2]
local pattern_data = deepcopy(require("Module:es-conj/data/"..ending.."/"..pattern))
local description = pattern_data["description"]
local categories = '[[Category:按變位分類的西班牙語動詞]][[Category:以'..ending..'結尾的西班牙語動詞]]'
if description then
return description..categories
else
return categories
end
end
return export