c62ea3383c
Port the validated sandbox Spanish realizer into the ELP .el runtime (STAGE only). - vocabulary-es.el: 342 entries generated from UniMorph via morphology_es_full (real forms; nouns carry REAL per-lemma lexicon gender in form2 — kills the el-mano/la-dia masculine-default class). - lang_profile_es.el: Spanish typology flags incl. mandatory contractions + govt. - morphology-es.el: add es_participle, es_inflect_adj, es_contract, es_article_for_gender; accent-correct plural/preterite/participle. - parity harness: 90.1% morphology parity vs Python oracle; gender heuristic 73.6% vs vocab-real 100%; contraction 100%.
101 lines
4.4 KiB
Python
101 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""gen_parity_es.py — emit an El parity program that checks the .el Spanish
|
|
morphology against the validated Python (UniMorph-backed) realizer.
|
|
|
|
Python is the ORACLE. For every lemma in the held-out inventory we embed the
|
|
Python-produced form, call the corresponding .el function, and the El program
|
|
prints PASS/FAIL per category. Aggregation is done in bash (grep -c), so no
|
|
El-side mutable counters are needed.
|
|
|
|
Categories:
|
|
Vpres verb present-ind-3sg es_conjugate(v,present,third,singular)
|
|
Vpret verb preterite-3sg es_conjugate(v,past,third,singular)
|
|
Vpart past participle es_participle(v)
|
|
Npl noun plural es_pluralize(n)
|
|
Gheur noun gender HEURISTIC es_gender(n) [exposes the bug]
|
|
Aheur def article via heuristic es_agree_article(n,true,sg) [inherits the bug]
|
|
Avocab def article via REAL g es_article_for_gender(realg,...) [the fix]
|
|
Ampl adj masc-plural es_inflect_adj(a,m,plural)
|
|
Afsg adj fem-singular es_inflect_adj(a,f,singular)
|
|
Ctr contraction del/al es_contract(prep, np)
|
|
"""
|
|
import morphology_es_full as M
|
|
import realizer_es as R
|
|
from gen_elp_es import _collect_from_specs, _CORE_VERBS, _CORE_NOUNS, _CORE_ADJS
|
|
|
|
|
|
def _esc(s):
|
|
return str(s).replace('\\', '\\\\').replace('"', '\\"')
|
|
|
|
|
|
def _check(cat, lemma, el_call, expected):
|
|
return (f' es_check("{cat}", "{_esc(lemma)}", {el_call}, "{_esc(expected)}")')
|
|
|
|
|
|
def main(out_path):
|
|
v_specs, n_specs, a_specs = _collect_from_specs()
|
|
verbs = sorted(set(_CORE_VERBS) | v_specs)
|
|
nouns = sorted(set(_CORE_NOUNS) | n_specs)
|
|
adjs = sorted(set(_CORE_ADJS) | a_specs)
|
|
|
|
lines = []
|
|
lines.append("// gen'd parity checks — Python oracle embedded, El functions called.")
|
|
lines.append("fn es_check(cat: String, lemma: String, got: String, exp: String) {")
|
|
lines.append(' if str_eq(got, exp) {')
|
|
lines.append(' println("PASS " + cat)')
|
|
lines.append(' } else {')
|
|
lines.append(' println("FAIL " + cat + " " + lemma + " got=" + got + " exp=" + exp)')
|
|
lines.append(' }')
|
|
lines.append("}")
|
|
lines.append("")
|
|
lines.append("fn es_parity() {")
|
|
|
|
# verbs
|
|
for v in verbs:
|
|
p0 = M.conjugate(v, "ind", "present", "third", "singular")[0]
|
|
p1 = M.conjugate(v, "ind", "preterite", "third", "singular")[0]
|
|
pp = M.participle(v)[0]
|
|
lines.append(_check("Vpres", v, f'es_conjugate("{_esc(v)}", "present", "third", "singular")', p0))
|
|
lines.append(_check("Vpret", v, f'es_conjugate("{_esc(v)}", "past", "third", "singular")', p1))
|
|
lines.append(_check("Vpart", v, f'es_participle("{_esc(v)}")', pp))
|
|
|
|
# nouns
|
|
for n in nouns:
|
|
pl = M.inflect_noun(n, "plural")[0]
|
|
g = M.noun_gender(n) # REAL lexicon gender
|
|
art = R._article(g, "singular", "def", n) # oracle article from real gender
|
|
lines.append(_check("Npl", n, f'es_pluralize("{_esc(n)}")', pl))
|
|
lines.append(_check("Gheur", n, f'es_gender("{_esc(n)}")', g))
|
|
lines.append(_check("Aheur", n, f'es_agree_article("{_esc(n)}", "true", "singular")', art))
|
|
lines.append(_check("Avocab", n, f'es_article_for_gender("{_esc(g)}", "{_esc(n)}", "true", "singular")', art))
|
|
|
|
# adjectives
|
|
for a in adjs:
|
|
mpl = M.inflect_adj(a, "m", "plural")[0]
|
|
fsg = M.inflect_adj(a, "f", "singular")[0]
|
|
lines.append(_check("Ampl", a, f'es_inflect_adj("{_esc(a)}", "m", "plural")', mpl))
|
|
lines.append(_check("Afsg", a, f'es_inflect_adj("{_esc(a)}", "f", "singular")', fsg))
|
|
|
|
# contractions (mandatory)
|
|
ctr_cases = [("de", "el día"), ("a", "el hombre"), ("de", "el mundo"),
|
|
("a", "el país"), ("en", "el mar"), ("de", "el año"),
|
|
("a", "la casa"), ("de", "la ciudad")]
|
|
for prep, np in ctr_cases:
|
|
exp = R._contract(prep, np)
|
|
lines.append(_check("Ctr", prep + "+" + np, f'es_contract("{_esc(prep)}", "{_esc(np)}")', exp))
|
|
|
|
lines.append("}")
|
|
lines.append("")
|
|
lines.append("fn main() {")
|
|
lines.append(" es_parity()")
|
|
lines.append("}")
|
|
|
|
with open(out_path, "w", encoding="utf-8") as fh:
|
|
fh.write("\n".join(lines) + "\n")
|
|
print(f"wrote {out_path} ({len(verbs)} verbs, {len(nouns)} nouns, {len(adjs)} adjs)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
main(sys.argv[1] if len(sys.argv) > 1 else "parity_es_checks.el")
|