See Template:ja-acc-table for usage and examples.
--CURRENTLY A WORK IN PROGRESS
local export = {}
local match = mw.ustring.match
local m_str_utils = require("Module:string utilities")
local find = m_str_utils.find
local usub = m_str_utils.sub
local ulen = m_str_utils.len
local gmatch = m_str_utils.gmatch
local gsub = m_str_utils.gsub
local m_ja_pron = require("Module:ja-pron")
local range = mw.loadData("Module:ja/data/range")
local a_kana = range.vowels.a
local i_kana = range.vowels.i
local u_kana = range.vowels.u
local e_kana = range.vowels.e
local o_kana = range.vowels.o
local n_kana = range.vowels.n
local submoraic_kana = range.submoraic_kana
local function string_to_positive_integer(str)
if not string.match(str, "^%d+$") then
error("String \"" .. str .. "\" is not a positive integer")
end
return tonumber(str)
end
local function string_list_to_positive_integer_list(str_list)
local result = {}
for _, str in ipairs(str_list) do
local i = string_to_positive_integer(str)
table.insert(result, i)
end
return result
end
local morae_negative_pattern = ""
local function count_morae(kana)
return ulen(kana) - select(2, gsub(kana, morae_negative_pattern, ""))
end
function export.show(frame)
local params = {
= {},
= {},
= {},
= {sublist=true},
= {sublist=true},
= {sublist=true}
}
for _, v in pairs(params) do v.allow_empty = true end
local args = require("Module:parameters").process(frame:getParent().args, params)
local used_args = {}
local function get_arg(key, required)
local ret = args
if required and (ret == nil or ret == "" or (type(ret) == "table" and #ret == 1 and ret == "")) then
error("Parameter " .. key .. " is required")
end
used_args = true
return ret
end
local function err_unused_args()
for k, v in pairs(args) do
if not used_args then
error("Parameter " .. k .. " is not used")
end
end
end
local style
local type = get_arg(1, true)
if type == "verb-godan" then
style = {verb=true, godan=true}
elseif type == "verb-ichidan" then
style = {verb=true, ichidan=true}
else
error("Unknown type " .. type)
end
local lemma = get_arg("lemma", false) or mw.title.getCurrentTitle().text
local lemma_kana = get_arg(2, true)
lemma_kana = gsub(lemma_kana, "+$", "")
local kanji = lemma
local kana = lemma_kana
local kana_morae_str = gsub(kana, "", "")
local kana_morae_str_without_submoraic = gsub(kana_morae_str, morae_negative_pattern, "")
local n_morae = count_morae(kana)
local accs = string_list_to_positive_integer_list(get_arg("acc", true))
for _, acc in ipairs(accs) do
if acc > n_morae then error("Accent is larger than kana") end
end
local wikitext
if style.verb or style.adjective then
kana = usub(kana, 1, ulen(kana) - 1) .. "." .. usub(kana, ulen(kana), ulen(kana) + 1)
if usub(lemma, ulen(lemma), ulen(lemma) + 1) ~= usub(kana_morae_str, ulen(kana_morae_str), ulen(kana_morae_str) + 1) then
error("Lemma and kana do not have the same ending: " .. lemma .. " " .. lemma_kana)
end
if n_morae < 2 then error("Kana must have at least 2 morae") end
for _, acc in ipairs(accs) do
if acc == n_morae then error("Accent cannot be Odaka") end
end
local function add_infl(infl_table, kanji, kana, acc)
table.insert(infl_table, {kanji=kanji, kana=kana, acc=acc})
end
local penultimate_jiritsuhaku_pos
if n_morae > 2 then
penultimate_jiritsuhaku_pos = 1
for i = 2, ulen(kana_morae_str_without_submoraic) - 1 do
local mora = usub(kana_morae_str_without_submoraic, i, i)
local mora_is_jiritsuhaku = not find(mora, "^$")
if mora_is_jiritsuhaku then
penultimate_jiritsuhaku_pos = i
end
end
end
local function acc_is_deep(acc)
return penultimate_jiritsuhaku_pos and acc > 0 and acc < penultimate_jiritsuhaku_pos
end
local output_table
if style.verb then
local te_form_accs = string_list_to_positive_integer_list(get_arg("て-form-acc", true))
local te = {}
local nai = {}
local ba = {}
local imperative = {}
local volitional = {}
local desiderative = {}
local masu = {}
local renyokei = {}
local zu = {}
local passive = {}
local causative = {}
local potential = {}
if style.godan then
local kanji_prefix = usub(kanji, 1, ulen(kanji) - 1)
local kana_prefix = usub(kana, 1, ulen(kana) - 1)
local te_form_kanji
local te_form_kana
local xi, xa, xe, xo
local last_char = usub(kana, ulen(kana), ulen(kana) + 1)
if last_char == "う" then
te_form_kanji = kanji_prefix .. "って"
te_form_kana = kana_prefix .. "って"
xi = "い" xa ="わ" xe = "え" xo = "お"
elseif last_char == "く" then
te_form_kanji = kanji_prefix .. "いて"
te_form_kana = kana_prefix .. "いて"
xi = "き" xa ="か" xe = "け" xo = "こ"
elseif last_char == "ぐ" then
te_form_kanji = kanji_prefix .. "いで"
te_form_kana = kana_prefix .. "いで"
xi = "ぎ" xa ="が" xe = "げ" xo = "ご"
elseif last_char == "す" then
te_form_kanji = kanji_prefix .. "して"
te_form_kana = kana_prefix .. "して"
xi = "し" xa ="さ" xe = "せ" xo = "そ"
elseif last_char == "つ" then
te_form_kanji = kanji_prefix .. "って"
te_form_kana = kana_prefix .. "って"
xi = "ち" xa ="た" xe = "て" xo = "と"
elseif last_char == "ぬ" then
te_form_kanji = kanji_prefix .. "んで"
te_form_kana = kana_prefix .. "んで"
xi = "に" xa ="な" xe = "ね" xo = "の"
elseif last_char == "ぶ" then
te_form_kanji = kanji_prefix .. "んで"
te_form_kana = kana_prefix .. "んで"
xi = "び" xa ="ば" xe = "べ" xo = "ぼ"
elseif last_char == "む" then
te_form_kanji = kanji_prefix .. "んで"
te_form_kana = kana_prefix .. "んで"
xi = "み" xa ="ま" xe = "め" xo = "も"
elseif last_char == "る" then
te_form_kanji = kanji_prefix .. "って"
te_form_kana = kana_prefix .. "って"
xi = "り" xa ="ら" xe = "れ" xo = "ろ"
else
error("Unknown godan verb ending " .. kanji)
end
for _, te_form_acc in ipairs(te_form_accs) do
add_infl(te, te_form_kanji, te_form_kana, te_form_acc)
end
for _, acc in ipairs(accs) do
add_infl(nai, kanji_prefix .. xa .. "ない", kana_prefix .. xa .. "ない", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
add_infl(ba, kanji_prefix .. xe .. "ば", kana_prefix .. xe .. "ば", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return n_morae else return acc end end)())
add_infl(imperative, kanji_prefix .. xe, kana_prefix .. xe, (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return acc end end)())
add_infl(volitional, kanji_prefix .. xo .. "う", kana_prefix .. xo .. "う", (function() if acc_is_deep(acc) then return acc else return n_morae end end)())
add_infl(desiderative, kanji_prefix .. xi .. "たい", kana_prefix .. xi .. "たい", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(masu, kanji_prefix .. xi .. "ます", kana_prefix .. xi .. "ます", (function() if acc_is_deep(acc) then return acc else return n_morae + 1 end end)())
add_infl(renyokei, kanji_prefix .. xi, kana_prefix .. xi, acc)
add_infl(zu, kanji_prefix .. xa .. "ず", kana_prefix .. xa .. "ず", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
add_infl(passive, kanji_prefix .. xa .. "れる", kana_prefix .. xa .. "れる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(causative, kanji_prefix .. xa .. "せる", kana_prefix .. xa .. "せる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(causative, kanji_prefix .. xa .. "す", kana_prefix .. xa .. "す", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
add_infl(potential, kanji_prefix .. xe .. "る", kana_prefix .. xe .. "る", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
end
elseif style.ichidan then
if not find(kana_morae_str, "る$") then
error("Unknown ichidan verb ending " .. lemma_kana)
end
local kanji_prefix = usub(kanji, 1, ulen(kanji) - 1)
local kana_prefix = usub(kana, 1, ulen(kana) - 1)
local te_form_kanji = kanji_prefix .. "て"
local te_form_kana = kana_prefix .. "て"
for _, te_form_acc in ipairs(te_form_accs) do
add_infl(te, te_form_kanji, te_form_kana, te_form_acc)
end
for _, acc in ipairs(accs) do
add_infl(nai, kanji_prefix .. "ない", kana_prefix .. "ない", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae - 1 end end)())
add_infl(ba, kanji_prefix .. "れば", kana_prefix .. "れば", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return n_morae else return acc end end)())
add_infl(imperative, kanji_prefix .. "ろ", kana_prefix .. "ろ", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return acc end end)())
add_infl(imperative, kanji_prefix .. "よ", kana_prefix .. "よ", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return acc end end)())
add_infl(volitional, kanji_prefix .. "よう", kana_prefix .. "よう", (function() if acc_is_deep(acc) then return acc else return n_morae end end)())
add_infl(desiderative, kanji_prefix .. "たい", kana_prefix .. "たい", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
add_infl(masu, kanji_prefix .. "ます", kana_prefix .. "ます", (function() if acc_is_deep(acc) then return acc else return n_morae end end)())
add_infl(zu, kanji_prefix .. "ず", kana_prefix .. "ず", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae - 1 end end)())
add_infl(passive, kanji_prefix .. "られる", kana_prefix .. "られる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(causative, kanji_prefix .. "させる", kana_prefix .. "させる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(causative, kanji_prefix .. "さす", kana_prefix .. "さす", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
add_infl(potential, kanji_prefix .. "られる", kana_prefix .. "られる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae + 1 end end)())
add_infl(potential, kanji_prefix .. "れる", kana_prefix .. "れる", (function() if acc_is_deep(acc) then return acc elseif acc == 0 then return 0 else return n_morae end end)())
if acc == 0 or acc_is_deep(acc) then
add_infl(renyokei, kanji_prefix, kana_prefix, acc)
else
for _, te_form_acc in ipairs(te_form_accs) do
add_infl(renyokei, kanji_prefix, kana_prefix, te_form_acc)
end
end
end
end
for _, infl in ipairs(te) do
local te_form_acc = infl.acc
local te_form_n_morae = count_morae(infl.kana)
if te_form_acc == te_form_n_morae then error("て-form accent cannot be Odaka") end
if te_form_acc > te_form_n_morae then error("て-form accent is larger than kana") end
end
local plain = {}
for _, acc in ipairs(accs) do
add_infl(plain, kanji, kana, acc)
end
local ta = {}
for _, infl in ipairs(te) do
if usub(infl.kanji, ulen(infl.kanji), ulen(infl.kanji) + 1) == "で" then
for _, infl in ipairs(te) do
add_infl(ta, usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "だ", usub(infl.kana, 1, ulen(infl.kana) - 1) .. "だ", infl.acc)
end
else
for _, infl in ipairs(te) do
add_infl(ta, usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "た", usub(infl.kana, 1, ulen(infl.kana) - 1) .. "た", infl.acc)
end
end
end
local nakatta = {}
for _, infl in ipairs(nai) do
local nakatta_kanji = usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "かった"
local nakatta_kana = usub(infl.kana, 1, ulen(infl.kana) - 1) .. "かった"
local nakatta_acc
if infl.acc == 0 then
nakatta_acc = count_morae(nakatta_kana) - 3
else
nakatta_acc = infl.acc
end
add_infl(nakatta, nakatta_kanji, nakatta_kana, nakatta_acc)
end
local tara = {}
for _, infl in ipairs(ta) do
local tara_acc
if infl.acc == 0 then
tara_acc = count_morae(infl.kana)
else
tara_acc = infl.acc
end
add_infl(tara, infl.kanji .. "ら", infl.kana .. "ら", tara_acc)
end
local masen = {}
local mashou = {}
local mashita = {}
for _, infl in ipairs(masu) do
add_infl(mashita, usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "した", usub(infl.kana, 1, ulen(infl.kana) - 1) .. "した", infl.acc)
local masen_mashou_acc
if acc_is_deep(infl.acc) then
masen_mashou_acc = infl.acc
else
masen_mashou_acc = infl.acc + 1
end
add_infl(masen, usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "せん", usub(infl.kana, 1, ulen(infl.kana) - 1) .. "せん", masen_mashou_acc)
add_infl(mashou, usub(infl.kanji, 1, ulen(infl.kanji) - 1) .. "しょう", usub(infl.kana, 1, ulen(infl.kana) - 1) .. "しょう", masen_mashou_acc)
end
local continuative = {}
for _, infl in ipairs(renyokei) do
add_infl(continuative, infl.kanji, infl.kana, infl.acc)
add_infl(continuative, infl.kanji .. "に", infl.kana .. "に", infl.acc)
end
local negative_continuative = {}
for _, infl in ipairs(zu) do
add_infl(negative_continuative, infl.kanji, infl.kana, infl.acc)
add_infl(negative_continuative, infl.kanji .. "に", infl.kana .. "に", infl.acc)
end
output_table = {
{"Plain", plain},
{"Conjunctive", te},
{"Perfective", ta},
{"Negative", nai},
{"Negative perfective", nakatta},
{"Hypothetical conditional", ba},
{"Past conditional", tara},
{"Imperative", imperative},
{"Volitional", volitional},
{"Desiderative", desiderative},
{"Formal", masu},
{"Formal negative", masen},
{"Formal volitional", mashou},
{"Formal perfective", mashita},
{"Continuative", continuative},
{"Negative continuative", negative_continuative},
{"Passive", passive},
{"Causative", causative},
{"Potential", potential}
}
end
local wikitext_stringbuffer = {}
table.insert(wikitext_stringbuffer, '<div class="vsSwitcher" data-toggle-category="accent">\n<div style="display: inline-block;">\n* Tokyo pitch accent of inflected forms of <span lang="ja" class="Jpan">')
table.insert(wikitext_stringbuffer, lemma)
table.insert(wikitext_stringbuffer, '</span><span class="vsToggleElement" style="margin-left: 1em;"></span></div>\n<div class="vsHide">\n{| class="wikitable" style="white-space: nowrap;"\n')
for _, v in ipairs(output_table) do
local label = v
local infl_table = v
table.insert(wikitext_stringbuffer, '! ')
table.insert(wikitext_stringbuffer, label)
table.insert(wikitext_stringbuffer, '\n| ')
local kanji = {}
local ja_pron_accs = {}
local ja_pron_romajis = {}
local kanji_duplicate = {}
local kana_acc_duplicate = {}
for _, infl in ipairs(infl_table) do
if not kanji_duplicate then
table.insert(kanji, infl.kanji)
kanji_duplicate = true
end
local kana_acc_duplicate_key = infl.kana .. " " .. infl.acc
if not kana_acc_duplicate then
local ja_pron_acc, ja_pron_romaji = match(m_ja_pron.accent(infl.kana, infl.acc), '(<span lang="ja" class="Jpan">.-) (<span class="Latn"><samp>.-</samp></span>)')
table.insert(ja_pron_accs, ja_pron_acc)
table.insert(ja_pron_romajis, ja_pron_romaji)
kana_acc_duplicate = true
end
end
for i, k in ipairs(kanji) do
table.insert(wikitext_stringbuffer, '<span class="Jpan" lang="ja-Jpan">')
table.insert(wikitext_stringbuffer, k)
table.insert(wikitext_stringbuffer, '</span>')
if i ~= #kanji then
table.insert(wikitext_stringbuffer, '<br>')
end
end
table.insert(wikitext_stringbuffer, '</span>')
table.insert(wikitext_stringbuffer, '\n| ')
for i, ja_pron_acc in ipairs(ja_pron_accs) do
table.insert(wikitext_stringbuffer, ja_pron_acc)
if i ~= #ja_pron_accs then
table.insert(wikitext_stringbuffer, '<br>')
end
end
table.insert(wikitext_stringbuffer, '\n| ')
for i, ja_pron_romaji in ipairs(ja_pron_romajis) do
table.insert(wikitext_stringbuffer, ja_pron_romaji)
if i ~= #ja_pron_romajis then
table.insert(wikitext_stringbuffer, '<br>')
end
end
table.insert(wikitext_stringbuffer, '\n|-\n')
end
table.insert(wikitext_stringbuffer, '|}</div></div>')
wikitext = table.concat(wikitext_stringbuffer)
end
err_unused_args()
return wikitext
end
return export