diff --git a/.vscode/sn.code-snippets b/.vscode/sn.code-snippets new file mode 100644 index 0000000..997e70b --- /dev/null +++ b/.vscode/sn.code-snippets @@ -0,0 +1,52 @@ +{ + "PS Sententce": { + "prefix": "pssentence", + "body": [ + "{", + "\tp: \"$1\",", + "\tf: \"$2\",", + "\te: \"$3\",", + "}" + ], + }, + "PS String": { + "prefix": "psstring", + "body": "{ p: \"$1\", f: \"$2\" }", + }, + "InlinePs": { + "prefix": "inlineps", + "body": "", + }, + "EditableVPEx": { + "prefix": "editablevpex", + "body": [ + "{", + "\t$1", + "}" + ] + }, + "EditableEPEx": { + "prefix": "editableepex", + "body": [ + "{", + "\t$1", + "}" + ] + }, + "Examples": { + "prefix": "examples", + "body": [ + "{[", + "\t{", + "\t\tp: \"$1\",", + "\t\tf: \"$2\",", + "\t\te: \"$3\",", + "\t},", + "]}", + ], + }, + "Link": { + "prefix": "link", + "body": "$2", + } +} \ No newline at end of file diff --git a/src/lib/src/accent-helpers.ts b/src/lib/src/accent-helpers.ts index 008539d..2c146f3 100644 --- a/src/lib/src/accent-helpers.ts +++ b/src/lib/src/accent-helpers.ts @@ -27,7 +27,7 @@ export function accentOnFront(s: T.SingleOrLengthOpts): T.SingleOrLe } return { ...s, - f: accentSyllable(removeAccents(s.f)), + f: accentLetter(removeAccents(s.f)), }; } @@ -78,7 +78,7 @@ export function accentFSylsOnNFromEnd(syls: string[] | string, n: number): strin } return [ ...syls.slice(0, syls.length-(n+1)), // before accent - accentSyllable(syls[syls.length-(n+1)]), // syllable to be accented + accentLetter(syls[syls.length-(n+1)]), // syllable to be accented ...(n !== 0) ? syls.slice(syls.length-n) : [], // after syllable to be accented ].join(""); } @@ -104,7 +104,7 @@ const accentReplacer = [ { vowel: "U", accented: "Ú" }, ]; -export function accentSyllable(s: string): string { +export function accentLetter(s: string): string { return s.replace(/a|e|i|o|u|U/, (match) => { const r = accentReplacer.find((x) => x.vowel === match); /* istanbul ignore next */ @@ -115,7 +115,7 @@ export function accentSyllable(s: string): string { export function accentPsSyllable(ps: T.PsString): T.PsString { return { p: ps.p, - f: accentSyllable(ps.f), + f: accentLetter(ps.f), }; } diff --git a/src/lib/src/new-verb-engine/roots-and-stems.test.ts b/src/lib/src/new-verb-engine/roots-and-stems.test.ts index 299c9ff..154d4b5 100644 --- a/src/lib/src/new-verb-engine/roots-and-stems.test.ts +++ b/src/lib/src/new-verb-engine/roots-and-stems.test.ts @@ -1,7 +1,6 @@ import * as T from "../../../types"; -import { getPastParticiple } from "./roots-and-stems"; +import { getPastParticiple, getRootStem } from "./roots-and-stems"; import { vEntry } from "./rs-helpers"; -import { getAllRs } from "./rs-helpers"; const wahul = vEntry({"ts":1527815399,"i":15049,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","r":4,"c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"}); const achawul = vEntry({"ts":1527811872,"i":224,"p":"اچول","f":"achawul","g":"achawul","e":"to put, pour, drop, throw, put on","r":4,"c":"v. trans.","ec":"put,puts,putting,put,put"}); @@ -26,6 +25,719 @@ const kenaastul = vEntry({"ts":1527812759,"i":11124,"p":"کېناستل","f":"ke const ghadzedul = vEntry({"ts":1527812615,"i":9500,"p":"غځېدل","f":"ghadzedul","g":"ghadzedul","e":"stretch out, lie, be extended, expand","r":3,"c":"v. intrans.","ec":"stretch","ep":"out"}); const prexodul = vEntry({"ts":1527815190,"i":2495,"p":"پرېښودل","f":"prexodúl","g":"prexodul","e":"to leave, abandon, forsake, let go, allow","r":4,"c":"v. trans.","psp":"پرېږد","psf":"preGd","noOo":true,"separationAtP":3,"separationAtF":3,"ec":"abandon"}); const raawustul = vEntry({"ts":1527819827,"i":6955,"p":"راوستل","f":"raawustúl","g":"raawustul","e":"to bring, deliver (animate objects), obtain, extract","r":3,"c":"v. trans.","psp":"راول","psf":"raawul","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"bring,brings,bringing,brought,brought"}); +const bandawul = vEntry( + {"ts":1527821309,"i":1792,"p":"بندول","f":"bandawul","g":"bandawul","e":"to close, block, stop, barricade, cut off, restrain, hold back","r":3,"c":"v. stat. comp. trans.","l":1577301753727,"ec":"close"}, + {"ts":1577301753727,"i":1780,"p":"بند","f":"band","g":"band","e":"closed, blocked, stopped","c":"adj."}, +); +const bandedul = vEntry( + {"ts":1588781671306,"i":1796,"p":"بندېدل","f":"bandedúl","g":"bandedul","e":"to be closed, blocked, stopped","r":4,"c":"v. stat. comp. intrans.","l":1577301753727,"ec":"be","ep":"closed"}, + {"ts":1577301753727,"i":1780,"p":"بند","f":"band","g":"band","e":"closed, blocked, stopped","c":"adj."}, +); +const stureyKawul = vEntry( + {"ts":1591033078746,"i":7877,"p":"ستړی کول","f":"stuRey kawul","g":"stuReykawul","e":"to make tired, wear out","r":4,"c":"v. stat. comp. trans.","l":1527815306,"ec":"make","ep":"tired"}, + {"ts":1527815306,"i":7876,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","r":4,"c":"adj. / adv."}, +); +const stureyKedul = vEntry( + {"ts":1591033069786,"i":7878,"p":"ستړی کېدل","f":"stuRey kedul","g":"stuReykedul","e":"to get tired, fatigued","r":4,"c":"v. stat. comp. intrans.","l":1527815306,"ec":"get","ep":"tired"}, + {"ts":1527815306,"i":7876,"p":"ستړی","f":"stúRey","g":"stuRey","e":"tired","r":4,"c":"adj. / adv."}, +); + +const ooPH: T.PH= { type: "PH", ps: { p: "و", f: "óo" }}; + +describe("imperfective stems", () => { + const tests: { + title: string, + tests: { + verb: T.VerbEntry, + genderNumber?: T.GenderNumber, + result: T.RootsStemsOutput, + }[], + }[] = [ + { + title: "is the shortened infinitive for regular verbs", + tests: [ + { + verb: ganul, + result: [[], [{ type: "VB", ps: [{ p: "ګڼ", f: "gaN" }]}]], + }, + { + verb: wahul, + result: [[], [{ type: "VB", ps: [{ p: "وه", f: "wah" }]}]], + }, + ], + }, + { + title: "is the -eG for for regular intransitive verbs", + tests: [ + { + verb: ghadzedul, + result: [[], [{ type: "VB", ps: [{ p: "غځېږ", f: "ghadzéG" }]}]], + }, + { + verb: rasedul, + result: [[], [{ + type: "VB", + ps: { + long: [{ p: "رسېږ", f: "raséG" }], + short: [{ p: "رس", f: "ras" }], + }, + }]], + }, + ], + }, + { + title: "is the special imperfective stem for irregular verbs with a special imperfective stem", + tests: [ + { + verb: khorul, + result: [[], [{ type: "VB", ps: [{ p: "خور", f: "khor" }]}]], + }, + { + verb: kexodul, + result: [[], [{ type: "VB", ps: [{ p: "ږد", f: "Gd" }] }]], + }, + ], + }, + { + title: "is the fused word for stative compounds that swallow the k", + tests: [ + { + verb: bandawul, + genderNumber: { gender: "masc", number: "singular" }, + result: [[], [{ type: "VB", ps: [{ p: "بندو", f: "bandawX" }]}]], + }, + { + verb: bandedul, + genderNumber: { gender: "masc", number: "singular" }, + result: [[], [{ type: "VB", ps: [{ p: "بندېږ", f: "bandéG" }]}]], + }, + ], + }, + { + title: "is welded together with the complement on seperated stative compounds", + tests: [ + { + verb: stureyKawul, + genderNumber: { gender: "fem", number: "singular" }, + result: [[], [{ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + number: "singular", + gender: "fem", + }, + }, + right: { + type: "VB", + ps: [{ p: "کو", f: "kawX" }], + }, + }]], + }, + { + verb: stureyKedul, + genderNumber: { gender: "fem", number: "singular" }, + result: [[], [{ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + number: "singular", + gender: "fem", + }, + }, + right: { + type: "VB", + ps: [{ p: "کېږ", f: "kéG" }], + }, + }]], + }, + ] + } + ]; + tests.forEach(x => { + test(x.title, () => { + x.tests.forEach(y => { + expect(getRootStem({ + verb: y.verb, + aspect: "imperfective", + type: "basic", + rs: "stem", + voice: "active", + genderNumber: y.genderNumber || { + gender: "masc", + number: "singular", + }, + })).toEqual(y.result); + }); + }) + }); +}); + +describe("imperfective roots", () => { + const tests: { + title: string, + tests: { + verb: T.VerbEntry, + genderNumber?: T.GenderNumber, + result: T.RootsStemsOutput, + }[], + }[] = [ + { + title: "is the infinitive with and without ل for regular verbs, with a trailing accent on the short form", + tests: [ + { + verb: wahul, + result: [[], [{ + type: "VB", + ps: { + long: [{ p: "وهل", f: "wahúl" }], + short: [{ p: "وه", f: "wahX" }], + }, + }] + ], + }, + ], + }, + { + title: "is the fused word for stative compounds that swallow the k", + tests: [ + { + verb: bandawul, + genderNumber: { gender: "masc", number: "singular" }, + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "بندول", f: "bandawúl" }], + short: [{ p: "بندو", f: "bandawX" }], + } + }, + ], + ], + }, + { + verb: bandedul, + genderNumber: { gender: "masc", number: "singular" }, + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "بندېدل", f: "bandedúl" }], + short: [{ p: "بندېد", f: "bandedX" }] + }, + }, + ], + ], + }, + ], + }, + { + title: "is welded together with the complement on seperated stative compounds", + tests: [ + { + verb: stureyKawul, + genderNumber: { gender: "fem", number: "singular" }, + result: [[], [{ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + number: "singular", + gender: "fem", + }, + }, + right: { + type: "VB", + ps: { + long: [{ p: "کول", f: "kawúl" }], + short: [{ p: "کو", f: "kawX" }], + }, + }, + }]], + }, + { + verb: stureyKedul, + genderNumber: { gender: "fem", number: "singular" }, + result: [[], [{ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړې", f: "stuRe" }, + number: "singular", + gender: "fem", + }, + }, + right: { + type: "VB", + ps: { + long: [{ p: "کېدل", f: "kedúl" }], + short: [{ p: "کېد", f: "kedX" }], + }, + }, + }]], + }, + ] + } + ]; + tests.forEach(x => { + test(x.title, () => { + x.tests.forEach(y => { + expect(getRootStem({ + verb: y.verb, + aspect: "imperfective", + type: "basic", + rs: "root", + voice: "active", + genderNumber: y.genderNumber || { + gender: "masc", + number: "singular", + }, + })).toEqual(y.result); + }); + }) + }); +}); + +describe("perfective stems", () => { + const tests: { + title: string, + tests: { + verb: T.VerbEntry, + genderNumber?: T.GenderNumber, + result: T.RootsStemsOutput, + }[], + }[] = [ + { + title: "is the imprefective stem with an oo- prefix for regular verbs", + tests: [ + { + verb: ganul, + result: [ + [ooPH], + [{ type: "VB", ps: [{ p: "ګڼ", f: "gaN" }]}], + ], + }, + { + verb: wahul, + result: [[ooPH], [{ type: "VB", ps: [{ p: "وه", f: "wah" }]}]], + }, + ], + }, + { + title: "the imperfective stem the perfective stem is regularly built off could be irregular", + tests: [ + { + verb: khorul, + result: [[ooPH], [{ type: "VB", ps: [{ p: "خور", f: "khor" }]}]], + }, + ], + }, + { + title: "is the irregular perfective stem if the entry has a ssp/ssf", + tests: [ + { + verb: wurul, + result: [ + [{ type: "PH", ps: { p: "یو", f: "yó" }}], + [{ type: "VB", ps: [{ p: "س", f: "s" }]}], + ], + } + ] + }, + { + title: "includes extra irregular short roots for kawul verbs", + tests: [ + { + verb: kawulDyn, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "کړ", f: "kR" }], + short: [{ p: "ک", f: "k" }], + }, + }, + ] + ], + }, + ], + }, + { + title: "doesn't have a perfective head for kawul stative", + tests: [ + { + verb: kawulStat, + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "کړ", f: "kR" }], + short: [{ p: "ک", f: "k" }], + }, + }, + ] + ], + }, + ], + }, + { + title: "irregular, inflecting stem for tlul", + tests: [ + { + verb: tlul, + genderNumber: { gender: "fem", number: "singular" }, + result: [ + [{ type: "PH", ps: { p: "لاړه ", f: "láaRa " }}], + [ + { type: "VB", ps: [{ p: "ش", f: "sh" }]}, + ], + ], + }, + { + verb: tlul, + genderNumber: { gender: "fem", number: "plural" }, + result: [ + [{ type: "PH", ps: { p: "لاړې ", f: "láaRe " }}], + [ + { type: "VB", ps: [{ p: "ش", f: "sh" }]}, + ], + ], + }, + { + verb: tlul, + genderNumber: { gender: "masc", number: "plural" }, + result: [ + [{ type: "PH", ps: { p: "لاړ ", f: "láaR " }}], + [ + { type: "VB", ps: [{ p: "ش", f: "sh" }]}, + ], + ], + }, + ], + }, + { + title: "broken apart with complement seperately in the perfective", + tests: [ + { + verb: bandawul, + genderNumber: { gender: "masc", number: "singular" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بند", f: "bánd" }, + gender: "masc", + number: "singular", + }, + }, + ], + [ + { + type: "VB", + ps: { + long: [{ p: "کړ", f: "kR" }], + short: [{ p: "ک", f: "k" }], + }, + }, + ], + ], + }, + { + verb: bandedul, + genderNumber: { gender: "fem", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بندې", f: "bánde" }, + gender: "fem", + number: "plural", + }, + }, + ], + [ + { + type: "VB", + ps: [{ p: "ش", f: "sh" }], + }, + ], + ], + }, + { + verb: stureyKedul, + genderNumber: { gender: "masc", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړي", f: "stúRee" }, + gender: "masc", + number: "plural", + }, + }, + ], + [ + { + type: "VB", + ps: [{ p: "ش", f: "sh" }], + }, + ], + ], + }, + ], + }, + ]; + tests.forEach(x => { + test(x.title, () => { + x.tests.forEach(y => { + expect(getRootStem({ + verb: y.verb, + aspect: "perfective", + type: "basic", + rs: "stem", + voice: "active", + genderNumber: y.genderNumber || { + gender: "masc", + number: "singular", + }, + })).toEqual(y.result); + }); + }) + }); +}); + +describe("perfective roots", () => { + const tests: { + title: string, + tests: { + verb: T.VerbEntry, + genderNumber?: T.GenderNumber, + result: T.RootsStemsOutput, + }[], + }[] = [ + { + title: "is the imprefective root with an oo- prefix for regular verbs", + tests: [ + { + verb: ganul, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "ګڼل", f: "gaNul" }], + short: [{ p: "ګڼ", f: "gaN" }], + }, + }, + ], + ], + }, + { + verb: wahul, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "وهل", f: "wahul" }], + short: [{ p: "وه", f: "wah" }], + }, + }, + ], + ], + }, + ], + }, + { + title: "is the irregular perfective root if the entry has a ssp/ssf", + tests: [ + { + verb: wurul, + result: [ + [{ type: "PH", ps: { p: "یو", f: "yó" }}], + [ + { + type: "VB", + ps: { + long: [{ p: "ړل", f: "Rul" }], + short: [{ p: "ړ", f: "R" }], + } + }, + ], + ], + }, + ], + }, + { + title: "includes extra irregular short roots for kawul verbs", + tests: [ + { + verb: kawulDyn, + result: [ + [ooPH], + [ + { + type: "VB", + ps: { + long: [{ p: "کړل", f: "kRul" }], + short: [{ p: "کړ", f: "kR" }], + mini: [{ p: "ک", f: "k" }], + }, + }, + ], + ], + }, + ], + }, + { + title: "doesn't have a perfective head for kawul stative", + tests: [ + { + verb: kawulStat, + result: [ + [], + [ + { + type: "VB", + ps: { + long: [{ p: "کړل", f: "kRul" }], + short: [{ p: "کړ", f: "kR" }], + mini: [{ p: "ک", f: "k" }], + }, + }, + ] + ], + }, + ], + }, + { + title: "broken apart with complement seperately in the perfective", + tests: [ + { + verb: bandawul, + genderNumber: { gender: "masc", number: "singular" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بند", f: "bánd" }, + gender: "masc", + number: "singular", + }, + }, + ], + [ + { + type: "VB", + ps: { + long: [{ p: "کړل", f: "kRul" }], + short: [{ p: "کړ", f: "kR" }], + mini: [{ p: "ک", f: "k" }], + }, + }, + ], + ], + }, + { + verb: bandedul, + genderNumber: { gender: "fem", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بندې", f: "bánde" }, + gender: "fem", + number: "plural", + }, + }, + ], + [ + { + type: "VB", + ps: { + long: [{ p: "شول", f: "shwul" }], + short: [{ p: "شو", f: "shw" }], + } + }, + ], + ], + }, + { + verb: stureyKedul, + genderNumber: { gender: "masc", number: "plural" }, + result: [ + [ + { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "ستړي", f: "stúRee" }, + gender: "masc", + number: "plural", + }, + }, + ], + [ + { + type: "VB", + ps: { + long: [{ p: "شول", f: "shwul" }], + short: [{ p: "شو", f: "shw" }], + } + }, + ], + ], + }, + ], + }, + ]; + tests.forEach(x => { + test(x.title, () => { + x.tests.forEach(y => { + expect(getRootStem({ + verb: y.verb, + aspect: "perfective", + type: "basic", + rs: "root", + voice: "active", + genderNumber: y.genderNumber || { + gender: "masc", + number: "singular", + }, + })).toEqual(y.result); + }); + }) + }); +}); describe("past participles", () => { test("for most verbs are just the imperfective root (imperative) plus ی - ey", () => { @@ -97,7 +809,19 @@ describe("past participles", () => { number: "plural", }); }); - test("kawul/kedul verbs have an irregular pprt fields that give us the irregular past participle", () => { + test("special short form with تلل - tlul", () => { + expect(getPastParticiple(tlul, "active", { gender: "masc", number: "plural" })) + .toEqual({ + type: "VB", + ps: { + long: [{ p: "تللي", f: "tlúlee" }], + short: [{ p: "تلي", f: "túlee" }], + }, + gender: "masc", + number: "plural", + }); + }); + test("kawul/kedul/raatlul verbs have an irregular pprt fields that give us the irregular past participle", () => { expect(getPastParticiple(kawulDyn, "active", { gender: "masc", number: "singular" })) .toEqual({ type: "VB", @@ -127,7 +851,118 @@ describe("past participles", () => { number: "plural", }); }); - + test("stative compounds weld the complement to the kawul/kedul participle", () => { + expect(getPastParticiple(bandawul, "active", { gender: "fem", number: "singular" })) + .toEqual({ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بنده", f: "banda" }, + gender: "fem", + number: "singular", + }, + }, + right: { + type: "VB", + ps: [{ p: "کړې", f: "kúRe" }], + gender: "fem", + number: "singular", + }, + }); + expect(getPastParticiple(bandedul, "active", { gender: "fem", number: "plural" })) + .toEqual({ + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بندې", f: "bande" }, + gender: "fem", + number: "plural", + }, + }, + right: { + type: "VB", + ps: [{ p: "شوې", f: "shúwe" }], + gender: "fem", + number: "plural", + }, + }); + }); + test("for passive with simple verbs, long perfective root welded to kedul participle", () => { + expect(getPastParticiple(ganul, "passive", { gender: "fem", number: "singular" })) + .toEqual({ + type: "welded", + left: { + type: "VB", + ps: [{ p: "ګڼل", f: "gaNul" }], + }, + right: { + type: "VB", + ps: [{ p: "شوې", f: "shúwe" }], + gender: "fem", + number: "singular", + }, + }); + }); + test("special passive forms for kawul verbs - kRul perfective root + shúwey", () => { + expect(getPastParticiple(kawulStat, "passive", { gender: "masc", number: "singular"})) + .toEqual({ + type: "welded", + left: { + type: "VB", + ps: [{ p: "کړل", f: "kRul" }], + }, + right: { + type: "VB", + ps: [{ p: "شوی", f: "shúwey" }], + gender: "masc", + number: "singular", + }, + }); + expect(getPastParticiple(kawulDyn, "passive", { gender: "masc", number: "singular"})) + .toEqual({ + type: "welded", + left: { + type: "VB", + ps: [{ p: "کړل", f: "kRul" }], + }, + right: { + type: "VB", + ps: [{ p: "شوی", f: "shúwey" }], + gender: "masc", + number: "singular", + }, + }); + expect(getPastParticiple(bandawul, "passive", { gender: "fem", number: "plural" })) + .toEqual({ + type: "welded", + left: { + type: "welded", + left: { + type: "NComp", + comp: { + type: "AdjComp", + ps: { p: "بندې", f: "bande" }, + gender: "fem", + number: "plural", + }, + }, + right: { + type: "VB", + ps: [{ p: "کړل", f: "kRul" }], + }, + }, + right: { + type: "VB", + ps: [{ "p": "شوې", "f": "shúwe" }], + gender: "fem", + number: "plural" + }, + }); + }) }); // const ooPh: T.PH = { diff --git a/src/lib/src/new-verb-engine/roots-and-stems.ts b/src/lib/src/new-verb-engine/roots-and-stems.ts index e1b2e4c..807cd37 100644 --- a/src/lib/src/new-verb-engine/roots-and-stems.ts +++ b/src/lib/src/new-verb-engine/roots-and-stems.ts @@ -11,13 +11,15 @@ import { } from "../p-text-helpers"; import * as T from "../../../types"; import { makePsString, removeFVarientsFromVerb } from "../accent-and-ps-utils"; -import { accentOnNFromEnd, accentSyllable, removeAccents } from "../accent-helpers"; +import { accentOnNFromEnd, countSyllables, removeAccents } from "../accent-helpers"; import { isKawulVerb, isTlulVerb } from "../type-predicates"; -import { vEntry, addAbilityEnding, weld, removeL, addTrailingAccent, tlulPerfectiveStem, getLongVB, possiblePPartLengths, isStatComp, statCompImperfectiveSpace, makeComplement } from "./rs-helpers"; +import { vEntry, addAbilityEnding, weld, removeL, addTrailingAccent, tlulPerfectiveStem, getLongVB, possiblePPartLengths, isStatComp, statCompImperfectiveSpace, makeComplement, vTransitivity } from "./rs-helpers"; import { inflectPattern3 } from "./new-inflectors"; -const kedulStat = vEntry({"ts":1581086654898,"i":11100,"p":"کېدل","f":"kedul","g":"kedul","e":"to become _____","r":2,"c":"v. intrans.","ssp":"ش","ssf":"sh","prp":"شول","prf":"shwul","pprtp":"شوی","pprtf":"shúwey","noOo":true,"ec":"become"}); -const kawulStat = vEntry({"ts":1579015359582,"i":11030,"p":"کول","f":"kawul","g":"kawul","e":"to make ____ ____ (as in \"He's making me angry.\")","r":4,"c":"v. trans.","ssp":"کړ","ssf":"kR","prp":"کړل","prf":"kRul","pprtp":"کړی","pprtf":"kúRey","noOo":true,"ec":"make,makes,making,made,made"}); +const statVerb = { + intransitive: vEntry({"ts":1581086654898,"i":11100,"p":"کېدل","f":"kedul","g":"kedul","e":"to become _____","r":2,"c":"v. intrans.","ssp":"ش","ssf":"sh","prp":"شول","prf":"shwul","pprtp":"شوی","pprtf":"shúwey","noOo":true,"ec":"become"}), + transitive: vEntry({"ts":1579015359582,"i":11030,"p":"کول","f":"kawul","g":"kawul","e":"to make ____ ____ (as in \"He's making me angry.\")","r":4,"c":"v. trans.","ssp":"کړ","ssf":"kR","prp":"کړل","prf":"kRul","pprtp":"کړی","pprtf":"kúRey","noOo":true,"ec":"make,makes,making,made,made"}), +}; const shwulVB: T.VBBasic = { type: "VB", @@ -54,9 +56,7 @@ export function getRootStem({ verb, rs, aspect, type, genderNumber, voice }: { ? aspect === "imperfective" ? getImperfectiveStem(v, genderNumber) : getPerfectiveStem(v, genderNumber) - : aspect === "imperfective" - ? getImperfectiveRoot(v, genderNumber) - : getPerfectiveRoot(v, genderNumber); + : getRoot(v, genderNumber, aspect); } function getAbilityRs( @@ -66,13 +66,10 @@ function getAbilityRs( voice: T.Voice, genderNum: T.GenderNumber, ): [[] | [T.VHead], [T.VB, T.VBA]] { - const losesAspect = isTlulVerb(verb) || (isStatComp(verb) && verb.entry.c?.includes("intrans.")); + const losesAspect = isTlulVerb(verb) || (isStatComp(verb) && vTransitivity(verb) === "intransitive"); const [vhead, [basicroot]] = voice === "passive" - // passive ability loses aspect ? getPassiveRs(verb, "imperfective", "root", genderNum) - : aspect === "imperfective" || losesAspect - ? getImperfectiveRoot(verb, genderNum) - : getPerfectiveRoot(verb, genderNum); + : getRoot(verb, genderNum, losesAspect ? "imperfective" : aspect); return [ vhead, [ @@ -88,6 +85,16 @@ export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, n if (voice === "passive") { return getPassivePp(v, { gender, number }); } + if (isStatComp(v) && v.complement) { + return weld( + makeComplement(v.complement, { gender, number }), + getPastParticiple( + statVerb[vTransitivity(verb)], + voice, + { gender, number }, + ) as T.VBGenNum, + ); + } if (verb.entry.pprtp && verb.entry.pprtf) { const base = makePsString(verb.entry.pprtp, verb.entry.pprtf); return { @@ -97,28 +104,19 @@ export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, n number, }; } - const basicRoot = getImperfectiveRoot(removeFVarientsFromVerb(verb), { gender, number })[1][0]; + const basicRoot = getRoot(removeFVarientsFromVerb(verb), { gender, number }, "imperfective")[1][0]; const longRoot = getLongVB(basicRoot); const rootWLengths = possiblePPartLengths(longRoot); - + /* istanbul ignore next */ if ("right" in rootWLengths) { - return { - ...rootWLengths, - right: { - ...rootWLengths.right, - ps: addTail(rootWLengths.right.ps), - gender, - number, - }, - }; - } else { - return { - ...rootWLengths, - ps: addTail(rootWLengths.ps), - gender, - number, - }; - } + throw new Error("should not have welded here"); + } + return { + ...rootWLengths, + ps: addTail(rootWLengths.ps), + gender, + number, + }; function addTail(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts { if ("long" in ps) { @@ -133,97 +131,87 @@ export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, n } function getPassivePp(verb: T.VerbEntryNoFVars, genderNumber: T.GenderNumber): T.WeldedGN { - const basicRoot = getImperfectiveRoot(verb, genderNumber)[1][0]; + if (isStatComp(verb) && verb.complement) { + return weld( + makeComplement(verb.complement, genderNumber), + getPassivePp(statVerb.transitive, genderNumber), + ); + } + const basicRoot = getRoot(verb, genderNumber, isKawulVerb(verb) ? "perfective" : "imperfective")[1][0]; const longRoot = getLongVB(basicRoot); - const kedulVb: T.VBGenNum = getPastParticiple(kedulStat, "active", genderNumber) as T.VBGenNum; + const kedulVb: T.VBGenNum = getPastParticiple(statVerb.intransitive, "active", genderNumber) as T.VBGenNum; return weld(longRoot, kedulVb); } -// TODO: could combine these two functions... function getPassiveRs(verb: T.VerbEntryNoFVars, aspect: T.Aspect, rs: "root" | "stem", genderNumber: T.GenderNumber): [[] | [T.VHead], [T.VBA]] { - const [vHead, [basicRoot]] = (aspect === "imperfective" - ? getImperfectiveRoot - : getPerfectiveRoot - )(verb, genderNumber); + const [vHead, [basicRoot]] = getRoot(verb, genderNumber, aspect); const longRoot = getLongVB(basicRoot); - const kedulVba = getRootStem({ verb: kedulStat, aspect, rs, type: "basic", voice: "active", genderNumber: { gender: "masc", number: "singular" }})[1][0] as T.VBBasic; + const kedulVba = getRootStem({ verb: statVerb.intransitive, aspect, rs, type: "basic", voice: "active", genderNumber: { gender: "masc", number: "singular" }})[1][0] as T.VBBasic; return [ vHead, [weld(longRoot, kedulVba)], ]; } -function getImperfectiveRoot(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber): [[], [T.VBA]] { - if (verb.complement && isStatComp(verb) && statCompImperfectiveSpace(verb)) { - const auxStem = getImperfectiveRoot(verb.entry.c?.includes("intrans.") - ? kedulStat - : kawulStat - , genderNum)[1][0]; - return [ - [], - [ - weld( - makeComplement(verb.complement, genderNum), - auxStem as T.VBBasic, - ), - ], - ]; +function getRoot(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber, aspect: T.Aspect): [[T.VHead] | [], [T.VBA]] { + if (verb.complement && isStatComp(verb) && (aspect === "perfective" || statCompImperfectiveSpace(verb))) { + const auxStem = getRoot( + statVerb[vTransitivity(verb)], + genderNum, + aspect, + )[1][0] as T.VBBasic; + const comp = makeComplement(verb.complement, genderNum); + return aspect === "perfective" + ? [[comp], [auxStem]] + : [ + [], + [ + weld( + makeComplement(verb.complement, genderNum), + auxStem as T.VBBasic, + ), + ], + ]; } - const infinitive = accentOnNFromEnd(makePsString(verb.entry.p, verb.entry.f), 0); - return [ - [], - [ - { - type: "VB", - ps: { - long: [infinitive], - short: [addTrailingAccent(removeL(infinitive))], - }, - }, - ], - ]; -} - -function getPerfectiveRoot(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber): [[T.VHead] | [], [T.VBA]] { - if (verb.complement && isStatComp(verb)) { - const auxStem = getPerfectiveRoot(verb.entry.c?.includes("intrans.") - ? kedulStat - : kawulStat, - genderNum)[1][0]; - return [ - [makeComplement(verb.complement, genderNum)], - [auxStem as T.VBBasic], - ]; - } - const base = removeAccents( - (verb.entry.prp && verb.entry.prf) - ? makePsString(verb.entry.prp, verb.entry.prf) - : makePsString(verb.entry.p, verb.entry.f) - ); - const [perfectiveHead, rest] = getPerfectiveHead(base, verb); + const base = aspect === "imperfective" + ? accentOnNFromEnd(makePsString(verb.entry.p, verb.entry.f), 0) + : removeAccents( + (verb.entry.prp && verb.entry.prf) + ? makePsString(verb.entry.prp, verb.entry.prf) + : makePsString(verb.entry.p, verb.entry.f) + ); + const [perfectiveHead, rest] = aspect === "perfective" + ? getPerfectiveHead(base, verb) + : [undefined, base]; return [ perfectiveHead ? [perfectiveHead] : [], [ { type: "VB", - ps: { - long: [rest], - short: [removeL(rest)], - ...isKawulVerb(verb) ? { - mini: [{ p: "ک", f: "k" }], - } : {}, - }, + ps: aspect === "imperfective" + ? { + long: [rest], + short: [addTrailingAccent(removeL(rest))], + } + : { + long: [rest], + short: [removeL(rest)], + ...(aspect === "perfective" && isKawulVerb(verb)) ? { + mini: [{ p: "ک", f: "k" }], + } : {}, + }, }, ], ]; } function getImperfectiveStem(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber): [[], [T.VB]] { - if (verb.complement && isStatComp(verb) && statCompImperfectiveSpace(verb)) { - const auxStem = getImperfectiveStem(verb.entry.c?.includes("intrans.") - ? kedulStat - : kawulStat, - genderNum)[1][0]; + const statComp = isStatComp(verb); + if (verb.complement && statComp && statCompImperfectiveSpace(verb)) { + const auxStem = getImperfectiveStem( + statVerb[vTransitivity(verb)], + genderNum, + )[1][0]; return [ [], [ @@ -245,12 +233,17 @@ function getImperfectiveStem(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber ], ]; } - const rawBase = removeL(makePsString(verb.entry.p, verb.entry.f)); - if (verb.entry.c?.includes("intrans.") && rawBase.p.endsWith("ېد")) { - const shortBase = trimOffPs(rawBase, 1, 2); + const extraRawBase = removeL(makePsString(verb.entry.p, verb.entry.f)); + // welded stative -awul verbs should always have a trailing accent + const rawBase = isKawulVerb(verb) || statComp || (countSyllables(extraRawBase) > 1 && extraRawBase.f.endsWith("aw")) + ? addTrailingAccent(extraRawBase) + : extraRawBase; + if (vTransitivity(verb) === "intransitive" && extraRawBase.p.endsWith("ېد")) { + // TODO: Factor out into a function + const shortBase = trimOffPs(extraRawBase, 2, 2); const long: T.PsString[] = [concatPsString( shortBase, - { p: "ږ", f: "éG" }, + { p: "ېږ", f: "éG" }, )]; const short: T.PsString[] | undefined = (verb.entry.shortIntrans) ? [shortBase] @@ -277,10 +270,7 @@ function getImperfectiveStem(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber function getPerfectiveStem(verb: T.VerbEntryNoFVars, genderNum: { gender: T.Gender, number: T.NounNumber }): [[T.VHead] | [], [T.VB]] { if (verb.complement && isStatComp(verb)) { - const auxStem = getPerfectiveStem(verb.entry.c?.includes("intrans.") - ? kedulStat - : kawulStat, - genderNum)[1][0]; + const auxStem = getPerfectiveStem(statVerb[vTransitivity(verb)], genderNum)[1][0]; return [ [makeComplement(verb.complement, genderNum)], [auxStem as T.VBBasic], @@ -319,10 +309,10 @@ function getPerfectiveHead(base: T.PsString, { entry }: T.VerbEntryNoFVars): [T. if (entry.separationAtP && entry.separationAtF) { const ph: T.PH = { type: "PH", - ps: { + ps: accentOnNFromEnd({ p: base.p.slice(0, entry.separationAtP), - f: accentSyllable(base.f.slice(0, entry.separationAtF)), - }, + f: base.f.slice(0, entry.separationAtF), + }, 0), }; const rest = { p: base.p.slice(entry.separationAtP), diff --git a/src/lib/src/new-verb-engine/rs-helpers.ts b/src/lib/src/new-verb-engine/rs-helpers.ts index 71ee360..c42f3f3 100644 --- a/src/lib/src/new-verb-engine/rs-helpers.ts +++ b/src/lib/src/new-verb-engine/rs-helpers.ts @@ -51,7 +51,7 @@ export function vEntry(e: any, c?: any): T.VerbEntryNoFVars { return { entry: removeFVarients(e), ...c ? { - c, + complement: c, } : {}, } as T.VerbEntryNoFVars; } @@ -108,9 +108,17 @@ export function verbEndingConcat(ps: T.PsString[], end: T.PsString[]): T.PsStrin )); } -export function weld(left: T.Welded["left"], right: T.VBGenNum): T.WeldedGN; -export function weld(left: T.Welded["left"], right: T.VBBasic): T.Welded; -export function weld(left: T.Welded["left"], right: T.VBBasic | T.VBGenNum): T.Welded | T.WeldedGN { +// TODO: THIS IS UGGGGLY NEED TO THINK THROUGH THE TYPING ON THE WELDING +export function weld(left: T.Welded["left"], right: T.VBGenNum | T.WeldedGN): T.WeldedGN; +export function weld(left: T.Welded["left"], right: T.VBBasic | T.NComp | T.Welded): T.Welded; +export function weld(left: T.Welded["left"], right: T.VBBasic | T.VBGenNum | T.Welded | T.NComp | T.WeldedGN): T.Welded | T.WeldedGN { + if (right.type === "welded") { + return weld(weld(left, right.left), right.right); + } + /* istanbul ignore next */ + if (right.type === "NComp") { + throw new Error("can't weld a complement on the right side"); + } return { type: "welded", left: removeAccentsFromLeft(left), @@ -154,13 +162,22 @@ export function addTrailingAccent(ps: T.PsString): T.PsString { export function removeL(ps: T.PsString): T.PsString { return trimOffPs(ps, 1, 2); } +/** + * returns a simple polar transitivity of the verb, only intransitive or transitive + * + * @param v + * @returns + */ +export function vTransitivity(v: T.VerbEntry): "intransitive" | "transitive" { + return v.entry.c?.includes("intrans.") ? "intransitive" : "transitive"; +} export function tlulPerfectiveStem(person: { gender: T.Gender, number: T.NounNumber }): [[T.PH], [T.VB]] { return [ [ { type: "PH", - ps: inflectPattern1({ p: "لاړ", f: "laaR" }, person).map(x => concatPsString(x, " "))[0], + ps: inflectPattern1({ p: "لاړ", f: "láaR" }, person).map(x => concatPsString(x, " "))[0], }, ], [ @@ -214,6 +231,15 @@ export function possiblePPartLengths(vba: T.VBNoLenghts): T.VBA { }; } const infinitive = vba.ps[0]; + if (infinitive.f === "tlúl") { + return { + type: "VB", + ps: { + long: [infinitive], + short: [{ p: "تل", f: "túl" }], + }, + }; + } const [trimP, trimF] = (infinitive.p.slice(-4) === "ښودل" && infinitive.p.length > 4 && infinitive.p !== "کېښودل" && infinitive.p !== "کښېښودل") // special thing for اېښودل - پرېښودل ? [3, 4]