Mova0.5 pre-release⌕
☰
home / docs / languages / Early Modern English / 13. Concrete improvements for Mova's parser and lexicon

13. Concrete improvements for Mova's parser and lexicon

Each item says what to change, where, how many sentences it touches (with the date and the set it was counted on), and its negative control: the case that must stay unchanged, so that the change can show red. Counts: SLM now = en-agreed.bin over 6 013 Torah sentences aligned with the db; db = 6 065 JPS sentences of parsedb/current.conllu; all 2026-10-17. Items are ordered by expected gain per line of code.

The items are written so that each can be a separate commit with its own measurement (two runs identical, the Torah and tales cycles as the check, the held-out sets untouched). The «Status» section says which are in the code.

Status (2026-10-18)

Done: T1, T2, T3, T4, L1, L2, L3, L5, L6, F1, S1; F2 and F3 for the words the tables cover. The rest are proposals.

#WhereWhat the code does now
L1–L3en/src/morph.rs (archaic, ending_verb, known_form)spellings of the stem ranked (CVC stem → «e» spelling, else the most frequent verb in UD); AGID-only superlatives are not dictionary forms; «-est»/«-st» after a past form → that verb, VBD
T1, T2, T4en/src/emode.rs (CLOSED, force, fix)78 entries (pronouns, modals, have/do/be forms, saith, lest, unto, behold, lo, aught, nought, whosoever, yea, nay, 35 adverbs, LORD/GOD in capitals, a second reading of «thine» as PRP) with context conditions; the tag is forced in the tagger's beam (PTagger::tag_forced), lemma/UPOS/FEATS set after the parse, FEATS filtered by the UD registry
T3en/src/emode.rs (ending)an unknown lower-case word in «-eth»/«-est»/«-st» over a known verb is forced VBZ/VBP/VBD; lemma the verb; FEATS person, number, tense, Style=Arch
S1en::emode::postverbal_not, called in en::annotate and gparse annotate«not» after a lexical verb (or its postposed pronoun) → the verb's advmod; not after let/be/have/do, not before VBG/VBN/TO/JJ/«only»
L5gparse/src/data.rs (Lex::fill)a retagged word unknown to GP_LEX is lemmatized for its new tag; a verb keeps an informative old lemma when the new one only repeats the form
F1gparse/src/data.rs (Lex::table), gparse annotateevery word the EModE table knows with its tags (retagged or not) takes lemma and FEATS from the table
L6annot/src/repair.rs; annot db-repair <in> <out>; drafts_fromrules table, ending, verb-lemma, lower-lemma, not over CoNLL-U lines; idempotent; the drafts get it before the gates

Annotation path: annot's Rust draft goes through en::annotate::annotate (one path with en annotate). Measurement tools: en compare <ref> <pred> (UD scores and agreement by class) and annot gate-check <drafts>.

Measured 2026-10-18, en-agreed.bin, graph parser live-0707 with GP_LEX = school-agreed, against the 6 065 JPS sentences of corpora/judaism/parsedb/current.conllu (a copy taken 2026-10-17 23:47); every run twice, identical:

main before (2026-10-17)now
SLM draft: UPOS / XPOS / UFeats94.25 / 92.20 / 92.3697.00 / 95.37 / 95.54
SLM draft: lemma / UAS / LAS / MLAS98.22 / 84.10 / 78.20 / 62.1898.53 / 85.83 / 81.03 / 68.29
SLM draft: closed EModE words UPOS / UFeats64.57 / 49.9396.69 / 95.03
SLM draft: -eth verbs UPOS; -est/-st verbs UPOS9.30; 5.48100.00; 97.26
SLM draft: sentences without a UPOS disagreement1 8732 834
SLM draft: refused by the gates (of 6 105)295
graph parser: UFeats / MLAS95.88 / 83.5596.90 / 85.41
graph parser: verbs with lemma = form (-eth)14 626 (546)13 994 (3)
graph parser: archaic pronouns with Person=31 981 (old drafts)0
graph parser vs the db repaired by L6: lemma / Feats98.51 / 94.2499.53 / 97.06
UD English EWT dev LAS (en-agreed.bin; en.bin)80.49; 80.2980.50; 80.30
UD English EWT test LAS (en-agreed.bin; en.bin)81.25; 81.0481.28; 81.09

Lemma agreement with the db itself falls (SLM -eth 67.94 → 38.87, graph parser 99.18 → 98.78) because the db keeps D1, D3 and D6: giveth → giveth, thee → thee, Lord for LORD. annot db-repair on a copy of the judaism db (7 982 sentences) changes 3 665 words by table, 668 by ending, 51 by not, 19 by lower-lemma, 3 by verb-lemma; on its JPS sentences D1 375 → 0, D2 21 → 0, D3 243 → 2, D4 141 → 0, archaic forms without Style=Arch 2 817 → 27 tokens, D6 611 → 36, D9 72 → 7; the gates refuse nothing before or after. The shared db is not rewritten: that is the operator's step.

Not done, with the reason: a rule letting a dictionary adjective under a verb tag take the ending («thou lightest») turned honest (VB) into hone; never and modern not in S1 cost 0.01 LAS on EWT test; both left out.

Summary table

#ChangeWhereSentences affectedKind
T1closed-class EModE table before the tagger: pronouns, auxiliaries, lest, unto, behold, aught …en (tagger input or a forced-tag pass)1 637 (SLM now)tag
T2the same for 27 pro-adverbs (thereof, wherewith, whither …)same; and archaic_adverbs selection479 (SLM now)tag
T3-eth / 2nd person -est guesser: unknown form = known verb stem + ending → verb tagen tagger features or a pass after it573 (SLM now)tag
—T1–T3 together2 242 of 6 013 (37 %); 704 would have no UPOS error left
T4LORD, GOD in capitals → PROPN, lemma LORDtagger pass705 (SLM now); 611 db lemmastag, lemma
T5capitalised divine pronouns (Me, Thy, Thou, He mid-sentence) → PRONtagger pass110 (SLM now)tag
L1archaic(): rank candidates by «is a verb lemma» then UD frequencyen/src/morph.rs55 tokens wrong today (com, se, hat, li, di, putt, marri …)lemma
L2ignore AGID-only JJS analyses for verb tags; drop AGID superlatives of non-adjectivesen/src/morph.rs or en/build.rsgoest 27, doest 8, seest 7, shouldest 8, liest 3, … ≈ 60 tokens; plus the SLM's JJS tagging of 126 sentenceslemma, tag
L32nd person past: -est/-st after a past form → that form's lemmaen/src/morph.rssaidst 7, broughtest 3, stoodest 2, knewest, drankest, sentest, defiledst, stretchedst, badest, sawest, smotest ≈ 20 tokenslemma
L4strong/old forms table (≈ 50 entries) and old pluralsen/data/archaic.tsv via build.rsdb: 67 tokens / 62 sentences (D7) + kine/brethren 137 tokenslemma
L5gparse Lex::fill: when the tag changes, re-lemmatize with en::morph instead of keeping the old lemmagparse/src/data.rsdb: 400 tokens / 328 sentences (D1, D2)lemma
L6annot drafts_from: extend the AUX lemma repair to VERB (any verb tag) and to thee → thouannot/src/main.rs328 + 202 sentenceslemma
F1FEATS of the archaic pronouns from a table, never from the tag fallbackgparse/src/data.rs (Lex::fill) and the table of T1db: 98 sentences with Person=3 on thou/thy/thine (D4)feats
F2Style=Arch on every archaic form, by the tableT1 table, L4 tabledb: 1 681 sentences lack it somewhere (D5)feats
F3verb person/number from the ending (-est → 2 Sing, -eth → 3 Sing)post-tag passdb: 3 stray `PlurPerson=3on-est` verbs; future drafts
S1re-attach postverbal not to its verbpost-parse ruledb: 72 tokens, about 70 sentencestree
S2«it came to pass»: one analysis (it expl, pass xcomp, event csubj/conj)post-parse ruledb: 106tree
S3subjunctive: VB with a subject and a conditional mark → `Mood=SubTense=PresVerbForm=Fin`post-parse rule
S4for ever, to-day, to-morrow, to-night: one analysis eachpost-parse ruledb: 67 + 14 + 9 + 1tree
S5NP + comma + resumptive pronoun → dislocatedpost-parse rulea few dozen («And Abel, he also…», «the LORD, He is God»)tree
S6ye + noun: ye head, noun nmod:unmarked (EWT)post-parse ruledb: 4tree
S7lower-case lemma for non-PROPN (Behold, Whosoever, Thy, Howbeit, Amen, Nay)lemma passdb: 91 tokens / 87 sentences (D9)lemma
P1negators: add nought, naught, nay; lest as negative purposeprag/src/feats.rs66 lest + 8 nought + 9 nay sentences at mostpragmatics
P2modal feature from the lemma, or map shalt→shall, wilt→will, mayest→may, canst→can, shouldest→should … in norm_wordprag/src/feats.rs750 Torah sentences with an archaic modalpragmatics
P3subject person: fall back to the pronoun's form (thou, thee, ye → 2) when FEATS disagreeprag/src/feats.rs98 (D4)pragmatics
P4add thyself to the second-person listprag/src/feats.rs32 thyself tokenspragmatics
W1extend archaic_adverbs with the 19 missing pro-adverbsWho can do what to whom — level-1 selectional preferences (2026-10-02)the reranker's lexical repair on 473 sentences (SLM now)world
W2register senses for false friends (even, corn, suffer, quick, sore, seed, stranger, know …)world dictionary, «formal»/archaic domain (world/src/domains.rs)at even 11, corn 32, seed 93, stranger 53 …world
W3biblical formulas into the expression base (found grace in the eyes of, lifted up his eyes, be cut off from, surely die, knew his wife)Expressions with their real meanings — the pragmatics lens base7 + 9 + 21 + 17 + 2 …world
W4partitive of after eat, take, drink, give, offer, bringframe readereat of 34, take of 26, … ≈ 80world
K1tokenizer: 'tis, 'twas, 'twould, may'st, could'st, ne'er, e'er, o'er, e'en, th'en tokenizertales: 112 lines with 'tis-type, 13 with -'st, 44 with ne'er-typetoken
K2an/and + nominative pronoun + finite verb = SCONJ ifpost-tag ruletales (book:pg29672:104 …)tag
R1retrain the SLM with the repaired Torah dben trainallmodel
R2add the repaired Torah db to GP_LEX (the graph parser's lexicon)cycle config CYCLE_LEXall retagged archaic tokenslexicon

Details

T1. A closed-class EModE table before the tagger

What. A table of forms whose analysis in the biblical register does not depend on context:

FormUPOSXPOSLemmaFEATS
thouPRONPRPthou`Case=Nom
theePRONPRPthou`Case=Acc
thyPRONPRP$thy`Case=Gen
thinePRONPRP$thysame
thyselfPRONPRPthyself`Case=Acc
yePRONPRPye`Case=Nom
shalt, wilt, canst, mayest, mayst, mightest, shouldest, shouldst, wouldest, wouldst, couldest, couldstAUXMDshall, will, can, may, may, might, should, should, would, would, could, could`Number=Sing
hastAUXVBPhave`Mood=Ind
hathAUXVBZhave`Mood=Ind
hadstAUXVBDhave`Mood=Ind
dost, doth, didstAUXVBP, VBZ, VBDdoperson, tense, Style=Arch
wast, wertAUXVBDbe`…
saith, sayestVERBVBZ, VBPsayperson, Style=Arch
lestSCONJINlest—
untoADPINunto—
behold (sentence-initial or before a comma), loINTJUHbehold, lo—
aught, nought, naughtPRONNNaught, nought, naughtPronType=Ind / PronType=Neg
whosoever, whosoPRONWPwhosoever, whosoPronType=Rel

The UPOS of hath, hast, hadst is AUX before a past participle and VERB otherwise; the parser decides (the table gives the lemma and FEATS and the XPOS; the UPOS between AUX and VERB comes from the context, as for modern have). art needs one context condition: AUX when thou is within one word before or after it, otherwise left to the tagger (it is mostly the noun in the tales).

Where. A forced-tag pass: the table is CLOSED in en/src/emode.rs (a Rust constant; each entry carries its «why»), force gives the tags to PTagger::tag_forced before the tagger decides the rest, fix sets lemma, UPOS and FEATS after the parse. The modals carry Style=Arch|VerbForm=Fin (EWT gives a modal VerbForm=Fin only, no person); thine has the lemma thy; art, wilt need thou up to two words before or one after; behold, lo are UH first in the clause, after a punctuation mark or and, or before a punctuation mark. hath, hast, hadst, dost, doth, didst take AUX or VERB from the parse; a copula among them becomes aux.

Count. SLM now: 1 637 sentences have a UPOS error on a T1 form. The table does not need a model.

Negative control. «the art of the perfumer» (db art|NOUN), «Ye Olde» (not in our texts; the table must not fire on a capitalised Ye before a capitalised noun in a modern text), wilt the verb (to droop) in a modern text: wilt is AUX only before a verb or after thou.

T2. Pro-adverbs

Add to the same table, as ADV with advmod: thereof, therein, thereon, thereby, thereto, therewith, whereof, wherein, whereon, wherewith, whereby, whither, whence, thither, hither, thence, hence, wherefore, peradventure, howbeit, yonder, nigh, betimes, hitherto, henceforth, thenceforth, yesternight. SLM now: 479 sentences. whither, whereof, wherein, wherewith, whereon, whereby get PronType=Rel when they open a relative clause. Negative control: hence and thence in modern prose («hence the name») are also ADV — no conflict; nigh as an adjective («the time is nigh») → let the parser choose ADJ when it is a predicate after be.

Now. In CLOSED: the 24 there-/thither/… words as RB/ADV with no FEATS, the 11 where- words as WRB/ADV with PronType from the annotation, nigh only when not after a form of be; yesternight is left out (the db has it as NOUN). Also yea, nay as UH/INTJ.

T3. The -eth / -est guesser

A form not in the dictionary (or in it only as an AGID superlative, L2) that ends in -eth/-th or -est/-st and whose stem (with the spelling rules of chapter 4.3) is a known verb lemma is a verb: VBZ with Number=Sing|Person=3|Style=Arch for -eth; VBP (or VBD after a past stem) with Number=Sing|Person=2|Style=Arch for -est. SLM now: 454 sentences with an -eth error and 126 with an -est error, 573 together.

Negative control (all from the Torah): priest, against, beast, feast, harvest, interest, youngest, greatest, earth, death, teeth, Beth, Heth, Japheth, twentieth — every one of these is in the dictionary as a noun, adjective or proper noun, or has a stem that is not a verb.

Now. en::emode::ending with en::morph::ending_verb; the word must be all letters and not capitalised inside the sentence (after a punctuation mark it may be). A lexical verb the parser made AUX is VERB unless its lemma is a registry auxiliary. The negative controls above, with first, must, best, lest, honest, forest, are tests.

L1–L3. Fixes inside archaic()

candidates(form):
  for ending in [eth, est, th, st, edst, dst]:
    stem = form - ending
    try: stem, stem+e, undoubled(stem), stem[-i]+y          # spelling rules
    keep candidates c with dict::lemma(c) having a verb paradigm (VB/VBZ/VBD forms)
    and, for -est/-st/-edst/-dst, also stems that are a VBD form → that form's lemma
  pick the kept candidate with the highest UD frequency

Unit tests to add (each from the Torah, with the right answer): cometh→come, seeth→see, hateth→hate, lieth→lie, dieth→die, putteth→put, marrieth→marry, biteth→bite, rideth→ride, writeth→write, goest→go, doest→do, seest→see, shouldest→should, liest→lie, saidst→say, broughtest→bring, stoodest→stand, knewest→know, sentest→send, badest→bid. Negative controls: digest, interest, harvest, greatest, rest with their usual tags (already in archaic_verbs), plus hat, com, putt as nouns.

Now. All the forms above are tests in en/src/morph.rs (archaic_endings) and pass. The ranking differs from the sketch: a stem ending consonant–vowel–consonant takes its «e» spelling first (biteth → bite, not bit), the others go by the verb's UD frequency, then the lemma's. A form is «known» unless AGID alone lists it, as a superlative or comparative (known_form). For the past, the VBD reading must be at least as frequent in UD as the form's own present reading (sawest → see; layest → lay). badest is in the verb-only list (AGID has no bade).

L4. The old-forms table

Proposed entries (verb tag required unless marked *):

FormLemmaFormLemmaFormLemma
spake*speakbrakebreakbarebear
sware*swearclave*cleavegatget
begat*begetdrave*drivesatesit
badebidtrode*treadclomb*climb
holp*, holpen*helpdurst*darewist*wit
wot*witwroughtworksmotesmite
abodeabidebuilded*builddigged*dig
sodseethesoddenseethewaxenwax
hewnhewmoltenmeltgravengrave
shapenshapestrickenstrikeladenlade
gottengetshew*, shewed*, shewn*showquoth*quoth
kine (NNS)*cowbrethren (NNS)*brother

wrought must stay ADJ with lemma wrought in «wrought iron»; sod, bare, abode, laden, bade keep their noun/adjective readings without a verb tag.

L5. Re-lemmatize after a re-tag

In gparse/src/data.rs, Lex::fill returns «the most frequent FEATS of the tag, with the old lemma» when the corpus does not know the (form, UPOS, XPOS) triple. Replace the old lemma by en::morph::Morph.lemmatize(form, Tag::parse(xpos)) (and the FEATS by those of T1/T3 when the form is in the tables). This is the step that turns giveth NOUN into giveth VERB today. db: 400 tokens in 328 sentences carry the result (D1 + D2). The same change keeps future rounds clean.

Negative control: a form whose tag does not change keeps its lemma (the current behaviour, annotate in gparse/src/main.rs already guards this).

Now. Done in Lex::fill: the EModE table first (F1), then the corpus, then the lemma for the new tag. A verb whose new lemma would only repeat its form keeps an old lemma that does not (smote VBD → VBP stays smite).

L6. A deterministic repair pass over the db

The current db can be repaired without a teacher: re-lemmatize every VERB/AUX whose lemma equals an archaic form (L1–L5), set thee → thou, thine → thy, mine → my, lower-case non-PROPN lemmas (S7), and apply F1/F2. Write the result as a new db version (the db keeps history.conllu and log.tsv), and report the changed token counts per rule. Then re-run the world and the course on it; Torah ★ (252 on 2026-10-17) is the check.

Now. annot db-repair <in.conllu> <out.conllu> writes the repaired copy and prints the counts per rule (see the status section); drafts_from applies the same rules to every draft before the gates. mine → my is not done (not in the table). Writing it into the shared db, and the world and course re-run, are left to the operator.

F1–F3. Features

Now. F1 in en::emode::fix (the SLM draft), Lex::table (the graph parser, every word of the table) and annot db-repair. F2 for every word of the tables, filtered by the registry (no Style=Arch on SCONJ or INTJ). F3 for the words T3 covers.

S1. Postverbal not

Rule: not (or never) directly after a lexical VERB tagged VB/VBD/VBP/VBZ, or after that verb's postposed pronoun subject, and attached to a word to its right → re-attach to the verb as advmod. db: 72 tokens attached elsewhere today. Negative controls: «not the sinew but the bone» (no verb before not); «I will not eat» (AUX before not); «let not the Lord be angry» (keep: not belongs to the lower clause — exception for let).

Now. en::emode::postverbal_not, after the parse in en::annotate, gparse annotate and annot db-repair. Only not: never and modern not («recommend not using», «know not to eat», «has not a Tom») moved EWT words, so the rule skips be, have, do and a not before VBG, VBN, TO, JJ or only. Torah SLM draft: 114 moved, their head agreeing with the db 33 → 73; the rest are the db's own D10 errors.

S2. «it came to pass»

Rewrite to: came root, it expl, to mark of pass, pass xcomp, the that-clause csubj of came, a temporal as/when-clause advcl. db: 106 occurrences, five analyses today. Negative control: «came to the place» (no pass), «come to pass» inside a quoted prophecy («it shall come to pass») — same rule, future tense.

S3. Subjunctive

A VB with a subject, under a mark in {if, though, lest, until, till, ere, whether, except, unless}, or a VB root with a third-person subject before it and no auxiliary («God give thee», «cursed be») → Mood=Sub|Tense=Pres| VerbForm=Fin plus the subject's person and number (EWT's convention). db: 53 VB tokens with VerbForm=Inf in this position, plus 35 be tokens (the two overlap). Negative controls: «that thou mayest know» (modal + infinitive); «if ye will do this» (indicative AUX); imperatives (no subject).

P1–P4. The pragmatic layer

All in prag/src/feats.rs:

W1–W4. The world layer

K1–K2. Tokenizer and the conditional an

R1–R2. Training data

What not to do

This page in Markdown → https://md.mova.elamur.ai/free/en/docs/languages/en-x-emode/13-improvements/