Add native El NLG system: morphology, vocabulary, grammar, realizer

Implements a complete natural language generation stack in El:
- morphology.el: English pluralization, verb conjugation (40+ irregulars), determiner agreement
- vocabulary.el: inline seed lexicon (~100 entries: pronouns, nouns, verbs, adjectives, etc.)
- grammar.el: CFG rules (S/NP/VP/PP), slot-map driven tree generator, s-expression renderer
- realizer.el: semantic form -> English text with tense/aspect/agreement, do-support for questions
- nlg.el: JSON-driven public API tying all modules together
- tests/run.sh: acceptance corpus runner (6 tests, all passing)
This commit is contained in:
Will Anderson
2026-05-02 14:16:23 -05:00
commit 1432c56cf7
13 changed files with 1956 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
// basic-sentence.el - Realize "I see the cat."
//
// SemanticForm: assert, agent=I, predicate=see, patient=the cat, present simple.
fn run_test() -> String {
let form: [String] = native_list_empty()
let form = native_list_append(form, "intent")
let form = native_list_append(form, "assert")
let form = native_list_append(form, "agent")
let form = native_list_append(form, "I")
let form = native_list_append(form, "predicate")
let form = native_list_append(form, "see")
let form = native_list_append(form, "patient")
let form = native_list_append(form, "the cat")
let form = native_list_append(form, "location")
let form = native_list_append(form, "")
let form = native_list_append(form, "tense")
let form = native_list_append(form, "present")
let form = native_list_append(form, "aspect")
let form = native_list_append(form, "simple")
return realize(form)
}
println(run_test())
+24
View File
@@ -0,0 +1,24 @@
// command.el - Realize "Go home."
//
// SemanticForm: command, predicate=go, location=home.
fn run_test() -> String {
let form: [String] = native_list_empty()
let form = native_list_append(form, "intent")
let form = native_list_append(form, "command")
let form = native_list_append(form, "agent")
let form = native_list_append(form, "")
let form = native_list_append(form, "predicate")
let form = native_list_append(form, "go")
let form = native_list_append(form, "patient")
let form = native_list_append(form, "")
let form = native_list_append(form, "location")
let form = native_list_append(form, "home")
let form = native_list_append(form, "tense")
let form = native_list_append(form, "present")
let form = native_list_append(form, "aspect")
let form = native_list_append(form, "simple")
return realize(form)
}
println(run_test())
+24
View File
@@ -0,0 +1,24 @@
// past-tense.el - Realize "She ran in the park."
//
// SemanticForm: assert, agent=she, predicate=run, location=in the park, past simple.
fn run_test() -> String {
let form: [String] = native_list_empty()
let form = native_list_append(form, "intent")
let form = native_list_append(form, "assert")
let form = native_list_append(form, "agent")
let form = native_list_append(form, "she")
let form = native_list_append(form, "predicate")
let form = native_list_append(form, "run")
let form = native_list_append(form, "patient")
let form = native_list_append(form, "")
let form = native_list_append(form, "location")
let form = native_list_append(form, "in the park")
let form = native_list_append(form, "tense")
let form = native_list_append(form, "past")
let form = native_list_append(form, "aspect")
let form = native_list_append(form, "simple")
return realize(form)
}
println(run_test())
+16
View File
@@ -0,0 +1,16 @@
// plural-noun.el - Test noun pluralization.
//
// Expected: "cats|children|boxes|cities|fish|leaves"
fn run_test() -> String {
let r: [String] = native_list_empty()
let r = native_list_append(r, pluralize("cat"))
let r = native_list_append(r, pluralize("child"))
let r = native_list_append(r, pluralize("box"))
let r = native_list_append(r, pluralize("city"))
let r = native_list_append(r, pluralize("fish"))
let r = native_list_append(r, pluralize("leaf"))
return str_join(r, "|")
}
println(run_test())
+24
View File
@@ -0,0 +1,24 @@
// question.el - Realize "Do you see the dog?"
//
// SemanticForm: question, agent=you, predicate=see, patient=the dog, present simple.
fn run_test() -> String {
let form: [String] = native_list_empty()
let form = native_list_append(form, "intent")
let form = native_list_append(form, "question")
let form = native_list_append(form, "agent")
let form = native_list_append(form, "you")
let form = native_list_append(form, "predicate")
let form = native_list_append(form, "see")
let form = native_list_append(form, "patient")
let form = native_list_append(form, "the dog")
let form = native_list_append(form, "location")
let form = native_list_append(form, "")
let form = native_list_append(form, "tense")
let form = native_list_append(form, "present")
let form = native_list_append(form, "aspect")
let form = native_list_append(form, "simple")
return realize(form)
}
println(run_test())
+15
View File
@@ -0,0 +1,15 @@
// verb-conjugation.el - Test verb conjugation.
//
// Expected: "ran|walked|is|am|sleeping"
fn run_test() -> String {
let r: [String] = native_list_empty()
let r = native_list_append(r, verb_form("run", "past", "third", "singular"))
let r = native_list_append(r, verb_form("walk", "past", "third", "singular"))
let r = native_list_append(r, verb_form("be", "present", "third", "singular"))
let r = native_list_append(r, verb_form("be", "present", "first", "singular"))
let r = native_list_append(r, verb_form("sleep","progressive","third","singular"))
return str_join(r, "|")
}
println(run_test())