feat: port arbor, dharma, forge El source into monorepo
Brings the remaining foundation repos that were not included in the original monorepo consolidation: - arbor/vessels/ — 6 vessels (arbor-cli, arbor-core, arbor-diagram, arbor-layout, arbor-parse, arbor-render) with manifests + src/main.el - dharma/ — CGI Provenance Registry package (flat layout, 14 .el files across registry/, sandbox/, training/, validation/, tests/) - forge/ — consciousness channel tool (8 src .el files + new manifest.el) - elp/src/ — 36 test fixture files not carried over in original merge (dedup_*, realizer_*, semantics_*, morph_*, ext_*, one_extern_* helpers) el-ide, engram, elql are already complete in ide/, engram/, ql/.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
import "language-profile.el"
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
import "dedup_test_a_nodedup.el"
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
extern fn fn_a(x: String) -> String
|
||||
@@ -0,0 +1 @@
|
||||
extern fn fn_a(x: String) -> String
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
extern fn fn_a(x: String) -> String
|
||||
@@ -0,0 +1,6 @@
|
||||
import "language-profile.el"
|
||||
import "dedup_test_a.el"
|
||||
|
||||
fn main_fn(x: String) -> String {
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
import "dedup_test_a.el"
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
import "dedup_test_a_notail.el"
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
extern fn fn_a(x: String) -> String
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
extern fn fn_b(x: String) -> String
|
||||
@@ -0,0 +1,761 @@
|
||||
// big language-profile for testing
|
||||
fn lang_profile_big0(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big0(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big0("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big1(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big1(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big1("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big2(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big2(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big2("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big3(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big3(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big3("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big4(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big4(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big4("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big5(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big5(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big5("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big6(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big6(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big6("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big7(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big7(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big7("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big8(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big8(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big8("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big9(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big9(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big9("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big10(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big10(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big10("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big11(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big11(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big11("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big12(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big12(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big12("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big13(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big13(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big13("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big14(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big14(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big14("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big15(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big15(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big15("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big16(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big16(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big16("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big17(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big17(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big17("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big18(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big18(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big18("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
fn lang_profile_big19(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "code")
|
||||
let r = native_list_append(r, code)
|
||||
let r = native_list_append(r, "word_order")
|
||||
let r = native_list_append(r, word_order)
|
||||
let r = native_list_append(r, "morph_type")
|
||||
let r = native_list_append(r, morph_type)
|
||||
let r = native_list_append(r, "has_case")
|
||||
let r = native_list_append(r, has_case)
|
||||
let r = native_list_append(r, "has_gender")
|
||||
let r = native_list_append(r, has_gender)
|
||||
let r = native_list_append(r, "script_dir")
|
||||
let r = native_list_append(r, script_dir)
|
||||
let r = native_list_append(r, "agreement")
|
||||
let r = native_list_append(r, agreement)
|
||||
let r = native_list_append(r, "null_subject")
|
||||
let r = native_list_append(r, null_subject)
|
||||
return r
|
||||
}
|
||||
|
||||
fn lang_get_big19(profile: [String], key: String) -> String {
|
||||
let n: Int = native_list_len(profile)
|
||||
let i: Int = 0
|
||||
while i < n - 1 {
|
||||
let k: String = native_list_get(profile, i)
|
||||
if str_eq(k, key) {
|
||||
return native_list_get(profile, i + 1)
|
||||
}
|
||||
let i = i + 2
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fn lang_profile_en() -> [String] {
|
||||
return lang_profile_big19("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import "language-profile.el"
|
||||
|
||||
extern fn es_pluralize(noun: String) -> String
|
||||
extern fn es_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn fr_pluralize(noun: String) -> String
|
||||
extern fn fr_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn de_noun_plural(noun: String, gender: String) -> String
|
||||
extern fn de_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn ru_noun_case(noun: String, gender: String, gram_case: String, number: String) -> String
|
||||
extern fn ru_conjugate(verb: String, tense: String, person: String, number: String, gender: String) -> String
|
||||
extern fn ja_conjugate(dict_form: String, form: String) -> String
|
||||
extern fn fi_apply_case(noun: String, gram_case: String, number: String) -> String
|
||||
extern fn fi_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn ar_sound_plural(noun: String, gender: String) -> String
|
||||
extern fn ar_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
|
||||
extern fn hi_noun_direct(noun: String, gender: String, number: String) -> String
|
||||
extern fn hi_gender(noun: String) -> String
|
||||
extern fn hi_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
|
||||
extern fn sw_noun_plural(noun: String) -> String
|
||||
extern fn sw_conjugate(verb: String, person: String, number: String, noun_class: String, tense: String) -> String
|
||||
extern fn la_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn he_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
|
||||
extern fn grc_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn ang_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn sa_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn got_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn non_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn enm_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn pi_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn fro_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn goh_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn sga_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn txb_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn peo_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn akk_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn uga_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn egy_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn sux_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn gez_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
extern fn cop_conjugate(verb: String, tense: String, person: String, number: String) -> String
|
||||
@@ -0,0 +1,3 @@
|
||||
fn morph_tiny(x: String) -> String {
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import "language-profile.el"
|
||||
extern fn es_pluralize(noun: String) -> String
|
||||
@@ -0,0 +1 @@
|
||||
extern fn es_pluralize(noun: String) -> String
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "morph_externsonly.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "grammar.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "morphology.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "morph_tiny.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "test_empty_gram.el"
|
||||
import "test_empty_gram.el"
|
||||
import "test_empty_gram.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile-big.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "test_empty_gram.el"
|
||||
import "test_empty_gram.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "morphology.el"
|
||||
import "test_empty_gram.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "morphology.el"
|
||||
import "grammar.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "one_extern_nolp.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "one_extern.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "grammar.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "morphology.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "morphology.el"
|
||||
import "test_tiny_gram.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
// realizer.el - Universal syntactic realizer: GramSpec -> surface text.
|
||||
//
|
||||
// The realizer is now language-agnostic. It reads the "lang" field from the
|
||||
// GramSpec to resolve a language profile, then dispatches word order, question
|
||||
// formation, and morphology through the engine functions in grammar.el and
|
||||
// morphology.el.
|
||||
//
|
||||
// English remains the default (backward compatible) when no "lang" key is set.
|
||||
//
|
||||
// Realization pipeline per call:
|
||||
// 1. Extract lang code -> resolve profile
|
||||
// 2. Extract agent, predicate, patient, location, tense, aspect, intent
|
||||
// 3. Compute person/number from agent (English heuristic; other languages TBD)
|
||||
// 4. Build VP: morph_conjugate with profile -> get verb and auxiliary surface
|
||||
// 5. Choose question strategy from gram_question_strategy(profile)
|
||||
// 6. Order constituents via gram_order_constituents(subj, verb, obj, profile)
|
||||
// 7. Capitalize and terminate
|
||||
//
|
||||
// Depends on: morphology (morph_conjugate, agree_determiner)
|
||||
// grammar (gram_order_constituents, gram_question_strategy,
|
||||
// gram_build_vp, build_np, build_pp, slots_get)
|
||||
// language-profile (lang_from_code, lang_get, ...)
|
||||
import "language-profile.el"
|
||||
import "ext_a.el"
|
||||
import "ext_b.el"
|
||||
|
||||
// ── Agent agreement analysis ──────────────────────────────────────────────────
|
||||
//
|
||||
// Person and number are inferred from English pronouns. For other languages
|
||||
// the grammatical person/number should come from the Engram vocabulary node
|
||||
// for the subject; here we use a heuristic that is correct for English and
|
||||
// passable for languages where the same pronoun strings are used.
|
||||
|
||||
fn agent_person(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "first" }
|
||||
if str_eq(agent, "me") { return "first" }
|
||||
if str_eq(agent, "we") { return "first" }
|
||||
if str_eq(agent, "us") { return "first" }
|
||||
if str_eq(agent, "you") { return "second" }
|
||||
return "third"
|
||||
}
|
||||
|
||||
fn agent_number(agent: String) -> String {
|
||||
if str_eq(agent, "I") { return "singular" }
|
||||
if str_eq(agent, "me") { return "singular" }
|
||||
if str_eq(agent, "he") { return "singular" }
|
||||
if str_eq(agent, "him") { return "singular" }
|
||||
if str_eq(agent, "she") { return "singular" }
|
||||
if str_eq(agent, "her") { return "singular" }
|
||||
if str_eq(agent, "it") { return "singular" }
|
||||
if str_eq(agent, "you") { return "singular" }
|
||||
if str_eq(agent, "we") { return "plural" }
|
||||
if str_eq(agent, "us") { return "plural" }
|
||||
if str_eq(agent, "they") { return "plural" }
|
||||
if str_eq(agent, "them") { return "plural" }
|
||||
return "singular"
|
||||
}
|
||||
|
||||
// ── NP realization ────────────────────────────────────────────────────────────
|
||||
|
||||
fn realize_np(referent: String, number: String) -> String {
|
||||
return referent
|
||||
}
|
||||
|
||||
// ── VP realization ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Returns [main_verb_surface, aux_surface_or_empty].
|
||||
// Delegates conjugation to morph_conjugate with the language profile.
|
||||
|
||||
fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: [String]) -> [String] {
|
||||
let empty_aux: String = ""
|
||||
|
||||
if str_eq(tense, "future") {
|
||||
// Future: modal "will" + base (English) or language-specific future marker.
|
||||
// For isolating/agglutinative languages the future marker is also the
|
||||
// base form (morph_conjugate returns base); the surface "will" only appears
|
||||
// for English because morph_conjugate("be", "future", ..., en_profile) = "will be".
|
||||
let code: String = lang_get(profile, "code")
|
||||
if str_eq(code, "en") {
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, base_verb)
|
||||
let result = native_list_append(result, "will")
|
||||
return result
|
||||
}
|
||||
// Other languages: conjugate normally (engine returns base form for
|
||||
// languages without loaded Engram suffix data).
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "progressive") {
|
||||
let gerund: String = morph_conjugate(base_verb, "progressive", person, number, profile)
|
||||
let be_aux: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, gerund)
|
||||
let result = native_list_append(result, be_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let pp: String = morph_conjugate(base_verb, "perfect", person, number, profile)
|
||||
let have_form: String = morph_conjugate("have", tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, pp)
|
||||
let result = native_list_append(result, have_form)
|
||||
return result
|
||||
}
|
||||
|
||||
let surf: String = morph_conjugate(base_verb, tense, person, number, profile)
|
||||
let result: [String] = native_list_empty()
|
||||
let result = native_list_append(result, surf)
|
||||
let result = native_list_append(result, empty_aux)
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Question formation ────────────────────────────────────────────────────────
|
||||
//
|
||||
// Strategy is resolved from gram_question_strategy(profile):
|
||||
//
|
||||
// "do-support" (en) - insert conjugated "do" before subject; verb stays base.
|
||||
// "particle" (ja, hi, fi) - statement order + sentence-final question particle.
|
||||
// "intonation" (zh, es, ar, ru, sw) - statement order + "?" punctuation only.
|
||||
// "inversion" (fr, de) - subject-verb inversion.
|
||||
|
||||
// realize_question_lang: build the question surface string for any language.
|
||||
// Returns the complete surface string (without final punctuation).
|
||||
|
||||
fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: [String]) -> String {
|
||||
let strategy: String = gram_question_strategy(profile)
|
||||
let code: String = lang_get(profile, "code")
|
||||
|
||||
// ── do-support (English) ──────────────────────────────────────────────────
|
||||
if str_eq(strategy, "do-support") {
|
||||
if str_eq(aspect, "progressive") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "progressive", person, number, profile)
|
||||
let gerund: String = native_list_get(vp_pair, 0)
|
||||
let be_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, gerund)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
if str_eq(aspect, "perfect") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, "perfect", person, number, profile)
|
||||
let pp: String = native_list_get(vp_pair, 0)
|
||||
let have_aux: String = native_list_get(vp_pair, 1)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, have_aux)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, pp)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// Simple: do-support
|
||||
if str_eq(predicate, "be") {
|
||||
let be_form: String = morph_conjugate("be", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, be_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
let do_form: String = morph_conjugate("do", tense, person, number, profile)
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, do_form)
|
||||
let parts = native_list_append(parts, agent)
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── particle (ja, hi, fi) ─────────────────────────────────────────────────
|
||||
// Build in statement order, then append the question particle.
|
||||
if str_eq(strategy, "particle") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
let loc_part: String = ""
|
||||
if !str_eq(location, "") {
|
||||
let loc_part = core + " " + location
|
||||
} else {
|
||||
let loc_part = core
|
||||
}
|
||||
// Language-specific question particles
|
||||
if str_eq(code, "ja") { return loc_part + " か" }
|
||||
if str_eq(code, "hi") { return loc_part + " क्या" }
|
||||
if str_eq(code, "fi") { return loc_part + "-ko" }
|
||||
return loc_part + "?"
|
||||
}
|
||||
|
||||
// ── inversion (fr, de) ────────────────────────────────────────────────────
|
||||
if str_eq(strategy, "inversion") {
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
// Inversion: Verb-Subject-Object order
|
||||
let parts: [String] = native_list_empty()
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, aux_s)
|
||||
} else {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
let parts = native_list_append(parts, agent)
|
||||
if !str_eq(aux_s, "") {
|
||||
let parts = native_list_append(parts, verb_s)
|
||||
}
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
return str_join(parts, " ")
|
||||
}
|
||||
|
||||
// ── intonation (zh, es, ar, ru, sw) — statement order, "?" added by caller ─
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_s: String = native_list_get(vp_pair, 0)
|
||||
let aux_s: String = native_list_get(vp_pair, 1)
|
||||
let vp_str: String = gram_build_vp(verb_s, aux_s, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
if !str_eq(location, "") {
|
||||
return core + " " + location
|
||||
}
|
||||
return core
|
||||
}
|
||||
|
||||
// ── Capitalization and punctuation ────────────────────────────────────────────
|
||||
|
||||
fn capitalize_first(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 {
|
||||
return s
|
||||
}
|
||||
let first: String = str_slice(s, 0, 1)
|
||||
let rest: String = str_slice(s, 1, n)
|
||||
return str_to_upper(first) + rest
|
||||
}
|
||||
|
||||
fn add_punct(s: String, intent: String) -> String {
|
||||
if str_eq(intent, "question") { return s + "?" }
|
||||
return s + "."
|
||||
}
|
||||
|
||||
// ── Main realization entry point ──────────────────────────────────────────────
|
||||
|
||||
fn realize_lang(form: [String], profile: [String]) -> String {
|
||||
let intent: String = slots_get(form, "intent")
|
||||
let agent: String = slots_get(form, "agent")
|
||||
let predicate: String = slots_get(form, "predicate")
|
||||
let patient: String = slots_get(form, "patient")
|
||||
let location: String = slots_get(form, "location")
|
||||
let tense_raw: String = slots_get(form, "tense")
|
||||
let aspect_raw: String= slots_get(form, "aspect")
|
||||
|
||||
let tense: String = tense_raw
|
||||
if str_eq(tense, "") { let tense = "present" }
|
||||
let aspect: String = aspect_raw
|
||||
if str_eq(aspect, "") { let aspect = "simple" }
|
||||
|
||||
let person: String = agent_person(agent)
|
||||
let number: String = agent_number(agent)
|
||||
|
||||
// ── Command (imperative) ──────────────────────────────────────────────────
|
||||
if str_eq(intent, "command") {
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, predicate)
|
||||
if !str_eq(patient, "") { let parts = native_list_append(parts, patient) }
|
||||
if !str_eq(location, "") { let parts = native_list_append(parts, location) }
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "command")
|
||||
}
|
||||
|
||||
// ── Question ──────────────────────────────────────────────────────────────
|
||||
if str_eq(intent, "question") {
|
||||
let surface: String = realize_question_lang(predicate, tense, aspect, person, number, agent, patient, location, profile)
|
||||
return add_punct(capitalize_first(surface), "question")
|
||||
}
|
||||
|
||||
// ── Assertion (declarative) ───────────────────────────────────────────────
|
||||
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
|
||||
let verb_surf: String = native_list_get(vp_pair, 0)
|
||||
let aux_surf: String = native_list_get(vp_pair, 1)
|
||||
|
||||
let vp_str: String = gram_build_vp(verb_surf, aux_surf, profile)
|
||||
let core: String = gram_order_constituents(agent, vp_str, patient, profile)
|
||||
|
||||
let parts: [String] = native_list_empty()
|
||||
let parts = native_list_append(parts, core)
|
||||
if !str_eq(location, "") {
|
||||
let parts = native_list_append(parts, location)
|
||||
}
|
||||
let sentence: String = str_join(parts, " ")
|
||||
return add_punct(capitalize_first(sentence), "assert")
|
||||
}
|
||||
|
||||
// realize: backward-compatible English entry point (original signature).
|
||||
fn realize(form: [String]) -> String {
|
||||
let lang_code: String = slots_get(form, "lang")
|
||||
if str_eq(lang_code, "") {
|
||||
return realize_lang(form, lang_default())
|
||||
}
|
||||
return realize_lang(form, lang_from_code(lang_code))
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// semantics.el - Semantic layer: SemFrame -> GramSpec (slot map for realizer).
|
||||
//
|
||||
// Bridges from intent/meaning representation to the grammar layer.
|
||||
// A SemFrame is a slot map ([String] key-value list) with these keys:
|
||||
//
|
||||
// "intent" - "assert" | "query" | "describe" | "greet"
|
||||
// "subject" - subject referent (pronoun or noun phrase)
|
||||
// "object" - object referent (optional, "" if absent)
|
||||
// "modifiers" - semicolon-separated modifier strings (e.g. "in the park;quickly")
|
||||
// "lang" - ISO 639-1 language code (optional, defaults to "en")
|
||||
//
|
||||
// sem_to_spec converts a SemFrame into a realizer slot map ready for realize().
|
||||
// sem_realize is the end-to-end shortcut: frame -> realized text.
|
||||
//
|
||||
// All existing function signatures are preserved; new *_lang variants add an
|
||||
// explicit lang_code parameter.
|
||||
//
|
||||
// Depends on: grammar (slots_*, realize), language-profile (lang_from_code)
|
||||
import "test_empty_gram.el"
|
||||
import "test_empty_gram.el"
|
||||
import "test_empty_gram.el"
|
||||
|
||||
// ── SemFrame constructors ─────────────────────────────────────────────────────
|
||||
|
||||
// Build a SemFrame with all four core fields. Language defaults to "en".
|
||||
fn sem_frame(intent: String, subject: String, obj: String, modifiers: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "intent")
|
||||
let r = native_list_append(r, intent)
|
||||
let r = native_list_append(r, "subject")
|
||||
let r = native_list_append(r, subject)
|
||||
let r = native_list_append(r, "object")
|
||||
let r = native_list_append(r, obj)
|
||||
let r = native_list_append(r, "modifiers")
|
||||
let r = native_list_append(r, modifiers)
|
||||
let r = native_list_append(r, "lang")
|
||||
let r = native_list_append(r, "en")
|
||||
return r
|
||||
}
|
||||
|
||||
// Build a SemFrame with an explicit language code.
|
||||
fn sem_frame_lang(intent: String, subject: String, obj: String, modifiers: String, lang_code: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "intent")
|
||||
let r = native_list_append(r, intent)
|
||||
let r = native_list_append(r, "subject")
|
||||
let r = native_list_append(r, subject)
|
||||
let r = native_list_append(r, "object")
|
||||
let r = native_list_append(r, obj)
|
||||
let r = native_list_append(r, "modifiers")
|
||||
let r = native_list_append(r, modifiers)
|
||||
let r = native_list_append(r, "lang")
|
||||
let r = native_list_append(r, lang_code)
|
||||
return r
|
||||
}
|
||||
|
||||
// Convenience: no object, no modifiers, English.
|
||||
fn sem_frame_simple(intent: String, subject: String) -> [String] {
|
||||
return sem_frame(intent, subject, "", "")
|
||||
}
|
||||
|
||||
// Convenience: with object, no modifiers, English.
|
||||
fn sem_frame_obj(intent: String, subject: String, obj: String) -> [String] {
|
||||
return sem_frame(intent, subject, obj, "")
|
||||
}
|
||||
|
||||
// ── SemFrame field accessors ──────────────────────────────────────────────────
|
||||
|
||||
fn sem_intent(frame: [String]) -> String {
|
||||
return slots_get(frame, "intent")
|
||||
}
|
||||
|
||||
fn sem_subject(frame: [String]) -> String {
|
||||
return slots_get(frame, "subject")
|
||||
}
|
||||
|
||||
fn sem_object(frame: [String]) -> String {
|
||||
return slots_get(frame, "object")
|
||||
}
|
||||
|
||||
fn sem_modifiers(frame: [String]) -> String {
|
||||
return slots_get(frame, "modifiers")
|
||||
}
|
||||
|
||||
fn sem_lang(frame: [String]) -> String {
|
||||
let code: String = slots_get(frame, "lang")
|
||||
if str_eq(code, "") {
|
||||
return "en"
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
// ── Modifier helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_first_modifier(mods: String) -> String {
|
||||
let n: Int = str_len(mods)
|
||||
if n == 0 {
|
||||
return ""
|
||||
}
|
||||
let i: Int = 0
|
||||
let running: Bool = true
|
||||
while running {
|
||||
if i >= n {
|
||||
let running = false
|
||||
} else {
|
||||
let c: String = str_slice(mods, i, i + 1)
|
||||
if str_eq(c, ";") {
|
||||
let running = false
|
||||
} else {
|
||||
let i = i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return str_slice(mods, 0, i)
|
||||
}
|
||||
|
||||
// ── Intent mapping ────────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_intent_to_realize(intent: String) -> String {
|
||||
if str_eq(intent, "assert") { return "assert" }
|
||||
if str_eq(intent, "query") { return "question" }
|
||||
if str_eq(intent, "describe") { return "assert" }
|
||||
if str_eq(intent, "greet") { return "greet" }
|
||||
return "assert"
|
||||
}
|
||||
|
||||
// ── sem_to_spec: SemFrame -> realizer slot map ────────────────────────────────
|
||||
//
|
||||
// The "lang" key from the SemFrame is forwarded into the GramSpec so that
|
||||
// realize() can resolve the correct language profile.
|
||||
|
||||
fn sem_to_spec(frame: [String]) -> [String] {
|
||||
let intent: String = sem_intent(frame)
|
||||
let subject: String = sem_subject(frame)
|
||||
let obj: String = sem_object(frame)
|
||||
let mods: String = sem_modifiers(frame)
|
||||
let lang_code: String = sem_lang(frame)
|
||||
let location: String = sem_first_modifier(mods)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "greet")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
if str_eq(intent, "describe") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "assert")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "be")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
let realize_intent: String = sem_intent_to_realize(intent)
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, realize_intent)
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
// ── sem_to_spec_full ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_to_spec_full(frame: [String], verb: String, tense: String, aspect: String) -> [String] {
|
||||
let intent: String = sem_intent(frame)
|
||||
let subject: String = sem_subject(frame)
|
||||
let obj: String = sem_object(frame)
|
||||
let mods: String = sem_modifiers(frame)
|
||||
let lang_code: String = sem_lang(frame)
|
||||
let location: String = sem_first_modifier(mods)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_to_spec(frame)
|
||||
}
|
||||
|
||||
if str_eq(intent, "describe") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "assert")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "be")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, tense)
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, aspect)
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
let realize_intent: String = sem_intent_to_realize(intent)
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, realize_intent)
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, verb)
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, tense)
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, aspect)
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
// ── Greet realization helper ──────────────────────────────────────────────────
|
||||
|
||||
fn sem_realize_greet(subject: String) -> String {
|
||||
if str_eq(subject, "") {
|
||||
return "Hello."
|
||||
}
|
||||
return "Hello, " + subject + "."
|
||||
}
|
||||
|
||||
// ── sem_realize: SemFrame -> text ─────────────────────────────────────────────
|
||||
|
||||
fn sem_realize(frame: [String]) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
let spec: [String] = sem_to_spec(frame)
|
||||
return realize(spec)
|
||||
}
|
||||
|
||||
// ── sem_realize_full ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_realize_full(frame: [String], verb: String, tense: String, aspect: String) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
let spec: [String] = sem_to_spec_full(frame, verb, tense, aspect)
|
||||
return realize(spec)
|
||||
}
|
||||
|
||||
// ── sem_realize_lang: realize in an explicitly specified language ──────────────
|
||||
//
|
||||
// Convenience for callers that want to specify the output language without
|
||||
// constructing a full SemFrame. The lang_code overrides whatever "lang" is
|
||||
// set in the frame.
|
||||
|
||||
fn sem_realize_lang(frame: [String], lang_code: String) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
// Inject the lang_code into the frame before converting to spec.
|
||||
let patched: [String] = slots_set(frame, "lang", lang_code)
|
||||
let spec: [String] = sem_to_spec(patched)
|
||||
return realize(spec)
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
// semantics.el - Semantic layer: SemFrame -> GramSpec (slot map for realizer).
|
||||
//
|
||||
// Bridges from intent/meaning representation to the grammar layer.
|
||||
// A SemFrame is a slot map ([String] key-value list) with these keys:
|
||||
//
|
||||
// "intent" - "assert" | "query" | "describe" | "greet"
|
||||
// "subject" - subject referent (pronoun or noun phrase)
|
||||
// "object" - object referent (optional, "" if absent)
|
||||
// "modifiers" - semicolon-separated modifier strings (e.g. "in the park;quickly")
|
||||
// "lang" - ISO 639-1 language code (optional, defaults to "en")
|
||||
//
|
||||
// sem_to_spec converts a SemFrame into a realizer slot map ready for realize().
|
||||
// sem_realize is the end-to-end shortcut: frame -> realized text.
|
||||
//
|
||||
// All existing function signatures are preserved; new *_lang variants add an
|
||||
// explicit lang_code parameter.
|
||||
//
|
||||
// Depends on: grammar (slots_*, realize), language-profile (lang_from_code)
|
||||
|
||||
// ── SemFrame constructors ─────────────────────────────────────────────────────
|
||||
|
||||
// Build a SemFrame with all four core fields. Language defaults to "en".
|
||||
fn sem_frame(intent: String, subject: String, obj: String, modifiers: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "intent")
|
||||
let r = native_list_append(r, intent)
|
||||
let r = native_list_append(r, "subject")
|
||||
let r = native_list_append(r, subject)
|
||||
let r = native_list_append(r, "object")
|
||||
let r = native_list_append(r, obj)
|
||||
let r = native_list_append(r, "modifiers")
|
||||
let r = native_list_append(r, modifiers)
|
||||
let r = native_list_append(r, "lang")
|
||||
let r = native_list_append(r, "en")
|
||||
return r
|
||||
}
|
||||
|
||||
// Build a SemFrame with an explicit language code.
|
||||
fn sem_frame_lang(intent: String, subject: String, obj: String, modifiers: String, lang_code: String) -> [String] {
|
||||
let r: [String] = native_list_empty()
|
||||
let r = native_list_append(r, "intent")
|
||||
let r = native_list_append(r, intent)
|
||||
let r = native_list_append(r, "subject")
|
||||
let r = native_list_append(r, subject)
|
||||
let r = native_list_append(r, "object")
|
||||
let r = native_list_append(r, obj)
|
||||
let r = native_list_append(r, "modifiers")
|
||||
let r = native_list_append(r, modifiers)
|
||||
let r = native_list_append(r, "lang")
|
||||
let r = native_list_append(r, lang_code)
|
||||
return r
|
||||
}
|
||||
|
||||
// Convenience: no object, no modifiers, English.
|
||||
fn sem_frame_simple(intent: String, subject: String) -> [String] {
|
||||
return sem_frame(intent, subject, "", "")
|
||||
}
|
||||
|
||||
// Convenience: with object, no modifiers, English.
|
||||
fn sem_frame_obj(intent: String, subject: String, obj: String) -> [String] {
|
||||
return sem_frame(intent, subject, obj, "")
|
||||
}
|
||||
|
||||
// ── SemFrame field accessors ──────────────────────────────────────────────────
|
||||
|
||||
fn sem_intent(frame: [String]) -> String {
|
||||
return slots_get(frame, "intent")
|
||||
}
|
||||
|
||||
fn sem_subject(frame: [String]) -> String {
|
||||
return slots_get(frame, "subject")
|
||||
}
|
||||
|
||||
fn sem_object(frame: [String]) -> String {
|
||||
return slots_get(frame, "object")
|
||||
}
|
||||
|
||||
fn sem_modifiers(frame: [String]) -> String {
|
||||
return slots_get(frame, "modifiers")
|
||||
}
|
||||
|
||||
fn sem_lang(frame: [String]) -> String {
|
||||
let code: String = slots_get(frame, "lang")
|
||||
if str_eq(code, "") {
|
||||
return "en"
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
// ── Modifier helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_first_modifier(mods: String) -> String {
|
||||
let n: Int = str_len(mods)
|
||||
if n == 0 {
|
||||
return ""
|
||||
}
|
||||
let i: Int = 0
|
||||
let running: Bool = true
|
||||
while running {
|
||||
if i >= n {
|
||||
let running = false
|
||||
} else {
|
||||
let c: String = str_slice(mods, i, i + 1)
|
||||
if str_eq(c, ";") {
|
||||
let running = false
|
||||
} else {
|
||||
let i = i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return str_slice(mods, 0, i)
|
||||
}
|
||||
|
||||
// ── Intent mapping ────────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_intent_to_realize(intent: String) -> String {
|
||||
if str_eq(intent, "assert") { return "assert" }
|
||||
if str_eq(intent, "query") { return "question" }
|
||||
if str_eq(intent, "describe") { return "assert" }
|
||||
if str_eq(intent, "greet") { return "greet" }
|
||||
return "assert"
|
||||
}
|
||||
|
||||
// ── sem_to_spec: SemFrame -> realizer slot map ────────────────────────────────
|
||||
//
|
||||
// The "lang" key from the SemFrame is forwarded into the GramSpec so that
|
||||
// realize() can resolve the correct language profile.
|
||||
|
||||
fn sem_to_spec(frame: [String]) -> [String] {
|
||||
let intent: String = sem_intent(frame)
|
||||
let subject: String = sem_subject(frame)
|
||||
let obj: String = sem_object(frame)
|
||||
let mods: String = sem_modifiers(frame)
|
||||
let lang_code: String = sem_lang(frame)
|
||||
let location: String = sem_first_modifier(mods)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "greet")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
if str_eq(intent, "describe") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "assert")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "be")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
let realize_intent: String = sem_intent_to_realize(intent)
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, realize_intent)
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, "")
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, "present")
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, "simple")
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
// ── sem_to_spec_full ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_to_spec_full(frame: [String], verb: String, tense: String, aspect: String) -> [String] {
|
||||
let intent: String = sem_intent(frame)
|
||||
let subject: String = sem_subject(frame)
|
||||
let obj: String = sem_object(frame)
|
||||
let mods: String = sem_modifiers(frame)
|
||||
let lang_code: String = sem_lang(frame)
|
||||
let location: String = sem_first_modifier(mods)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_to_spec(frame)
|
||||
}
|
||||
|
||||
if str_eq(intent, "describe") {
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, "assert")
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, "be")
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, tense)
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, aspect)
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
let realize_intent: String = sem_intent_to_realize(intent)
|
||||
let spec: [String] = native_list_empty()
|
||||
let spec = native_list_append(spec, "intent")
|
||||
let spec = native_list_append(spec, realize_intent)
|
||||
let spec = native_list_append(spec, "agent")
|
||||
let spec = native_list_append(spec, subject)
|
||||
let spec = native_list_append(spec, "predicate")
|
||||
let spec = native_list_append(spec, verb)
|
||||
let spec = native_list_append(spec, "patient")
|
||||
let spec = native_list_append(spec, obj)
|
||||
let spec = native_list_append(spec, "location")
|
||||
let spec = native_list_append(spec, location)
|
||||
let spec = native_list_append(spec, "tense")
|
||||
let spec = native_list_append(spec, tense)
|
||||
let spec = native_list_append(spec, "aspect")
|
||||
let spec = native_list_append(spec, aspect)
|
||||
let spec = native_list_append(spec, "lang")
|
||||
let spec = native_list_append(spec, lang_code)
|
||||
return spec
|
||||
}
|
||||
|
||||
// ── Greet realization helper ──────────────────────────────────────────────────
|
||||
|
||||
fn sem_realize_greet(subject: String) -> String {
|
||||
if str_eq(subject, "") {
|
||||
return "Hello."
|
||||
}
|
||||
return "Hello, " + subject + "."
|
||||
}
|
||||
|
||||
// ── sem_realize: SemFrame -> text ─────────────────────────────────────────────
|
||||
|
||||
fn sem_realize(frame: [String]) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
let spec: [String] = sem_to_spec(frame)
|
||||
return realize(spec)
|
||||
}
|
||||
|
||||
// ── sem_realize_full ──────────────────────────────────────────────────────────
|
||||
|
||||
fn sem_realize_full(frame: [String], verb: String, tense: String, aspect: String) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
let spec: [String] = sem_to_spec_full(frame, verb, tense, aspect)
|
||||
return realize(spec)
|
||||
}
|
||||
|
||||
// ── sem_realize_lang: realize in an explicitly specified language ──────────────
|
||||
//
|
||||
// Convenience for callers that want to specify the output language without
|
||||
// constructing a full SemFrame. The lang_code overrides whatever "lang" is
|
||||
// set in the frame.
|
||||
|
||||
fn sem_realize_lang(frame: [String], lang_code: String) -> String {
|
||||
let intent: String = sem_intent(frame)
|
||||
|
||||
if str_eq(intent, "greet") {
|
||||
return sem_realize_greet(sem_subject(frame))
|
||||
}
|
||||
|
||||
// Inject the lang_code into the frame before converting to spec.
|
||||
let patched: [String] = slots_set(frame, "lang", lang_code)
|
||||
let spec: [String] = sem_to_spec(patched)
|
||||
return realize(spec)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fn gram_fn(x: String) -> String {
|
||||
return x
|
||||
}
|
||||
Reference in New Issue
Block a user