Module:nv-conj
- The following documentation is located at Module:nv-conj/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
The purpose of this module is to automatically generate conjugation tables for Navajo verbs, similar to the output of the {{nv-verbtable}}
template.
Introduction
[edit]This module is originally based on Kari's thesis (1978) with a sizeable number of additions, adaptations and fixes.
Overview of the supported features:
Covered | Not covered | |
---|---|---|
Mode | - Imperfective (∅, ni) - Perfective (yi, ni, si) - Future (∅, yi) |
- Iterative - Optative |
Persons | - 1 to 4 | - Unspecified - Spatial |
Numbers | - singular - dual - plural |
|
Paradigms | - highly to fairly productive - highly to fairly regular |
- unproductive or rare - too irregular - seriative |
Stem | - must be provided |
Usage
[edit]function
- Use
conj
when invoking the module directly, andshow
when invoking from a template.
- Use
|1=
- Mode, to choose from:
impf
,perf
orfut
. |2=
- Aspect marker (position VII), to choose from
∅
,ni
,si
,yi
oryii
. |3=
- Classifier (position IX).
|4=
- Stem (position X) must be provided by the user.
|disj=
- Disjunct prefix (position 0/I).
- If needed use
:
to separate multiple prefixes.
- If needed use
|obj=
- Object prefix (position IV/V).
|conj=
- Conjunct prefix (position VI).
- If needed use
:
to separate multiple prefixes.
The input prefixes can usually be written in their usual orthography with the glottal stop, but mind the following special conventions:
a
orʼi
- for either the a-away disjunct prefix or the unspecified object prefix.
á
orʼí
- for the á-thus disjunct prefix
ho
orhwi
.
- for the spatial object prefix
Pi
- for the b/y indirect object alternation.
As some verbs exhibit a number of irregular alternations, additional options are provided for the user to help the module generate the correct form.
|nodevoice=1
- Do not devoice stem initial consonant even after 1st person singular sh- or 2nd person duoplural h-.
|d-effect=
- Provides the form taken by the stem initial consonant when following the 1st person duoplural iid- prefix, when different from the expected d-effect.
|nospread=1
- Do not spread disjunct prefix high-tone to conjunct pre-stem syllable.
|hop=far
- Perform glottal stop hopping further right inside a 2nd singular prefix.
|dashift=
=1
- Shift to si- conjugation in the perfective plural for all persons.
=3
- Shift to si- conjugation in the perfective plural for 3rd and 4th persons only.
|neuter=
=ni
- Use ni- as the prefix for 3rd and 4th persons in ni- conjugations.
=∅
- Use ∅- as the prefix for 3rd and 4th persons in ni- conjugations.
Finally, in case the module is unable to generate the correct output for a particular form using the general rules, it is possible for the user to provide it explicitly with the following optional arguments:
|1sg=
|2sg=
|3sg=
|4sg=
|1dl=
|2dl=
|1pl=
|2pl=
|3pl=
|4pl=
Alternative usage
[edit]In the usage describe above, 4 parameters are mandatory (mode, aspect, classifier, stem) while the others are optional (including disjunct, object and conjunct prefixes).
There is also an alternative usage of the module with 7 mandatory parameters for mode, disjunct, obj, conjunct, aspect, classifier and stem, allowing a somewhat more condensed expression.
See examples below.
Examples
[edit]{{#invoke:nv-conj|conj|impf|∅|∅|cha}}
or using the wrapper template {{nv-conj}}
:
{{nv-conj|impf|∅|∅|cha}}
IMPERFECTIVE | singular | duoplural | plural |
---|---|---|---|
1st person | yishcha | yiicha | deiicha |
2nd person | nicha | wohcha | daahcha |
3rd person | yicha | daacha | |
4th person | jicha | dajicha |
{{nv-conj|perf|disj=kʼi|obj=y|conj=di|yi|∅|lééł|d-effect=ly}}
or using the condensed usage:
{{nv-conj|perf|kʼi|y|di|yi|∅|lééł|d-effect=ly}}
PERFECTIVE | singular | duoplural | plural |
---|---|---|---|
1st person | kʼidíílééł | kʼidiilyééł | kʼidadiilyééł |
2nd person | kʼidíínílééł | kʼidoolééł | kʼidadoolééł |
3rd person | kʼiidíílééł | kʼideidíílééł | |
4th person | kʼizhdíílééł | kʼidazhdíílééł |
{{nv-conj|fut|disj=Pí|obj=ho|yii|ł|ʼááł}}
FUTURE | singular | duoplural | plural |
---|---|---|---|
1st person | bíhwiideeshʼááł | bíhwiidiilʼááł | bídahwiidiilʼááł |
2nd person | bíhwiidííłʼááł | bíhwiidoołʼááł | bídahwiidoołʼááł |
3rd person | yíhwiidoołʼááł | yídahwiidoołʼááł | |
4th person | bíhwiizhdoołʼááł | bídahwiizhdoołʼááł |
Note that the following call would have given the same output:
{{nv-conj|fut|disj=Pí|obj=hwii|∅|ł|ʼááł}}
As a matter of fact, it might be sometimes useful to try shuffling prefixes around until the correct forms be generated.
Unsupported paradigms
[edit]Imperfective
[edit]- seriative
- ...
Perfective
[edit]- "make"-verbs based on the -dzaa, -laa or -ʼį́į́d stems.
- paradigms with ní ~ néé ~ née ~ nées alternations.
- paradigms with díní ~ déé ~ dées alternations.
- paradigms with di-si ~ diiz alternations.
- most of yini-/yíní- paradigms.
- seriative
- ...
Future
[edit]- seriative
- ...
--[[
Based on Kari's paper (1978)
with several personal additions, adaptations and fixes.
NOTES:
- Lua regex are very expensive, had to scale back my all-regex coding paradigm.
- In order to facilitate usage of Lua regex (which are very limited), consonants are converted to a one-symbol format (ex: q for k', č for ch...), then rules are applied, then the word is converted back to conventional orthography.
TODO:
- seriative,
- "make" verbs in the perfective,
- get rid of the ":" altogether as a formative boundary.
]]
local p = {}
local umatch= mw.ustring.match
local ufind = mw.ustring.find
local subst = mw.ustring.gsub
local UTF8_char = "[\1-\127\194-\244][\128-\191]*"
-- forward declarations
local convert, fut_adjustment_conj
-- ENTRY POINTS
function p.show(frame)
return p.conj(frame:getParent())
end
function p.conj(frame)
local f = frame.args
-- retrieve parameters
get_params(frame)
local data = {}
data.form_1sg = f["1sg"] or proc("1sg")
data.form_2sg = f["2sg"] or proc("2sg")
data.form_3sg = f["3sg"] or proc("3sg")
data.form_4sg = f["4sg"] or proc("4sg")
data.form_1dl = f["1dl"] or proc("1dl")
data.form_2dl = f["2dl"] or proc("2dl")
data.form_1pl = f["1pl"] or proc("1pl")
data.form_2pl = f["2pl"] or proc("2pl")
data.form_3pl = f["3pl"] or proc("3pl")
data.form_4pl = f["4pl"] or proc("4pl")
if frame.args["test"] then
return make_string(data)
else
return make_table(data)
end
end
function get_params(frame)
-- convert 7-args mode to 4-args mode
if frame.args[7] then
frame.args["conj"]=frame.args[4]
frame.args["obj"] =frame.args[3]
frame.args["disj"]=frame.args[2]
frame.args[4] =frame.args[7]
frame.args[3] =frame.args[6]
frame.args[2] =frame.args[5]
end
mode_ = frame.args[1]
asp_ = frame.args[2]
cl_ = frame.args[3]
stem_ = frame.args[4]
disj_ = frame.args["disj"] or ""
conj_ = frame.args["conj"] or ""
obj_ = frame.args["obj"] or ""
neuter_= frame.args["neuter"] -- ni / ∅
nodevoice_= frame.args["nodevoice"]
d_effect_= frame.args["d-effect"]
nospread_= frame.args["nospread"]
dashift_= frame.args["dashift"]
hop_ = frame.args["hop"] or ""
-- underlying representations
-- TODO: improve below code
-- manage multiple disj/conj prefs
if disj_ == "a" then disj_ = "ʼi"
elseif disj_ == "á" then disj_ = "ʼí"
--elseif disj_ == "á" then disj_ = "ʼá"
end
disj_ = subst(disj_, "kó", "kwí")
if obj_ == "a" then obj_ = "ʼi"
elseif obj_ == "y" then obj_ = "yi"
elseif obj_ == "ho" then obj_="hwi"
end
fut_=""
if mode_=="fut" then
fut_adjustment_conj()
end
disj_ = convert(disj_)
obj_ = convert(obj_)
conj_ = convert(conj_)
stem_ = convert(stem_)
has_hiss = ufind(stem_, "[szcʒ]")
has_hush = ufind(stem_, "[šžčćj]")
end
-- PARADIGMS
local paradigms={}
paradigms["impf"] = {}
P = paradigms["impf"]
P["∅"] ={ "š","ni", "", "iid", "oh"}
P["ni"] ={"niš","ní","ni","niid","noh"}
P["yii"]={"iiš","ii","ii", "iid","ooh"}
--P["í"] ={"ísh","íní","í", "íid", "óh"}
paradigms["perf"] = {}
P = paradigms["perf"]
P["yi"] ={"ğí", "ğíní","ğí","iid","oo"}
P["yid"]={"ğiš","ğíní","ği","iid","ooh"}
P["ni"] ={"ní","ğíní","ní","niid","noo"}
P["nid"]={"niš","ğíní","ni","niid","nooh"}
P["si"] ={"sé", "síní","z","siid","soo"}
P["sid"]={"sis","síní","s","siid","sooh"}
P["si2"] ={"é", "íní","ğez","eed","soo"}
P["si2d"]={"és","íní","ğes","eed","sooh"}
P["yii"]={"ii","ini","ii", "iid","oo"}
P["yiid"]={"iiš","ini","ii", "iid","ooh"}
paradigms["fut"] = {}
P = paradigms["fut"]
P["∅"] ={"ğeš", "ğí","ğo","ğiid","ğoh"}
--P["∅"] ={"eeš", "íí","oo","iid","ooh"}
-- REGEXP
local vowels = "aąáą́eęéę́iįíį́oǫóǫ́"
local V = "[".. vowels.."]"
local L = "[aąeęiįoǫ]"
local H = "[áą́éę́íį́óǫ́]"
local C = "[^:=#" .. vowels .."]"
local C0= "[^=#" .. vowels .."]*="
local K = "[^:=#yʼ" .. vowels .."]"
local I = "[ií]"
local O = "[oó]"
local S = "[sš]"
local high_tone = {
["a"] = "á", ["e"] = "é",
["i"] = "í", ["o"] = "ó"
}
local low_tone = {
["á"] = "a", ["é"] = "e",
["í"] = "i", ["ó"] = "o"
}
local d_effect_map = {
["z"] = "ʒ", ["ž"] = "j",
["ğ"] = "g", ["y"] = "ʼy",
["w"] = "ʼw", ["l"] = "dl",
["ʼ"] = "tʼ", ["m"] = "ʼm",
["n"] = "ʼn"
}
--Note: stem must be provided with etymological y or gh, so as to elicit proper d-effect.
local devoicing = {
["z"] = "s", ["ğ"] = "h",
["ž"] = "š", ["l"] = "ł",
["w"] = "h", ["y"] = "h",
}
local surds = "([sšhł])"
local voiced = "([zžğwyl])"
local function at(str, i)
if i == 0 then
return ""
elseif i < 0 then
local n = 0
local characters = {}
for character in string.gmatch(str, UTF8_char) do
n = n + 1
characters[n] = character
end
return characters[n + i + 1]
else
local n = 0
for character in string.gmatch(str, UTF8_char) do
n = n + 1
if n == i then
return character
end
end
end
return ""
end
local function assimilate(i, v)
v = at(v, 1) -- first vowel if long
if i == "í" then
return high_tone[v] or v
end
v = low_tone[v] or v
return subst(i, "i", v)
end
local function split_pref(pref)
cv,f = umatch(pref, "^(.-)([sšhd]*)$")
return cv, f
end
local function append(pref)
if not pref or pref == "" then
return
end
if form_ ~= "" then
last = at(form_, -1)
if last == "#" or last == "=" then
form_ = form_.. pref
else
form_ = form_.. ":".. pref
end
else
form_ = pref
end
end
local abbrs = {
V = V, H = H, L = L, C0 = C0, C = C, I = I, O = O, K = K,
}
local function expand_regex(str)
return string.gsub(str, "[VHLCIOK]0?", abbrs)
--[[ expanding manually instead to speed up? Not faster actually...
ret=""
d=""
for c in mw.ustring.gmatch(str,".") do
if c == "V" then ret=ret..V
elseif c == "H" then ret=ret..H
elseif c == "L" then ret=ret..L
elseif d == "C" and c== "0" then
ret=ret..C0
elseif d == "C" and c ~= "0" then
ret=ret..C..c
elseif c == "I" then ret=ret..I
elseif c == "O" then ret=ret..O
elseif c == "K" then ret=ret..K
elseif c ~= "C" then ret=ret..c
end
d = c
end
return ret
]]
end
local function replace(str1, str2)
str1 = expand_regex(str1)
form_ = subst(form_, str1, str2)
end
-- basic replace without wildcard
local function replace2(str1, str2)
form_ = subst(form_, str1, str2)
end
local function match(str2)
str2 = expand_regex(str2)
return umatch(form_, str2)
end
-- basic replace without wildcard
local function match2(str2)
return umatch(form_, str2)
end
di2mono = {
["kw"] = "q",
["hw"] = "f",
["kʼ"] = "ç",
["čʼ"] = "ć", -- trick
["tʼ"] = "ť",
["ts"] = "c",
["sh"] = "š",
["zh"] = "ž",
["gh"] = "ğ",
["ch"] = "č",
["dz"] = "ʒ"
}
mono2di = {
["q"] = "kw",
["f"] = "hw",
["ç"] = "kʼ",
["ć"] = "chʼ",
["ť"] = "tʼ",
["c"] = "ts",
["š"] = "sh",
["ž"] = "zh",
["ğ"] = "gh",
["č"] = "ch",
["ʒ"] = "dz",
["ñ"] = "n"
}
-- declared as local above
function convert(str)
-- using regex only is too expensive
-- doing it manually
ret = ""
d = ""
for c in mw.ustring.gmatch(str,".") do
if d == "" then
d=c
else
m = di2mono[d..c]
if m and m == "č" then
d = "č"
elseif d == "č" and not m then
ret = ret.."č"
d = c
elseif m then
ret = ret.. m
d = ""
else
ret = ret.. d
d = c
end
end
end
ret = ret.. d
return ret
end
local function convert_back()
-- using regex only is too expensive
-- doing it manually
ret =""
d = ""
for c in mw.ustring.gmatch(form_,".") do
if c ==":" or c=="=" or c=="#" then
elseif ret == "" and c == "ʼ" then
elseif d == "s" and c == "h" then
ret = ret.."x"
elseif d == "s" and c == "s" then
elseif d == "sh" and c == "š" then
elseif d == "z" and c == "z" then
elseif d == "zh" and c == "ž" then
elseif c == "ğ" or c == "f" then
d = c
elseif d == "ğ" then
if umatch(c, "[eęiįéę́íį́]") then
d="y"
elseif umatch(c,"[oǫóǫ́]") then
d="w"
else
d="gh"
end
ret=ret.. d..c
elseif d == "f" then
if umatch(c, "[oǫóǫ́]") then
d="h"
else
d="hw"
end
ret=ret..d..c
else
d = mono2di[c] or c
ret = ret .. d
end
end
form_=ret
end
--#################################
-- RULES
-- declared as local above
function fut_adjustment_conj()
fut_="di"
if asp_=="yii" then
fut_="ği:".. fut_
asp_="∅"
end
end
local function fut_adjustments()
-- di- positioning
replace2("di:([yh][ií])", "%1:di")
-- high-tone future
replace2("d[ií]:n[ií]", "dí:ní")
-- methateses that need early ordering
replace ("ji:y(I)", "y%1:ji")
replace2("(.[:#])ji:ği", "%1ği:ji")
replace2("(.+)#yi:ği", "%1#yi")
end
local function ni_adjustments()
if neuter_ then
if neuter_ == "∅" then
replace2(":?ni=", "=")
end
replace2("(.[#:])łi=", "%1l=")
else -- "active" verb
-- yini/yíní tentatively managed hee
replace2("yí:ni=", "ó=") -- yíníshta'
replace2("ğí:ni=", "ó=") -- 'ííníshta'
-- yinishyé-wolyé-joolyé-daolyé mess
replace2("da#ği:ni=", "da#ğo=")
replace2("^#ği:ni=", "#ğo=")
replace2("ği:ni=", "oo=")
-- conj-dominant
if conj_ ~= "" then
replace2(":ni=", ":ğe=")
else
-- ∅- or da- dominant
replace2("^#ni=", "#yí=")
replace2("^da#ni=", "da#yí=")
-- disj-dominant
replace2("#ni=", "#=")
end
end
end
local function yii_adjustments()
-- yi_doubling
replace2("^#yi:ii", "#yi:yi:ii")
-- dis: ii > i, but da#ii > dayii or dei
if mode_ == "impf" then
replace2("da#ii=", "da#yi:ii=")
else
replace2("da#ii=", "da#yi=")
end
replace("(V)#ii(:?š?)=", "%1#i%2=")
-- ho adjustments: hwi+ii > hoo
replace2("fi:ii(:?š?)=", "ho:o%1=")
-- object-dominant 2sg
if obj ~= "" and conj_ == "" and rank == 2 then
replace2("ini=", "iini=")
end
end
local function yi_adjustments()
-- yi_doubling
replace2("^#yi:ğí=", "#yi:yi:ğí=")
-- hwi-delab needed before gamma_del
-- for 1sg: hwi:ğí= > hóó, not hwíí
replace2("fi:ğí=", "ho:ğí=")
end
local function yi_d_adjustments()
-- conjunct
if rank == 3 then
replace2("#(.+)ği=", "#%1ğo=")
elseif rank == 1 then
replace2("#(.+)ği:š=", "#%1ğe:š=")
end
-- a-away + perfective = ee
replace2("ʼi#ği(:?š?)=", "ʼi#ğe%1=")
end
local function si_adjustments()
-- yini
replace2("da#ği:([sz])=","da#ğo:%1=")
replace2("ği:([sz])=","oo:%1=")
-- yiz + ł = yis
replace2("z=ł:", "s=ł:")
-- #s=gan > sigan
replace2("^#[sz]=([∅ł])", "#si=%1")
-- ni:soo > noo or sinoo
if rank==5 then
replace2("^#ni:soo", "#si:noo")
replace2("^da#ni:soo", "da#si:noo")
replace2("ni:soo", "noo")
end
end
local function seriative_h_deletion() --13
replace("(#.+:)hi(C0)","%1ii%2")
replace2("(#.+:)hi:","%1yi:")
end
local function d_effect()
-- handle 1dl cases first
replace2( ":d=ł:l", "=dl")
replace2( ":d=[łl]:", "=l:")
replace2( ":d=[d∅]:", "=d:")
replace2( "=∅:", "=")
-- apply d-effect
-- special cases
if stem_ == "zǫ́ǫ́z" or stem_=="zǫ́ǫ́s" then
replace2("=d:z", "=d")
elseif stem_ == "ʼeeł" or stem_ == "ʼéél" or stem_ == "ʼoł" then
replace2("=d:", "=")
else
c = match("=d:(C)")
if c then
dc = d_effect_ or d_effect_map[c] or c
replace2("=d:"..c, "=".. dc)
end
end
end
local function continuant_devoicing() --18
if nodevoice_ then
return
end
exp = surds.."([:=])"..voiced
s, sep, v = match2(exp)
if s and sep and v then
f = devoicing[v]
replace2(s..sep..v, s..sep..f)
end
end
local function barred_l_deletion() --23
replace2("=ł:([sšł])", "=%1")
end
local function h_deletion() --32
replace2(":h=ł:", "=ł")
end
local function classifier_deletion() --30
replace2("([sš])=ł:", "%1=")
end
local function cons_degemination() --26
-- replace(":?s=s", "=s")
-- replace(":?š=š", "=š")
end
local function pepet_vowel_insertion() --46
replace("#(C0)", "#i%1")
end
local function vowel_deletion() --12
replace("(C)i:(V)", "%1%2")
end
local function tone_assimilation() --39
-- acceleration
if not has_high then return end
--disjunct
if not nospread_ and has_disj then
h,l,c0 =match("(H#C?:?C?:?C?)(L)(C0)")
if h and l and c0 then
a = high_tone[l]
replace2(h..l..c0, h..a..c0)
end
end
--conjunct
t,h,l = match("#(.*)(H:?C?:C)(L)")
if t and h and l then
a = high_tone[l]
replace2(t..h..l,t.. h..a)
end
end
local function tone_lowering() --48
--used for ní:ii --> nii
--what about ní:oh --> nó ?
--[[ moved to paradigm adjustments
h, l = match("(H)(:L)")
if h and l then
replace2(h..l, low_tone[h]..l)
end
]]
end
local function gamma_tone_assim()
-- acceleration
if not has_high or nospread_ or not has_disj then return end
h,l,c0 = match("(H#ğ)(L)(C0)")
if h and l and c0 then
a = high_tone[l]
replace2(h..l..c0, h..a..c0)
end
end
local function gamma_deletion() --41
replace2("(#.*)ğ([ieoíéó].*=)", "%1%2")
-- future mode might need a second run
replace2("(#.*)ğ([ieoíéó].*=)", "%1%2")
end
local function n_deletion() --?
-- made it a late rule instead
-- bą́:ná#ʼ:dí:š doesn't work, why?
-- chʼínéísííd doesn't contract,
-- chʼééínísííd does.
-- acceleration
if not (has_disj and has_high) then return end
c, v, c0, c1 = match(
"(C)(V):n[áé][#:][ií]?:?(C.-)V(.*=)")
if c and v and c0 and c1 and
c ~= "ʼ" then
h = high_tone[v] or v
if h == "í" then
h="é"
end
replace2(c..v..":n[áé]", c..h..h)
end
end
local function tone_raising() --49
-- acceleration
if not has_high then return end
l,s,h = match("(L)([#:])([íá])")
if l and s and h then
a = high_tone[l]
replace2(l..s..h, a..s..h)
end
end
local function vowel_assimilation() --57
-- special cases
if has_disj then
c, c0 = match("(C)i#i(C0)")
if c and c0 and
c ~="n" and c ~= "ʼ" then
replace2("i#i", "e#e")
end
end
-- a+o = aa dialects, 2dl/pl only
if pref == "oh" then
replace2("([aá])#o", "%1#a")
end
-- progressive
v, s, i, c0 = match("(V)([#:])(I+)(C0)")
if v and s and i and c0 and
not ufind(v..s..i, "[aá]#ii") then
a = assimilate(i, v)
replace2(v..s..i..c0,
v..s..a..c0)
end
-- regressive disj
if has_disj then
b, i, v, c0 = match(
"([^kqhtc])(I)#(V+)(C0)")
if b and i and v and c0 then
a = assimilate(i, v)
replace2(b..i.."#"..v..c0,
b..a.."#"..v..c0)
end
end
-- regressive conj
-- Note: hwi:o > hwo:o, should > ho:o
-- to manage in convert_back
-- along with gho > wo
c,i,v = match("#(.*)(I):(V)")
if c and i and v then
a = assimilate(i,v)
replace("#".. c.. i..":".. v,
"#".. c.. a..":".. v)
end
end
local function vowel_absorption() --62
-- acceleration
if not has_disj then return end
-- acceleration
if not has_high then return end
-- in C0 environment only
if match("V#VC0") then
replace2("([ʼł])í#i","%1í#")
replace2("í#i","é#")
replace2("ó#o","ó#")
replace2("á#a","á#")
replace2("é#e","é#")
end
--[[ not necessarily faster...
c, h, l, c0 = match("(C)(H)#(L)(C0)")
if c and h and l and c0 then
if h=="í" and l=="i" or
h=="á" and l=="a" or
h=="ó" and l=="o" or
h=="é" and l=="e" then
v=h
if h == "í" and
not(c=="ʼ" or c=="ł") then
v="é"
end
replace2(h.."#"..l,v.."#")
end
end
]]
end
--function optative_tone_lowering() --51
local function y_deletion() --42
-- acceleration
if not has_disj then return end
-- short i only
replace("(V)#y(I)([:=]C)", "%1#%2%3")
end
local function vowel_fronting() --67
-- acceleration
if not has_disj then return end
replace("([^kqht])a#(I)", "%1e#%2")
replace("([^kqht])á#(I)", "%1é#%2")
end
local function vowel_degemination() --47
-- TODO: might not be enough
-- need refactoring
replace("(I)[#:]ii", "%1i")
replace("(O)[#:]oo", "%1o")
end
local function seriative_assimilation()
-- split from vcv_assimilation
-- must take place before ni-abs
-- to prevent náhí- from assimilating
-- acceleration
if not has_disj then return end
v, i, c0 = match("(V)#h(I)(C0)")
if v and i and c0 then
replace2(v.."#h"..i, v.."#h"..v)
end
end
local function vcv_assimilation() --44
-- NOTE: seriative case has been split
-- only at #-boundary?
-- only in zero environment?
-- acceleration
if not has_disj then return end
-- special case
replace2("ʼi#ʼi([:=])", "ʼe#ʼe%1")
-- regressive
k,i,c,v = match("(C)(I)#([mkghʼ])(V)")
if k and i and c and v and k~="y" then
a = assimilate(i, v)
replace2(i.."#"..c..v,
a.."#"..c..v)
end
end
local function i_to_a() --71
--NOTE: easier to split rule in 2 parts
replace("ʼi=", "ʼa=")
-- can't do that here
-- because of ná'í- 2sg vs 3sg, unless
-- i_to_a applies after tone_assim?
--replace("ʼí=", "ʼá=")
i,s,c= match("ʼ(I)([#:]=?)(C)")
if i and s and c and c ~= "ʼ" then
a = assimilate(i,"a")
replace2( "ʼ"..i..s..c,
"ʼ"..a..s..c)
end
end
local function delabialization1() --78
--TODO: C should exclude "y" here.
--NOTE: Getting huge contradictions
-- with regards to the ordering of
-- the ho-to-ha, v-deletion,
-- gamma-deletion, ni-absorption
-- and pepet vowel insertion rules
-- ==> handle some cases directly here
-- ==> split hwi from kwí
-- kwí must be done before pepet
-- hwi must be done after gamma_del
--
-- Maybe should replace all this with a
-- with a late labialization rule
-- instead, where :
-- ho + ííní = hwííní
-- ho + eesh = hweesh...
-- but ho + í_C[ = hóó by assimilation
-- acceleration
if not has_high then return end
replace("qí([#:=]*C)", "kó%1")
replace("qí#(O)", "kó#")
end
local function delabialization2()
replace("fi(C0)", "ha%1")
replace("fi:(C)", "ho:%1")
-- below managed as in convert_back
--replace("f(O)", "h%1")
end
local function ni_absorption() --11
--
v = match2("([io]):ni=")
if v then
a = high_tone[v]
replace2(v..":ni=", a.."=" )
end
end
local function pg_strident_assimilation() --83
-- might be other cases?
replace2("ji:ʒi", "ji:ji")
-- might combine directly w/ j_el
-- ji:dzi > ji:ji > i:ji
end
local function j_deletion() --94
replace2("ji:ji", "i:ji")
end
local function vowel_elision() --86
-- K = C - {y, ʼ}
-- "ji" doesn't elide in front of
-- another j (ex. dajijooba)
if match2("ji:j") then
return
end
replace("(.[:#]ʼ)i(:KV)", "%1%2")
replace("(.[:#][jʒ])i(:KV)", "%1%2")
end
local function deaffrication() --89
replace("j:(C)", "ž:%1")
replace("ʒ:(C)", "z:%1")
end
local function glottal_zh_metathesis() --91
replace2("ʼ:ž:", "ž:ʼ:")
end
local function glottal_cv_metathesis()
-- "far" hop allows glottal stop to
-- to hop "inside" 2sg prefix
-- ex: bighá#ʼdííní > bighá#dííʼní
-- but bą́ą́#ʼdííní > bą́ą́#ʼdííní
if hop_ == "far" then
replace("(ž?:?ʼ):(d:?V+:?V?):?(K:?V+)", "%2:%1:%3")
else
replace("(ž?:?ʼ):(d:?V+):?(K:?V+)", "%2:%1:%3")
end
end
local function zh_cv_metathesis()
-- doesn't apply to jidinii,
-- is that a more generic rule?
if match2("ji:di:n:ii") then
return
end
replace("ji:(C:?V+):(C:?V+)", "%1:ž:%2")
end
local function strident_assimilation() --81
if has_hiss then
replace2("š", "s")
elseif has_hush then
replace2("s", "š")
replace2("z", "ž")
end
end
local function syllabic_n() --100
-- split b/c of Lua regex limitations
replace2("n[ia]([#:]ʼ?:?[dtjʒ])","n%1")
replace2("n[íá]([#:]ʼ?:?[dtjʒ])","ń%1")
replace("na#(ʼ?:?[sš]V)", "ni#%1")
replace("ná#(ʼ?:?[sš]V)", "ní#%1")
replace2("na#(ž:ʼ?:?d)", "ni#%1")
replace2("ná#(ž:ʼ?:?d)", "ní#%1")
end
local function gamma_insertion() --6
-- acceleration
if has_disj then return end
replace("^#(V)", "#ğ%1")
end
local function gamma_gliding() --7
replace("ğ(I)", "y%1")
replace("ğ(O)", "w%1")
end
--#################################
-- MAIN FUNCTION
function proc(person)
-- PERSON
pers, numb = umatch(person,"([0-9])(..)")
pers = tonumber(pers)
da = (numb == "pl") and "da" or ""
subj = (pers == 4) and "ji" or ""
obj = (obj_ == "yi" and pers ~= 3 ) and "" or obj_
rank = (pers >= 3) and 3 or (numb == "sg") and pers or (pers + 3)
if dashift_ and numb=="pl" and
(dashift_ ~= "3" or rank==3) then
asp_="si"
end
-- Determination of paradigm to use
asp2_ = asp_
if mode_ == "perf" then
if asp_=="si" and
umatch(conj_, "[dnh]i$") then
asp2_ = asp_.."2"
end
if cl_=="d" or cl_=="l" then
asp2_ = asp2_ .. "d"
end
end
pref = paradigms[mode_][asp2_][rank]
p, pf = split_pref(pref)
-- UNDERLYING FORM
form_ = disj_
append(da); form_ = form_.."#"
append(obj)
append(subj)
append(fut_)
append(conj_)
append(p)
append(pf); form_ = form_.."="
append(cl_)
append(stem_)
--attempt at accelerating regex
has_disj= (disj_..da ~= "")
has_high= match("H")
if pers == 3 then
replace2("P", "y")
else
replace2("P", "b")
end
--form_=convert(form_)
--if true then return form_ end
-- IRREGULAR STEMS
if stem_ == "ááh" then
if person == "2sg" then
replace("=∅:ááh", "=nááh")
elseif pers == 2 then
replace("=∅:ááh", "=∅:hááh")
elseif rank == 3 then
replace("=∅:ááh", "=∅:ğááh")
end
elseif stem_=="yą́" or stem_=="yį́į́ł" then
if pers == 1 then
replace("=∅:y", "=")
elseif pers == 2 then
replace("h=∅:y", "h=s")
end
end
-- MODE READJUSTMENT RULES
if mode_ == "fut" then
fut_adjustments()
elseif asp_ == "∅" then
-- make this a more general rule?
-- or amend the tone-lowering rule?
-- or make "ní" its own paradigm?
-- how do manage both:
-- á#ní:iid > ániildííl, and
-- ní:iid > níilʼį́ ??
replace2("ní:ii", "ni:ii")
replace2("ní:o:h","nó:h")
-- prevent ni-absorption if ni6
if rank == 3 then
replace2("ni=", "ñi=")
end
elseif asp_ == "ni" then
ni_adjustments()
elseif asp_ == "yii" then
yii_adjustments()
elseif asp2_ == "yi" then
yi_adjustments()
elseif asp2_ == "yid" then
yi_d_adjustments()
elseif asp_ == "si" then
si_adjustments()
end
-- PHONOLOGICAL RULES
seriative_h_deletion() --13
d_effect() -- 24,35,25
continuant_devoicing() --18
barred_l_deletion() --23
h_deletion() --32
classifier_deletion() --30
-- below ordering is tricky
delabialization1() --78
--delab2 could go here w/ a labial rule
--delabialization2()
pepet_vowel_insertion() --46
vowel_deletion() --12
--tone_assimilation() --39
--tone_lowering() --48
gamma_tone_assim() --hack
gamma_deletion() --41
-- trying this here
-- must be before ni-abs so that
-- 2sg náhí- doesn't assimilate to náhá-
seriative_assimilation()
-- trying hwi-delab here
-- must be before ni-abs
-- hwi:ni-> ho:ni -> hó-
delabialization2()
ni_absorption() --11
-- moved tone_assim to later rule
-- so as to allow proper hwi delab
-- before tone assimilation kicks in
-- ná#haso -> ná#háso and not ná#hwíso
-- Might have to move it even after
-- v-elision and deaffrication for
-- words like łí#ji:di -> łí#zh:dí
-- issue: but tone_assim must be before
-- gamma_del for words like :
-- ná#ghi > ná#ghí > ná#í
-- ==> wrote a gamma_tone_assim rule
--tone_assimilation()
-- made it a late rule instead b/c
-- y_deletion hasn't applied yet
-- cf. chʼínéísííd (no contraction).
-- Actually, chʼínéísííd doesn't
-- contract b/c éí is considered one
-- vowel, so conditions are not met.
-- chʼééínísííd on the other side does
-- contract thanks to intervening ní.
--n_deletion() --?
tone_raising() --49
vowel_assimilation() --57
vowel_absorption() --62
--optative_tone_lowering() --51
y_deletion() --42
vowel_fronting() --67
vowel_degemination() --47
pg_strident_assimilation() --83
j_deletion() --94
vowel_elision() --86
deaffrication() --89
glottal_zh_metathesis() --91
glottal_cv_metathesis()
zh_cv_metathesis()
strident_assimilation() --81
-- i_to_a must be before
-- tone-assim but after ni-abs:
-- 2sg: ná#'i:ni > ná#'í
-- 3sg: ná#'i > ná#'a > ná#'á
-- if tone_assim before,
-- can't distinguish 2sg from 3sg
-- 3sg: ná#'i > ná#'í > ná#'á ??
i_to_a()
tone_assimilation()
vcv_assimilation() --44
-- LATE RULES
n_deletion()
--cons_degemination() --26
--i_to_a() --72
syllabic_n() --100
-- done in convert_back()
gamma_insertion() --III.6
--gamma_gliding() --III.7
-- FORMAT
convert_back()
return form_
end
--##################################
local nv = require("Module:languages").getByCode("nv")
local full_link = require("Module:links").full_link
function link(term)
return full_link{ term = term, lang = nv }
end
function make_table(data)
mode = "IMPERFECTIVE"
if mode_ == "perf" then
mode = "PERFECTIVE"
elseif mode_ == "fut" then
mode = "FUTURE"
end
return (string.gsub(
[=[{| style="margin-bottom: .1em; margin-right: 1em; width: 50em; border: 1px solid #AAAAAA; border-collapse: collapse; text-align: center;" cellpadding="4" rules="all"
! style="width: 98px; background-color: #EFEAAA; text-align: left; font-size: 90%;" | {{{mode}}}
! style="width: 162px; background-color: #EFEFFF; font-size: 90%;" | singular
! style="width: 162px; background-color: #EFEFFF; font-size: 90%;" | [[duoplural]]
! style="width: 162px; background-color: #EFEFFF; font-size: 90%;" | plural
|-
! style="background-color: #EFEFFF; text-align: left; font-size: 90%;" | 1st person
| {{{form_1sg}}}
| {{{form_1dl}}}
| {{{form_1pl}}}
|-
! style="background-color: #EFEFFF; text-align: left; font-size: 90%;" | 2nd person
| {{{form_2sg}}}
| {{{form_2dl}}}
| {{{form_2pl}}}
|-
! style="background-color: #EFEFFF; text-align: left; font-size: 90%;" | 3rd person
| colspan="2" | {{{form_3sg}}}
| {{{form_3pl}}}
|-
! style="background-color: #EFEFFF; text-align: left; font-size: 90%;" | 4th person
| colspan="2" | {{{form_4sg}}}
| {{{form_4pl}}}
|}]=],
'%{%{%{([^}]+)%}%}%}',
function(code)
local form_data = data[code]
return form_data and link(form_data) or code == 'mode' and mode or error('No content for the code ' .. code .. '.')
end))
end
function make_string(data)
return data.form_1sg.. " ".. data.form_1dl.. " "..data.form_1pl .. " "..data.form_2sg.. " ".. data.form_2dl.." "..data.form_2pl.. " ".. data.form_3sg.. " ".. data.form_3pl.. " "..data.form_4sg.. " "..data.form_4pl
end
return p