"""
English verb conjugation
Original Author: Tom De Smedt <tomdesmedt@organisms.be> of Nodebox
Refactored by Griatch 2021, for Evennia.
This is distributed under the GPL2 license. See ./LICENSE.txt for details.
The verb.txt morphology was adopted from the XTAG morph_englis.flat:
http://www.cis.upenn.edu/~xtag/
"""
import os
_VERBS_FILE = "verbs.txt"
# Each verb and its tenses is a list in verbs.txt,
# indexed according to the following keys:
# the negated forms (for supported verbs) are ind+11.
verb_tenses_keys = {
"infinitive": 0,
"1st singular present": 1,
"2nd singular present": 2,
"3rd singular present": 3,
"present plural": 4,
"present participle": 5,
"1st singular past": 6,
"2nd singular past": 7,
"3rd singular past": 8,
"past plural": 9,
"past": 10,
"past participle": 11,
}
# allow to specify tenses with a shorter notation
verb_tenses_aliases = {
"inf": "infinitive",
"1sgpres": "1st singular present",
"2sgpres": "2nd singular present",
"3sgpres": "3rd singular present",
"pl": "present plural",
"prog": "present participle",
"1sgpast": "1st singular past",
"2sgpast": "2nd singular past",
"3sgpast": "3rd singular past",
"pastpl": "past plural",
"ppart": "past participle",
}
# Each verb has morphs for infinitve,
# 3rd singular present, present participle,
# past and past participle.
# Verbs like "be" have other morphs as well
# (i.e. I am, you are, she is, they aren't)
# Additionally, the following verbs can be negated:
# be, can, do, will, must, have, may, need, dare, ought.
# load the conjugation forms from ./verbs.txt
verb_tenses = {}
path = os.path.join(os.path.dirname(__file__), _VERBS_FILE)
with open(path) as fil:
for line in fil.readlines():
wordlist = [part.strip() for part in line.split(",")]
verb_tenses[wordlist[0]] = wordlist
# Each verb can be lemmatised:
# inflected morphs of the verb point
# to its infinitive in this dictionary.
verb_lemmas = {}
for infinitive in verb_tenses:
for tense in verb_tenses[infinitive]:
if tense:
verb_lemmas[tense] = infinitive
[docs]def verb_infinitive(verb):
"""
Returns the uninflected form of the verb, like 'are' -> 'be'
Args:
verb (str): The verb to get the uninflected form of.
Returns:
str: The uninflected verb form of `verb`.
"""
return verb_lemmas.get(verb, "")
[docs]def verb_conjugate(verb, tense="infinitive", negate=False):
"""
Inflects the verb to the given tense.
Args:
verb (str): The single verb to conjugate.
tense (str): The tense to convert to. This can be given either as a long or short form
- "infinitive" ("inf") - be
- "1st/2nd/3rd singular present" ("1/2/3sgpres") - am/are/is
- "present plural" ("pl") - are
- "present participle" ("prog") - being
- "1st/2nd/3rd singular past" ("1/2/3sgpast") - was/were/was
- "past plural" ("pastpl") - were
- "past" - were
- "past participle" ("ppart") - been
negate (bool): Negates the verb. This only supported
for a limited number of verbs: be, can, do, will, must, have, may,
need, dare, ought.
Returns:
str: The conjugated verb. If conjugation fails, the original verb is returned.
Examples:
The verb 'be':
- present: I am, you are, she is,
- present participle: being,
- past: I was, you were, he was,
- past participle: been,
- negated present: I am not, you aren't, it isn't.
"""
tense = verb_tenses_aliases.get(tense, tense)
verb = verb_infinitive(verb)
ind = verb_tenses_keys[tense]
if negate:
ind += len(verb_tenses_keys)
try:
return verb_tenses[verb][ind]
except (IndexError, KeyError):
# TODO implement simple algorithm here with +s for certain tenses?
return verb
[docs]def verb_present(verb, person="", negate=False):
"""
Inflects the verb in the present tense.
Args:
person (str or int): This can be 1, 2, 3, "1st", "2nd", "3rd", "plural" or "*".
negate (bool): Some verbs like be, have, must, can be negated.
Returns:
str: The present tense verb.
Example:
had -> have
"""
person = str(person).replace("pl", "*").strip("stndrgural")
mapping = {
"1": "1st singular present",
"2": "2nd singular present",
"3": "3rd singular present",
"*": "present plural",
}
if person in mapping and verb_conjugate(verb, mapping[person], negate) != "":
return verb_conjugate(verb, mapping[person], negate)
return verb_conjugate(verb, "infinitive", negate)
[docs]def verb_present_participle(verb):
"""
Inflects the verb in the present participle.
Args:
verb (str): The verb to inflect.
Returns:
str: The inflected verb.
Examples:
give -> giving, be -> being, swim -> swimming
"""
return verb_conjugate(verb, "present participle")
[docs]def verb_past(verb, person="", negate=False):
"""
Inflects the verb in the past tense.
Args:
verb (str): The verb to inflect.
person (str, optional): The person can be specified with 1, 2, 3,
"1st", "2nd", "3rd", "plural", "*".
negate (bool, optional): Some verbs like be, have, must, can be negated.
Returns:
str: The inflected verb.
Examples:
give -> gave, be -> was, swim -> swam
"""
person = str(person).replace("pl", "*").strip("stndrgural")
mapping = {
"1": "1st singular past",
"2": "2nd singular past",
"3": "3rd singular past",
"*": "past plural",
}
if person in mapping and verb_conjugate(verb, mapping[person], negate) != "":
return verb_conjugate(verb, mapping[person], negate)
return verb_conjugate(verb, "past", negate=negate)
[docs]def verb_past_participle(verb):
"""
Inflects the verb in the present participle.
Args:
verb (str): The verb to inflect.
Returns:
str: The inflected verb.
Examples:
give -> given, be -> been, swim -> swum
"""
return verb_conjugate(verb, "past participle")
[docs]def verb_all_tenses():
"""
Get all all possible verb tenses.
Returns:
list: A list if string names.
"""
return list(verb_tenses_keys.keys())
[docs]def verb_tense(verb):
"""
Returns a string from verb_tenses_keys representing the verb's tense.
Args:
verb (str): The verb to check the tense of.
Returns:
str: The tense.
Example:
given -> "past participle"
"""
infinitive = verb_infinitive(verb)
data = verb_tenses.get(infinitive)
if not data:
return infinitive
for tense in verb_tenses_keys:
if data[verb_tenses_keys[tense]] == verb:
return tense
if data[verb_tenses_keys[tense] + len(verb_tenses_keys)] == verb:
return tense
[docs]def verb_is_tense(verb, tense):
"""
Checks whether the verb is in the given tense.
Args:
verb (str): The verb to check.
tense (str): The tense to check.
Return:
bool: If verb matches given tense.
"""
tense = verb_tenses_aliases.get(tense, tense)
return verb_tense(verb) == tense
[docs]def verb_is_present(verb, person="", negated=False):
"""
Checks whether the verb is in the present tense.
Args:
verb (str): The verb to check.
person (str): Check which person.
negated (bool): Check if verb was negated.
Returns:
bool: If verb was in present tense.
"""
person = str(person).replace("*", "plural")
tense = verb_tense(verb)
if tense is not None:
if "present" in tense and person in tense:
if not negated:
return True
elif "n't" in verb or " not" in verb:
return True
return False
[docs]def verb_is_present_participle(verb):
"""
Checks whether the verb is in present participle.
Args:
verb (str): The verb to check.
Returns:
bool: Result of check.
"""
tense = verb_tense(verb)
return tense == "present participle"
[docs]def verb_is_past(verb, person="", negated=False):
"""
Checks whether the verb is in the past tense.
Args:
verb (str): The verb to check.
person (str): The person to check.
negated (bool): Check if verb is negated.
Returns:
bool: Result of check.
"""
person = str(person).replace("*", "plural")
tense = verb_tense(verb)
if tense is not None:
if "past" in tense and person in tense:
if not negated:
return True
elif "n't" in verb or " not" in verb:
return True
return False
[docs]def verb_is_past_participle(verb):
"""
Checks whether the verb is in past participle.
Args:
verb (str): The verb to check.
Returns:
bool: The result of the check.
"""
tense = verb_tense(verb)
return tense == "past participle"
[docs]def verb_actor_stance_components(verb, plural=False):
"""
Figure out actor stance components of a verb.
Args:
verb (str): The verb to analyze
plural (bool): Whether to force 3rd person to plural form
Returns:
tuple: The 2nd person (you) and 3rd person forms of the verb,
in the same tense as the ingoing verb.
"""
tense = verb_tense(verb)
them = "*" if plural else "3"
them_suff = "" if plural else "s"
if "participle" in tense or "plural" in tense:
return (verb, verb)
if tense == "infinitive" or "present" in tense:
you_str = verb_present(verb, person="2") or verb
them_str = verb_present(verb, person=them) or verb + them_suff
else:
you_str = verb_past(verb, person="2") or verb
them_str = verb_past(verb, person=them) or verb + them_suff
return (you_str, them_str)