Module:User:Erutuon/grc

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Lua error at line 913: attempt to call field 'pattern_escape' (a nil value) Lua error at line 913: attempt to call field 'pattern_escape' (a nil value) Lua error at line 913: attempt to call field 'pattern_escape' (a nil value) Lua error at line 913: attempt to call field 'pattern_escape' (a nil value)

==Ancient Greek==

===Pronunciation===
{{grc-IPA}}

===Participle===
{{grc-part-1&3|εἰδυῖᾰ|εἰδός}}

# {{inflection of|grc|οἶδᾰ||perf|act|part}}

====Declension====
{{grc-adecl|εἰδώς|εἰδυῖᾰ}}
==Ancient Greek==

===Pronunciation===
{{grc-IPA|ἔδοσᾰν}}

===Verb===
{{grc-verb form|ἔδοσᾰν}}

# {{inflection of|grc|δῐ́δωμῐ||3|p|aor|act|ind}}
==Ancient Greek==

===Pronunciation===
{{grc-IPA|ἔδοσᾰν}}

===Verb===
{{grc-verb form|ἔδοσᾰν}}

# {{inflection of|grc|δῐ́δωμῐ||3|p|aor|act|ind}}

Lua error at line 913: attempt to call field 'pattern_escape' (a nil value)

==Ancient Greek==

===Etymology===
Substantivization of the feminine of {{subst:chars|m|grc|doti^ko/s}}.

===Pronunciation===
{{grc-IPA|δοτῐκή}}

===Noun===
{{grc-noun|δοτῐκή|δοτῐκῆς|f|first}}

# the dative case

====Declension====
{{grc-decl|δοτῐκή|δοτῐκῆς}}

===Further reading===
* {{R:LSJ|δοτικός}}

Lua error at line 913: attempt to call field 'pattern_escape' (a nil value)

==Ancient Greek==

===Pronunciation===
{{grc-IPA}}

===Adjective===
{{grc-adj-1&2|σή|σόν}}

# your

====Declension====
{{grc-adecl|σός|σή}}

===Further reading===
* {{R:LSJ}}
==Ancient Greek==

===Pronunciation===
{{grc-IPA|Πηληῐ̈ᾰ́δης}}

===Noun===
{{grc-noun|Πηληῐ̈ᾰ́δης|Πηληῐ̈ᾰ́δεω|m|first}} {{tlb|grc|Epic}}

# son of Peleus

====Declension====
{{grc-decl|Πηληῐ̈ᾰ́δης|Πηληῐ̈ᾰ́δεω|form=sing|dial=epi}}

===Further reading===
* {{R:LSJ}}
==Ancient Greek==

===Pronunciation===
{{grc-IPA}}

===Noun===
{{grc-noun|δήμου|m|second}}

# people, nation

====Declension====
{{grc-decl|δῆμος|δήμου}}

===Further reading===
* {{R:LSJ}}
* {{R:Cunliffe}}

local export = {}

local add_dotted_circle = require("Module:Unicode data").add_dotted_circle
local highlight = require("Module:debug").highlight { lang = "html" }
local Latin_to_Greek = require("Module:User:Erutuon/grc/Latin to Greek")
local tokenize = require("Module:grc-utilities").tokenize

local grc = require("Module:languages").getByCode("grc")
local function make_entry_name(text)
	return grc:makeEntryName(text)
end

local title = mw.title.getCurrentTitle()
local namespace = title.nsText
local pagename = title.text
local nonmainspace = namespace ~= ""

local str_find = string.find
local str_gsub = string.gsub
local str_gmatch = string.gmatch

local ufind = mw.ustring.find
local umatch = mw.ustring.match
local decompose = mw.ustring.toNFD
local U = mw.ustring.char
local macron = U(0x304)
local breve = U(0x306)
local rough = U(0x314)
local smooth = U(0x313)
local diaeresis = U(0x308)
local acute = U(0x301)
local grave = U(0x300)
local circumflex = U(0x342)
local subscript = U(0x345)
local diacritic_patt = table.concat {
	"[",
	macron, breve,
	rough, smooth, diaeresis,
	acute, grave, circumflex,
	subscript,
	"]"
}

local UTF8_char = "[%z\1-\127\194-\244][\128-\191]*"
local basic_Greek = "[\206-\207][\128-\191]" -- excluding first line of Greek and Coptic block: ͰͱͲͳʹ͵Ͷͷͺͻͼͽ;Ϳ

-- Includes ͰͱͲͳʹ͵Ͷͷͺͻͼͽ;Ϳ
-- local diacritic = "[\204-\205][\128-\191]"

local decompose = mw.ustring.toNFD

local function quote(str)
	return "“" ..  str .. "”"
end

local info = {}

-- The tables are shared among different characters so that they can be checked
-- for equality if needed, and to use less space.
local vowel = { vowel = true, diacritic_seat = true }
local iota = { vowel = true, diacritic_seat = true, offglide = true }
local upsilon = { vowel = true, diacritic_seat = true, offglide = true }
-- Technically rho is only a seat for rough or smooth breathing.
local rho = { consonant = true, diacritic_seat = true }
local consonant = { consonant = true }
local diacritic = { diacritic = true }
-- Needed for equality comparisons.
local breathing = { diacritic = true }

local function add_info(characters, t)
	if type(characters) == "string" then
		for character in string.gmatch(characters, UTF8_char) do
			info[character] = t
		end
	else
		for i, character in ipairs(characters) do
			info[character] = t
		end
	end
end

add_info({ macron, breve,
		diaeresis,
		acute, grave, circumflex,
		subscript,
	}, diacritic)

add_info({rough, smooth}, breathing)
add_info("ΑΕΗΟΩαεηοω", vowel)
add_info("Ιι", iota)
add_info("Υυ", upsilon)
add_info("ΒΓΔΖΘΚΛΜΝΞΠΡΣΤΦΧΨϜϘϺϷͶϠβγδζθκλμνξπρσςτφχψϝϙϻϸͷϡ", consonant)
add_info("Ρρ", rho)

local not_recognized = {}
setmetatable(info, { __index =
	function(t, key)
		return not_recognized
	end
})

-- Equivalent of the current function.
function export.tokenize(text)
	local tokens, vowel_info, prev_info = {}, {}, {}
	local token_i = 1
	local prev
	for character in str_gmatch(decompose(text), UTF8_char) do
		local curr_info = info[character]
		-- Split vowels between tokens if not a diphthong.
		if curr_info.vowel then
			if prev and (not (curr_info.offglide and prev_info.vowel)
					-- υυ → υ, υ
					-- ιυ → ι, υ
					or prev_info.offglide and curr_info == upsilon) then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
			table.insert(vowel_info, { index = token_i })
		elseif curr_info.diacritic then
			tokens[token_i] = (tokens[token_i] or "") .. character
			if prev_info.vowel or prev_info.diacritic then
				if character == diaeresis then
					-- Current token is vowel, vowel, possibly other diacritics,
					-- and a diaeresis.
					-- Split the current token into two:
					-- the first letter, then the second letter plus any diacritics.
					local previous_vowel, vowel_with_diaeresis = string.match(tokens[token_i], "^(" .. basic_Greek .. ")(" .. basic_Greek .. ".+)")
					if previous_vowel then
						tokens[token_i], tokens[token_i + 1] = previous_vowel, vowel_with_diaeresis
						token_i = token_i + 1
					end
				end
			elseif prev_info == rho then
				if curr_info ~= breathing then
					return string.format("The character %s cannot have the accent %s on it.", prev, add_dotted_circle(character))
				end
			else
				error("The character " .. quote(prev) .. " cannot have a diacritic on it.")
			end
		elseif curr_info == rho then
			if prev and not (prev_info == breathing and info[string.match(tokens[token_i], "^" .. basic_Greek)] == rho) then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
		else
			if prev then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
		end
		prev = character
		prev_info = curr_info
	end
	return tokens
end


function export.tokenize_vowels(text)
	text = decompose(text)
	
	local tokens, vowel_info, prev_info = {}, {}, {}
	local token_i = 1
	local prev
	for character in str_gmatch(text, UTF8_char) do
		local curr_info = info[character]
		-- Split vowels between tokens if not a diphthong.
		if curr_info.vowel then
			if prev and not (curr_info.offglide and prev_info.vowel
					-- υυ → υ, υ
					-- ιυ → ι, υ
					and not (prev_info.offglide and curr_info == upsilon)) then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
			table.insert(vowel_info, { index = token_i })
		elseif curr_info.diacritic then
			tokens[token_i] = (tokens[token_i] or "") .. character
			if prev_info.vowel or prev_info.diacritic then
				if character == diaeresis then
					-- Current token is vowel, vowel, possibly other diacritics,
					-- and a diaeresis.
					-- Split the current token into two:
					-- the first letter, then the second letter plus any diacritics.
					local previous_vowel, vowel_with_diaeresis = string.match(tokens[token_i], "^(" .. basic_Greek .. ")(" .. basic_Greek .. ".+)")
					if previous_vowel then
						tokens[token_i], tokens[token_i + 1] = previous_vowel, vowel_with_diaeresis
						token_i = token_i + 1
					end
				end
			elseif prev_info == rho then
				if curr_info ~= breathing then
					return string.format("The character %s cannot have the accent %s on it.", prev, add_dotted_circle(character))
				end
			else
				error("The character " .. quote(prev) .. " cannot have a diacritic on it.")
			end
		elseif curr_info == rho then
			if prev and not (prev_info == breathing and info[string.match(tokens[token_i], "^" .. basic_Greek)] == rho) then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
		else -- consonant or "not recognized"
			if prev and not (prev_info.consonant or prev_info == not_recognized) then
				token_i = token_i + 1
			end
			tokens[token_i] = (tokens[token_i] or "") .. character
		end
		prev = character
		prev_info = curr_info
	end
	return tokens
end

function export.show(frame)
	local map = require("Module:User:Erutuon/functional").map
	local token_format = '<span class="polytonic" style="background-color: #EFEFEF;>%s</span>'
	local spacing = {
		["\n"] = "&para;",
		["\r"] = "&para;",
		[" "] = "&ensp;",
	}
	local function print_tokens(tokens)
		if type(tokens) == "string" then
			return tokens
		end
		local output = {}
		for i, token in ipairs(tokens) do
			output[i] = string.format(token_format, str_gsub(token, "%s", spacing))
		end
		return table.concat(output, " ")
	end
	return table.concat(map(print_tokens, map(export.tokenize, frame.args)), "<br>")
end

-- Assumes val is string or nil, as will be true if it is a template parameter.
local function boolean_or_string(val)
	if not val then
		return false
	else
		val = val:lower()
	end
	local number = tonumber(val)
	if number == 0 or val == "no" or val == "false" then
		return false
	elseif number == 1 or val == "yes" or val == "true" then
		return true
	else
		return val
	end
end

-- Modification of findAmbig function in [[Module:grc-utilities]] that returns
-- boolean value.
local function has_ambiguous_vowel(text)
	local lengthDiacritic = "[" .. macron .. breve .. circumflex .. subscript .. "]"
	local aiu_diacritic = "^([" .. "αιυ" .. "])(" .. diacritic_patt .. "*)$"
	
	-- breaks the word into units
	for _, token in ipairs(tokenize(text)) do
		local vowel, diacritics = umatch(token, aiu_diacritic)
			
		if vowel and (diacritics == "" or
				not ufind(diacritics, lengthDiacritic)) then
			return true
		end
	end
		
	return false
end


local function has_breve_or_macron(text)
	text = decompose(text)
	return str_find(text, macron) or str_find(text, breve)
end

local function add_to_t(t1, t2)
	for k, v in pairs(t2) do
		if t1[k] == nil then
			t1[k] = v
		else
			error("Table 1 already has value for " .. quote(k) .. ".")
		end
	end
	return t1
end

local function in_array(array, val)
	for i, v in ipairs(array) do
		if val == v then
			return i
		end
	end
	return false
end

local function make_param(value, name)
	return value and "|" .. (name and name .. "=" or "") .. value or nil
end

local function add_content(template, content_table)
	return str_gsub(template,
		"{{{([^}]+)}}}",
		function (code)
			local content = content_table[code]
			return in_array({ "string", "nil" }, type(content)) and (content or "")
				or error("Invalid type for content variable " .. quote(tostring(code)) .. ": " .. type(content) .. ".")
		end)
end

local function accent_recessively(form)
	local m_accent = require "Module:grc-accent"
	return m_accent.add_accent(m_accent.strip_tone(form), -3)
end

local function get_participle_information(masculine, contraction_vowel)
	local decl, feminine, neuter, lemma
	
	if not (not contraction_vowel or contraction_vowel == "a"
	or contraction_vowel == "e" or contraction_vowel == "o") then
		error("Invalid contraction vowel. Either omit or choose between a, e, o.")
	end
	
	masculine = mw.ustring.toNFC(masculine)
	
	if masculine:find("ος$") then
		decl = "1&2"
		feminine = accent_recessively(masculine:gsub("ος$", "η"))
		neuter = masculine:gsub("ς$", "ν")
		
		-- Warning! This simply assumes the participle is present mediopassive,
		-- like λεγόμενος, not second aorist, like λαβόμενος.
		if masculine:find("όμενος$") then
			lemma = accent_recessively(masculine:gsub("όμενος$", "ω"))
		end
	else
		decl = "1&3"
		
		local m_utilities_data = require "Module:grc-utilities/data"
		-- Warning! This pattern will not work if there's a vowel before the
		-- participle ending, as in τεθνεώς, perfect active participle of
		-- θνῄσκω.
		local ending = mw.ustring.match(mw.ustring.toNFD(masculine),
			m_utilities_data.vowel .. "?[ιυ]?[^" .. m_utilities_data.vowels .. "]+$")
		
		if ending then
			local m_accent = require "Module:grc-accent"
			ending = mw.ustring.toNFC(m_accent.strip_tone(ending))
			
			local accent_pos, accent_type = m_accent.detect_accent(masculine)
			local toneless_masculine = m_accent.strip_tone(masculine)
			
			if ending == "ων" then -- recessive, oxytone, properispomenon
				local stem = mw.ustring.gsub(toneless_masculine, "ων$", "")
				if contraction_vowel == "a" then
					-- τῑμῶν, τῑμῶσᾰ, τῑμῶν
					feminine = stem .. "ωσᾰ"
					neuter = masculine
					lemma = stem .. "ᾰ́ω"
				else
					-- λέγων, λέγουσα, λέγον; λαβών, λαβοῦσᾰ, λαβόν;
					-- ποιῶν, ποιοῦσᾰ, ποιοῦν; δηλῶν, δηλοῦσᾰ, δηλοῦν
					feminine = stem .. "ουσᾰ"
					if contraction_vowel == "e" or contraction_vowel == "o" then
						neuter = stem .. "ουν"
						lemma = stem .. (contraction_vowel == "e" and "έω" or "όω")
					else
						-- If accent is paroxytone, then this is a present-tense
						-- verb.
						if m_accent.detect_accent(masculine, true) == 2 then
							lemma = accent_recessively(stem .. "ω")
						end
						neuter = stem .. "ον"
					end
				end
			elseif ending == "ᾱς" then -- recessive except in athematic verbs
				stem = mw.ustring.gsub(toneless_masculine,
					"α" .. m_utilities_data.diacritics.macron .. m_utilities_data.diacritics.acute .. "?ς",
					"")
				feminine = stem .. "ᾱσᾰ"
				neuter = stem .. "ᾰν"
			
			-- Aorist passive or athematic; always oxytone?
			elseif ending == "εις" then
				stem = masculine:gsub("είς", "")
				feminine = stem .. "εῖσᾰ"
				neuter = stem .. "έν"
			elseif ending == "ως" then -- Perfect active; always oxytone?
				stem = masculine:gsub("ώς", "")
				feminine = stem .. "υῖᾰ"
				neuter = stem .. "ός"
			
			-- Present active, δεικνῡ́ς and such
			elseif ending == "ῡς" then
				stem = masculine:gsub("ῡ́ς", "")
				feminine = stem .. "ῦσᾰ"
				neuter = stem .. "ῠ́ν"
			end
			
			if feminine and neuter then
				local options = {
					circumflex = accent_type == "circumflex"
				}
				feminine, neuter =
					m_accent.add_accent(feminine, accent_pos, options),
					m_accent.add_accent(neuter, accent_pos, options)
			end
		end
	end
	
	return decl, feminine, neuter, lemma
end
export.get_participle_information = get_participle_information

local function needs_head_parameter(pagename)
	return nonmainspace or pagename:find "'" or has_ambiguous_vowel(pagename)
end

local dialect_abbr = {
	["aio"] = "Aeolic Greek",
	["ark"] = "Arcadocypriot",
	["att"] = "Attic",
	["boi"] = "Boeotian",
	["del"] = "Delphic",
	["dor"] = "Doric",
	["ele"] = "Elean",
	["epi"] = "Epic",
	["hom"] = "Homeric",
	["ion"] = "Ionic",
	["koi"] = "Koine",
	["kre"] = "Cretan",
	["lak"] = "Lacedaemonian",
	["lok"] = "Locrian",
	["lur"] = "Lyric",
	["muk"] = "Mycenaean",
	["pam"] = "Pamphylian",
	["pho"] = "Phocian",
	["poi"] = "poetic",
	["the"] = "Thessalian",
}

local function make_term_label(dialect_code)
	if not dialect_code then
		return nil
	end
	
	local dialect = dialect_abbr[dialect_code]
	if dialect then
		return " {{tlb|grc|" .. dialect .. "}}"
	else
		error("The dialect code " .. dialect_code .. " was not recognized.")
	end
end

local templates = {
	language_header = [=[
==Ancient Greek==

]=],
	etymology = [=[
===Etymology===
{{{etym}}}

]=],
	pronunciation = [=[
===Pronunciation===
{{grc-IPA{{{pronunciation}}}}}

]=],
	noun = [=[
===Noun===
{{grc-noun{{{head}}}|{{{genitive}}}|{{{gender}}}|{{{declension}}}}}{{{dialectlabel}}}

# {{{definition1}}}

====Declension====
{{grc-decl|{{{pagename}}}|{{{genitive}}}{{{form}}}{{{dialect}}}}}

]=],
	adjective = [=[
===Adjective===
{{grc-adj-{{{declensions}}}{{{head}}}{{{feminine}}}{{{neuter}}}}}

# {{{definition1}}}

====Declension====
{{grc-adecl|{{{masculine_or_stem}}}{{{feminine_or_neuter}}}{{{form}}}{{{dialect}}}}}

]=],
	participle = [=[
===Participle===
{{grc-part-{{{declensions}}}{{{head}}}{{{feminine}}}{{{neuter}}}}}

# {{inflection of|grc|{{{lemma}}}||{{{infl}}}|part}}

====Declension====
{{grc-adecl|{{{masculine_or_stem}}}{{{feminine_or_neuter}}}{{{form}}}{{{dialect}}}}}

]=],
	verb = [=[
===Verb===
{{grc-verb{{{head}}}}}

# {{{definition1}}}

]=],
	verb_form = [=[
===Verb===
{{grc-verb form{{{head}}}}}{{{dialect}}}

# {{{definition1}}}
]=],
	ref_header = [=[
===Further reading===
]=],
	lsj = [=[
* {{R:LSJ{{{LSJheadword}}}}}
]=],
	middle = [=[
* {{R:Middle Liddell{{{Middleheadword}}}}}
]=],
	cunliffe = [=[
* {{R:Cunliffe{{{Cunliffeheadword}}}}}
]=],
	autenrieth = [=[
* {{R:Autenrieth{{{Autenriethheadword}}}}}
]=],
	slater = [=[
* {{R:Slater{{{Slaterheadword}}}}}
]=],
	dge = [=[
* {{R:DGE{{{DGEheadword}}}}}
]=],
	inflection_of = [=[
{{inflection of|grc|{{{lemma}}}||{{{inflection_categories}}}}}
]=],
}

local noun_decl = {
	first = true, second = true, third = true,
}
local adj_decl = {
	["1&2"] = true, ["1&3"] = true, ["2nd"] = true, ["3rd"] = true,
}

local pos_data = {}

pos_data.noun = {
	params = {
		gen = { required = true },
		g = { required = true },
		decl = { required = true },
		def = { required = true },
		dial = {},
		form = {},
	},
	grc_params = {
		gen = true,
	},
	func = function (args)
		local head = args.head
		local decl = args.decl
		if not (decl and noun_decl[decl]) then
			-- Allow 1, 2, 3 or 1st, 2nd, 3rd.
			local number = decl and tonumber(decl:match("^%d+"))
			if number then
				decl = ({ [1] = "first", [2] = "second", [3] = "third" })[number]
			end
			
			if not decl then
				error("Please supply a valid declension: first, second, or third.")
			end
		end
		
		local content = {
			genitive = args.gen,
			gender = args.g,
			declension = decl,
			dialectlabel = make_term_label(args.dial),
			definition1 = args.def,
			pagename = head or pagename,
			dialect = make_param(args.dial, "dial"),
			form = make_param(args.form, "form"),
		}
		
		local template = templates.language_header
			.. (args.etym and templates.etymology or "")
			.. templates.pronunciation .. templates.noun
		
		return template, content
	end
}

pos_data.verb = {
	params = {
		def = { required = true },
	},
	grc_params = {
		
	},
	func = function(args)
		local content = {
			definition1 = args.def,
		}
		
		local template = templates.language_header
			.. (args.etym and templates.etymology or "")
			.. templates.pronunciation
			.. templates.verb
		
		return template, content
	end,
}

pos_data.adjective = {
	params = {
		fem = {},
		f = { alias_of = "fem" },
		neut = { required = true },
		n = { alias_of = "neut" },
		def = { required = true },
		decl = { required = true },
		dial = {},
		form = {},
	},
	grc_params = {
		fem = true,
		neut = true,
	},
	func = function(args)
		local stem_in_decl_template = args.decl == "3rd"
		local head = args.head
		local content = {
			declensions = adj_decl[args.decl] and args.decl
				or error("The adjective declension code " .. quote(args.decl) ..
				" was not recognized."),
			feminine = make_param(args.fem),
			neuter = make_param(args.neut),
			dialectlabel = make_term_label(args.dial),
			definition1 = args.def,
			masculine_or_stem = stem_in_decl_template and args.neut or head or pagename,
			feminine_or_neuter = make_param(not stem_in_decl_template and (args.fem or args.neut)),
		}
		
		local template = templates.language_header .. (args.etym and templates.etymology or "") .. templates.pronunciation .. templates.adjective
		
		return template, content
	end,
}

pos_data.participle = {
	params = {
		[2] = { list = true },
		fem = {},
		f = { alias_of = "fem" },
		neut = {},
		n = { alias_of = "neut" },
		con = {}, -- contraction vowel
		lemma = {},
		infl = {},
		decl = {},
		dial = {},
		form = {},
	},
	grc_params = {
		fem = true,
		neut = true,
		lemma = true,
	},
	process_args = function(args)
		local numbered_params = args[2]
		if #numbered_params > 3 then
			error("Too many numbered parameters: " .. (#numbered_params + 1) .. ", expected 3 or 4.")
		end
		
		if #numbered_params > 1 then
			if args.head or args.lemma or args.infl then
				error("!")
			end
			
			if needs_head_parameter(pagename) then
				if #numbered_params == 3 then
					args.head, args.lemma, args.infl =
						Latin_to_Greek(numbered_params[1]),
						Latin_to_Greek(numbered_params[2]),
						numbered_params[3]
				elseif #numbered_params == 2 then
					args.head, args.infl =
						Latin_to_Greek(numbered_params[1]),
						numbered_params[2]
				else
					error("Expected three positional parameters: headword, lemma, inflectional categories.")
				end
			else
				if #numbered_params == 2 then
					args.lemma, args.infl =
						Latin_to_Greek(numbered_params[1]),
						numbered_params[2]
				elseif #numbered_params == 1 then
					args.infl = numbered_params[2]
				else
					error("Expected two positional parameters: lemma and inflectional categories")
				end
			end
		end
	end,
	func = function(args)
		local stem_in_decl_template = args.decl == "3rd"
		local head = args.head
		
		local decl, feminine, neuter, lemma =
			get_participle_information(head or pagename, args.con)
		
		feminine = args.fem or feminine
		neuter = args.neut or neuter
		decl = args.decl and adj_decl[args.decl] and (args.decl
			or error("The adjective declension code " .. quote(args.decl) ..
			" was not recognized.")) or decl
		if lemma and not args.lemma and mw.ustring.toNFC(head or pagename):find("όμενος$") then
			if args.infl then
				local tense = args.infl:match("^%S+")
				
				if tense ~= "present" then
					local form_of_data = require "Module:form of/data"
					tense = form_of_data.shortcuts[tense] or tense
				end
				
				if tense ~= "present" then
					error("Not a present-tense participle; please supply lemma.")
				end
			end
		end
		lemma = args.lemma or lemma or error("Please supply the lemma of this participle.")
		
		if not (feminine and neuter and decl) then
			error("Either the declension or the feminine or neuter form could not be automatically determined. "
				.. "Please supply them in the |decl=, |f=, or |n= parameters.")
		end
		
		local content = {
			declensions = decl,
			feminine = make_param(feminine),
			neuter = make_param(neuter),
			dialectlabel = make_term_label(args.dial),
			lemma = lemma,
			infl = args.infl:gsub(" ", "|"),
			masculine_or_stem = head or pagename,
			feminine_or_neuter = make_param(feminine or neuter),
		}
		
		local template = templates.language_header
			.. (args.etym and templates.etymology or "")
			.. templates.pronunciation .. templates.participle
		
		return template, content
	end,
}

pos_data.verb_form = {
	params = {
		[2] = { list = true },
		lemma = {}, -- Make into list parameter?
		infl = {}, -- Make into list parameter?
		dial = {},
	},
	grc_params = {
		lemma = true,
	},
	process_args = function(args)
		local numbered_params = args[2]
		if #numbered_params > 3 then
			error("Too many numbered parameters: " .. (#numbered_params + 1) .. ", expected 3 or 4.")
		end
		
		if #numbered_params > 1 then
			if args.head or args.lemma or args.infl then
				error("!")
			end
			
			if needs_head_parameter(pagename) then
				if #numbered_params == 3 then
					args.head, args.lemma, args.infl =
						Latin_to_Greek(numbered_params[1]),
						Latin_to_Greek(numbered_params[2]),
						numbered_params[3]
				else
					error("Expected three positional parameters: headword, lemma, inflectional categories.")
				end
			else
				if #numbered_params == 2 then
					args.lemma, args.infl =
						Latin_to_Greek(numbered_params[1]),
						numbered_params[2]
				else
					error("Expected two positional parameters: lemma and inflectional categories")
				end
			end
		end
	end,
	func = function(args)
		if not args.lemma then
			error("Please provide lemma argument for {{inflection of}} in |lemma= parameter.")
		end
		
		if not args.infl then
			error("Please provide inflection category arguments for {{inflection of}} in |infl= parameter.")
		end
		
		local content = {
			definition1 = add_content(templates.inflection_of, {
				lemma = args.lemma,
				inflection_categories = args.infl:gsub(" ", "|"),
			}),
			dialect = args.dial and " {{tlb|grc|" .. args.dial .. "}}"
		}
		
		local template = templates.language_header
			.. (args.etym and templates.etymology or "")
			.. templates.pronunciation
			.. templates.verb_form
		
		return template, content
	end,
}


local pos_aliases = {
	v = "verb",
	vf = "verb_form",
}
setmetatable(pos_data, { __index = function (self, key)
	if pos_aliases[key] then
		return self[pos_aliases[key]]
	end
end })

local function convert_Greek_args(args, grc_params)
	-- Convert ASCII code in the style of [[Module:typing-aids/data/grc]]
	-- to Greek script.
	local forms_with_ambiguous_vowels = require("Module:array")()
	for k in pairs(grc_params) do
		local arg = args[k]
		if arg then
			arg = Latin_to_Greek(arg)
			
			if has_ambiguous_vowel(arg) then
				forms_with_ambiguous_vowels:insert {
					key = k, value = args[k], transformed = arg
				}
			end
			
			args[k] = arg
		end
	end
	
	if #forms_with_ambiguous_vowels > 0 then
		local agreement = #forms_with_ambiguous_vowels == 1 and "" or "s"
		local parameter_format = quote "%s" .. " (" .. quote "%s" .. " → " .. quote "%s" .. ")"
		error("Mark length of α, ι, or υ in parameter" .. agreement
			.. " " .. forms_with_ambiguous_vowels
				:map(function (data)
					return parameter_format
						:format(data.key, data.value, data.transformed)
				end)
				:concat(", ")
			.. " by putting " .. quote("^") .. " after short vowels and "
			.. quote("_") .. " after long ones.")
	end
end

local function process_ref_arguments(args, content, ref_arguments)
	local refs = ""
	for _, ref in ipairs(ref_arguments) do
		local arg_prefix, arg_name
		if type(ref) == "table" then
			arg_name, arg_prefix = unpack(ref)
		else
			arg_name, arg_prefix = ref, ref:gsub("^.", string.upper)
		end
		local arg = boolean_or_string(args[arg_name])
		if type(arg) == "string" then
			arg = Latin_to_Greek(arg)
		end
		if arg then
			refs = refs .. templates[arg_name]
		end
		content[arg_prefix .. "headword"] = make_param(type(arg) == "string" and arg)
		args[arg_name] = arg
	end
	return refs
end

function export.new (frame)
	local parent_frame = frame:getParent()
	local args = parent_frame:getTitle() == "Template:grc-new" and parent_frame.args or frame.args
	if not next(args) and title.fullText == "Template:grc-new" then
		return nil
	end
	
	-- Allow |verb form= as well as |verb_form=.
	local pos = args.pos or args[1]
	pos = pos and mw.text.trim(pos):gsub(" ", "_")
	args.pos = pos -- needed beyond this point or not?
	
	local data
	if not pos or pos == "" then
		error("pos parameter is required.")
	else
		data = pos_data[pos]
		if not data then
			-- Check for prefix matches in pos_data.
			local matches = {}
			local patt = "^" .. require "Module:utilities".pattern_escape(pos)
			for pos_key in pairs(pos_data) do
				if pos_key:find(patt) then
					table.insert(matches, pos_key)
				end
			end
			if #matches == 1 then
				data = pos_data[matches[1]]
			elseif #matches == 0 then
				error("The part of speech " .. quote(pos) .. " is not supported.")
			elseif #matches > 1 then
				error("Choose between these parts of speech: " .. table.concat(matches, ", "))
			end
		end
	end
	
	local params = {
		[1] = { alias_of = "pos" },
		pos = { required = true },
		etym = {},
		head = {},
		lsj = {},
		middle = {},
		cunliffe = {},
		slater = {},
		autenrieth = {},
		dge = {},
	}
	add_to_t(params, data.params)
	args = require("Module:parameters").process(args, params)
	
	if data.process_args then
		data.process_args(args)
	end
	
	if nonmainspace and not args.head then
		error("head parameter required outside of mainspace.")
	end
	
	convert_Greek_args(args, add_to_t({ head = true }, data.grc_params))
	
	if nonmainspace then
		args.head = decompose(args.head)
		pagename = decompose(make_entry_name(args.head))
		if args.head == pagename then
			args.head = nil
		end
	elseif head and decompose(args.head) == decompose(pagename) then
		error("Head parameter has been provided, but as it is identical to the "
			.. "page name, it is not needed.")
	end
	
	local template, content = data.func(args)
	
	local refs = process_ref_arguments(args, content, { { "lsj", "LSJ" }, "middle", "cunliffe", "slater", "autenrieth", { "dge", "DGE" } })
	content.head = make_param(args.head)
	content.pronunciation = content.head
	content.etym = args.etym
	
	if refs ~= "" then
		template = template .. templates.ref_header .. refs
	end
	
	local wikitext = add_content(template, content)
	wikitext = mw.text.trim(wikitext)
	
	if nonmainspace then
		return highlight(wikitext)
	else
		return wikitext
	end
end

return export