The Derivation Idea
Most Old English verb forms are not memorized individually — they are derived from a small number of inputs using a fixed sequence of rules. For strong verbs, those inputs are the four principal parts: the infinitive, the past singular, the past plural, and the past participle. Every other form can be produced mechanically from these four, given the right rules for endings, i-mutation, and consonant collision.
This page documents those rules explicitly, so they can serve both as a learning aid and as the specification for the paradigm generator used to produce the conjugation tables in the verb reference.
Principal Parts and Stems
A strong verb is specified by four principal parts. We use the infinitive as the first part rather than the 3rd person singular present — this is because the 3rd person singular present forms (which involve i-mutation and consonant collision) are themselves derived by the rules. Supplying the infinitive is therefore sufficient; the 3rd singular is a computed output, not an input.
The four principal parts are: infinitive, past singular, past plural, past participle. Each yields one stem by stripping its characteristic ending:
bær → past sg stem: bær-
bǣron → past pl stem: bǣr-
boren → past part stem: bor-
import re
def extract_stems(principal_parts):
inf, past_sg, past_pl, past_part = principal_parts
present_stem = re.sub(r'an$', '', inf)
past_sg_stem = past_sg
past_pl_stem = re.sub(r'on$', '', past_pl)
past_part_stem = re.sub(r'en$', '', re.sub(r'^ġe', '', past_part))
return {
'present_stem': present_stem,
'past_sg_stem': past_sg_stem,
'past_pl_stem': past_pl_stem,
'past_part_stem': past_part_stem,
}
The Ending Table
Once the four stems are known, each inflected form is built by concatenating the appropriate stem with its ending. The present sg2 and sg3 use the i-mutated stem (with collision rules applied); all other present forms use the plain present stem.
| Form | Stem | Ending |
|---|---|---|
| Pres. ind. sg1 | present | + e |
| Pres. ind. sg2 | mutated | + st (apply collision rules) |
| Pres. ind. sg3 | mutated | + þ (apply collision rules) |
| Pres. ind. pl | present | + aþ |
| Past ind. sg1 | past sg | (bare stem) |
| Past ind. sg2 | past pl | + e |
| Past ind. sg3 | past sg | (bare stem) |
| Past ind. pl | past pl | + on |
| Pres. subj. sg | present | + e |
| Pres. subj. pl | present | + en |
| Past subj. sg | past pl | + e |
| Past subj. pl | past pl | + en |
| Inflected inf. | present | tō + … + enne |
| Pres. participle | present | + ende |
| Past participle | past part | ġe + … + en |
| Imperative sg | present | (bare stem) |
| Imperative pl | present | + aþ |
def build_forms(stems, mutated_stem):
ps = stems['present_stem']
sg = stems['past_sg_stem']
pl = stems['past_pl_stem']
pp = stems['past_part_stem']
ms = mutated_stem
return {
'pres_ind': {'sg1': ps+'e', 'sg2': apply_collision(ms,'st'),
'sg3': apply_collision(ms,'þ'), 'pl': ps+'aþ'},
'past_ind': {'sg1': sg, 'sg2': pl+'e', 'sg3': sg, 'pl': pl+'on'},
'pres_subj': {'sg': ps+'e', 'pl': ps+'en'},
'past_subj': {'sg': pl+'e', 'pl': pl+'en'},
'infinitive': ps+'an',
'inflected_infinitive': 'tō '+ps+'enne',
'pres_participle': ps+'ende',
'past_participle': 'ġe'+pp+'en',
'imperative_sg': ps,
'imperative_pl': ps+'aþ',
}
I-Mutation
I-mutation (also called i-umlaut) is a historical sound change in which a back or low vowel was fronted and raised when a high front vowel /i/ or /j/ followed in the next syllable. That triggering vowel was later lost, leaving the mutated stem vowel as the only trace. In the Old English present tense, i-mutation applies to the 2nd and 3rd person singular, which historically took a suffix beginning with i. The long vowel ē is already a front vowel and does not mutate.
| Base vowel | Mutated |
|---|---|
| a | æ |
| ā | ǣ |
| e | i |
| o | e |
| ō | ē |
| u | y |
| ū | ȳ |
| ea | ie |
| ēa | īe |
| eo | ie |
| ēo | īe |
| an | en |
| am | em |
I_MUTATION = {
'a': 'æ', 'ā': 'ǣ', 'e': 'i', 'o': 'e',
'ō': 'ē', 'u': 'y', 'ū': 'ȳ', 'ea': 'ie',
'ēa': 'īe', 'eo': 'ie','ēo': 'īe', 'an': 'en',
'am': 'em',
}
# Match longest vowel sequence first to avoid 'e' matching inside 'eo'
VOWELS_LONGEST_FIRST = sorted(I_MUTATION, key=len, reverse=True)
def apply_i_mutation(stem):
for v in VOWELS_LONGEST_FIRST:
idx = stem.find(v)
if idx != -1:
return stem[:idx] + I_MUTATION[v] + stem[idx+len(v):]
return stem # no vowel found — return unchanged
Consonant Collision
When the stem ends in certain consonants and the ending begins with another consonant (-st for 2nd sg, -þ for 3rd sg), the two consonants collide and must be resolved. The collision produces a single merged spelling rather than an impossible cluster. Additionally, a doubled consonant (nn, mm, ll, pp) is simplified to a single consonant before another consonant.
| Context | Result |
|---|---|
| d + þ (3rd sg) | tt |
| t + þ (3rd sg) | tt |
| s + þ (3rd sg) | st |
| d + st (2nd sg) | tst |
| þ + st (2nd sg) | st |
| nn/mm/ll/pp + C | n/m/l/p + C |
The live engine handles additional consonant clusters and special cases beyond those shown here — including dotted-letter changes (ċ → c, ċġ → ġ), nasal-cluster simplification (e.g. findan → fint), and weak verb past-tense formation. If interested, feel free to explore the guts of the engine in the linked GitHub repo: paradigm.js
THIRD_SG_COLLISION = {'d+þ': 'tt', 't+þ': 'tt', 's+þ': 'st'}
SECOND_SG_COLLISION = {'d+st': 'tst', 'þ+st': 'st'}
# Doubled consonants drop one before another consonant
def apply_collision(stem, ending):
# Simplify doubled final consonant before a consonant ending
if len(stem) >= 2 and stem[-1] == stem[-2] and ending[0] not in 'aeiouāǣēīōūȳ':
stem = stem[:-1]
key = stem[-1] + '+' + ending
if ending == 'þ' and key in THIRD_SG_COLLISION:
return stem[:-1] + THIRD_SG_COLLISION[key]
if ending == 'st' and key in SECOND_SG_COLLISION:
return stem[:-1] + SECOND_SG_COLLISION[key]
return stem + ending
Worked Example — beran
Input: beran — principal parts ['beran', 'bær', 'bǣron', 'boren']
beran − -an → presentStem =
berbær (bare stem) → pastSgStem = bærbǣron − -on → pastPlStem =
bǣrboren − ġe- (none) − -en →
pastPartStem = bor
ber.
Scan longest-first: vowel e found at index 1 → mutated to
i → mutatedStem = bir
bir + st).
Final consonant r: no collision rule applies, no doubled consonant → birst (epenthetic e optional: bir(e)st)
bir + þ).
Final consonant r: no collision rule applies →
birþ (epenthetic e optional: bir(e)þ)
ber and
mutatedStem bir:sg1 =
ber + e = bere ·
sg2 = bir(e)st ·
sg3 = bir(e)þ ·
pl = ber + aþ = beraþ
bær and
pastPlStem bǣr:sg1 =
bær (bare) ·
sg2 = bǣr + e = bǣre ·
sg3 = bær (bare) ·
pl = bǣr + on = bǣron
ber and
pastPartStem bor:inflected infinitive = tō +
ber + enne = tō berennepresent participle =
ber + ende = berendepast participle = ġe +
bor + en = ġeboren
ber:sg =
ber (bare) · pl = ber + aþ = beraþ
| 1st sg. | bere |
| 2nd sg. | bir(e)st |
| 3rd sg. | bir(e)þ |
| plural | beraþ |
| 1st sg. | bær |
| 2nd sg. | bǣre |
| 3rd sg. | bær |
| plural | bǣron |
| singular | bere |
| plural | beren |
| singular | bǣre |
| plural | bǣren |