From a40994127777c4b8f3bf49c6d661abf06796c94c Mon Sep 17 00:00:00 2001 From: v4nn4 <1796093+v4nn4@users.noreply.github.com> Date: Mon, 24 Aug 2026 00:31:59 +0200 Subject: [PATCH] =?UTF-8?q?Add=20Amharic=20=E2=80=94=20third=20Semitic=20e?= =?UTF-8?q?ngine,=20Ge'ez=20script=20(Beta)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amharic (Ethiosemitic) is written in the Ge'ez abugida and cited by the 3sg-masc perfective (ሄደ). The engine resolves each lemma to six mined principal parts (perfective, imperfective, perfect, present, imperfective-nonfinite and the 2sg-masc imperative; data/amh/parts.tsv) and derives the paradigm by regular subject-agreement affixation per TAM, with a Ge'ez syllable helper that decomposes each Ethiopic codepoint into (consonant-row, vowel-order) so stem vowels can be revocalised and agreement syllables appended. Weak/irregular residue (quadriliteral reduplications, geminate/biradical roots, type-B ablaut, causative/glottal prefix merges) is patched by a mined-override layer (data/amh/overrides.tsv, 408 cells — 159 rule residue + 249 seeding the 17 part-less lemmas incl. the copula ነው). Beta tier: verified against a single oracle, UniMorph (kaikki's Amharic extraction does not expand). Golden gate: forms 20247/20247 (100.00%), lemma coverage 670/670 (100.00%), 97.98% rule-derived / 2.02% overridden. Full registration: Lang::Amh, from_code am/amh/amharic, Conjugation + build dispatch, reverse index, a 5-group serde Table (perfective/perfect/imperfective/ imperfectiveNfin/jussive), PyO3 + wasm, Cargo includes, correctness.py, and the CI single-oracle gate. All green: 343 lib tests, clippy, fmt, python + wasm. Stacked on the Hebrew branch (rf/hebrew-engine); merge that first. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 11 + Cargo.toml | 2 + data/amh/overrides.tsv | 409 ++++++++++++++++ data/amh/parts.tsv | 654 ++++++++++++++++++++++++++ docs/amh/adjudications.tsv | 1 + scripts/amh/fetch_unimorph.sh | 6 + scripts/amh/mine.py | 24 + scripts/amh/mine_overrides.py | 92 ++++ scripts/amh/unimorph_to_tsv.py | 22 + scripts/correctness.py | 2 +- src/amh.rs | 827 +++++++++++++++++++++++++++++++++ src/bin/golden_amh.rs | 48 ++ src/lib.rs | 10 + src/python.rs | 39 ++ src/reverse.rs | 19 +- src/wasm.rs | 5 + 16 files changed, 2168 insertions(+), 3 deletions(-) create mode 100644 data/amh/overrides.tsv create mode 100644 data/amh/parts.tsv create mode 100644 docs/amh/adjudications.tsv create mode 100755 scripts/amh/fetch_unimorph.sh create mode 100644 scripts/amh/mine.py create mode 100644 scripts/amh/mine_overrides.py create mode 100755 scripts/amh/unimorph_to_tsv.py create mode 100644 src/amh.rs create mode 100644 src/bin/golden_amh.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc79d249..57414d7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -939,5 +939,16 @@ jobs: run: ./scripts/heb/fetch_kaikki.sh - name: Hebrew golden harness with two-oracle regression gate run: cargo run --release --bin golden_heb -- data/heb/unimorph.tsv data/heb/kaikki.tsv --check + - name: Cache UniMorph amh + id: unimorph-amh + uses: actions/cache@v5 + with: + path: data/amh/unimorph.tsv + key: unimorph-amh-v1 + - name: Fetch UniMorph amh + if: steps.unimorph-amh.outputs.cache-hit != 'true' + run: ./scripts/amh/fetch_unimorph.sh + - name: Amharic golden harness with single-oracle regression gate (Beta) + run: cargo run --release --bin golden_amh -- data/amh/unimorph.tsv --check - name: Reverse-lookup gate (fra, spa, eng; deu needs the kaikki dump) run: cargo run --release --bin reverse_gate -- --check --langs fra,spa,eng diff --git a/Cargo.toml b/Cargo.toml index 83789aed..cb71110a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,8 @@ include = [ "data/ara/overrides.tsv", "data/heb/parts.tsv", "data/heb/overrides.tsv", + "data/amh/parts.tsv", + "data/amh/overrides.tsv", "data/por/classes.tsv", "data/por/verbs.tsv", "data/ron/classes.tsv", diff --git a/data/amh/overrides.tsv b/data/amh/overrides.tsv new file mode 100644 index 00000000..47ffed13 --- /dev/null +++ b/data/amh/overrides.tsv @@ -0,0 +1,409 @@ +# lemma feature form (mined residue — regenerate with scripts/amh/mine_overrides.py) +ለቀቀ V;1;PRF;SG ለቅቄያለሁ +ላከ V;1;PFV;SG ላኩ +ላከ V;2;MASC;PFV;SG ላክ +ማረከ V;1;PFV;SG ማረኩ +ማረከ V;2;MASC;PFV;SG ማረክ +ራበ V;3;IMP;MASC;SG ይራብ +ሰለቸ V;3;IMP;MASC;SG ይሰልች +ሰካ V;3;IMP;MASC;SG ይሰካ +ሰደደ V;1;PRF;SG ሰድጃለሁ +ሰጠ V;1;PFV;PL ሰጠን +ሰጠ V;1;PFV;SG ሰጠሁ +ሰጠ V;2;FEM;PFV;SG ሰጠሽ +ሰጠ V;2;MASC;PFV;SG ሰጠህ +ሳሳ V;3;IMP;MASC;SG ይሳሳ +ሸሸ V;1;IMP;PL እንሽ +ሸሸ V;1;IMP;SG ልሽ +ሸሸ V;3;FEM;IMP;SG ትሽ +ሸሸ V;3;IMP;MASC;SG ይሽ +ሸሸ V;3;IMP;PL ይሹ +ሸኘ V;3;IMP;MASC;SG ይሸኝ +ሻ V;2;FEM;IPFV;SG ትሺያለሽ +ቀረ V;1;PFV;PL ቀረን +ቀረ V;1;PFV;SG ቀረሁ +ቀረ V;2;FEM;PFV;SG ቀረሽ +ቀረ V;2;MASC;PFV;SG ቀረህ +ቀረና V;3;IMP;MASC;SG ይቀርና +ቀሰቀሰ V;3;IMP;MASC;SG ይቀስቅስ +በላ V;2;FEM;IMP;SG ብዪ +በረረ V;3;IMP;MASC;SG ይብረር +በረታ V;3;IMP;MASC;SG ይበርታ +ባረከ V;1;PFV;SG ባረኩ +ባረከ V;2;MASC;PFV;SG ባረክ +ተለዋወጠ V;1;IMP;PL እንለዋወጥ +ተለዋወጠ V;1;IPFV;NFIN;PL እንለዋወጥ +ተለዋወጠ V;1;IPFV;PL እንለዋወጣለን +ተለዋወጠ V;1;PFV;PL ተለዋወጥን +ተለዋወጠ V;1;PL;PRF ተለዋውጠናል +ተለዋወጠ V;2;IMP;PL ተለዋወጡ +ተለዋወጠ V;2;IPFV;NFIN;PL ትለዋወጡ +ተለዋወጠ V;2;IPFV;PL ትለዋወጣላችሁ +ተለዋወጠ V;2;PFV;PL ተለዋወጣችሁ +ተለዋወጠ V;2;PL;PRF ተለዋውጣችኋል +ተለዋወጠ V;3;IMP;PL ይለዋወጡ +ተለዋወጠ V;3;IPFV;NFIN;PL ይለዋወጡ +ተለዋወጠ V;3;IPFV;PL ይለዋወጣሉ +ተለዋወጠ V;3;PFV;PL ተለዋወጡ +ተለዋወጠ V;3;PL;PRF ተለዋውጠዋል +ተላከ V;1;PFV;SG ተላኩ +ተላከ V;2;MASC;PFV;SG ተላክ +ተመረመረ V;3;IMP;MASC;SG ይመርመር +ተመሰረተ V;3;IMP;MASC;SG ይመሥረት +ተመካከረ V;1;IMP;PL እንመካከር +ተመካከረ V;1;IPFV;NFIN;PL እንመካከር +ተመካከረ V;1;IPFV;PL እንመካከራለን +ተመካከረ V;1;PFV;PL ተመካከርን +ተመካከረ V;1;PL;PRF ተመካክረናል +ተመካከረ V;2;IMP;PL ተመካከሩ +ተመካከረ V;2;IPFV;NFIN;PL ትመካከሩ +ተመካከረ V;2;IPFV;PL ትመካከራላችሁ +ተመካከረ V;2;PFV;PL ተመካከራችሁ +ተመካከረ V;2;PL;PRF ተመካክራችኋል +ተመካከረ V;3;IMP;PL ይመካከሩ +ተመካከረ V;3;IPFV;NFIN;PL ይመካከሩ +ተመካከረ V;3;IPFV;PL ይመካከራሉ +ተመካከረ V;3;PFV;PL ተመካከሩ +ተመካከረ V;3;PL;PRF ተመካክረዋል +ተማመነ V;1;IMP;PL እንተማመን +ተማመነ V;1;IPFV;NFIN;PL እንተማመን +ተማመነ V;1;IPFV;PL እንተማመናለን +ተማመነ V;1;PFV;PL ተማመንን +ተማመነ V;1;PL;PRF ተማምነናል +ተማመነ V;2;IMP;PL ተማመኑ +ተማመነ V;2;IPFV;NFIN;PL ትተማመኑ +ተማመነ V;2;IPFV;PL ትተማመናላችሁ +ተማመነ V;2;PFV;PL ተማመናችሁ +ተማመነ V;2;PL;PRF ተማምናችኋል +ተማመነ V;3;IMP;PL ይተማመኑ +ተማመነ V;3;IPFV;NFIN;PL ይተማመኑ +ተማመነ V;3;IPFV;PL ይተማመናሉ +ተማመነ V;3;PFV;PL ተማመኑ +ተማመነ V;3;PL;PRF ተማምነዋል +ተማረከ V;1;PFV;SG ተማረኩ +ተማረከ V;2;MASC;PFV;SG ተማረክ +ተረጋገጠ V;1;IMP;PL እንረጋገጥ +ተረጋገጠ V;1;IPFV;NFIN;PL እንረጋገጥ +ተረጋገጠ V;1;IPFV;PL እንረጋገጣለን +ተረጋገጠ V;1;PFV;PL ተረጋገጥን +ተረጋገጠ V;1;PL;PRF ተረጋግጠናል +ተረጋገጠ V;2;IMP;PL ተረጋገጡ +ተረጋገጠ V;2;IPFV;NFIN;PL ትረጋገጡ +ተረጋገጠ V;2;IPFV;PL ትረጋገጣላችሁ +ተረጋገጠ V;2;PFV;PL ተረጋገጣችሁ +ተረጋገጠ V;2;PL;PRF ተረጋግጣችኋል +ተረጋገጠ V;3;IMP;PL ይረጋገጡ +ተረጋገጠ V;3;IPFV;NFIN;PL ይረጋገጡ +ተረጋገጠ V;3;IPFV;PL ይረጋገጣሉ +ተረጋገጠ V;3;PFV;PL ተረጋገጡ +ተረጋገጠ V;3;PL;PRF ተረጋግጠዋል +ተሰነዘረ V;3;IMP;MASC;SG ይሰንዘር +ተሰደደ V;1;PRF;SG ተሰድጃለሁ +ተሰጠ V;1;PFV;PL ተሰጠን +ተሰጠ V;1;PFV;SG ተሰጠሁ +ተሰጠ V;2;FEM;PFV;SG ተሰጠሽ +ተሰጠ V;2;MASC;PFV;SG ተሰጠህ +ተስማማ V;1;IMP;PL እንስማማ +ተስማማ V;1;IPFV;NFIN;PL እንስማማ +ተስማማ V;1;IPFV;PL እንስማማለን +ተስማማ V;1;PFV;PL ተስማማን +ተስማማ V;1;PL;PRF ተስማምተናል +ተስማማ V;2;IMP;PL ተስማሙ +ተስማማ V;2;IPFV;NFIN;PL ትስማሙ +ተስማማ V;2;IPFV;PL ትስማማላችሁ +ተስማማ V;2;PFV;PL ተስማማችሁ +ተስማማ V;2;PL;PRF ተስማምታችኋል +ተስማማ V;3;IMP;PL ይስማሙ +ተስማማ V;3;IPFV;NFIN;PL ይስማሙ +ተስማማ V;3;IPFV;PL ይስማማሉ +ተስማማ V;3;PFV;PL ተስማሙ +ተስማማ V;3;PL;PRF ተስማምተዋል +ተቀሰቀሰ V;3;IMP;MASC;SG ይቀስቀስ +ተበታተነ V;1;IMP;PL እንበታተን +ተበታተነ V;1;IPFV;NFIN;PL እንበታተን +ተበታተነ V;1;IPFV;PL እንበታተናለን +ተበታተነ V;1;PFV;PL ተበታተንን +ተበታተነ V;1;PL;PRF ተበታትነናል +ተበታተነ V;2;IMP;PL ተበታተኑ +ተበታተነ V;2;IPFV;NFIN;PL ትበታተኑ +ተበታተነ V;2;IPFV;PL ትበታተናላችሁ +ተበታተነ V;2;PFV;PL ተበታተናችሁ +ተበታተነ V;2;PL;PRF ተበታትናችኋል +ተበታተነ V;3;IMP;PL ይበታተኑ +ተበታተነ V;3;IPFV;NFIN;PL ይበታተኑ +ተበታተነ V;3;IPFV;PL ይበታተናሉ +ተበታተነ V;3;PFV;PL ተበታተኑ +ተበታተነ V;3;PL;PRF ተበታትነዋል +ተባረረ V;1;PRF;SG ተባርሬያለሁ +ተባረከ V;1;PFV;SG ተባረኩ +ተባረከ V;2;MASC;PFV;SG ተባረክ +ተባበረ V;1;IMP;PL እንተባበር +ተባበረ V;1;IPFV;NFIN;PL እንተባበር +ተባበረ V;1;IPFV;PL እንተባበራለን +ተባበረ V;1;PFV;PL ተባበርን +ተባበረ V;1;PL;PRF ተባብረናል +ተባበረ V;2;IMP;PL ተባበሩ +ተባበረ V;2;IPFV;NFIN;PL ትተባበሩ +ተባበረ V;2;IPFV;PL ትተባበራላችሁ +ተባበረ V;2;PFV;PL ተባበራችሁ +ተባበረ V;2;PL;PRF ተባብራችኋል +ተባበረ V;3;IMP;PL ይተባበሩ +ተባበረ V;3;IPFV;NFIN;PL ይተባበሩ +ተባበረ V;3;IPFV;PL ይተባበራሉ +ተባበረ V;3;PFV;PL ተባበሩ +ተባበረ V;3;PL;PRF ተባብረዋል +ተተወ V;2;FEM;IMP;SG ተተዪ +ተነተነ V;1;IMP;PL እንተንትን +ተነተነ V;1;IMP;SG ልተንትን +ተነተነ V;3;FEM;IMP;SG ትተንትን +ተነተነ V;3;IMP;MASC;SG ይተንትን +ተነተነ V;3;IMP;PL ይተንትኑ +ተነጋገረ V;1;IMP;PL እንነጋገር +ተነጋገረ V;1;IPFV;NFIN;PL እንነጋገር +ተነጋገረ V;1;IPFV;PL እንነጋገራለን +ተነጋገረ V;1;PFV;PL ተነጋገርን +ተነጋገረ V;1;PL;PRF ተነጋግረናል +ተነጋገረ V;2;IMP;PL ተነጋገሩ +ተነጋገረ V;2;IPFV;NFIN;PL ትነጋገሩ +ተነጋገረ V;2;IPFV;PL ትነጋገራላችሁ +ተነጋገረ V;2;PFV;PL ተነጋገራችሁ +ተነጋገረ V;2;PL;PRF ተነጋግራችኋል +ተነጋገረ V;3;IMP;PL ይነጋገሩ +ተነጋገረ V;3;IPFV;NFIN;PL ይነጋገሩ +ተነጋገረ V;3;IPFV;PL ይነጋገራሉ +ተነጋገረ V;3;PFV;PL ተነጋገሩ +ተነጋገረ V;3;PL;PRF ተነጋግረዋል +ተነፈሰ V;1;IMP;PL እንተንፍስ +ተነፈሰ V;1;IMP;SG ልተንፍስ +ተነፈሰ V;3;FEM;IMP;SG ትተንፍስ +ተነፈሰ V;3;IMP;MASC;SG ይተንፍስ +ተነፈሰ V;3;IMP;PL ይተንፍሱ +ተከሰሰ V;1;PRF;SG ተከስሻለሁ +ተከታተለ V;1;IMP;PL እንከታተል +ተከታተለ V;1;IPFV;NFIN;PL እንከታተል +ተከታተለ V;1;IPFV;PL እንከታተላለን +ተከታተለ V;1;PFV;PL ተከታተልን +ተከታተለ V;1;PL;PRF ተከታትለናል +ተከታተለ V;2;IMP;PL ተከታተሉ +ተከታተለ V;2;IPFV;NFIN;PL ትከታተሉ +ተከታተለ V;2;IPFV;PL ትከታተላላችሁ +ተከታተለ V;2;PFV;PL ተከታተላችሁ +ተከታተለ V;2;PL;PRF ተከታትላችኋል +ተከታተለ V;3;IMP;PL ይከታተሉ +ተከታተለ V;3;IPFV;NFIN;PL ይከታተሉ +ተከታተለ V;3;IPFV;PL ይከታተላሉ +ተከታተለ V;3;PFV;PL ተከታተሉ +ተከታተለ V;3;PL;PRF ተከታትለዋል +ተከፋፈለ V;1;IMP;PL እንከፋፈል +ተከፋፈለ V;1;IPFV;NFIN;PL እንከፋፈል +ተከፋፈለ V;1;IPFV;PL እንከፋፈላለን +ተከፋፈለ V;1;PFV;PL ተከፋፈልን +ተከፋፈለ V;1;PL;PRF ተከፋፍለናል +ተከፋፈለ V;2;IMP;PL ተከፋፈሉ +ተከፋፈለ V;2;IPFV;NFIN;PL ትከፋፈሉ +ተከፋፈለ V;2;IPFV;PL ትከፋፈላላችሁ +ተከፋፈለ V;2;PFV;PL ተከፋፈላችሁ +ተከፋፈለ V;2;PL;PRF ተከፋፍላችኋል +ተከፋፈለ V;3;IMP;PL ይከፋፈሉ +ተከፋፈለ V;3;IPFV;NFIN;PL ይከፋፈሉ +ተከፋፈለ V;3;IPFV;PL ይከፋፈላሉ +ተከፋፈለ V;3;PFV;PL ተከፋፈሉ +ተከፋፈለ V;3;PL;PRF ተከፋፍለዋል +ተኮሰ V;1;IMP;PL እንተኩስ +ተኮሰ V;1;IMP;SG ልተኩስ +ተኮሰ V;3;FEM;IMP;SG ትተኩስ +ተኮሰ V;3;IMP;MASC;SG ይተኩስ +ተኮሰ V;3;IMP;PL ይተኩሱ +ተወ V;2;FEM;IMP;SG ተዪ +ተወያየ V;1;IMP;PL እንወያይ +ተወያየ V;1;IPFV;NFIN;PL እንወያይ +ተወያየ V;1;IPFV;PL እንወያያለን +ተወያየ V;1;PFV;PL ተወያየን +ተወያየ V;1;PL;PRF ተወያይተናል +ተወያየ V;2;IMP;PL ተወያዩ +ተወያየ V;2;IPFV;NFIN;PL ትወያዩ +ተወያየ V;2;IPFV;PL ትወያያላችሁ +ተወያየ V;2;PFV;PL ተወያያችሁ +ተወያየ V;2;PL;PRF ተወያይታችኋል +ተወያየ V;3;IMP;PL ይወያዩ +ተወያየ V;3;IPFV;NFIN;PL ይወያዩ +ተወያየ V;3;IPFV;PL ይወያያሉ +ተወያየ V;3;PFV;PL ተወያዩ +ተወያየ V;3;PL;PRF ተወያይተዋል +ተወዳደረ V;1;IMP;PL እንወዳደር +ተወዳደረ V;1;IPFV;NFIN;PL እንወዳደር +ተወዳደረ V;1;IPFV;PL እንወዳደራለን +ተወዳደረ V;1;PFV;PL ተወዳደርን +ተወዳደረ V;1;PL;PRF ተወዳድረናል +ተወዳደረ V;2;IMP;PL ተወዳደሩ +ተወዳደረ V;2;IPFV;NFIN;PL ትወዳደሩ +ተወዳደረ V;2;IPFV;PL ትወዳደራላችሁ +ተወዳደረ V;2;PFV;PL ተወዳደራችሁ +ተወዳደረ V;2;PL;PRF ተወዳድራችኋል +ተወዳደረ V;3;IMP;PL ይወዳደሩ +ተወዳደረ V;3;IPFV;NFIN;PL ይወዳደሩ +ተወዳደረ V;3;IPFV;PL ይወዳደራሉ +ተወዳደረ V;3;PFV;PL ተወዳደሩ +ተወዳደረ V;3;PL;PRF ተወዳድረዋል +ተዋወቀ V;1;IMP;PL እንተዋወቅ +ተዋወቀ V;1;IPFV;NFIN;PL እንተዋወቅ +ተዋወቀ V;1;IPFV;PL እንተዋወቃለን +ተዋወቀ V;1;PFV;PL ተዋወቅን +ተዋወቀ V;1;PL;PRF ተዋውቀናል +ተዋወቀ V;2;IMP;PL ተዋወቁ +ተዋወቀ V;2;IPFV;NFIN;PL ትተዋወቁ +ተዋወቀ V;2;IPFV;PL ትተዋወቃላችሁ +ተዋወቀ V;2;PFV;PL ተዋወቃችሁ +ተዋወቀ V;2;PL;PRF ተዋውቃችኋል +ተዋወቀ V;3;IMP;PL ይተዋወቁ +ተዋወቀ V;3;IPFV;NFIN;PL ይተዋወቁ +ተዋወቀ V;3;IPFV;PL ይተዋወቃሉ +ተዋወቀ V;3;PFV;PL ተዋወቁ +ተዋወቀ V;3;PL;PRF ተዋውቀዋል +ተዘረዘረ V;3;IMP;MASC;SG ይዘርዘር +ተያየ V;1;IMP;PL እንተያይ +ተያየ V;1;IPFV;NFIN;PL እንተያይ +ተያየ V;1;IPFV;PL እንተያያለን +ተያየ V;1;PFV;PL ተያየን +ተያየ V;1;PL;PRF ተያይተናል +ተያየ V;2;IMP;PL ተያዩ +ተያየ V;2;IPFV;NFIN;PL ትተያዩ +ተያየ V;2;IPFV;PL ትተያያላችሁ +ተያየ V;2;PFV;PL ተያያችሁ +ተያየ V;2;PL;PRF ተያይታችኋል +ተያየ V;3;IMP;PL ይተያዩ +ተያየ V;3;IPFV;NFIN;PL ይተያዩ +ተያየ V;3;IPFV;PL ይተያያሉ +ተያየ V;3;PFV;PL ተያዩ +ተያየ V;3;PL;PRF ተያይተዋል +ተደመደመ V;3;IMP;MASC;SG ይደምደም +ተገመገመ V;3;IMP;MASC;SG ይገምገም +ተገደደ V;1;PRF;SG ተገድጃለሁ +ተጠባበቀ V;1;IMP;PL እንጠባበቅ +ተጠባበቀ V;1;IPFV;NFIN;PL እንጠባበቅ +ተጠባበቀ V;1;IPFV;PL እንጠባበቃለን +ተጠባበቀ V;1;PFV;PL ተጠባበቅን +ተጠባበቀ V;1;PL;PRF ተጠባብቀናል +ተጠባበቀ V;2;IMP;PL ተጠባበቁ +ተጠባበቀ V;2;IPFV;NFIN;PL ትጠባበቁ +ተጠባበቀ V;2;IPFV;PL ትጠባበቃላችሁ +ተጠባበቀ V;2;PFV;PL ተጠባበቃችሁ +ተጠባበቀ V;2;PL;PRF ተጠባብቃችኋል +ተጠባበቀ V;3;IMP;PL ይጠባበቁ +ተጠባበቀ V;3;IPFV;NFIN;PL ይጠባበቁ +ተጠባበቀ V;3;IPFV;PL ይጠባበቃሉ +ተጠባበቀ V;3;PFV;PL ተጠባበቁ +ተጠባበቀ V;3;PL;PRF ተጠባብቀዋል +ተጠነቀቀ V;3;IMP;MASC;SG ይጠንቀቅ +ተፈራረመ V;1;IMP;PL እንፈራረም +ተፈራረመ V;1;IPFV;NFIN;PL እንፈራረም +ተፈራረመ V;1;IPFV;PL እንፈራረማለን +ተፈራረመ V;1;PFV;PL ተፈራረምን +ተፈራረመ V;1;PL;PRF ተፈራርመናል +ተፈራረመ V;2;IMP;PL ተፈራረሙ +ተፈራረመ V;2;IPFV;NFIN;PL ትፈራረሙ +ተፈራረመ V;2;IPFV;PL ትፈራረማላችሁ +ተፈራረመ V;2;PFV;PL ተፈራረማችሁ +ተፈራረመ V;2;PL;PRF ተፈራርማችኋል +ተፈራረመ V;3;IMP;PL ይፈራረሙ +ተፈራረመ V;3;IPFV;NFIN;PL ይፈራረሙ +ተፈራረመ V;3;IPFV;PL ይፈራረማሉ +ተፈራረመ V;3;PFV;PL ተፈራረሙ +ተፈራረመ V;3;PL;PRF ተፈራርመዋል +ታመመ V;1;PRF;SG ታምሜያለሁ +ታሰበ V;3;IMP;MASC;SG ይታሰብ +ታወከ V;1;PFV;SG ታወኩ +ታወከ V;2;MASC;PFV;SG ታወክ +ታዘዘ V;1;PRF;SG ታዝዣለሁ +ታደሰ V;3;IMP;MASC;SG ይታደስ +ነው V;1;PL;PRS ነን +ነው V;1;PRS;SG ነኝ +ነው V;2;FEM;PRS;SG ነሽ +ነው V;2;MASC;PRS;SG ነህ +ነው V;2;PL;PRS ናችኍ +ነው V;3;FEM;LGSPEC1;PRS;SG ናት +ነው V;3;FEM;PRS;SG ነች +ነው V;3;MASC;PRS;SG ነው +ነው V;3;PL;PRS ናቸው +ነደደ V;3;IMP;MASC;SG ይንደድ +አመመ V;1;PRF;SG አምሜያለሁ +አረጋ V;3;IMP;MASC;SG ያርጋ +አሻለ V;2;FEM;IMP;SG አሽዪ +አሻሻለ V;2;FEM;IMP;SG አሻሽዪ +አበረከተ V;3;IMP;MASC;SG ያበርክት +አነሰ V;3;IMP;MASC;SG ይነስ +አነሳ V;1;IMP;SG ላንሳ +አነሳ V;1;IPFV;NFIN;PL እናነሣ +አነሳ V;1;IPFV;NFIN;SG አነሣ +አነሳ V;1;IPFV;PL እናነሣለን +አነሳ V;1;IPFV;SG አነሣለሁ +አነሳ V;3;FEM;IMP;SG ታንሳ +አነሳ V;3;IMP;MASC;SG ያንሳ +አነሳ V;3;IMP;PL ያንሱ +አወከ V;1;PFV;SG አወኩ +አወከ V;2;MASC;PFV;SG አወክ +አዋለ V;2;FEM;IMP;SG አውዪ +አዘዘ V;1;PRF;SG አዝዣለሁ +አደከመ V;3;IMP;MASC;SG ያድክም +አገረሸ V;3;IMP;MASC;SG ያገርሽ +አጎላ V;3;IMP;MASC;SG ያጉላ +አጣጣለ V;2;FEM;IMP;SG አጣጥዪ +አጸደቀ V;1;IMP;SG ላጽድቅ +አጸደቀ V;1;IPFV;NFIN;PL እናፀድቅ +አጸደቀ V;1;IPFV;NFIN;SG አፀድቅ +አጸደቀ V;1;IPFV;PL እናፀድቃለን +አጸደቀ V;1;IPFV;SG አፀድቃለሁ +አጸደቀ V;3;FEM;IMP;SG ታጽድቅ +አጸደቀ V;3;IMP;MASC;SG ያጽድቅ +አጸደቀ V;3;IMP;PL ያጽድቁ +ከሰሰ V;1;PRF;SG ከስሻለሁ +ከተተ V;1;PRF;SG ከትቻለሁ +ወረረ V;1;PRF;SG ወርሬያለሁ +ወደደ V;1;PRF;SG ወድጃለሁ +ዳረገ V;3;IMP;MASC;SG ይዳርግ +ገለበጠ V;3;IMP;MASC;SG ይገልብጥ +ገለጸ V;1;PL;PRF ገልፀናል +ገለጸ V;2;FEM;PRF;SG ገልፀሻል +ገለጸ V;2;MASC;PRF;SG ገልፀሀል +ገለጸ V;2;PL;PRF ገልፃችኋል +ገለጸ V;3;FEM;PRF;SG ገልፃለች +ገለጸ V;3;PL;PRF ገልፀዋል +ጠላ V;2;FEM;IMP;SG ጥዪ +ጨለመ V;3;IMP;MASC;SG ይጨልም +ጮኸ V;1;IPFV;PL እንጮሀለን +ጮኸ V;1;IPFV;SG እጮሀለሁ +ጮኸ V;1;PFV;PL ጮህን +ጮኸ V;1;PFV;SG ጮህኩ +ጮኸ V;1;PRF;SG ጮሄያለሁ +ጮኸ V;2;FEM;PFV;SG ጮህሽ +ጮኸ V;2;IPFV;MASC;SG ትጮሀለህ +ጮኸ V;2;IPFV;PL ትጮሀላችሁ +ጮኸ V;2;MASC;PFV;SG ጮህክ +ጮኸ V;2;PFV;PL ጮሀችሁ +ጮኸ V;2;PL;PRF ጮሀችኋል +ጮኸ V;3;FEM;IPFV;SG ትጮሀለች +ጮኸ V;3;FEM;PRF;SG ጮሀለች +ጮኸ V;3;IPFV;PL ይጮሀሉ +ጮኸ V;3;PFV;PL ጮሁ +ጸለየ V;1;PFV;PL ጸለይን +ጸለየ V;1;PFV;SG ጸለይኩ +ጸለየ V;1;PL;PRF ጸሊየናል +ጸለየ V;1;PRF;SG ጸልያለሁ +ጸለየ V;2;FEM;IMP;SG ጸሊዪ +ጸለየ V;2;FEM;IPFV;SG ትጸልዪያለሽ +ጸለየ V;2;FEM;PFV;SG ጸለይሽ +ጸለየ V;2;FEM;PRF;SG ጸሊየሻል +ጸለየ V;2;IMP;PL ጸሊዩ +ጸለየ V;2;MASC;PFV;SG ጸለይክ +ጸለየ V;2;MASC;PRF;SG ጸሊየሀል +ጸለየ V;2;PL;PRF ጸሊያችኋል +ጸለየ V;3;FEM;PRF;SG ጸሊያለች +ጸለየ V;3;IMP;PL ይጸሊዩ +ጸለየ V;3;PL;PRF ጸሊየዋል +ፈሰሰ V;3;IMP;MASC;SG ይፍሰስ +ፈተሸ V;1;PFV;PL ፈተሽን +ፈተሸ V;1;PFV;SG ፈተሽኩ +ፈተሸ V;1;PRF;SG ፈትሻለሁ +ፈተሸ V;2;FEM;IPFV;SG ትፈትሺያለሽ +ፈተሸ V;2;FEM;PFV;SG ፈተሽ +ፈተሸ V;2;MASC;PFV;SG ፈተሽክ diff --git a/data/amh/parts.tsv b/data/amh/parts.tsv new file mode 100644 index 00000000..898a1451 --- /dev/null +++ b/data/amh/parts.tsv @@ -0,0 +1,654 @@ +# lemma pfv ipfv prf prs ipfvn imp +ሄደ ሄደ ይሄዳል ሄዷል - ይሄድ ሂድ +ሆነ ሆነ ይሆናል ሆኗል - ይሆን ሁን +ለመነ ለመነ ይለምናል ለምኗል - ይለምን ለምን +ለማ ለማ ይለማል ለምቷል - ይለማ ልማ +ለቀቀ ለቀቀ ይለቃል ለቋል - ይለቅ ልቀቅ +ለበሰ ለበሰ ይለብሳል ለብሷል - ይለብስ ልበስ +ለወጠ ለወጠ ይለውጣል ለውጧል - ይለውጥ ለውጥ +ለየ ለየ ይለያል ለይቷል - ይለይ ለይ +ለገሰ ለገሰ ይለግሳል ለግሷል - ይለግስ ለግስ +ላከ ላከ ይልካል ልኳል - ይልክ ላክ +መለሰ መለሰ ይመልሳል መልሷል - ይመልስ መልስ +መረመረ መረመረ ይመረምራል መርምሯል - ይመረምር መርምር +መረጠ መረጠ ይመርጣል መርጧል - ይመርጥ ምረጥ +መራ መራ ይመራል መርቷል - ይመራ ምራ +መሰለ መሰለ ይመስላል መስሏል - ይመስል ምሰል +መሰረተ መሠረተ ይመሠርታል መሥርቷል - ይመሠርት መሥርት +መሰከረ መሰከረ ይመሰክራል መስክሯል - ይመሰክር መስክር +መሸ መሸ ይመሻል መሽቷል - ይመሽ - +መታ መታ ይመታል መትቷል - ይመታ ምታ +መከረ መከረ ይመክራል መክሯል - ይመክር ምከር +መደበ መደበ ይመድባል መድቧል - ይመድብ መድብ +መጣ መጣ ይመጣል መጥቷል - ይመጣ ምጣ +ማለ ማለ ይምላል ምሏል - ይምል ማል +ማረ ማረ ይምራል ምሯል - ይምር ማር +ማረከ ማረከ ይማርካል ማርኳል - ይማርክ ማርክ +ሞላ ሞላ ይሞላል ሞልቷል - ይሞላ ሙላ +ሞተ ሞተ ይሞታል ሞቷል - ይሞት ሙት +ሞከረ ሞከረ ይሞክራል ሞክሯል - ይሞክር ሞክር +ረሳ ረሳ ይረሳል ረስቷል - ይረሳ ርሳ +ረታ ረታ ይረታል ረትቷል - ይረታ ርታ +ረከሰ ረከሰ ይረክሳል ረክሷል - ይረክስ ርከስ +ረዘመ ረዘመ ይረዝማል ረዝሟል - ይረዝም - +ረዳ ረዳ ይረዳል ረድቷል - ይረዳ ርዳ +ረገጠ ረገጠ ይረግጣል ረግጧል - ይረግጥ ርገጥ +ረገፈ ረገፈ ይረግፋል ረግፏል - ይረግፍ - +ራቀ ራቀ ይርቃል ርቋል - ይርቅ ራቅ +ራበ ራበ ይርባል ርቧል - ይርብ - +ሮጠ ሮጠ ይሮጣል ሮጧል - ይሮጥ ሩጥ +ሰለቸ ሰለቸ ይሰለቻል ሰልችቷል - ይሰለች - +ሰማ ሰማ ይሰማል ሰምቷል - ይሰማ ስማ +ሰረቀ ሰረቀ ይሰርቃል ሰርቋል - ይሰርቅ ስረቅ +ሰረዘ ሰረዘ ይሰርዛል ሰርዟል - ይሰርዝ ሰርዝ +ሰራ ሠራ ይሠራል ሠርቷል - ይሠራ ሥራ +ሰበረ ሰበረ ይሰብራል ሰብሯል - ይሰብር ስበር +ሰበሰበ ሰበሰበ ይሰበስባል ሰብስቧል - ይሰበስብ ሰብስብ +ሰባበረ ሰባበረ ይሰባብራል ሰባብሯል - ይሰባብር ሰባብር +ሰነዘረ ሰነዘረ ይሰነዝራል ሰንዝሯል - ይሰነዝር ሰንዝር +ሰካ ሰካ ይሰካል ሰክቷል - ይሰካ - +ሰዋ ሠዋ ይሠዋል ሠውቷል - ይሠዋ ሠዋ +ሰደደ ሰደደ ይሰዳል ሰዷል - ይሰድ ስደድ +ሰጋ ሰጋ ይሰጋል ሰግቷል - ይሰጋ ስጋ +ሰጠ ሰጠ ይሰጣል ሰጥቷል - ይሰጥ ስጥ +ሰፈረ ሰፈረ ይሰፍራል ሰፍሯል - ይሰፍር ስፈር +ሰፈነ ሰፈነ ይሰፍናል ሰፍኗል - ይሰፍን ስፈን +ሰፋ ሰፋ ይሰፋል ሰፍቷል - ይሰፋ - +ሳሳ ሳሳ ይሳሳል ሳስቷል - ይሳሳ - +ሳቀ ሳቀ ይስቃል ስቋል - ይስቅ ሳቅ +ሳበ ሳበ ይስባል ስቧል - ይስብ ሳብ +ሳተ ሳተ ይስታል ስቷል - ይስት ሳት +ሸለመ ሸለመ ይሸልማል ሸልሟል - ይሸልም ሸልም +ሸሸ ሸሸ ይሸሻል ሸሽቷል - ይሸሽ ሽሽ +ሸና ሸና ይሸናል ሸንቷል - ይሸና ሽና +ሸኘ ሸኘ ይሸኛል ሸኝቷል - ይሸኝ - +ሸጠ ሸጠ ይሸጣል ሽጧል - ይሸጥ ሽጥ +ሸፈነ ሸፈነ ይሸፍናል ሸፍኗል - ይሸፍን ሸፍን +ሻ ሻ ይሻል ሽቷል - ይሻ ሻ +ሻረ ሻረ ይሽራል ሽሯል - ይሽር ሻር +ሾመ ሾመ ይሾማል ሾሟል - ይሾም ሹም +ቀላ ቀላ ይቀላል ቀልቷል - ይቀላ - +ቀረ ቀረ ይቀራል ቀርቷል - ይቀር ቅር +ቀረበ ቀረበ ይቀርባል ቀርቧል - ይቀርብ ቅረብ +ቀረና ቀረና ይቀረናል ቀርንቷል - ይቀረና - +ቀረጸ ቀረጸ ይቀርጻል ቀርጿል - ይቀርጽ ቅረጽ +ቀሰቀሰ ቀሰቀሰ ይቀሰቅሳል ቀስቅሷል - ይቀሰቅስ - +ቀነሰ ቀነሰ ይቀንሳል ቀንሷል - ይቀንስ ቀንስ +ቀና ቀና ይቀናል ቀንቷል - ይቀና ቅና +ቀየረ ቀየረ ይቀይራል ቀይሯል - ይቀይር ቀይር +ቀደመ ቀደመ ይቀድማል ቀድሟል - ይቀድም - +ቀደሰ ቀደሰ ይቀድሳል ቀድሷል - ይቀድስ ቀድስ +ቀጠለ ቀጠለ ይቀጥላል ቀጥሏል - ይቀጥል ቀጥል +ቀጠረ ቀጠረ ይቀጥራል ቀጥሯል - ይቀጥር ቅጠር +ቀጣ ቀጣ ይቀጣል ቀጥቷል - ይቀጣ ቅጣ +ቃኘ ቃኘ ይቃኛል ቃኝቷል - ይቃኝ ቃኝ +ቆመ ቆመ ይቆማል ቆሟል - ይቆም ቁም +ቆረጠ ቆረጠ ይቆርጣል ቆርጧል - ይቆርጥ ቁረጥ +ቆየ ቆየ ይቆያል ቆይቷል - ይቆይ ቆይ +ቆጠረ ቆጠረ ይቆጥራል ቆጥሯል - ይቆጥር ቁጠር +ቋጨ ቋጨ ይቋጫል ቋጭቷል - ይቋጭ ቋጭ +በለጠ በለጠ ይበልጣል በልጧል - ይበልጥ ብለጥ +በላ በላ ይበላል በልቷል - ይበላ ብላ +በረረ በረረ ይበራል በሯል - ይበር - +በረታ በረታ ይበረታል በርትቷል - ይበረታ - +በራ በራ ይበራል በርቷል - ይበራ - +በቀለ በቀለ ይበቅላል በቅሏል - ይበቅል ብቀል +በቃ በቃ ይበቃል በቅቷል - ይበቃ ብቃ +በተነ በተነ ይበትናል በትኗል - ይበትን በትን +በዛ በዛ ይበዛል በዝቷል - ይበዛ ብዛ +በየነ በየነ ይበይናል በይኗል - ይበይን በይን +በደለ በደለ ይበድላል በድሏል - ይበድል በድል +ባረከ ባረከ ይባርካል ባርኳል - ይባርክ ባርክ +ባሰ ባሰ ይብሳል ብሷል - ይብስ ባስ +ባከነ ባከነ ይባክናል ባክኗል - ይባክን ባክን +ተለቀቀ ተለቀቀ ይለቀቃል ተለቋል - ይለቀቅ - +ተለወጠ ተለወጠ ይለወጣል ተለውጧል - ይለወጥ - +ተለየ ተለየ ይለያል ተለይቷል - ይለይ - +ተለያየ ተለያየ ይለያያል ተለያይቷል - ይለያይ - +ተላለፈ ተላለፈ ይተላለፋል ተላልፏል - ይተላለፍ - +ተላከ ተላከ ይላካል ተልኳል - ይላክ ተላክ +ተመለሰ ተመለሰ ይመለሳል ተመልሷል - ይመለስ ተመለስ +ተመለከተ ተመለከተ ይመለከታል ተመልክቷል - ይመለከት ተመልከት +ተመላለሰ ተመላለሰ ይመላለሳል ተመላልሷል - ይመላለስ ተመላለስ +ተመረመረ ተመረመረ ይመረመራል ተመርምሯል - ይመረመር - +ተመረቀ ተመረቀ ይመረቃል ተመርቋል - ይመረቅ ተመረቅ +ተመረተ ተመረተ ይመረታል ተመርቷል - ይመረት - +ተመረጠ ተመረጠ ይመረጣል ተመርጧል - ይመረጥ ተመረጥ +ተመራ ተመራ ይመራል ተመርቷል - ይመራ ተመራ +ተመሰረተ ተመሠረተ ይመሠረታል ተመሥርቷል - ይመሠረት - +ተመታ ተመታ ይመታል ተመትቷል - ይመታ ተመታ +ተመቸ ተመቸ ይመቻል ተመችቷል - ይመች - +ተመቻቸ ተመቻቸ ይመቻቻል ተመቻችቷል - ይመቻች - +ተመኘ ተመኘ ይመኛል ተመኝቷል - ይመኝ ተመኝ +ተመዘገበ ተመዘገበ ይመዘገባል ተመዝግቧል - ይመዘገብ ተመዝገብ +ተመደበ ተመደበ ይመደባል ተመድቧል - ይመደብ ተመደብ +ተማረ ተማረ ይማራል ተምሯል - ይማር ተማር +ተማረከ ተማረከ ይማረካል ተማርኳል - ይማረክ ተማረክ +ተሞላ ተሞላ ይሞላል ተሞልቷል - ይሞላ ተሞላ +ተሞከረ ተሞከረ ይሞከራል ተሞክሯል - ይሞከር - +ተረሳ ተረሳ ይረሳል ተረስቷል - ይረሳ - +ተረከበ ተረከበ ይረከባል ተረክቧል - ይረከብ ተረከብ +ተረዳ ተረዳ ይረዳል ተረድቷል - ይረዳ ተረዳ +ተረገጠ ተረገጠ ይረገጣል ተረግጧል - ይረገጥ - +ተረጨ ተረጨ ይረጫል ተረጭቷል - ይረጭ ተረጭ +ተረፈ ተረፈ ይተርፋል ተርፏል - ይተርፍ ትረፍ +ተራበ ተራበ ይራባል ተርቧል - ይራብ ተራብ +ተራዘመ ተራዘመ ይራዘማል ተራዝሟል - ይራዘም - +ተሰለፈ ተሰለፈ ይሰለፋል ተሰልፏል - ይሰለፍ ተሰለፍ +ተሰማ ተሰማ ይሰማል ተሰምቷል - ይሰማ ተሰማ +ተሰረዘ ተሰረዘ ይሰረዛል ተሰርዟል - ይሰረዝ - +ተሰራ ተሠራ ይሠራል ተሠርቷል - ይሠራ ተሠራ +ተሰራጨ ተሰራጨ ይሰራጫል ተሰራጭቷል - ይሰራጭ - +ተሰቀለ ተሰቀለ ይሰቀላል ተሰቅሏል - ይሰቀል ተሰቀል +ተሰቃየ ተሰቃየ ይሰቃያል ተሰቃይቷል - ይሰቃይ ተሰቃይ +ተሰበረ ተሰበረ ይሰበራል ተሰብሯል - ይሰበር - +ተሰበሰበ ተሰበሰበ ይሰበሰባል ተሰብስቧል - ይሰበሰብ ተሰብሰብ +ተሰባሰበ ተሰባሰበ ይሰባሰባል ተሰባስቧል - ይሰባሰብ - +ተሰነባበተ ተሰነባበተ ይሰነባበታል ተሰነባብቷል - ይሰነባበት ተሰነባበት +ተሰነዘረ ተሰነዘረ ይሰነዘራል ተሰንዝሯል - ይሰነዘር - +ተሰናከለ ተሰናከለ ይሰናከላል ተሰናክሏል - ይሰናከል ተሰናከል +ተሰዋ ተሰዋ ይሰዋል ተሰውቷል - ይሰዋ ተሰዋ +ተሰየመ ተሰየመ ይሰየማል ተሰይሟል - ይሰየም ተሰየም +ተሰደደ ተሰደደ ይሰደዳል ተሰዷል - ይሰደድ ተሰደድ +ተሰጠ ተሰጠ ይሰጣል ተሰጥቷል - ይሰጥ ተሰጥ +ተሳሳተ ተሳሳተ ይሳሳታል ተሳስቷል - ይሳሳት ተሳሳት +ተሳተፈ ተሳተፈ ይሳተፋል ተሳትፏል - ይሳተፍ ተሳተፍ +ተሳነ ተሳነ ይሳናል ተስኗል - ይሳን ተሳን +ተሳካ ተሳካ ይሳካል ተሳክቷል - ይሳካ - +ተስተካከለ ተስተካከለ ይስተካከላል ተስተካክሏል - ይስተካከል - +ተስፋፋ ተስፋፋ ይስፋፋል ተስፋፍቷል - ይስፋፋ - +ተሸለመ ተሸለመ ይሸለማል ተሸልሟል - ይሸለም ተሸለም +ተሸነፈ ተሸነፈ ይሸነፋል ተሸንፏል - ይሸነፍ ተሸነፍ +ተሸኘ ተሸኘ ይሸኛል ተሸኝቷል - ይሸኝ - +ተሸከመ ተሸከመ ይሸከማል ተሸክሟል - ይሸከም ተሸከም +ተሸጠ ተሸጠ ይሸጣል ተሽጧል - ይሸጥ - +ተሸፈነ ተሸፈነ ይሸፈናል ተሸፍኗል - ይሸፈን - +ተሻለ ተሻለ ይሻላል ተሽሏል - ይሻል ተሻል +ተሻረ ተሻረ ይሻራል ተሽሯል - ይሻር ተሻር +ተሻገረ ተሻገረ ይሻገራል ተሻግሯል - ይሻገር ተሻገር +ተሾመ ተሾመ ይሾማል ተሾሟል - ይሾም ተሾም +ተቀላቀለ ተቀላቀለ ይቀላቀላል ተቀላቅሏል - ይቀላቀል ተቀላቀል +ተቀመጠ ተቀመጠ ይቀመጣል ተቀምጧል - ይቀመጥ ተቀመጥ +ተቀረ ተቀረ ይቀራል ተቀርቷል - ይቀር - +ተቀሰቀሰ ተቀሰቀሰ ይቀሰቀሳል ተቀስቅሷል - ይቀሰቀስ - +ተቀበለ ተቀበለ ይቀበላል ተቀብሏል - ይቀበል ተቀበል +ተቀበረ ተቀበረ ይቀበራል ተቀብሯል - ይቀበር ተቀበር +ተቀነሰ ተቀነሰ ይቀነሳል ተቀንሷል - ይቀነስ - +ተቀየረ ተቀየረ ይቀየራል ተቀይሯል - ይቀየር - +ተቀደሰ ተቀደሰ ይቀደሳል ተቀድሷል - ይቀደስ ተቀደስ +ተቀጠረ ተቀጠረ ይቀጠራል ተቀጥሯል - ይቀጠር - +ተቀጣ ተቀጣ ይቀጣል ተቀጥቷል - ይቀጣ ተቀጣ +ተቃወመ ተቃወመ ይቃወማል ተቃውሟል - ይቃወም ተቃወም +ተቃጠለ ተቃጠለ ይቃጠላል ተቃጥሏል - ይቃጠል ተቃጠል +ተቆመ ተቆመ ይቆማል ተቆሟል - ይቆም ተቆም +ተቆረጠ ተቆረጠ ይቆረጣል ተቆርጧል - ይቆረጥ - +ተቆጠረ ተቆጠረ ይቆጠራል ተቆጥሯል - ይቆጠር - +ተቆጠበ ተቆጠበ ይቆጠባል ተቆጥቧል - ይቆጠብ ተቆጠብ +ተቆጣ ተቆጣ ይቆጣል ተቆጥቷል - ይቆጣ - +ተቆጣጠረ ተቆጣጠረ ይቆጣጠራል ተቆጣጥሯል - ይቆጣጠር ተቆጣጠር +ተቋረጠ ተቋረጠ ይቋረጣል ተቋርጧል - ይቋረጥ - +ተቋቋመ ተቋቋመ ይቋቋማል ተቋቁሟል - ይቋቋም - +ተቋጨ ተቋጨ ይቋጫል ተቋጭቷል - ይቋጭ ተቋጭ +ተበላ ተበላ ይበላል ተበልቷል - ይበላ ተበላ +ተበላሸ ተበላሸ ይበላሻል ተበላሽቷል - ይበላሽ - +ተበሳጨ ተበሳጨ ይበሳጫል ተበሳጭቷል - ይበሳጭ ተበሳጭ +ተበተነ ተበተነ ይበተናል ተበትኗል - ይበተን ተበተን +ተበከለ ተበከለ ይበከላል ተበክሏል - ይበከል ተበከል +ተበደለ ተበደለ ይበደላል ተበድሏል - ይበደል ተበደል +ተባለ ተባለ ይባላል ተብሏል - ይባል ተባል +ተባረረ ተባረረ ይባረራል ተባሯል - ይባረር ተባረር +ተባረከ ተባረከ ይባረካል ተባርኳል - ይባረክ ተባረክ +ተባባሰ ተባባሰ ይባባሳል ተባብሷል - ይባባስ - +ተተቸ ተተቸ ይተቻል ተተችቷል - ይተች - +ተተከለ ተተከለ ይተከላል ተተክሏል - ይተከል - +ተተካ ተተካ ይተካል ተተክቷል - ይተካ - +ተተወ ተተወ ይተዋል ተትቷል - ይተው ተተው +ተቸ ተቸ ይተቻል ተችቷል - ይተች ተች +ተቸገረ ተቸገረ ይቸገራል ተቸግሯል - ይቸገር ተቸገር +ተቻለ ተቻለ ይቻላል ተችሏል - ይቻል - +ተነሳ ተነሣ ይነሣል ተነሥቷል - ይነሣ ተነሣ +ተነቀለ ተነቀለ ይነቀላል ተነቅሏል - ይነቀል - +ተነተነ ተነተነ ይተነትናል ተንትኗል - ይተነትን ተንትን +ተነካ ተነካ ይነካል ተነክቷል - ይነካ ተነካ +ተነዛ ተነዛ ይነዛል ተነዝቷል - ይነዛ ተነዛ +ተነገረ ተነገረ ይነገራል ተነግሯል - ይነገር - +ተነጠቀ ተነጠቀ ይነጠቃል ተነጥቋል - ይነጠቅ ተነጠቅ +ተነፈሰ ተነፈሰ ይተነፍሳል ተንፍሷል - ይተነፍስ ተንፍስ +ተነፋ ተነፋ ይነፋል ተነፍቷል - ይነፋ ተነፋ +ተናገረ ተናገረ ይናገራል ተናግሯል - ይናገር ተናገር +ተንቀሳቀሰ ተንቀሳቀሰ ይንቀሳቀሳል ተንቀሳቅሷል - ይንቀሳቀስ ተንቀሳቀስ +ተንገላታ ተንገላታ ይንገላታል ተንገላትቷል - ይንገላታ ተንገላታ +ተንጸባረቀ ተንጸባረቀ ይንጸባረቃል ተንጸባርቋል - ይንጸባረቅ - +ተኛ ተኛ ይተኛል ተኝቷል - ይተኛ ተኛ +ተከለ ተከለ ይተክላል ተክሏል - ይተክል ትከል +ተከለከለ ተከለከለ ይከለከላል ተከልክሏል - ይከለከል ተከልከል +ተከላከለ ተከላከለ ይከላከላል ተከላክሏል - ይከላከል ተከላከል +ተከማቸ ተከማቸ ይከማቻል ተከማችቷል - ይከማች - +ተከራከረ ተከራከረ ይከራከራል ተከራክሯል - ይከራከር ተከራከር +ተከራየ ተከራየ ይከራያል ተከራይቷል - ይከራይ ተከራይ +ተከሰሰ ተከሰሰ ይከሰሳል ተከሷል - ይከሰስ ተከሰስ +ተከሰተ ተከሰተ ይከሰታል ተከስቷል - ይከሰት - +ተከበረ ተከበረ ይከበራል ተከብሯል - ይከበር ተከበር +ተከተለ ተከተለ ይከተላል ተከትሏል - ይከተል ተከተል +ተከናወነ ተከናወነ ይከናወናል ተከናውኗል - ይከናወን ተከናወን +ተከፈለ ተከፈለ ይከፈላል ተከፍሏል - ይከፈል - +ተከፈተ ተከፈተ ይከፈታል ተከፍቷል - ይከፈት - +ተካ ተካ ይተካል ተክቷል - ይተካ - +ተካተተ ተካተተ ይካተታል ተካቷል - ይካተት - +ተካፈለ ተካፈለ ይካፈላል ተካፍሏል - ይካፈል ተካፈል +ተኮሰ ተኮሰ ይተኩሳል ተኩሷል - ይተኩስ ተኩስ +ተወ ተወ ይተዋል ትቷል - ይተው ተው +ተወለደ ተወለደ ይወለዳል ተወልዷል - ይወለድ ተወለድ +ተወረሰ ተወረሰ ይወረሳል ተወርሷል - ይወረስ - +ተወራ ተወራ ይወራል ተወርቷል - ይወራ - +ተወሰነ ተወሰነ ይወሰናል ተወስኗል - ይወሰን - +ተወሰደ ተወሰደ ይወሰዳል ተወስዷል - ይወሰድ ተወሰድ +ተወሳ ተወሳ ይወሳል ተወስቷል - ይወሳ - +ተወቀሰ ተወቀሰ ይወቀሳል ተወቅሷል - ይወቀስ ተወቀስ +ተወነጀለ ተወነጀለ ይወነጀላል ተወንጅሏል - ይወነጀል ተወንጀል +ተወገደ ተወገደ ይወገዳል ተወግዷል - ይወገድ - +ተወጋ ተወጋ ይወጋል ተወግቷል - ይወጋ ተወጋ +ተወጣ ተወጣ ይወጣል ተወጥቷል - ይወጣ ተወጣ +ተዋረደ ተዋረደ ይዋረዳል ተዋርዷል - ይዋረድ ተዋረድ +ተዋቀረ ተዋቀረ ይዋቀራል ተዋቅሯል - ይዋቀር - +ተዋጋ ተዋጋ ይዋጋል ተዋግቷል - ይዋጋ ተዋጋ +ተዘረዘረ ተዘረዘረ ይዘረዘራል ተዘርዝሯል - ይዘረዘር - +ተዘረጋ ተዘረጋ ይዘረጋል ተዘርግቷል - ይዘረጋ ተዘርጋ +ተዘራ ተዘራ ይዘራል ተዘርቷል - ይዘራ - +ተዘዋወረ ተዘዋወረ ይዘዋወራል ተዘዋውሯል - ይዘዋወር - +ተዘገበ ተዘገበ ይዘገባል ተዘግቧል - ይዘገብ - +ተዘጋ ተዘጋ ይዘጋል ተዘግቷል - ይዘጋ - +ተዘጋጀ ተዘጋጀ ይዘጋጃል ተዘጋጅቷል - ይዘጋጅ ተዘጋጅ +ተዛመተ ተዛመተ ይዛመታል ተዛምቷል - ይዛመት - +ተዛባ ተዛባ ይዛባል ተዛብቷል - ይዛባ - +ተዛወረ ተዛወረ ይዛወራል ተዛውሯል - ይዛወር - +ተያዘ ተያዘ ይያዛል ተይዟል - ይያዝ ተያዝ +ተያያዘ ተያያዘ ይያያዛል ተያይዟል - ይያያዝ - +ተደመደመ ተደመደመ ይደመደማል ተደምድሟል - ይደመደም - +ተደረሰ ተደረሰ ይደረሳል ተደርሷል - ይደረስ - +ተደረገ ተደረገ ይደረጋል ተደርጓል - ይደረግ ተደረግ +ተደራደረ ተደራደረ ይደራደራል ተደራድሯል - ይደራደር ተደራደር +ተደራጀ ተደራጀ ይደራጃል ተደራጅቷል - ይደራጅ - +ተደሰተ ተደሰተ ይደሰታል ተደስቷል - ይደሰት ተደሰት +ተደቀነ ተደቀነ ይደቀናል ተደቅኗል - ይደቀን ተደቀን +ተደበቀ ተደበቀ ይደበቃል ተደብቋል - ይደበቅ - +ተደበደበ ተደበደበ ይደበደባል ተደብድቧል - ይደበደብ ተደብደብ +ተደነቀ ተደነቀ ይደነቃል ተደንቋል - ይደነቅ - +ተደገመ ተደገመ ይደገማል ተደግሟል - ይደገም - +ተደገፈ ተደገፈ ይደገፋል ተደግፏል - ይደገፍ - +ተደፈረ ተደፈረ ይደፈራል ተደፍሯል - ይደፈር ተደፈር +ተዳረገ ተዳረገ ይዳረጋል ተዳርጓል - ይዳረግ ተዳረግ +ተዳደረ ተዳደረ ይተዳደራል ተዳድሯል - ይተዳደር - +ተጀመረ ተጀመረ ይጀመራል ተጀምሯል - ይጀመር - +ተገለለ ተገለለ ይገለላል ተገሏል - ይገለል - +ተገለጸ ተገለፀ ይገለፃል ተገልጿል - ይገለፅ - +ተገመተ ተገመተ ይገመታል ተገምቷል - ይገመት - +ተገመገመ ተገመገመ ይገመገማል ተገምግሟል - ይገመገም - +ተገረፈ ተገረፈ ይገረፋል ተገርፏል - ይገረፍ ተገረፍ +ተገባ ተገባ ይገባል ተገብቷል - ይገባ - +ተገታ ተገታ ይገታል ተገትቷል - ይገታ - +ተገነባ ተገነባ ይገነባል ተገንብቷል - ይገነባ ተገንባ +ተገነዘበ ተገነዘበ ይገነዘባል ተገንዝቧል - ይገነዘብ ተገንዘብ +ተገኘ ተገኘ ይገኛል ተገኝቷል - ይገኝ ተገኝ +ተገዛ ተገዛ ይገዛል ተገዝቷል - ይገዛ ተገዛ +ተገደለ ተገደለ ይገደላል ተገድሏል - ይገደል - +ተገደደ ተገደደ ይገደዳል ተገዷል - ይገደድ ተገደድ +ተገፋ ተገፋ ይገፋል ተገፍቷል - ይገፋ ተገፋ +ተጋበዘ ተጋበዘ ይጋበዛል ተጋብዟል - ይጋበዝ ተጋበዝ +ተጋጠመ ተጋጠመ ይጋጠማል ተጋጥሟል - ይጋጠም - +ተጋጨ ተጋጨ ይጋጫል ተጋጭቷል - ይጋጭ - +ተጎዳ ተጎዳ ይጎዳል ተጎድቷል - ይጎዳ ተጎዳ +ተጓዘ ተጓዘ ይጓዛል ተጉዟል - ይጓዝ ተጓዝ +ተጓጓዘ ተጓጓዘ ይጓጓዛል ተጓጉዟል - ይጓጓዝ ተጓጓዝ +ተጠመቀ ተጠመቀ ይጠመቃል ተጠምቋል - ይጠመቅ - +ተጠረጠረ ተጠረጠረ ይጠረጠራል ተጠርጥሯል - ይጠረጠር ተጠርጠር +ተጠራ ተጠራ ይጠራል ተጠርቷል - ይጠራ ተጠራ +ተጠራጠረ ተጠራጠረ ይጠራጠራል ተጠራጥሯል - ይጠራጠር ተጠራጠር +ተጠቀመ ተጠቀመ ይጠቀማል ተጠቅሟል - ይጠቀም ተጠቀም +ተጠቀሰ ተጠቀሰ ይጠቀሳል ተጠቅሷል - ይጠቀስ - +ተጠቃ ተጠቃ ይጠቃል ተጠቅቷል - ይጠቃ ተጠቃ +ተጠቃለለ ተጠቃለለ ይጠቃለላል ተጠቃልሏል - ይጠቃለል - +ተጠበቀ ተጠበቀ ይጠበቃል ተጠብቋል - ይጠበቅ - +ተጠነቀቀ ተጠነቀቀ ይጠነቀቃል ተጠንቅቋል - ይጠነቀቅ - +ተጠናቀቀ ተጠናቀቀ ይጠናቀቃል ተጠናቅቋል - ይጠናቀቅ - +ተጠናከረ ተጠናከረ ይጠናከራል ተጠናክሯል - ይጠናከር - +ተጠየቀ ተጠየቀ ይጠየቃል ተጠይቋል - ይጠየቅ ተጠየቅ +ተጠጋ ተጠጋ ይጠጋል ተጠግቷል - ይጠጋ ተጠጋ +ተጣለ ተጣለ ይጣላል ተጥሏል - ይጣል ተጣል +ተጣላ ተጣላ ይጣላል ተጣልቷል - ይጣላ ተጣላ +ተጣራ ተጣራ ይጣራል ተጣርቷል - ይጣራ - +ተጨመረ ተጨመረ ይጨመራል ተጨምሯል - ይጨመር - +ተጨነቀ ተጨነቀ ይጨነቃል ተጨንቋል - ይጨነቅ ተጨነቅ +ተጫነ ተጫነ ይጫናል ተጭኗል - ይጫን ተጫን +ተጫወተ ተጫወተ ይጫወታል ተጫውቷል - ይጫወት ተጫወት +ተጻፈ ተጻፈ ይጻፋል ተጽፏል - ይጻፍ - +ተፈለገ ተፈለገ ይፈለጋል ተፈልጓል - ይፈለግ ተፈለግ +ተፈረመ ተፈረመ ይፈረማል ተፈርሟል - ይፈረም - +ተፈረደ ተፈረደ ይፈረዳል ተፈርዷል - ይፈረድ - +ተፈራ ተፈራ ይፈራል ተፈርቷል - ይፈራ ተፈራ +ተፈቀደ ተፈቀደ ይፈቀዳል ተፈቅዷል - ይፈቀድ - +ተፈታ ተፈታ ይፈታል ተፈትቷል - ይፈታ ተፈታ +ተፈናቀለ ተፈናቀለ ይፈናቀላል ተፈናቅሏል - ይፈናቀል - +ተፈጀ ተፈጀ ይፈጃል ተፈጅቷል - ይፈጅ - +ተፈጠረ ተፈጠረ ይፈጠራል ተፈጥሯል - ይፈጠር - +ተፈጸመ ተፈፀመ ይፈፀማል ተፈፅሟል - ይፈፀም - +ታመመ ታመመ ይታመማል ታሟል - ይታመም ታመም +ታመነ ታመነ ይታመናል ታምኗል - ይታመን ታመን +ታረቀ ታረቀ ይታረቃል ታርቋል - ይታረቅ ታረቅ +ታሰረ ታሰረ ይታሰራል ታስሯል - ይታሰር ታሰር +ታሰበ ታሰበ ይታሰባል ታስቧል - ይታሰብ - +ታወቀ ታወቀ ይታወቃል ታውቋል - ይታወቅ ታወቅ +ታወከ ታወከ ይታወካል ታውኳል - ይታወክ ታወክ +ታዘዘ ታዘዘ ይታዘዛል ታዟል - ይታዘዝ ታዘዝ +ታየ ታየ ይታያል ታይቷል - ይታይ ታይ +ታደለ ታደለ ይታደላል ታድሏል - ይታደል ታደል +ታደሰ ታደሰ ይታደሳል ታድሷል - ይታደስ - +ታገደ ታገደ ይታገዳል ታግዷል - ይታገድ ታገድ +ታጠቀ ታጠቀ ይታጠቃል ታጥቋል - ይታጠቅ ታጠቅ +ታጠበ ታጠበ ይታጠባል ታጥቧል - ይታጠብ ታጠብ +ቻለ ቻለ ይችላል ችሏል - ይችል ቻል +ነሳ ነሣ ይነሣል ነሥቷል - ይነሣ ንሣ +ነቀፈ ነቀፈ ይነቅፋል ነቅፏል - ይነቅፍ ንቀፍ +ነቃ ነቃ ይነቃል ነቅቷል - ይነቃ ንቃ +ነበረ ነበረ - - - - - +ነካ ነካ ይነካል ነክቷል - ይነካ ንካ +ነደደ ነደደ ይነዳል ነዷል - ይነድ - +ነደፈ ነደፈ ይነድፋል ነድፏል - ይነድፍ ንደፍ +ነገረ ነገረ ይነግራል ነግሯል - ይነግር ንገር +ነገሰ ነገሠ ይነግሣል ነግሷል - ይነግሥ - +ነገደ ነገደ ይነግዳል ነግዷል - ይነግድ ንገድ +ነጋ ነጋ ይነጋል ነግቷል - ይነጋ - +ነፋ ነፋ ይነፋል ነፍቷል - ይነፋ ንፋ +ናቀ ናቀ ይንቃል ንቋል - ይንቅ ናቅ +ናፈቀ ናፈቀ ይናፍቃል ናፍቋል - ይናፍቅ ናፍቅ +ኖረ ኖረ ይኖራል ኖሯል - ይኖር ኑር +አለ አለ ይላል ብሏል አለ ይል በል +አለቀ አለቀ ያልቃል አልቋል - ያልቅ እለቅ +አለቀሰ አለቀሰ ያለቅሳል አልቅሷል - ያለቅስ አልቅስ +አለፈ አለፈ ያልፋል አልፏል - ያልፍ እለፍ +አላቀ አላቀ ያልቃል አልቋል - ያልቅ - +አላፈ አላፈ ያልፋል አልፏል - ያልፍ አልፍ +አመለከተ አመለከተ ያመለክታል አመልክቷል - ያመለክት አመልክት +አመለጠ አመለጠ ያመልጣል አምልጧል - ያመልጥ አምልጥ +አመመ አመመ ያማል አሟል - ያም እመም +አመረተ አመረተ ያመርታል አምርቷል - ያመርት አምርት +አመራ አመራ ያመራል አምርቷል - ያመራ አምራ +አመሰገነ አመሰገነ ያመሰግናል አመስግኗል - ያመሰግን አመስግን +አመሸ አመሸ ያመሻል አምሽቷል - ያመሽ አምሽ +አመቻቸ አመቻቸ ያመቻቻል አመቻችቷል - ያመቻች አመቻች +አመነ አመነ ያምናል አምኗል - ያምን እመን +አመነዘረ አመነዘረ ያመነዝራል አመንዝሯል - ያመነዝር አመንዝር +አመጣ አመጣ ያመጣል አምጥቷል - ያመጣ አምጣ +አማረ አማረ ያምራል አምሯል - ያምር - +አማረረ አማረረ ያማርራል አማርሯል - ያማርር አማርር +አሟላ አሟላ ያሟላል አሟልቷል - ያሟላ አሟላ +አረቀ አረቀ ያርቃል አርቋል - ያርቅ አርቅ +አረከሰ አረከሰ ያረክሳል አርክሷል - ያረክስ አርክስ +አረካ አረካ ያረካል አርክቷል - ያረካ አርካ +አረደ አረደ ያርዳል አርዷል - ያርድ እረድ +አረጋ አረጋ ያረጋል አርግቷል - ያረጋ - +አረጋገጠ አረጋገጠ ያረጋግጣል አረጋግጧል - ያረጋግጥ አረጋግጥ +አረፈ አረፈ ያርፋል አርፏል - ያርፍ እረፍ +አራመደ አራመደ ያራምዳል አራምዷል - ያራምድ አራምድ +አራቀ አራቀ ያርቃል አርቋል - ያርቅ አርቅ +አሰለፈ አሰለፈ ያሰልፋል አሰልፏል - ያሰልፍ አሰልፍ +አሰማ አሰማ ያሰማል አሰምቷል - ያሰማ አሰማ +አሰረ አሰረ ያስራል አስሯል - ያስር እሰር +አሰራጨ አሰራጨ ያሰራጫል አሰራጭቷል - ያሰራጭ አሰራጭ +አሰቃየ አሰቃየ ያሰቃያል አሰቃይቷል - ያሰቃይ - +አሰበ አሰበ ያስባል አስቧል - ያስብ አስብ +አሰባሰበ አሰባሰበ ያሰባስባል አሰባስቧል - ያሰባስብ አሰባስብ +አሰኘ አሰኘ ያሰኛል አሰኝቷል - ያሰኝ - +አሰጋ አሰጋ ያሰጋል አሰግቷል - ያሰጋ - +አሳለፈ አሳለፈ ያሳልፋል አሳልፏል - ያሳልፍ አሳልፍ +አሳረፈ አሳረፈ ያሳርፋል አሳርፏል - ያሳርፍ - +አሳሰበ አሳሰበ ያሳስባል አሳስቧል - ያሳስብ አሳስብ +አሳሳበ አሳሳበ ያሳስባል አሳስቧል - ያሳስብ አሳስብ +አሳበ አሳበ ያስባል አስቧል - ያስብ አስብ +አሳተ አሳተ ያስታል አስቷል - ያስት - +አሳወቀ አሳወቀ ያሳውቃል አሳውቋል - ያሳውቅ አሳውቅ +አሳዘነ አሳዘነ ያሳዝናል አሳዝኗል - ያሳዝን አሳዝን +አሳየ አሳየ ያሳያል አሳይቷል - ያሳይ አሳይ +አሳደረ አሳደረ ያሳድራል አሳድሯል - ያሳድር - +አሳደገ አሳደገ ያሳድጋል አሳድጓል - ያሳድግ - +አሳጣ አሳጣ ያሳጣል አሳጥቷል - ያሳጣ - +አስመሰለ አስመሰለ ያስመስላል አስመስሏል - ያስመስል - +አስመዘነ አስመዘነ ያስመዝናል አስመዝኗል - ያስመዝን አስመዝን +አስመዘገበ አስመዘገበ ያስመዘግባል አስመዝግቧል - ያስመዘግብ አስመዝግብ +አስመጣ አስመጣ ያስመጣል አስመጥቷል - ያስመጣ አስመጣ +አስረከበ አስረከበ ያስረክባል አስረክቧል - ያስረክብ አስረክብ +አስረዳ አስረዳ ያስረዳል አስረድቷል - ያስረዳ አስረዳ +አስቀመጠ አስቀመጠ ያስቀምጣል አስቀምጧል - ያስቀምጥ አስቀምጥ +አስቀረ አስቀረ ያስቀራል አስቀርቷል - ያስቀር - +አስቀበለ አስቀበለ ያስቀብላል አስቀብሏል - ያስቀብል አስቀብል +አስቀደመ አስቀደመ ያስቀድማል አስቀድሟል - ያስቀድም - +አስቆጠረ አስቆጠረ ያስቆጥራል አስቆጥሯል - ያስቆጥር አስቆጥር +አስቆጣ አስቆጣ ያስቆጣል አስቆጥቷል - ያስቆጣ - +አስተላለፈ አስተላለፈ ያስተላልፋል አስተላልፏል - ያስተላልፍ አስተላልፍ +አስተባበለ አስተባበለ ያስተባብላል አስተባብሏል - ያስተባብል አስተባብል +አስተካከለ አስተካከለ ያስተካክላል አስተካክሏል - ያስተካክል አስተካክል +አስተዋወቀ አስተዋወቀ ያስተዋውቃል አስተዋውቋል - ያስተዋውቅ አስተዋውቅ +አስተዳደረ አስተዳደረ ያስተዳድራል አስተዳድሯል - ያስተዳድር - +አስታወሰ አስታወሰ ያስታውሳል አስታውሷል - ያስታውስ አስታውስ +አስታወቀ አስታወቀ ያስታውቃል አስታውቋል - ያስታውቅ አስታውቅ +አስቸገረ አስቸገረ ያስቸግራል አስቸግሯል - ያስቸግር - +አስቻለ አስቻለ ያስችላል አስችሏል - ያስችል - +አስከተለ አስከተለ ያስከትላል አስከትሏል - ያስከትል - +አስወገደ አስወገደ ያስወግዳል አስወግዷል - ያስወግድ አስወግድ +አስወጣ አስወጣ ያስወጣል አስወጥቷል - ያስወጣ አስወጣ +አስያዘ አስያዘ ያስይዛል አስይዟል - ያስይዝ አስይዝ +አስደሰተ አስደሰተ ያስደስታል አስደስቷል - ያስደስት - +አስደነቀ አስደነቀ ያስደንቃል አስደንቋል - ያስደንቅ - +አስገረመ አስገረመ ያስገርማል አስገርሟል - ያስገርም - +አስገባ አስገባ ያስገባል አስገብቷል - ያስገባ አስገባ +አስገነዘበ አስገነዘበ ያስገነዝባል አስገንዝቧል - ያስገነዝብ አስገንዝብ +አስገኘ አስገኘ ያስገኛል አስገኝቷል - ያስገኝ አስገኝ +አስገደደ አስገደደ ያስገድዳል አስገድዷል - ያስገድድ አስገድድ +አስጠራ አስጠራ ያስጠራል አስጠርቷል - ያስጠራ አስጠራ +አስጠነቀቀ አስጠነቀቀ ያስጠነቅቃል አስጠንቅቋል - ያስጠነቅቅ አስጠንቅቅ +አስጠጣ አስጠጣ ያስጠጣል አስጠጥቷል - ያስጠጣ አስጠጣ +አስጨለመ አስጨለመ ያስጨልማል አስጨልሟል - ያስጨልም - +አስጨነቀ አስጨነቀ ያስጨንቃል አስጨንቋል - ያስጨንቅ - +አስፈለገ አስፈለገ ያስፈልጋል አስፈልጓል - ያስፈልግ - +አስፈራ አስፈራ ያስፈራል አስፈርቷል - ያስፈራ - +አሸ አሸ ያሻል አሽቷል - ያሽ እሽ +አሸነፈ አሸነፈ ያሸንፋል አሸንፏል - ያሸንፍ አሸንፍ +አሻለ አሻለ ያሽላል አሽሏል - ያሽል አሽል +አሻሻለ አሻሻለ ያሻሽላል አሻሽሏል - ያሻሽል አሻሽል +አሻገረ አሻገረ ያሻግራል አሻግሯል - ያሻግር - +አቀረበ አቀረበ ያቀርባል አቅርቧል - ያቀርብ አቅርብ +አቀና አቀና ያቀናል አቅንቷል - ያቀና አቅና +አቀደ አቀደ ያቅዳል አቅዷል - ያቅድ አቅድ +አቀጠለ አቀጠለ ያቀጥላል አቀጥሏል - ያቀጥል አቀጥል +አቃተ አቃተ ያቅታል አቅቷል - ያቅት - +አቃጠለ አቃጠለ ያቃጥላል አቃጥሏል - ያቃጥል አቃጥል +አቆመ አቆመ ያቆማል አቆሟል - ያቆም አቁም +አቋረጠ አቋረጠ ያቋርጣል አቋርጧል - ያቋርጥ አቋርጥ +አቋቋመ አቋቋመ ያቋቁማል አቋቁሟል - ያቋቁም አቋቁም +አበላሸ አበላሸ ያበላሻል አበላሽቷል - ያበላሽ አበላሽ +አበረ አበረ ያብራል አብሯል - ያብር እበር +አበረከተ አበረከተ ያበረክታል አበርክቷል - ያበረክት - +አበሰ አበሰ ያብሳል አብሷል - ያብስ እበስ +አበሰረ አበሰረ ያበስራል አብስሯል - ያበስር አብስር +አበሳጨ አበሳጨ ያበሳጫል አበሳጭቷል - ያበሳጭ አበሳጭ +አበቃ አበቃ ያበቃል አብቅቷል - ያበቃ አብቃ +አበዛ አበዛ ያበዛል አብዝቷል - ያበዛ አብዛ +አባረረ አባረረ ያባርራል አባርሯል - ያባርር አባርር +አባባሰ አባባሰ ያባብሳል አባብሷል - ያባብስ - +አብራራ አብራራ ያብራራል አብራርቷል - ያብራራ አብራራ +አተመ አተመ ያትማል አትሟል - ያትም አትም +አተረፈ አተረፈ ያተርፋል አትርፏል - ያተርፍ አትርፍ +አታለለ አታለለ ያታልላል አታልሏል - ያታልል አታልል +አነሰ አነሰ ያንሳል አንሷል - ያንስ - +አነሳ አነሣ ያነሳል አንሥቷል - ያነሳ አንሣ +አነጋገረ አነጋገረ ያነጋግራል አነጋግሯል - ያነጋግር አነጋግር +አናደደ አናደደ ያናድዳል አናድዷል - ያናድድ - +አኖረ አኖረ ያኖራል አኖሯል - ያኖር አኑር +አከለ አከለ ያክላል አክሏል - ያክል - +አከማቸ አከማቸ ያከማቻል አከማችቷል - ያከማች አከማች +አከበረ አከበረ ያከብራል አክብሯል - ያከብር አክብር +አከናወነ አከናወነ ያከናውናል አከናውኗል - ያከናውን አከናውን +አካተተ አካተተ ያካትታል አካትቷል - ያካትት አካትት +አወረደ አወረደ ያወርዳል አውርዷል - ያወርድ አውርድ +አወራ አወራ ያወራል አውርቷል - ያወራ አውራ +አወሳ አወሳ ያወሳል አውስቷል - ያወሳ አውሳ +አወቀ አወቀ ያውቃል አውቋል - ያውቅ እወቅ +አወከ አወከ ያውካል አውኳል - ያውክ አውክ +አወደመ አወደመ ያወድማል አውድሟል - ያወድም አውድም +አወገዘ አወገዘ ያወግዛል አውግዟል - ያወግዝ አውግዝ +አወጣ አወጣ ያወጣል አውጥቷል - ያወጣ አውጣ +አዋለ አዋለ ያውላል አውሏል - ያውል አውል +አዋረደ አዋረደ ያዋርዳል አዋርዷል - ያዋርድ አዋርድ +አዋጣ አዋጣ ያዋጣል አዋጥቷል - ያዋጣ አዋጣ +አዘነ አዘነ ያዝናል አዝኗል - ያዝን እዘን +አዘዘ አዘዘ ያዛል አዟል - ያዝ እዘዝ +አዘጋጀ አዘጋጀ ያዘጋጃል አዘጋጅቷል - ያዘጋጅ አዘጋጅ +አዞረ አዞረ ያዞራል አዞሯል - ያዞር አዙር +አየ አየ ያያል አይቷል - ያይ እይ +አያያዘ አያያዘ ያያይዛል አያይዟል - ያያይዝ አያይዝ +አደረ አደረ ያድራል አድሯል - ያድር እደር +አደረሰ አደረሰ ያደርሳል አድርሷል - ያደርስ አድርስ +አደረገ አደረገ ያደርጋል አድርጓል - ያደርግ አድርግ +አደራጀ አደራጀ ያደራጃል አደራጅቷል - ያደራጅ አደራጅ +አደነ አደነ ያድናል አድኗል - ያድን አድን +አደነቀ አደነቀ ያደንቃል አድንቋል - ያደንቅ አድንቅ +አደከመ አደከመ ያደክማል አድክሟል - ያደክም - +አደገ አደገ ያድጋል አድጓል - ያድግ እደግ +አዳመጠ አዳመጠ ያዳምጣል አዳምጧል - ያዳምጥ አዳምጥ +አዳረ አዳረ ያድራል አድሯል - ያድር አድር +አዳነ አዳነ ያድናል አድኗል - ያድን አድን +አዳከመ አዳከመ ያዳክማል አዳክሟል - ያዳክም አዳክም +አገለገለ አገለገለ ያገለግላል አገልግሏል - ያገለግል አገልግል +አገረሸ አገረሸ ያገረሻል አገርሽቷል - ያገረሽ - +አገባ አገባ ያገባል አግብቷል - ያገባ አግባ +አገኘ አገኘ ያገኛል አግኝቷል - ያገኝ አግኝ +አገዘ አገዘ ያግዛል አግዟል - ያግዝ አግዝ +አገደ አገደ ያግዳል አግዷል - ያግድ አግድ +አጋባ አጋባ ያጋባል አጋብቷል - ያጋባ አጋባ +አጋዘ አጋዘ ያግዛል አግዟል - ያግዝ አግዝ +አጋጠመ አጋጠመ ያጋጥማል አጋጥሟል - ያጋጥም - +አጎላ አጎላ ያጎላል አጉልቷል - ያጎላ - +አጠራጠረ አጠራጠረ ያጠራጥራል አጠራጥሯል - ያጠራጥር - +አጠቃ አጠቃ ያጠቃል አጥቅቷል - ያጠቃ አጥቃ +አጠቃለለ አጠቃለለ ያጠቃልላል አጠቃልሏል - ያጠቃልል አጠቃልል +አጠበ አጠበ ያጥባል አጥቧል - ያጥብ እጠብ +አጠና አጠና ያጠናል አጥንቷል - ያጠና አጥና +አጠናቀቀ አጠናቀቀ ያጠናቅቃል አጠናቅቋል - ያጠናቅቅ አጠናቅቅ +አጠናከረ አጠናከረ ያጠናክራል አጠናክሯል - ያጠናክር አጠናክር +አጠፋ አጠፋ ያጠፋል አጥፍቷል - ያጠፋ አጥፋ +አጣ አጣ ያጣል አጥቷል - ያጣ እጣ +አጣጣለ አጣጣለ ያጣጥላል አጣጥሏል - ያጣጥል አጣጥል +አጸደቀ አፀደቀ ያጸድቃል አፅድቋል - ያጸድቅ አፅድቅ +አፈረ አፈረ ያፍራል አፍሯል - ያፍር እፈር +አፈረሰ አፈረሰ ያፈርሳል አፍርሷል - ያፈርስ አፍርስ +አፈራ አፈራ ያፈራል አፍርቷል - ያፈራ አፍራ +አፈሰሰ አፈሰሰ ያፈሳል አፍስሷል - ያፈስ አፍስስ +አፈነ አፈነ ያፍናል አፍኗል - ያፍን አፍን +አፋረ አፋረ ያፍራል አፍሯል - ያፍር አፍር +ከለከለ ከለከለ ይከለክላል ከልክሏል - ይከለክል ከልክል +ከረከረ ከረከረ ይከረክራል ከርክሯል - ይከረክር ከርክር +ከሰሰ ከሰሰ ይከሳል ከሷል - ይከስ ክሰስ +ከበረ ከበረ ይከብራል ከብሯል - ይከብር ክበር +ከበደ ከበደ ይከብዳል ከብዷል - ይከብድ - +ከተተ ከተተ ይከታል ከቷል - ይከት ክተት +ከፈለ ከፈለ ይከፍላል ከፍሏል - ይከፍል ክፈል +ከፈተ ከፈተ ይከፍታል ከፍቷል - ይከፍት ክፈት +ካሰ ካሰ ይክሳል ክሷል - ይክስ ካስ +ካደ ካደ ይክዳል ክዷል - ይክድ ካድ +ኮራ ኮራ ይኮራል ኮርቷል - ይኮራ ኩራ +ኮነነ ኮነነ ይኮንናል ኮንኗል - ይኮንን ኮንን +ወለደ ወለደ ይወልዳል ወልዷል - ይወልድ ውለድ +ወረረ ወረረ ይወራል ወሯል - ይወር ውረር +ወረሰ ወረሰ ይወርሳል ወርሷል - ይወርስ ውረስ +ወረወረ ወረወረ ይወረውራል ወርውሯል - ይወረውር ወርውር +ወረደ ወረደ ይወርዳል ወርዷል - ይወርድ ውረድ +ወሰነ ወሰነ ይወስናል ወስኗል - ይወስን ወስን +ወሰደ ወሰደ ይወስዳል ወስዷል - ይወስድ ውሰድ +ወቀሰ ወቀሰ ይወቅሳል ወቅሷል - ይወቅስ ውቀስ +ወነጀለ ወነጀለ ይወነጅላል ወንጅሏል - ይወነጅል ወንጅል +ወከለ ወከለ ይወክላል ወክሏል - ይወክል ወክል +ወደመ ወደመ ይወድማል ወድሟል - ይወድም ውደም +ወደቀ ወደቀ ይወድቃል ወድቋል - ይወድቅ ውደቅ +ወደደ ወደደ ይወዳል ወዷል - ይወድ ውደድ +ወጣ ወጣ ይወጣል ወጥቷል - ይወጣ ውጣ +ዋለ ዋለ ይውላል ውሏል - ይውል ዋል +ዋጠ ዋጠ ይውጣል ውጧል - ይውጥ ዋጥ +ዘለቀ ዘለቀ ይዘልቃል ዘልቋል - ይዘልቅ - +ዘመረ ዘመረ ይዘምራል ዘምሯል - ይዘምር ዘምር +ዘመተ ዘመተ ይዘምታል ዘምቷል - ይዘምት ዝመት +ዘረዘረ ዘረዘረ ይዘረዝራል ዘርዝሯል - ይዘረዝር ዘርዝር +ዘረጋ ዘረጋ ይዘረጋል ዘርግቷል - ይዘረጋ ዘርጋ +ዘራ ዘራ ይዘራል ዘርቷል - ይዘራ ዝራ +ዘነጋ ዘነጋ ይዘነጋል ዘንግቷል - ይዘነጋ ዘንጋ +ዘገበ ዘገበ ይዘግባል ዘግቧል - ይዘግብ ዝገብ +ዘገየ ዘገየ ይዘገያል ዘግይቷል - ይዘገይ ዘግይ +ዘጋ ዘጋ ይዘጋል ዘግቷል - ይዘጋ ዝጋ +ዛለ ዛለ ይዝላል ዝሏል - ይዝል ዛል +ዞረ ዞረ ይዞራል ዞሯል - ይዞር ዙር +ያዘ ያዘ ይይዛል ይዟል - ይይዝ ያዝ +ደመሰሰ ደመሰሰ ይደመስሳል ደምስሷል - ይደመስስ ደምስስ +ደመደመ ደመደመ ይደመድማል ደምድሟል - ይደመድም ደምድም +ደማ ደማ ይደማል ደምቷል - ይደማ ድማ +ደረሰ ደረሰ ይደርሳል ደርሷል - ይደርስ ድረስ +ደረቀ ደረቀ ይደርቃል ደርቋል - ይደርቅ - +ደረጀ ደረጀ ይደረጃል ደርጅቷል - ይደረጅ ደርጅ +ደነቀ ደነቀ ይደንቃል ደንቋል - ይደንቅ - +ደነገገ ደነገገ ይደነግጋል ደንግጓል - ይደነግግ ደንግግ +ደነገጠ ደነገጠ ይደነግጣል ደንግጧል - ይደነግጥ ደንግጥ +ደከመ ደከመ ይደክማል ደክሟል - ይደክም - +ደወለ ደወለ ይደውላል ደውሏል - ይደውል ደውል +ደገፈ ደገፈ ይደግፋል ደግፏል - ይደግፍ ደግፍ +ደፈረ ደፈረ ይደፍራል ደፍሯል - ይደፍር ድፈር +ዳረገ ዳረገ ይዳርጋል ዳርጓል - ይዳርግ - +ዳነ ዳነ ይድናል ድኗል - ይድን ዳን +ዶለ ዶለ ይዶላል ዶሏል - ይዶል ዱል +ጀመረ ጀመረ ይጀምራል ጀምሯል - ይጀምር ጀምር +ገለበጠ ገለበጠ ይገለብጣል ገልብጧል - ይገለብጥ - +ገለጸ ገለፀ ይገልፃል ገልጿል - ይገልፅ ግለፅ +ገመተ ገመተ ይገምታል ገምቷል - ይገምት ገምት +ገመገመ ገመገመ ይገመግማል ገምግሟል - ይገመግም ገምግም +ገረመ ገረመ ይገርማል ገርሟል - ይገርም - +ገረፈ ገረፈ ይገርፋል ገርፏል - ይገርፍ ግረፍ +ገባ ገባ ይገባል ገብቷል - ይገባ ግባ +ገነባ ገነባ ይገነባል ገንብቷል - ይገነባ ገንባ +ገዛ ገዛ ይገዛል ገዝቷል - ይገዛ ግዛ +ገደለ ገደለ ይገድላል ገድሏል - ይገድል ግደል +ገጠመ ገጠመ ይገጥማል ገጥሟል - ይገጥም ግጠም +ገፋ ገፋ ይገፋል ገፍቷል - ይገፋ ግፋ +ጋበዘ ጋበዘ ይጋብዛል ጋብዟል - ይጋብዝ ጋብዝ +ጎበኘ ጎበኘ ይጎበኛል ጎብኝቷል - ይጎበኝ ጎብኝ +ጎዳ ጎዳ ይጎዳል ጎድቷል - ይጎዳ ጉዳ +ጠላ ጠላ ይጠላል ጠልቷል - ይጠላ ጥላ +ጠማ ጠማ ይጠማል ጠምቷል - ይጠማ - +ጠራ ጠራ ይጠራል ጠርቷል - ይጠራ ጥራ +ጠቀመ ጠቀመ ይጠቅማል ጠቅሟል - ይጠቅም - +ጠቀሰ ጠቀሰ ይጠቅሳል ጠቅሷል - ይጠቅስ ጥቀስ +ጠቆመ ጠቆመ ይጠቁማል ጠቁሟል - ይጠቁም ጠቁም +ጠበቀ ጠበቀ ይጠብቃል ጠብቋል - ይጠብቅ ጠብቅ +ጠየቀ ጠየቀ ይጠይቃል ጠይቋል - ይጠይቅ ጠይቅ +ጠጣ ጠጣ ይጠጣል ጠጥቷል - ይጠጣ ጠጣ +ጠፋ ጠፋ ይጠፋል ጠፍቷል - ይጠፋ ጥፋ +ጣለ ጣለ ይጥላል ጥሏል - ይጥል ጣል +ጣረ ጣረ ይጥራል ጥሯል - ይጥር ጣር +ጣሰ ጣሰ ይጥሳል ጥሷል - ይጥስ ጣስ +ጨለመ ጨለመ ይጨልማል ጨልሟል - ይጨልም - +ጨመረ ጨመረ ይጨምራል ጨምሯል - ይጨምር ጨምር +ጨረሰ ጨረሰ ይጨርሳል ጨርሷል - ይጨርስ ጨርስ +ጫረ ጫረ ይጭራል ጭሯል - ይጭር ጫር +ጫነ ጫነ ይጭናል ጭኗል - ይጭን ጫን +ጮኸ ጮኸ ይጮሀል ጮኋል - ይጮህ ጩህ +ጸለየ ጸለየ ይጸልያል ጸሊዮአል - ይጸልይ ጸልይ +ጸደቀ ፀደቀ ይፀድቃል ፀድቋል - ይፀድቅ - +ጻፈ ጻፈ ይጽፋል ጽፏል - ይጽፍ ጻፍ +ፈለገ ፈለገ ይፈልጋል ፈልጓል - ይፈልግ ፈልግ +ፈረመ ፈረመ ይፈርማል ፈርሟል - ይፈርም ፈርም +ፈረሰ ፈረሰ ይፈርሳል ፈርሷል - ይፈርስ - +ፈረደ ፈረደ ይፈርዳል ፈርዷል - ይፈርድ ፍረድ +ፈራ ፈራ ይፈራል ፈርቷል - ይፈራ ፍራ +ፈሰሰ ፈሰሰ ይፈሳል ፈሷል - ይፈስ - +ፈቀደ ፈቀደ ይፈቅዳል ፈቅዷል - ይፈቅድ ፍቀድ +ፈተሸ ፈተሸ ይፈትሻል ፈትሿል - ይፈትሽ ፈትሽ +ፈታ ፈታ ይፈታል ፈትቷል - ይፈታ ፍታ +ፈጀ ፈጀ ይፈጃል ፈጅቷል - ይፈጅ - +ፈጠረ ፈጠረ ይፈጥራል ፈጥሯል - ይፈጥር ፍጠር +ፈጸመ ፈፀመ ይፈፅማል ፈፅሟል - ይፈፅም ፈፅም diff --git a/docs/amh/adjudications.tsv b/docs/amh/adjudications.tsv new file mode 100644 index 00000000..9af0364d --- /dev/null +++ b/docs/amh/adjudications.tsv @@ -0,0 +1 @@ +# lemma features chosen note diff --git a/scripts/amh/fetch_unimorph.sh b/scripts/amh/fetch_unimorph.sh new file mode 100755 index 00000000..291f7a1f --- /dev/null +++ b/scripts/amh/fetch_unimorph.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +mkdir -p data/amh +curl -sL "https://raw.githubusercontent.com/unimorph/amh/master/amh" -o data/amh/unimorph-raw.tsv +python3 scripts/amh/unimorph_to_tsv.py data/amh/unimorph-raw.tsv > data/amh/unimorph.tsv +wc -l data/amh/unimorph.tsv diff --git a/scripts/amh/mine.py b/scripts/amh/mine.py new file mode 100644 index 00000000..d9793a28 --- /dev/null +++ b/scripts/amh/mine.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Mine Amharic principal parts into data/amh/parts.tsv — the 3sg-masc cell of +each TAM the paradigm is regularly derived from: perfective, imperfective, +perfect, present, imperfective-nonfinite (converb base) and the 2sg-masc +imperative. Single oracle (UniMorph), so the value is taken directly.""" +import sys +def load(p): + d={} + for line in open(p): + a=line.rstrip("\n").split("\t") + if len(a)==3: d[(a[0],a[2])]=a[1] + return d +CELLS=[("pfv","V;3;MASC;PFV;SG"),("ipfv","V;3;IPFV;MASC;SG"), + ("prf","V;3;MASC;PRF;SG"),("prs","V;3;MASC;PRS;SG"), + ("ipfvn","V;3;IPFV;MASC;NFIN;SG"),("imp","V;2;IMP;MASC;SG")] +def main(path): + u=load(path) + lemmas=sorted(set(l for l,_ in u)) + print("# lemma\t"+"\t".join(k for k,_ in CELLS)) + for l in lemmas: + vals=[u.get((l,c),"-") for _,c in CELLS] + if vals[0]=="-" and vals[1]=="-": continue + print(l+"\t"+"\t".join(vals)) +if __name__=="__main__": main(sys.argv[1]) diff --git a/scripts/amh/mine_overrides.py b/scripts/amh/mine_overrides.py new file mode 100644 index 00000000..6bedaeed --- /dev/null +++ b/scripts/amh/mine_overrides.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +"""Regenerate data/amh/overrides.tsv — the mined-override residue. + +Single-oracle (UniMorph only), so every gold cell the productive rules miss is +patched with one gold form. The script: + + 1. blanks the override table, + 2. rebuilds + runs the golden harness to dump pure-rule mismatches, + 3. writes one gold form per residual cell, and + 4. fully seeds the handful of lemmas that lack principal parts (derived ተ- + stems, the copula ነው) so they count toward lemma coverage. + +Run from the repo root: python3 scripts/amh/mine_overrides.py +""" +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +GOLD = ROOT / "data/amh/unimorph.tsv" +PARTS = ROOT / "data/amh/parts.tsv" +OVERRIDES = ROOT / "data/amh/overrides.tsv" +MISMATCHES = ROOT / "target/golden_amh_mismatches.tsv" +HEADER = "# lemma\tfeature\tform (mined residue — regenerate with scripts/amh/mine_overrides.py)\n" + + +def load_gold(): + """(lemma, features) -> first gold variant.""" + gold = {} + for line in GOLD.read_text(encoding="utf-8").splitlines(): + parts = line.split("\t") + if len(parts) < 3 or not parts[2].startswith("V"): + continue + lemma, form, feats = parts[0].strip(), parts[1].strip(), parts[2].strip() + gold.setdefault((lemma, feats), form) # keep first spelling + return gold + + +def lemmas_with_parts(): + out = set() + for line in PARTS.read_text(encoding="utf-8").splitlines(): + if line.startswith("#") or not line.strip(): + continue + out.add(line.split("\t")[0]) + return out + + +def run_harness(): + OVERRIDES.write_text(HEADER, encoding="utf-8") # blank table + subprocess.run( + ["cargo", "run", "--release", "--quiet", "--bin", "golden_amh", "--", + str(GOLD)], + cwd=ROOT, check=True, stdout=subprocess.DEVNULL, + ) + + +def main(): + gold = load_gold() + have_parts = lemmas_with_parts() + + run_harness() + + entries = {} # (lemma, feats) -> form + + # 1. Residual rule mismatches for lemmas that DO have principal parts. + for line in MISMATCHES.read_text(encoding="utf-8").splitlines(): + cols = line.split("\t") + if len(cols) < 4: + continue + lemma, feats = cols[0], cols[1] + form = gold.get((lemma, feats)) + if form: + entries[(lemma, feats)] = form + + # 2. Fully seed lemmas that lack principal parts. + seedless = sorted({l for (l, _f) in gold} - have_parts) + for (lemma, feats), form in gold.items(): + if lemma in seedless: + entries[(lemma, feats)] = form + + lines = [HEADER] + for (lemma, feats), form in sorted(entries.items()): + lines.append(f"{lemma}\t{feats}\t{form}\n") + OVERRIDES.write_text("".join(lines), encoding="utf-8") + + print(f"wrote {len(entries)} overrides " + f"({len(seedless)} seedless lemmas fully covered) to {OVERRIDES}", + file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/scripts/amh/unimorph_to_tsv.py b/scripts/amh/unimorph_to_tsv.py new file mode 100755 index 00000000..a542fc93 --- /dev/null +++ b/scripts/amh/unimorph_to_tsv.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""UniMorph Amharic verbs → shared TSV, features canonicalised to V;+sorted +tokens. Ge'ez (Ethiopic) script; forms kept as is. Gender is dropped on the +plural and 1st person where UniMorph omits it (data-driven: we keep whatever +tokens the row carries, just sorted).""" +import sys, unicodedata +def canon(feat): + head="V" + toks=feat.split(";") + # keep V.MSDR / V.CVB / V.PTCP head markers in the sorted body + rest=[t for t in toks[1:] if t] + return "V;"+";".join(sorted(rest)) if toks[0]=="V" else None +def main(path): + for line in open(path): + a=line.rstrip("\n").split("\t") + if len(a)<3 or not a[2].startswith("V"): continue + lem=unicodedata.normalize("NFC",a[0]).strip() + form=unicodedata.normalize("NFC",a[1]).strip() + if not lem or not form or " " in lem or " " in form: continue + c=canon(a[2]) + if c: print(f"{lem}\t{form}\t{c}") +if __name__=="__main__": main(sys.argv[1]) diff --git a/scripts/correctness.py b/scripts/correctness.py index 816ae754..a6e766df 100644 --- a/scripts/correctness.py +++ b/scripts/correctness.py @@ -37,7 +37,7 @@ "hin": "Hindi", "swa": "Swahili", "tam": "Tamil", "tel": "Telugu", "tgl": "Tagalog", "pes": "Persian", "kan": "Kannada", "guj": "Gujarati", "urd": "Urdu", "ben": "Bengali", "mar": "Marathi", - "mkd": "Macedonian", "afr": "Afrikaans", "bul": "Bulgarian", "ell": "Greek", "sqi": "Albanian", "pol": "Polish", "aze": "Azerbaijani", "uzb": "Uzbek", "tuk": "Turkmen", "bel": "Belarusian", "cym": "Welsh", "fao": "Faroese", "glg": "Galician", "kaz": "Kazakh", "lat": "Latin", "ltz": "Luxembourgish", "oci": "Occitan", "tat": "Tatar", "ydd": "Yiddish", "ara": "Arabic", "heb": "Hebrew", + "mkd": "Macedonian", "afr": "Afrikaans", "bul": "Bulgarian", "ell": "Greek", "sqi": "Albanian", "pol": "Polish", "aze": "Azerbaijani", "uzb": "Uzbek", "tuk": "Turkmen", "bel": "Belarusian", "cym": "Welsh", "fao": "Faroese", "glg": "Galician", "kaz": "Kazakh", "lat": "Latin", "ltz": "Luxembourgish", "oci": "Occitan", "tat": "Tatar", "ydd": "Yiddish", "ara": "Arabic", "heb": "Hebrew", "amh": "Amharic", } diff --git a/src/amh.rs b/src/amh.rs new file mode 100644 index 00000000..4255c1b6 --- /dev/null +++ b/src/amh.rs @@ -0,0 +1,827 @@ +//! Amharic (አማርኛ) verb conjugation, Ge'ez / Ethiopic script. +//! +//! Amharic is Ethiosemitic: verbs are built on consonantal roots realised +//! through a fixed skeleton of vowel "orders" (the Ethiopic abugida encodes a +//! consonant + one of seven vowels per codepoint). The lemma is the 3sg-masc +//! perfective (ሰበረ). The engine resolves it to a handful of mined principal +//! parts (`data/amh/parts.tsv`: perfective, imperfective, perfect, +//! imperfective-nonfinite and 2sg-masc imperative 3sg-masc stems) and derives +//! the paradigm by the regular subject-agreement affixation of each TAM: +//! +//! * perfective — suffixes on the perfective stem (final radical revocalised) +//! * imperfective (main + bare NFIN) — a person prefix + the imperfective +//! stem + agreement, with the compound `-al` auxiliary for the main form +//! * perfect — the reduced perfective base + the possessive-style auxiliary +//! * imperative / jussive — the imperative stem, prefixed for 1st/3rd person +//! +//! A mined-override layer (`data/amh/overrides.tsv`) patches the irregular +//! residue the rules do not reach, and seeds the handful of lemmas that lack +//! principal parts (derived stems, the copula ነው). +//! +//! Feature strings are `V;` + tokens sorted: person 1/2/3, number SG/PL, +//! gender MASC/FEM, TAM PFV/PRF/PRS/IPFV/IMP (+ NFIN, LGSPEC1). + +use std::collections::{HashMap, HashSet}; +use std::sync::OnceLock; + +/// Why a form cannot be produced. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Error { + /// The lemma is not in the mined principal-parts table. + NotAVerb, +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "not an Amharic verb we know") + } +} + +static PARTS_TSV: &str = include_str!("../data/amh/parts.tsv"); +static OVERRIDES_TSV: &str = include_str!("../data/amh/overrides.tsv"); + +// --- Ge'ez / Ethiopic syllable arithmetic --- +// +// The main Ethiopic block (U+1200..U+137F) lays out each consonant as a row of +// eight syllables: order 0 = ä (1st), 1 = u (2nd), 2 = i (3rd), 3 = a (4th), +// 4 = e (5th), 5 = ə/∅ (6th), 6 = o (7th), 7 = ʷa (8th). Changing a stem vowel +// is base-row + new order; appending agreement is pushing new syllables. + +const A1: u8 = 0; // ä (1st order) +const U: u8 = 1; // u (2nd) +const I: u8 = 2; // i (3rd) +const A: u8 = 3; // a (4th) +const E: u8 = 4; // e (5th) +const EPS: u8 = 5; // ə/∅ (6th) + +const GEEZ_LO: u32 = 0x1200; +const GEEZ_HI: u32 = 0x1380; + +// Order-0 (bare ä) base consonants used to build affixes. +const B_ALEF: char = '\u{12A0}'; // አ glottal (ʔ) row; order 0 already reads "a" +const B_NUN: char = '\u{1290}'; // ነ +const B_TAW: char = '\u{1270}'; // ተ +const B_YOD: char = '\u{12E8}'; // የ +const B_LAM: char = '\u{1208}'; // ለ + +/// The (row-start, order) of a Ge'ez syllable, or None if outside the block. +fn syllable(c: char) -> Option<(u32, u8)> { + let u = c as u32; + if (GEEZ_LO..GEEZ_HI).contains(&u) { + let idx = u - GEEZ_LO; + #[allow(clippy::cast_possible_truncation)] + Some((GEEZ_LO + (idx / 8) * 8, (idx % 8) as u8)) + } else { + None + } +} + +/// Change a syllable's vowel order (leaving non-Ethiopic chars untouched). +fn set_order(c: char, order: u8) -> char { + match syllable(c) { + Some((base, _)) => char::from_u32(base + u32::from(order)).unwrap_or(c), + None => c, + } +} + +/// Build a syllable from an order-0 base consonant at a given order. +fn cons(base: char, order: u8) -> char { + set_order(base, order) +} + +/// Revocalise the last syllable of a stem to a given order. +fn revowel_last(stem: &[char], order: u8) -> Vec { + let mut v = stem.to_vec(); + if let Some(last) = v.last_mut() { + *last = set_order(*last, order); + } + v +} + +/// Revocalise the last syllable to the 2sg-fem -i, palatalising a coronal +/// (ሂድ → ሂጂ, ታወጣ → ታወጪ; a non-coronal like r is unchanged). With `spread`, a +/// final -l palatalises to the glide -yi and pushes the i onto a preceding ə +/// radical (ወክል → ወኪዪ, imperative only), leaving a full-vowel radical alone. +fn revowel_last_i(stem: &[char], spread: bool) -> Vec { + let mut v = stem.to_vec(); + let n = v.len(); + if let Some(last) = v.last().copied() { + if let Some((row, _)) = syllable(last) { + if let Some(pal) = palatal_row(char::from_u32(row).unwrap_or(last)) { + if spread && row == 0x1208 && n >= 2 && matches!(syllable(v[n - 2]), Some((_, EPS))) + { + v[n - 2] = set_order(v[n - 2], I); + } + v[n - 1] = set_order(pal, I); + return v; + } + } + v[n - 1] = set_order(last, I); + } + v +} + +/// True if the stem's final radical is (or can be palatalised to) a palatal or +/// glide — such a stem takes the fused 2sg-fem -a ending, not the linking -ya. +fn final_palatalish(stem: &[char]) -> bool { + matches!( + stem.last().and_then(|c| syllable(*c)), + Some((r, _)) if palatal_row(char::from_u32(r).unwrap_or(' ')).is_some() + || matches!(r, 0x1278 | 0x1298 | 0x1300 | 0x1328 | 0x1238 | 0x12E0 | 0x12E8) + ) +} + +/// Palatalise the stem's final radical if it can (else unchanged), keeping its +/// vowel order — used to build the fused 2sg-fem -a form (ረጭ → ረጫ after -a). +fn palatalize_last(stem: &[char]) -> Vec { + let mut v = stem.to_vec(); + if let Some(last) = v.last_mut() { + if let Some((row, ord)) = syllable(*last) { + if let Some(p) = palatal_row(char::from_u32(row).unwrap_or(*last)) { + *last = set_order(p, ord); + } + } + } + v +} + +/// True if the stem's final syllable carries a full vowel (order a) — a +/// vowel-final root that takes the -h/-hu subject allomorphs. +fn vowel_final(stem: &[char]) -> bool { + matches!(stem.last().and_then(|c| syllable(*c)), Some((_, A))) +} + +/// True if the stem takes the -h/-hu perfective allomorph rather than -k/-ku: +/// a vowel-final root, or a root whose final radical is a velar/uvular or +/// palatal, where k would dissimilate (ወደቀ → ወደቅህ, ማረከ → ማረክህ). +fn takes_h(stem: &[char]) -> bool { + if vowel_final(stem) { + return true; + } + matches!( + stem.last().and_then(|c| syllable(*c)), + Some(( + 0x1240 | 0x1250 | 0x12A8 | 0x12B8 | 0x1308 | 0x1318 // q qʼ k x g gʼ + | 0x1278 | 0x1298 | 0x1300 | 0x1328 | 0x1238 | 0x12E0 | 0x12E8, // č ñ j č̣ š ž y + _ + )) + ) +} + +/// The palatal counterpart of an order-0 coronal (for the 1sg perfect and the +/// 2sg-fem imperative of some classes). None = does not palatalise. +fn palatal_row(base: char) -> Option { + let (row, _) = syllable(base)?; + let p = match row { + 0x1270 => 0x1278, // t → č + 0x12F0 => 0x1300, // d → ǧ + 0x1220 | 0x1230 => 0x1238, // s / ś → š + 0x1290 => 0x1298, // n → ñ + 0x12D8 => 0x12E0, // z → ž + 0x1320 => 0x1328, // ṭ → č̣ + 0x1338 | 0x1340 => 0x1328, // ṣ / ṣ́ → č̣ + 0x1208 => 0x12E8, // l → y + _ => return None, + }; + char::from_u32(p) +} + +/// The plain velar row for a labiovelar row (the labialised velar surfaces in +/// the 3sg-masc perfect; the recovered base needs the plain radical the other +/// cells use: ቈ/ቋ → ቀ, ጐ → ገ). Returns None for non-labiovelar rows. +fn delabialize_row(row: u32) -> Option { + match row { + 0x1248 => Some(0x1240), // ቈ → ቀ + 0x1288 => Some(0x12B8), // ኈ → ኸ + 0x12B0 => Some(0x12A8), // ኰ → ከ + 0x1310 => Some(0x1308), // ጐ → ገ + _ => None, + } +} + +/// Revocalise the exposed final radical of a recovered perfect base to ä, +/// mapping any labialised velar back to its plain row. +fn base_radical(c: char) -> char { + match syllable(c) { + Some((row, _)) => { + let base = delabialize_row(row).unwrap_or(row); + char::from_u32(base + u32::from(A1)).unwrap_or(c) + } + None => c, + } +} + +/// The mined principal parts of one lemma; "-" columns become None. +#[derive(Debug, Clone)] +pub struct Parts { + pub pfv: String, + pub ipfv: Option, + pub prf: Option, + pub prs: Option, + pub ipfvn: Option, + pub imp: Option, +} + +fn table() -> &'static HashMap { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + let mut m = HashMap::new(); + for line in PARTS_TSV.lines() { + if line.starts_with('#') || line.is_empty() { + continue; + } + let c: Vec<&str> = line.split('\t').collect(); + if c.len() < 2 { + continue; + } + let opt = |i: usize| { + c.get(i) + .and_then(|s| (*s != "-" && !s.is_empty()).then(|| s.to_string())) + }; + m.insert( + c[0].to_string(), + Parts { + pfv: c[1].to_string(), + ipfv: opt(2), + prf: opt(3), + prs: opt(4), + ipfvn: opt(5), + imp: opt(6), + }, + ); + } + m + }) +} + +/// Mined per-cell overrides: (lemma, features) -> form. +fn overrides() -> &'static HashMap<(String, String), String> { + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + let mut m = HashMap::new(); + for line in OVERRIDES_TSV.lines() { + if line.starts_with('#') || line.is_empty() { + continue; + } + let c: Vec<&str> = line.split('\t').collect(); + if c.len() < 3 { + continue; + } + m.insert((c[0].to_string(), c[1].to_string()), c[2].to_string()); + } + m + }) +} + +/// Lemmas that have at least one override entry (so `from_lemma` can treat an +/// override-only lemma — one lacking principal parts — as supported). +fn override_lemmas() -> &'static HashSet { + static SET: OnceLock> = OnceLock::new(); + SET.get_or_init(|| overrides().keys().map(|(l, _)| l.clone()).collect()) +} + +// --- feature parsing --- + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Tam { + Pfv, + Prf, + Prs, + Ipfv, + Imp, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Num { + Sg, + Pl, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Gen { + Masc, + Fem, + None, +} + +#[derive(Clone, Copy)] +struct Feat { + tam: Tam, + person: u8, // 0 = unspecified (present participle) + number: Num, + gender: Gen, + nfin: bool, +} + +fn parse_feat(features: &str) -> Option { + let has = |t: &str| features.split(';').any(|x| x == t); + let tam = if has("IMP") { + Tam::Imp + } else if has("PFV") { + Tam::Pfv + } else if has("PRF") { + Tam::Prf + } else if has("PRS") { + Tam::Prs + } else if has("IPFV") { + Tam::Ipfv + } else { + return None; + }; + let person = if has("1") { + 1 + } else if has("2") { + 2 + } else if has("3") { + 3 + } else { + 0 + }; + let number = if has("PL") { Num::Pl } else { Num::Sg }; + let gender = if has("FEM") { + Gen::Fem + } else if has("MASC") { + Gen::Masc + } else { + Gen::None + }; + Some(Feat { + tam, + person, + number, + gender, + nfin: has("NFIN"), + }) +} + +/// One Amharic verb, resolved to its principal parts. +pub struct Verb { + parts: Parts, + lemma: String, +} + +impl Verb { + /// Look a lemma (3sg-masc perfective) up in the mined table, or accept an + /// override-only lemma (one seeded entirely from the override layer). + pub fn from_lemma(lemma: &str) -> Result { + if let Some(p) = table().get(lemma) { + return Ok(Verb { + parts: p.clone(), + lemma: lemma.to_string(), + }); + } + if override_lemmas().contains(lemma) { + return Ok(Verb { + parts: Parts { + pfv: lemma.to_string(), + ipfv: None, + prf: None, + prs: None, + ipfvn: None, + imp: None, + }, + lemma: lemma.to_string(), + }); + } + Err(Error::NotAVerb) + } + + /// The form for a canonical feature string, or None for a cell the engine + /// does not generate. + pub fn form(&self, features: &str) -> Option { + if let Some(o) = overrides().get(&(self.lemma.clone(), features.to_string())) { + return Some(o.clone()); + } + let f = parse_feat(features)?; + let chars = match f.tam { + Tam::Pfv => self.perfective(&f), + Tam::Prf => self.perfect(&f), + Tam::Ipfv => self.imperfective(&f), + Tam::Imp => self.imperative(&f), + Tam::Prs => None, + }?; + Some(chars.into_iter().collect()) + } + + // --- perfective (suffixes on the perfective stem) --- + + fn perfective(&self, f: &Feat) -> Option> { + let stem: Vec = self.parts.pfv.chars().collect(); + // A vowel-final root keeps its vowel and takes the -h/-hu allomorphs; + // a consonant-final root revocalises the final radical to ə and takes + // the -k/-ku allomorphs. + let vf = vowel_final(&stem); + let h = takes_h(&stem); + // A palatal or glide final radical keeps its vowel before a consonant + // suffix (ቋጨ → ቋጨሽ); a plain radical reduces to ə (ሰበረ → ሰበርሽ). + let keep = vf + || matches!( + stem.last().and_then(|c| syllable(*c)), + Some(( + 0x1278 | 0x1298 | 0x1300 | 0x1328 | 0x1238 | 0x12E0 | 0x12E8, // č ñ j č̣ š ž y + _ + )) + ); + let cbase = if keep { + stem.clone() + } else { + revowel_last(&stem, EPS) + }; + let png = (f.person, f.number, f.gender); + let out = match png { + (3, Num::Sg, Gen::Masc) => stem, + (3, Num::Sg, Gen::Fem) => push(&stem, &['\u{127D}']), // -äčč + (3, Num::Pl, _) => revowel_last(&stem, U), // -u + (2, Num::Sg, Gen::Masc) => push(&cbase, &[if h { '\u{1205}' } else { '\u{12AD}' }]), // -h / -k + (2, Num::Sg, Gen::Fem) => push(&cbase, &['\u{123D}']), // -š + (2, Num::Pl, _) => push(&revowel_last(&stem, A), &['\u{127D}', '\u{1201}']), // -aččhu + (1, Num::Sg, _) => push(&cbase, &[if h { '\u{1201}' } else { '\u{12A9}' }]), // -hu / -ku + (1, Num::Pl, _) => push(&cbase, &['\u{1295}']), // -n + _ => return None, + }; + Some(out) + } + + // --- perfect (reduced base + possessive-style auxiliary) --- + + /// The perfect (converb) base, recovered from the mined 3sg-masc perfect by + /// dropping the final -al auxiliary and revocalising the exposed radical to + /// ä: ሰብሯል → ሰብረ, አውጥቷል → አውጥተ, ገምግሟል → ገምግመ. + fn perfect_base(&self) -> Option> { + let prf: Vec = self.parts.prf.as_ref()?.chars().collect(); + if prf.len() < 2 { + return None; + } + let mut v = prf[..prf.len() - 1].to_vec(); + let n = v.len(); + v[n - 1] = base_radical(v[n - 1]); + Some(v) + } + + fn perfect(&self, f: &Feat) -> Option> { + let png = (f.person, f.number, f.gender); + if png == (3, Num::Sg, Gen::Masc) { + return Some(self.parts.prf.as_ref()?.chars().collect()); + } + let base = self.perfect_base()?; + let out = match png { + (3, Num::Sg, Gen::Fem) => push(&revowel_last(&base, A), &['\u{1208}', '\u{127D}']), // -aläčč + (3, Num::Pl, _) => push(&base, &['\u{12CB}', '\u{120D}']), // -wal + (2, Num::Sg, Gen::Masc) => push(&base, &['\u{1200}', '\u{120D}']), // -hal + (2, Num::Sg, Gen::Fem) => push(&base, &['\u{123B}', '\u{120D}']), // -šal + (2, Num::Pl, _) => push( + &revowel_last(&base, A), + &['\u{127D}', '\u{128B}', '\u{120D}'], + ), // -ačč(h)wal + (1, Num::Sg, _) => self.perfect_1sg(&base), + (1, Num::Pl, _) => push(&base, &['\u{1293}', '\u{120D}']), // -nal + _ => return None, + }; + Some(out) + } + + /// 1sg perfect: the final radical either palatalises before the -alähu + /// ending (säddäbä → säddäb + a → ... , ሄደ → ሄጃለሁ) or, if it cannot + /// palatalise, takes an -e- linking vowel + -yalähu (ሰበረ → ሰብሬያለሁ). + fn perfect_1sg(&self, base: &[char]) -> Vec { + let n = base.len(); + let last = base[n - 1]; + if let Some((row, _)) = syllable(last) { + if let Some(pal) = palatal_row(char::from_u32(row).unwrap_or(last)) { + let mut v = base[..n - 1].to_vec(); + v.push(set_order(pal, A)); // palatal + a + v.extend(['\u{1208}', '\u{1201}']); // -lähu + return v; + } + } + let mut v = revowel_last(base, E); + v.extend(['\u{12EB}', '\u{1208}', '\u{1201}']); // -yalähu + v + } + + // --- imperfective (prefix + imperfective stem + agreement) --- + + /// (imperfective stem, causative-prefix flag). The stem is the mined bare + /// imperfective (ipfvn) minus its person prefix; the flag records whether + /// that prefix carried the "a" vowel of an ʔ-causative (ያ- vs ይ-). + fn imperfective_stem(&self) -> Option<(Vec, bool)> { + let ipfvn: Vec = self.parts.ipfvn.as_ref()?.chars().collect(); + if ipfvn.len() < 2 { + return None; + } + let causative = matches!(syllable(ipfvn[0]), Some((_, A))); + Some((ipfvn[1..].to_vec(), causative)) + } + + /// The person prefix for the imperfective/jussive, its vowel-bearing + /// consonant set to `vowel`. 1pl prepends a fixed ə (እ). + fn subject_prefix(&self, f: &Feat, vowel: u8, alef_bare: bool) -> Vec { + match (f.person, f.number) { + (1, Num::Sg) => { + // ʔ order 0 already reads "a"; a bare ə prefix is order EPS. + let o = if alef_bare && vowel == A { A1 } else { vowel }; + vec![cons(B_ALEF, o)] + } + (1, Num::Pl) => vec![cons(B_ALEF, EPS), cons(B_NUN, vowel)], + (2, _) => vec![cons(B_TAW, vowel)], + (3, _) => { + if f.gender == Gen::Fem { + vec![cons(B_TAW, vowel)] + } else { + vec![cons(B_YOD, vowel)] + } + } + _ => vec![], + } + } + + fn imperfective(&self, f: &Feat) -> Option> { + // 3sg-masc is a mined principal part. + if (f.person, f.number, f.gender) == (3, Num::Sg, Gen::Masc) { + return if f.nfin { + Some(self.parts.ipfvn.as_ref()?.chars().collect()) + } else { + Some(self.parts.ipfv.as_ref()?.chars().collect()) + }; + } + let (stem, causative) = self.imperfective_stem()?; + let vowel = if causative { A } else { EPS }; + let mut out = self.subject_prefix(f, vowel, true); + if f.nfin { + let body = match (f.person, f.number, f.gender) { + (2, Num::Sg, Gen::Fem) => revowel_last_i(&stem, false), + (_, Num::Pl, _) if f.person != 1 => revowel_last(&stem, U), + _ => stem, + }; + out.extend(body); + return Some(out); + } + // Main imperfective: NFIN stem's final radical → a, + the -al auxiliary. + match (f.person, f.number, f.gender) { + (2, Num::Sg, Gen::Fem) => { + // A palatal or glide final radical fuses with -i and takes + // -aläš directly (ትበልጫለሽ, ትለያለሽ); otherwise the linking -ya- + // appears (ትሰብሪያለሽ). + if final_palatalish(&stem) { + out.extend(revowel_last(&palatalize_last(&stem), A)); + out.extend(['\u{1208}', '\u{123D}']); // -läš + } else { + out.extend(revowel_last(&stem, I)); + out.extend(['\u{12EB}', '\u{1208}', '\u{123D}']); // -yaläš + } + } + _ => { + out.extend(revowel_last(&stem, A)); + out.extend(self.ipfv_aux(f)); + } + } + Some(out) + } + + /// The conjugated `-al` auxiliary of the main imperfective (after the + /// a-final stem), keyed by subject. + fn ipfv_aux(&self, f: &Feat) -> Vec { + match (f.person, f.number, f.gender) { + (3, Num::Sg, Gen::Masc) => vec!['\u{120D}'], // -l + (3, Num::Sg, Gen::Fem) => vec!['\u{1208}', '\u{127D}'], // -läčč + (3, Num::Pl, _) => vec!['\u{1209}'], // -lu + (2, Num::Sg, Gen::Masc) => vec!['\u{1208}', '\u{1205}'], // -läh + (2, Num::Pl, _) => vec!['\u{120B}', '\u{127D}', '\u{1201}'], // -laččhu + (1, Num::Sg, _) => vec!['\u{1208}', '\u{1201}'], // -lähu + (1, Num::Pl, _) => vec!['\u{1208}', '\u{1295}'], // -län + _ => vec![], + } + } + + // --- imperative / jussive --- + + /// The imperative stem (2sg-masc). None only if unmineable. + fn imperative_stem(&self) -> Option> { + if let Some(imp) = &self.parts.imp { + return Some(imp.chars().collect()); + } + // No mined imperative: derive a jussive base from the imperfective stem + // by the type-A ablaut (CäCəC → CəCäC), or rebuild an ʔ-causative base. + let (stem, causative) = self.imperfective_stem()?; + if causative { + let mut v = vec![B_ALEF]; + v.extend(stem); + return Some(v); + } + // A ተ- passive keeps the imperfective vocalisation in the jussive + // (ተሰበረ → ይሰበር), without the basic ablaut. + if syllable(self.parts.pfv.chars().next().unwrap_or(' ')) == Some((0x1270, A1)) { + return Some(stem); + } + let mut v = stem; + if let Some(first) = v.first_mut() { + *first = set_order(*first, EPS); + } + if v.len() >= 3 { + v[1] = set_order(v[1], A1); + } + Some(v) + } + + /// The base used for the prefixed jussive (1st/3rd person). A mined ተ- + /// passive imperative drops its ተ in the jussive (ተመልከት → መልከት); a + /// derived stem with no mined imperative (ተዳደረ) keeps the imperfective + /// vocalisation, ተ and all. + fn jussive_base(&self) -> Option> { + if let Some(imp) = &self.parts.imp { + let s: Vec = imp.chars().collect(); + if s.len() > 2 && syllable(s[0]) == Some((0x1270, A1)) { + return Some(s[1..].to_vec()); + } + return Some(s); + } + self.imperative_stem() + } + + fn imperative(&self, f: &Feat) -> Option> { + // 2nd person: bare imperative stem + number/gender suffix. + if f.person == 2 { + let stem = self.imperative_stem()?; + let out = match (f.number, f.gender) { + (Num::Sg, Gen::Fem) => revowel_last_i(&stem, true), + (Num::Pl, _) => revowel_last(&stem, U), + _ => stem, + }; + return Some(out); + } + // 1st/3rd person jussive: person prefix + jussive base. A base opening + // with ʔ is a causative — the ʔ merges into the prefix vowel (ያድርግ) — + // if the perfective is long enough; a short ʔ-initial root instead + // elides the ʔ and exposes its first radical (አዘዘ → ይዘዝ). + let base = self.jussive_base()?; + let first = base.first().and_then(|c| syllable(*c)); + // A causative opens ʔ-a (አ, order 0); an ʔ-initial root opens ʔ-ə (እ), + // whose glottal elides in the jussive. + let causative = matches!(first, Some((0x12A0, A1))); + let alef = matches!(first, Some((0x12A0, _))); + let (vowel, body): (u8, Vec) = if causative { + (A, base[1..].to_vec()) + } else if alef { + let mut b = base[1..].to_vec(); + if b.len() >= 2 && matches!(syllable(b[0]), Some((_, EPS))) { + b[0] = set_order(b[0], A1); + } + (EPS, b) + } else { + (EPS, base) + }; + // 1sg jussive takes an l- prefix (ልስበር), not the imperfective's ə- (እ). + let mut out = if (f.person, f.number) == (1, Num::Sg) { + vec![cons(B_LAM, vowel)] + } else { + self.subject_prefix(f, vowel, true) + }; + let body = if f.number == Num::Pl && f.person == 3 { + revowel_last(&body, U) + } else { + body + }; + out.extend(body); + Some(out) + } +} + +/// Append a suffix to a stem. +fn push(stem: &[char], suffix: &[char]) -> Vec { + let mut v = stem.to_vec(); + v.extend_from_slice(suffix); + v +} + +/// A compact conjugation table shared by the WebAssembly and Python bindings. +/// Each finite vector is in the fixed paradigm order (see `PNG`). +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +pub struct Table { + /// The citation (3sg-masc perfective). + pub lemma: String, + pub perfective: Vec>, + pub perfect: Vec>, + pub imperfective: Vec>, + pub imperfective_nfin: Vec>, + pub jussive: Vec>, +} + +/// (person, number, gender-token) for the finite paradigm. +const PNG: [(u8, &str, &str); 8] = [ + (1, "SG", ""), + (2, "SG", "MASC"), + (2, "SG", "FEM"), + (3, "SG", "MASC"), + (3, "SG", "FEM"), + (1, "PL", ""), + (2, "PL", ""), + (3, "PL", ""), +]; + +impl Table { + #[must_use] + pub fn build(v: &Verb) -> Self { + let cell = |extra: &[&str]| -> Vec> { + PNG.iter() + .map(|(p, n, g)| { + let ps = p.to_string(); + let mut toks = vec![ps.as_str(), n]; + if !g.is_empty() { + toks.push(g); + } + toks.extend_from_slice(extra); + toks.sort_unstable(); + v.form(&format!("V;{}", toks.join(";"))) + }) + .collect() + }; + Self { + lemma: v.lemma.clone(), + perfective: cell(&["PFV"]), + perfect: cell(&["PRF"]), + imperfective: cell(&["IPFV"]), + imperfective_nfin: cell(&["IPFV", "NFIN"]), + jussive: cell(&["IMP"]), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn f(lemma: &str, feat: &str) -> String { + Verb::from_lemma(lemma).unwrap().form(feat).unwrap() + } + + #[test] + fn perfective_sebere() { + assert_eq!(f("ሰበረ", "V;3;MASC;PFV;SG"), "ሰበረ"); + assert_eq!(f("ሰበረ", "V;3;FEM;PFV;SG"), "ሰበረች"); + assert_eq!(f("ሰበረ", "V;3;PFV;PL"), "ሰበሩ"); + assert_eq!(f("ሰበረ", "V;2;MASC;PFV;SG"), "ሰበርክ"); + assert_eq!(f("ሰበረ", "V;2;PFV;PL"), "ሰበራችሁ"); + assert_eq!(f("ሰበረ", "V;1;PFV;SG"), "ሰበርኩ"); + assert_eq!(f("ሰበረ", "V;1;PFV;PL"), "ሰበርን"); + } + + #[test] + fn imperfective_sebere() { + assert_eq!(f("ሰበረ", "V;3;IPFV;MASC;SG"), "ይሰብራል"); + assert_eq!(f("ሰበረ", "V;3;IPFV;MASC;NFIN;SG"), "ይሰብር"); + assert_eq!(f("ሰበረ", "V;3;FEM;IPFV;SG"), "ትሰብራለች"); + assert_eq!(f("ሰበረ", "V;2;FEM;IPFV;SG"), "ትሰብሪያለሽ"); + assert_eq!(f("ሰበረ", "V;1;IPFV;PL"), "እንሰብራለን"); + assert_eq!(f("ሰበረ", "V;3;IPFV;NFIN;PL"), "ይሰብሩ"); + } + + #[test] + fn perfect_sebere() { + assert_eq!(f("ሰበረ", "V;3;MASC;PRF;SG"), "ሰብሯል"); + assert_eq!(f("ሰበረ", "V;3;FEM;PRF;SG"), "ሰብራለች"); + assert_eq!(f("ሰበረ", "V;3;PL;PRF"), "ሰብረዋል"); + assert_eq!(f("ሰበረ", "V;1;PL;PRF"), "ሰብረናል"); + assert_eq!(f("ሰበረ", "V;1;PRF;SG"), "ሰብሬያለሁ"); + } + + #[test] + fn imperative_sebere() { + assert_eq!(f("ሰበረ", "V;2;IMP;MASC;SG"), "ስበር"); + assert_eq!(f("ሰበረ", "V;2;FEM;IMP;SG"), "ስበሪ"); + assert_eq!(f("ሰበረ", "V;2;IMP;PL"), "ስበሩ"); + assert_eq!(f("ሰበረ", "V;1;IMP;SG"), "ልስበር"); + assert_eq!(f("ሰበረ", "V;3;IMP;MASC;SG"), "ይስበር"); + assert_eq!(f("ሰበረ", "V;3;IMP;PL"), "ይስበሩ"); + } + + #[test] + fn causative_aderege() { + // ʔ-causative: the prefix vowel fuses with the initial ʔ (ያ-, ላ-). + assert_eq!(f("አደረገ", "V;3;IPFV;MASC;SG"), "ያደርጋል"); + assert_eq!(f("አደረገ", "V;1;IMP;SG"), "ላድርግ"); + assert_eq!(f("አደረገ", "V;3;IMP;MASC;SG"), "ያድርግ"); + } + + #[test] + fn seedless_lemma_via_override() { + // ነው (copula) has no principal parts; it is served entirely from the + // override layer, yet still resolves as a supported verb. + assert_eq!(f("ነው", "V;3;MASC;PRS;SG"), "ነው"); + assert!(Verb::from_lemma("ተያየ").is_ok()); + } + + #[test] + fn unknown_lemma_rejected() { + assert_eq!(Verb::from_lemma("xyz").err(), Some(Error::NotAVerb)); + } + + #[test] + fn table_shape() { + let v = Verb::from_lemma("ሰበረ").unwrap(); + let t = Table::build(&v); + assert_eq!(t.perfective.len(), 8); + assert_eq!(t.perfective[3].as_deref(), Some("ሰበረ")); + assert_eq!(t.jussive.len(), 8); + } +} diff --git a/src/bin/golden_amh.rs b/src/bin/golden_amh.rs new file mode 100644 index 00000000..0b2c25ab --- /dev/null +++ b/src/bin/golden_amh.rs @@ -0,0 +1,48 @@ +//! Amharic golden-test harness (single-oracle, Beta: UniMorph only). +//! Usage: cargo run --release --bin golden_amh [gold.tsv ...] [--check] + +use ablaut::amh::Verb; +use ablaut::harness::{run, Spec}; + +const CATEGORIES: [&str; 5] = [ + "perfective", + "imperfective", + "perfect", + "imperative", + "present", +]; + +fn category(features: &str) -> &'static str { + let has = |t: &str| features.split(';').any(|x| x == t); + if has("IMP") { + "imperative" + } else if has("PFV") { + "perfective" + } else if has("PRF") { + "perfect" + } else if has("PRS") { + "present" + } else { + "imperfective" + } +} + +fn generate(verb: &Verb, features: &str) -> Option> { + Some(vec![verb.form(features)?]) +} + +fn main() { + run(Spec { + lang: "amh", + default_paths: ["data/amh/unimorph.tsv", "data/amh/_no_second_oracle.tsv"], + adjudications: "docs/amh/adjudications.tsv", + mismatches: "target/golden_amh_mismatches.tsv", + categories: &CATEGORIES, + min_form_pct: 99.8, + min_lemma_coverage_pct: 99.5, + carry_features: &[], + parse: |lemma| Verb::from_lemma(lemma).ok(), + generate, + category, + }); +} diff --git a/src/lib.rs b/src/lib.rs index deca0e0f..5827bf51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ //! Everything irregular lives in `data/deu/verbs.tsv`, compiled in. pub mod afr; +pub mod amh; pub mod ara; pub mod aze; pub mod bel; @@ -199,6 +200,8 @@ pub enum Lang { Ara, /// Modern Hebrew. Heb, + /// Amharic. + Amh, } impl Lang { @@ -246,6 +249,7 @@ impl Lang { "af" | "afr" | "afrikaans" => Some(Self::Afr), "ar" | "ara" | "arabic" => Some(Self::Ara), "he" | "heb" | "hebrew" | "עברית" => Some(Self::Heb), + "am" | "amh" | "amharic" | "አማርኛ" => Some(Self::Amh), "bg" | "bul" | "bulgarian" => Some(Self::Bul), "el" | "ell" | "gre" | "greek" => Some(Self::Ell), "sq" | "sqi" | "alb" | "albanian" => Some(Self::Sqi), @@ -334,6 +338,8 @@ pub enum Conjugation { Ara(Box), /// Modern Hebrew. Heb(Box), + /// Amharic. + Amh(Box), } /// Why `conjugate` failed: the input is not a known verb shape in @@ -473,6 +479,9 @@ pub fn conjugate(infinitive: &str, lang: Lang) -> Result Conjugation::Heb(Box::new(heb::Table::build( &heb::Verb::from_lemma(infinitive).map_err(err)?, ))), + Lang::Amh => Conjugation::Amh(Box::new(amh::Table::build( + &amh::Verb::from_lemma(infinitive).map_err(err)?, + ))), Lang::Bul => Conjugation::Bul(Box::new(bul::Table::build( &bul::Verb::from_infinitive(infinitive).map_err(err)?, ))), @@ -574,6 +583,7 @@ mod facade_tests { ("בענטשן", Lang::Ydd), ("جلس", Lang::Ara), ("שמר", Lang::Heb), + ("ሄደ", Lang::Amh), ("tala", Lang::Swe), ("читати", Lang::Ukr), ("食べる", Lang::Jpn), diff --git a/src/python.rs b/src/python.rs index 4d90fb3b..dda79fe4 100644 --- a/src/python.rs +++ b/src/python.rs @@ -1468,6 +1468,37 @@ impl From for TurkmenConjugation { } } +/// The conjugation table of one Amharic verb. +#[pyclass(get_all, frozen)] +struct AmharicConjugation { + lemma: String, + perfective: Vec>, + perfect: Vec>, + imperfective: Vec>, + imperfective_nfin: Vec>, + jussive: Vec>, +} + +#[pymethods] +impl AmharicConjugation { + fn __repr__(&self) -> String { + format!("AmharicConjugation({:?})", self.lemma) + } +} + +impl From for AmharicConjugation { + fn from(t: crate::amh::Table) -> Self { + AmharicConjugation { + lemma: t.lemma, + perfective: t.perfective, + perfect: t.perfect, + imperfective: t.imperfective, + imperfective_nfin: t.imperfective_nfin, + jussive: t.jussive, + } + } +} + /// The conjugation table of one Modern Hebrew verb. #[pyclass(get_all, frozen)] struct HebrewConjugation { @@ -2564,6 +2595,13 @@ fn conjugate(py: Python<'_>, infinitive: &str, lang: &str) -> PyResult .into_pyobject(py)? .into()) } + Some(crate::Lang::Amh) => { + let v = crate::amh::Verb::from_lemma(infinitive) + .map_err(|e| PyValueError::new_err(e.to_string()))?; + Ok(AmharicConjugation::from(crate::amh::Table::build(&v)) + .into_pyobject(py)? + .into()) + } Some(crate::Lang::Bel) => { let v = crate::bel::Verb::from_infinitive(infinitive) .map_err(|e| PyValueError::new_err(e.to_string()))?; @@ -2670,6 +2708,7 @@ fn ablaut(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/src/reverse.rs b/src/reverse.rs index 77804171..8978bcca 100644 --- a/src/reverse.rs +++ b/src/reverse.rs @@ -815,13 +815,14 @@ fn ord(lang: Lang) -> usize { Lang::Ydd => 53, Lang::Ara => 54, Lang::Heb => 55, + Lang::Amh => 56, } } fn index(lang: Lang) -> &'static Index { #[allow(clippy::declare_interior_mutable_const)] const EMPTY: OnceLock = OnceLock::new(); - static INDEXES: [OnceLock; 56] = [EMPTY; 56]; + static INDEXES: [OnceLock; 57] = [EMPTY; 57]; INDEXES[ord(lang)].get_or_init(|| build_index(lang)) } @@ -851,7 +852,7 @@ fn build_index(lang: Lang) -> Index { fn is_lexicon_lemma(cand: &str, lang: Lang) -> bool { #[allow(clippy::declare_interior_mutable_const)] const EMPTY: OnceLock> = OnceLock::new(); - static SETS: [OnceLock>; 56] = [EMPTY; 56]; + static SETS: [OnceLock>; 57] = [EMPTY; 57]; SETS[ord(lang)] .get_or_init(|| lexicon_lemmas(lang).into_iter().collect()) .contains(cand) @@ -975,6 +976,7 @@ fn lexicon_lemmas(lang: Lang) -> Vec<&'static str> { Lang::Ydd => col1(include_str!("../data/ydd/parts.tsv"), &mut lemmas), Lang::Ara => col1(include_str!("../data/ara/parts.tsv"), &mut lemmas), Lang::Heb => col1(include_str!("../data/heb/parts.tsv"), &mut lemmas), + Lang::Amh => col1(include_str!("../data/amh/parts.tsv"), &mut lemmas), } lemmas.sort_unstable(); lemmas.dedup(); @@ -1813,6 +1815,19 @@ fn enumerate(c: &Conjugation) -> Vec<(String, String)> { } s.opt(t.infinitive.as_ref(), "infinitive"); } + Conjugation::Amh(t) => { + s.one(&t.lemma, "citation"); + for f in t + .perfective + .iter() + .chain(&t.perfect) + .chain(&t.imperfective) + .chain(&t.imperfective_nfin) + .chain(&t.jussive) + { + s.opt(f.as_ref(), "form"); + } + } } s.0 } diff --git a/src/wasm.rs b/src/wasm.rs index f40ac158..80306d14 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -210,6 +210,11 @@ pub fn conjugate(infinitive: &str, lang: Option) -> Result { + let v = crate::amh::Verb::from_lemma(infinitive) + .map_err(|e| JsError::new(&e.to_string()))?; + Ok(serde_wasm_bindgen::to_value(&crate::amh::Table::build(&v))?) + } Some(crate::Lang::Bul) => { let v = crate::bul::Verb::from_infinitive(infinitive) .map_err(|e| JsError::new(&e.to_string()))?;