more refactoring and work on the phrase builder
This commit is contained in:
parent
e4cf7558ee
commit
06fa7966f8
|
@ -5,7 +5,7 @@ import {
|
||||||
} from "./np-picker/picker-tools";
|
} from "./np-picker/picker-tools";
|
||||||
import {
|
import {
|
||||||
Types as T,
|
Types as T,
|
||||||
// ButtonSelect,
|
ButtonSelect,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
const tenseOptions: { label: string, value: VerbTense }[] = [{
|
const tenseOptions: { label: string, value: VerbTense }[] = [{
|
||||||
|
@ -65,14 +65,14 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// function onPosNegSelect(value: string) {
|
function onPosNegSelect(value: string) {
|
||||||
// if (verb) {
|
if (verb) {
|
||||||
// onChange({
|
onChange({
|
||||||
// ...verb,
|
...verb,
|
||||||
// negative: value === "true",
|
negative: value === "true",
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
return <div style={{ maxWidth: "225px" }}>
|
return <div style={{ maxWidth: "225px" }}>
|
||||||
<div>Verb:</div>
|
<div>Verb:</div>
|
||||||
<Select
|
<Select
|
||||||
|
@ -99,8 +99,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
|
||||||
placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."}
|
placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."}
|
||||||
{...zIndexProps}
|
{...zIndexProps}
|
||||||
/>
|
/>
|
||||||
{/* The negative is not ready yet for people to use */}
|
{verb && <div className="text-center my-3">
|
||||||
{/* {verb && <div className="text-center my-3">
|
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
value={verb.negative.toString()}
|
value={verb.negative.toString()}
|
||||||
|
@ -113,7 +112,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
|
||||||
}]}
|
}]}
|
||||||
handleChange={onPosNegSelect}
|
handleChange={onPosNegSelect}
|
||||||
/>
|
/>
|
||||||
</div>} */}
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,110 @@
|
||||||
import {
|
import {
|
||||||
Types as T,
|
Types as T,
|
||||||
concatPsString,
|
concatPsString,
|
||||||
|
removeAccents,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
const nu: T.PsString = { p: "نه", f: "nu" };
|
|
||||||
|
|
||||||
export function compileVP(VP: VPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] } {
|
export function compileVP(VP: VPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] } {
|
||||||
|
console.log(VP);
|
||||||
|
const { head, rest } = VP.verb.ps;
|
||||||
|
const subj = VP.subject.ps;
|
||||||
|
const obj = typeof VP.object === "object" ? VP.object.ps : undefined;
|
||||||
|
// better: feed in array of NPs [subj, obj, etc...]
|
||||||
|
return {
|
||||||
|
ps: arrangePs(subj, obj, head, rest, VP.verb.negative),
|
||||||
|
e: compileEnglish(VP),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrangePs(
|
||||||
|
subj: T.PsString[],
|
||||||
|
obj: T.PsString[] | undefined,
|
||||||
|
head: T.PsString | undefined,
|
||||||
|
rest: T.PsString[],
|
||||||
|
negative: boolean,
|
||||||
|
): T.PsString[];
|
||||||
|
function arrangePs(
|
||||||
|
subj: T.PsString[],
|
||||||
|
obj: T.PsString[] | undefined,
|
||||||
|
head: T.PsString | undefined,
|
||||||
|
rest: T.SingleOrLengthOpts<T.PsString[]>,
|
||||||
|
negative: boolean,
|
||||||
|
): T.SingleOrLengthOpts<T.PsString[]>;
|
||||||
|
function arrangePs(
|
||||||
|
subj: T.PsString[],
|
||||||
|
obj: T.PsString[] | undefined,
|
||||||
|
head: T.PsString | undefined,
|
||||||
|
rest: T.SingleOrLengthOpts<T.PsString[]>,
|
||||||
|
negative: boolean,
|
||||||
|
): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
|
if ("long" in rest) {
|
||||||
|
return {
|
||||||
|
long: arrangePs(subj, obj, head, rest.long, negative),
|
||||||
|
short: arrangePs(subj, obj, head, rest.short, negative),
|
||||||
|
...rest.mini ? {
|
||||||
|
mini: arrangePs(subj, obj, head, rest.mini, negative),
|
||||||
|
} : {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const verbWNeg = arrangeVerbWNeg(head, rest, negative);
|
||||||
|
if (obj) {
|
||||||
|
return subj.flatMap(s => (
|
||||||
|
obj.flatMap(o =>
|
||||||
|
verbWNeg.flatMap(v => (
|
||||||
|
concatPsString(s, " ", o, " ", v)
|
||||||
|
// concatPsString(o, " ", s, " ", v),
|
||||||
|
))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return subj.flatMap(s => (
|
||||||
|
verbWNeg.flatMap(v => (
|
||||||
|
concatPsString(s, " ", v)
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrangeVerbWNeg(head: T.PsString | undefined, rest: T.PsString[], negative: boolean): T.PsString[] {
|
||||||
|
if (!negative) {
|
||||||
|
return rest.map(ps => concatPsString(head || "", ps));
|
||||||
|
}
|
||||||
|
|
||||||
|
const nu: T.PsString = { p: "نه", f: "nú" };
|
||||||
|
if (!head) {
|
||||||
|
return rest.map(r => concatPsString(nu, " ", removeAccents(r)));
|
||||||
|
}
|
||||||
|
const regularPrefix = head.p === "و" || head.p === "وا";
|
||||||
|
const withNuAfterHead = rest.map(r => concatPsString(
|
||||||
|
removeAccents(head),
|
||||||
|
{ p: "", f: "-" },
|
||||||
|
nu,
|
||||||
|
" ",
|
||||||
|
removeAccents(r),
|
||||||
|
));
|
||||||
|
if (regularPrefix) {
|
||||||
|
return withNuAfterHead;
|
||||||
|
}
|
||||||
|
const withNuBeforeHead = rest.map(r => concatPsString(
|
||||||
|
nu,
|
||||||
|
" ",
|
||||||
|
removeAccents(head),
|
||||||
|
removeAccents(r),
|
||||||
|
));
|
||||||
|
return [
|
||||||
|
...withNuAfterHead,
|
||||||
|
...withNuBeforeHead,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileEnglish(VP: VPRendered): string[] | undefined {
|
||||||
function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
|
function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
|
||||||
return e.replace("$SUBJ", subject).replace("$OBJ", object || "");
|
return e.replace("$SUBJ", subject).replace("$OBJ", object || "");
|
||||||
}
|
}
|
||||||
// TODO: display of short and long options etc.
|
|
||||||
const vPs = "long" in VP.verb.ps ? VP.verb.ps.long : VP.verb.ps;
|
|
||||||
const engSubj = VP.subject.e || undefined;
|
const engSubj = VP.subject.e || undefined;
|
||||||
const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
|
const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
|
||||||
// require all English parts for making the English phrase
|
// require all English parts for making the English phrase
|
||||||
const e = (VP.englishBase && engSubj && engObj) ? VP.englishBase.map(e => insertEWords(e, {
|
return (VP.englishBase && engSubj && engObj) ? VP.englishBase.map(e => insertEWords(e, {
|
||||||
subject: engSubj,
|
subject: engSubj,
|
||||||
object: engObj,
|
object: engObj,
|
||||||
})) : undefined;
|
})) : undefined;
|
||||||
const obj = typeof VP.object === "object" ? VP.object : undefined;
|
|
||||||
const ps = VP.subject.ps.flatMap(s => (
|
|
||||||
obj ? obj.ps.flatMap(o => (
|
|
||||||
vPs.flatMap(v => (
|
|
||||||
VP.verb.negative
|
|
||||||
// this will not work yet for perfectives etc - super rough start
|
|
||||||
? concatPsString(s, " ", o, " ", nu, " ", v)
|
|
||||||
: concatPsString(s, " ", o, " ", v)
|
|
||||||
))
|
|
||||||
)) : vPs.flatMap(v => (
|
|
||||||
VP.verb.negative
|
|
||||||
? concatPsString(s, " ", nu, " ", v)
|
|
||||||
: concatPsString(s, " ", v)
|
|
||||||
))
|
|
||||||
));
|
|
||||||
return { ps, e };
|
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import {
|
||||||
parseEc,
|
parseEc,
|
||||||
conjugateVerb,
|
conjugateVerb,
|
||||||
concatPsString,
|
concatPsString,
|
||||||
|
removeAccents,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import {
|
import {
|
||||||
psStringFromEntry,
|
psStringFromEntry,
|
||||||
|
@ -18,8 +19,12 @@ export function renderVP(VP: VPSelection): VPRendered {
|
||||||
const isTransitive = VP.object !== "none";
|
const isTransitive = VP.object !== "none";
|
||||||
const { king, /* servant */ } = getKingAndServant(isPast, isTransitive);
|
const { king, /* servant */ } = getKingAndServant(isPast, isTransitive);
|
||||||
const kingPerson = getPersonFromNP(VP[king]);
|
const kingPerson = getPersonFromNP(VP[king]);
|
||||||
|
// TODO: more elegant way of handling this type safety
|
||||||
|
if (kingPerson === undefined) {
|
||||||
|
throw new Error("king of sentance does not exist");
|
||||||
|
}
|
||||||
const subjectPerson = getPersonFromNP(VP.subject);
|
const subjectPerson = getPersonFromNP(VP.subject);
|
||||||
// const objectPerson = getPersonFromNP(VP.object);
|
const objectPerson = getPersonFromNP(VP.object);
|
||||||
// TODO: also don't inflect if it's a pattern one animate noun
|
// TODO: also don't inflect if it's a pattern one animate noun
|
||||||
const inflectSubject = isPast && isTransitive;
|
const inflectSubject = isPast && isTransitive;
|
||||||
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
|
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
|
||||||
|
@ -28,7 +33,7 @@ export function renderVP(VP: VPSelection): VPRendered {
|
||||||
type: "VPRendered",
|
type: "VPRendered",
|
||||||
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
||||||
object: renderNPSelection(VP.object, inflectObject, true, "object"),
|
object: renderNPSelection(VP.object, inflectObject, true, "object"),
|
||||||
verb: renderVerbSelection(VP.verb, kingPerson),
|
verb: renderVerbSelection(VP.verb, kingPerson, objectPerson),
|
||||||
englishBase: renderEnglishVPBase({
|
englishBase: renderEnglishVPBase({
|
||||||
subjectPerson,
|
subjectPerson,
|
||||||
object: VP.object,
|
object: VP.object,
|
||||||
|
@ -46,14 +51,62 @@ function renderNPSelection(NP: NPSelection | ObjectNP, inflected: boolean, infle
|
||||||
}
|
}
|
||||||
return NP;
|
return NP;
|
||||||
}
|
}
|
||||||
return {
|
if (NP.type === "noun") {
|
||||||
...NP,
|
return renderNounSelection(NP, inflected);
|
||||||
inflected,
|
}
|
||||||
...textOfNP(NP, inflected, inflectEnglish),
|
if (NP.type === "pronoun") {
|
||||||
};
|
return renderPronounSelection(NP, inflected, inflectEnglish);
|
||||||
|
}
|
||||||
|
if (NP.type === "participle") {
|
||||||
|
return renderParticipleSelection(NP, inflected)
|
||||||
|
}
|
||||||
|
throw new Error("unknown NP type");
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderVerbSelection(vs: VerbSelection, person: T.Person): VerbRendered {
|
function renderNounSelection(n: NounSelection, inflected: boolean): Rendered<NounSelection> {
|
||||||
|
const english = getEnglishFromNoun(n.entry, n.number);
|
||||||
|
const pashto = ((): T.PsString[] => {
|
||||||
|
const infs = inflectWord(n.entry);
|
||||||
|
const ps = n.number === "singular"
|
||||||
|
? getInf(infs, "inflections", n.gender, false, inflected)
|
||||||
|
: [
|
||||||
|
...getInf(infs, "plural", n.gender, true, inflected),
|
||||||
|
...getInf(infs, "arabicPlural", n.gender, true, inflected),
|
||||||
|
...getInf(infs, "inflections", n.gender, true, inflected),
|
||||||
|
];
|
||||||
|
return ps.length > 0
|
||||||
|
? ps
|
||||||
|
: [psStringFromEntry(n.entry)];
|
||||||
|
})();
|
||||||
|
return {
|
||||||
|
...n,
|
||||||
|
inflected,
|
||||||
|
ps: pashto,
|
||||||
|
e: english,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPronounSelection(p: PronounSelection, inflected: boolean, englishInflected: boolean): Rendered<PronounSelection> {
|
||||||
|
const [row, col] = getVerbBlockPosFromPerson(p.person);
|
||||||
|
return {
|
||||||
|
...p,
|
||||||
|
inflected,
|
||||||
|
ps: grammarUnits.pronouns[p.distance][inflected ? "inflected" : "plain"][row][col],
|
||||||
|
e: grammarUnits.persons[p.person].label[englishInflected ? "object" : "subject"],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderParticipleSelection(p: ParticipleSelection, inflected: boolean): Rendered<ParticipleSelection> {
|
||||||
|
return {
|
||||||
|
...p,
|
||||||
|
inflected,
|
||||||
|
// TODO: More robust inflection of inflecting pariticiples - get from the conjugation engine
|
||||||
|
ps: [psStringFromEntry(p.verb.entry)].map(ps => inflected ? concatPsString(ps, { p: "و", f: "o" }) : ps),
|
||||||
|
e: getEnglishParticiple(p.verb.entry),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderVerbSelection(vs: VerbSelection, person: T.Person, objectPerson: T.Person | undefined): VerbRendered {
|
||||||
const conjugations = conjugateVerb(vs.verb.entry, vs.verb.complement);
|
const conjugations = conjugateVerb(vs.verb.entry, vs.verb.complement);
|
||||||
// TODO: error handle this?
|
// TODO: error handle this?
|
||||||
// TODO: option to manually select these
|
// TODO: option to manually select these
|
||||||
|
@ -62,11 +115,11 @@ function renderVerbSelection(vs: VerbSelection, person: T.Person): VerbRendered
|
||||||
: "stative" in conjugations
|
: "stative" in conjugations
|
||||||
? conjugations.stative
|
? conjugations.stative
|
||||||
: conjugations;
|
: conjugations;
|
||||||
// TODO: get the object person from the matrix on stative compounds
|
// TODO: deliver the perfective split!
|
||||||
return {
|
return {
|
||||||
...vs,
|
...vs,
|
||||||
person,
|
person,
|
||||||
ps: getPsVerbConjugation(conj, vs.tense, person),
|
ps: getPsVerbConjugation(conj, vs.tense, person, objectPerson),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +179,30 @@ function renderEnglishVPBase({ subjectPerson, object, vs }: {
|
||||||
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
|
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, person: T.Person, objectPerson: T.Person | undefined): {
|
||||||
|
head: T.PsString | undefined,
|
||||||
|
rest: T.SingleOrLengthOpts<T.PsString[]>,
|
||||||
|
} {
|
||||||
const f = getTenseVerbForm(conj, tense);
|
const f = getTenseVerbForm(conj, tense);
|
||||||
// TODO: ability to grab the correct part of matrix
|
const block = getMatrixBlock(f, objectPerson, person);
|
||||||
const block = "mascSing" in f
|
const perfective = isPerfective(tense);
|
||||||
? f.mascSing
|
const verbForm = getVerbFromBlock(block, person);
|
||||||
: f;
|
if (perfective) {
|
||||||
|
const past = isPastTense(tense);
|
||||||
|
const splitInfo = conj.info[past ? "root" : "stem"].perfectiveSplit;
|
||||||
|
if (!splitInfo) return { head: undefined, rest: verbForm };
|
||||||
|
// TODO: Either solve this in the inflector or here, it seems silly (or redundant)
|
||||||
|
// to have a length option in the perfective split stem??
|
||||||
|
const [splitHead] = getLong(getMatrixBlock(splitInfo, objectPerson, person));
|
||||||
|
return {
|
||||||
|
head: splitHead,
|
||||||
|
rest: removeHead(splitHead, verbForm),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { head: undefined, rest: verbForm };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVerbFromBlock(block: T.SingleOrLengthOpts<T.VerbBlock>, person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
function grabFromBlock(b: T.VerbBlock, [row, col]: [ row: number, col: number ]): T.PsString[] {
|
function grabFromBlock(b: T.VerbBlock, [row, col]: [ row: number, col: number ]): T.PsString[] {
|
||||||
return b[row][col];
|
return b[row][col];
|
||||||
}
|
}
|
||||||
|
@ -148,6 +219,63 @@ function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, person:
|
||||||
return grabFromBlock(block, pos);
|
return grabFromBlock(block, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeHead(head: T.PsString, rest: T.PsString[]): T.PsString[];
|
||||||
|
function removeHead(head: T.PsString, rest: T.SingleOrLengthOpts<T.PsString[]>): T.SingleOrLengthOpts<T.PsString[]>;
|
||||||
|
function removeHead(head: T.PsString, rest: T.SingleOrLengthOpts<T.PsString[]>): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
|
if ("long" in rest) {
|
||||||
|
return {
|
||||||
|
long: removeHead(head, rest.long),
|
||||||
|
short: removeHead(head, rest.short),
|
||||||
|
...rest.mini ? {
|
||||||
|
mini: removeHead(head, rest.mini),
|
||||||
|
} : {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rest.map((ps) => {
|
||||||
|
const pMatches = removeAccents(ps.p.slice(0, head.p.length)) === removeAccents(head.p);
|
||||||
|
const fMatches = removeAccents(ps.f.slice(0, head.f.length)) === removeAccents(head.f);
|
||||||
|
if (!(pMatches && fMatches)) {
|
||||||
|
throw new Error(`split head does not match - ${JSON.stringify(ps)} ${JSON.stringify(head)}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
p: ps.p.slice(head.p.length),
|
||||||
|
f: ps.f.slice(head.f.length),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
|
||||||
|
if ("long" in x) {
|
||||||
|
return x.long;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
function getMatrixBlock<U>(f: {
|
||||||
|
mascSing: T.SingleOrLengthOpts<U>;
|
||||||
|
mascPlur: T.SingleOrLengthOpts<U>;
|
||||||
|
femSing: T.SingleOrLengthOpts<U>;
|
||||||
|
femPlur: T.SingleOrLengthOpts<U>;
|
||||||
|
} | T.SingleOrLengthOpts<U>, objectPerson: T.Person | undefined, kingPerson: T.Person): T.SingleOrLengthOpts<U> {
|
||||||
|
if (!("mascSing" in f)) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
function personToLabel(p: T.Person): "mascSing" | "mascPlur" | "femSing" | "femPlur" {
|
||||||
|
if (p === T.Person.FirstSingMale || p === T.Person.SecondSingMale || p === T.Person.ThirdSingMale) {
|
||||||
|
return "mascSing";
|
||||||
|
}
|
||||||
|
if (p === T.Person.FirstSingFemale || p === T.Person.SecondSingFemale || p === T.Person.ThirdSingFemale) {
|
||||||
|
return "femSing";
|
||||||
|
}
|
||||||
|
if (p === T.Person.FirstPlurMale || p === T.Person.SecondPlurMale || p === T.Person.ThirdPlurMale) {
|
||||||
|
return "mascPlur";
|
||||||
|
}
|
||||||
|
return "femPlur";
|
||||||
|
}
|
||||||
|
// if there's an object the matrix will agree with that, otherwise with the kingPerson (subject for intransitive)
|
||||||
|
const person = (objectPerson === undefined) ? kingPerson : objectPerson;
|
||||||
|
return f[personToLabel(person)];
|
||||||
|
}
|
||||||
|
|
||||||
function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm {
|
function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm {
|
||||||
if (tense === "present") {
|
if (tense === "present") {
|
||||||
return conj.imperfective.nonImperative;
|
return conj.imperfective.nonImperative;
|
||||||
|
@ -164,9 +292,11 @@ function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm
|
||||||
throw new Error("unknown tense");
|
throw new Error("unknown tense");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPersonFromNP(np: NPSelection | ObjectNP): T.Person {
|
function getPersonFromNP(np: NPSelection): T.Person;
|
||||||
|
function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined;
|
||||||
|
function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined {
|
||||||
if (np === "none") {
|
if (np === "none") {
|
||||||
throw new Error("empty entity");
|
return undefined;
|
||||||
}
|
}
|
||||||
if (typeof np === "number") return np;
|
if (typeof np === "number") return np;
|
||||||
if (np.type === "participle") {
|
if (np.type === "participle") {
|
||||||
|
@ -180,25 +310,6 @@ function getPersonFromNP(np: NPSelection | ObjectNP): T.Person {
|
||||||
: (np.gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
: (np.gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
||||||
}
|
}
|
||||||
|
|
||||||
function textOfNP(np: NPSelection, inflected: boolean, englishInflected: boolean): { ps: T.PsString[], e: string } {
|
|
||||||
if (np.type === "participle") {
|
|
||||||
return textOfParticiple(np, inflected);
|
|
||||||
}
|
|
||||||
if (np.type === "pronoun") {
|
|
||||||
return textOfPronoun(np, inflected, englishInflected);
|
|
||||||
}
|
|
||||||
return textOfNoun(np, inflected);
|
|
||||||
}
|
|
||||||
|
|
||||||
function textOfParticiple({ verb: { entry }}: ParticipleSelection, inflected: boolean): { ps: T.PsString[], e: string } {
|
|
||||||
// TODO: ability to inflect participles
|
|
||||||
return {
|
|
||||||
// TODO: More robust inflection of inflecting pariticiples - get from the conjugation engine
|
|
||||||
ps: [psStringFromEntry(entry)].map(ps => inflected ? concatPsString(ps, { p: "و", f: "o" }) : ps),
|
|
||||||
e: getEnglishParticiple(entry),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
||||||
if (!entry.ec) {
|
if (!entry.ec) {
|
||||||
console.log("errored participle");
|
console.log("errored participle");
|
||||||
|
@ -212,33 +323,6 @@ function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
||||||
: participle;
|
: participle;
|
||||||
}
|
}
|
||||||
|
|
||||||
function textOfPronoun(p: PronounSelection, inflected: boolean, englishInflected: boolean): { ps: T.PsString[], e: string } {
|
|
||||||
// TODO: Will need to handle inflecting and inflecting english pronouns etc.
|
|
||||||
const [row, col] = getVerbBlockPosFromPerson(p.person);
|
|
||||||
return {
|
|
||||||
ps: grammarUnits.pronouns[p.distance][inflected ? "inflected" : "plain"][row][col],
|
|
||||||
e: grammarUnits.persons[p.person].label[englishInflected ? "object" : "subject"],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function textOfNoun(n: NounSelection, inflected: boolean): { ps: T.PsString[], e: string } {
|
|
||||||
const english = getEnglishFromNoun(n.entry, n.number);
|
|
||||||
const pashto = ((): T.PsString[] => {
|
|
||||||
const infs = inflectWord(n.entry);
|
|
||||||
const ps = n.number === "singular"
|
|
||||||
? getInf(infs, "inflections", n.gender, false, inflected)
|
|
||||||
: [
|
|
||||||
...getInf(infs, "plural", n.gender, true, inflected),
|
|
||||||
...getInf(infs, "arabicPlural", n.gender, true, inflected),
|
|
||||||
...getInf(infs, "inflections", n.gender, true, inflected),
|
|
||||||
];
|
|
||||||
return ps.length > 0
|
|
||||||
? ps
|
|
||||||
: [psStringFromEntry(n.entry)];
|
|
||||||
})();
|
|
||||||
return { ps: pashto, e: english };
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnglishFromNoun(entry: T.DictionaryEntry, number: NounNumber): string {
|
function getEnglishFromNoun(entry: T.DictionaryEntry, number: NounNumber): string {
|
||||||
const articles = {
|
const articles = {
|
||||||
singular: "(a/the)",
|
singular: "(a/the)",
|
||||||
|
@ -296,3 +380,13 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur
|
||||||
if (o.type !== "pronoun") return false;
|
if (o.type !== "pronoun") return false;
|
||||||
return [0,1,2,3,6,7,8,9].includes(o.person);
|
return [0,1,2,3,6,7,8,9].includes(o.person);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPerfective(t: VerbTense): boolean {
|
||||||
|
if (t === "present" || t === "imperfectivePast") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (t === "perfectivePast" || t === "subjunctive") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw new Error("tense not implemented yet");
|
||||||
|
}
|
||||||
|
|
|
@ -28,13 +28,17 @@ type VerbSelection = {
|
||||||
verb: VerbEntry,
|
verb: VerbEntry,
|
||||||
tense: VerbTense,
|
tense: VerbTense,
|
||||||
object: VerbObject,
|
object: VerbObject,
|
||||||
|
// TODO: add in perfective element here??
|
||||||
negative: boolean,
|
negative: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type VerbRendered = Omit<VerbSelection, "object"> & {
|
type VerbRendered = Omit<VerbSelection, "object"> & {
|
||||||
ps: import("@lingdocs/pashto-inflector").Types.SingleOrLengthOpts<
|
ps: {
|
||||||
import("@lingdocs/pashto-inflector").Types.PsString[]
|
head: import("@lingdocs/pashto-inflector").Types.PsString | undefined,
|
||||||
>,
|
rest: import("@lingdocs/pashto-inflector").Types.SingleOrLengthOpts<
|
||||||
|
import("@lingdocs/pashto-inflector").Types.PsString[]
|
||||||
|
>,
|
||||||
|
},
|
||||||
person: import("@lingdocs/pashto-inflector").Types.Person,
|
person: import("@lingdocs/pashto-inflector").Types.Person,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue