ba particles working and a couple of bugs with past tense and nouns etc

This commit is contained in:
lingdocs 2022-03-20 11:05:17 +05:00
parent 004bdeb352
commit 9204ca150c
7 changed files with 96 additions and 50 deletions

View File

@ -14,6 +14,12 @@ const tenseOptions: { label: string, value: VerbTense }[] = [{
}, { }, {
label: "subjunctive", label: "subjunctive",
value: "subjunctive", value: "subjunctive",
}, {
label: "imperf. future",
value: "imperfectiveFuture",
}, {
label: "perf. future",
value: "perfectiveFuture",
}, { }, {
label: "simple past", label: "simple past",
value: "perfectivePast", value: "perfectivePast",
@ -73,7 +79,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
}); });
} }
} }
return <div style={{ maxWidth: "225px" }}> return <div style={{ maxWidth: "225px", minWidth: "10px" }}>
<div>Verb:</div> <div>Verb:</div>
<Select <Select
value={verb && verb.verb.entry.ts.toString()} value={verb && verb.verb.entry.ts.toString()}

View File

@ -8,7 +8,7 @@ import { useState } from "react";
import { nouns, verbs } from "../../words/words"; import { nouns, verbs } from "../../words/words";
// import { capitalizeFirstLetter } from "../../lib/text-tools"; // import { capitalizeFirstLetter } from "../../lib/text-tools";
const npTypes: NPType[] = ["noun", "pronoun", "participle"]; const npTypes: NPType[] = ["pronoun", "noun", "participle"];
function NPPicker({ np, onChange, counterPart }: { onChange: (nps: NPSelection | undefined) => void, np: NPSelection | undefined, counterPart: NPSelection | VerbObject | undefined }) { function NPPicker({ np, onChange, counterPart }: { onChange: (nps: NPSelection | undefined) => void, np: NPSelection | undefined, counterPart: NPSelection | VerbObject | undefined }) {
// eslint-disable-next-line // eslint-disable-next-line
@ -35,19 +35,18 @@ function NPPicker({ np, onChange, counterPart }: { onChange: (nps: NPSelection |
} }
} }
return <div style={{ maxWidth: "300px"}}> return <div style={{ maxWidth: "300px"}}>
{!npType ? {!npType ? <div className="text-center mt-3">
<div> {npTypes.map((npt) => <div className="mb-2">
{npTypes.map((npt) => ( <button
<button key={npt}
key={npt} type="button"
type="button" className="mr-2 btn btn-sm btn-outline-secondary"
className="mr-2 btn btn-sm btn-outline-secondary" onClick={() => handleNPTypeChange(npt)}
onClick={() => handleNPTypeChange(npt)} >
> {npt}
{npt} </button>
</button> </div>)}
))} </div>
</div>
: <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>} : <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>}
{np ? {np ?
((np.type === "pronoun" ((np.type === "pronoun"

View File

@ -111,7 +111,7 @@ function PronounPicker({ onChange, pronoun, isObject }: {
/> />
<button className="btn btn-sm btn-outline-secondary" onClick={handleDisplayChange}>{display === "persons" ? "#" : display === "p" ? "PS" : "EN"}</button> <button className="btn btn-sm btn-outline-secondary" onClick={handleDisplayChange}>{display === "persons" ? "#" : display === "p" ? "PS" : "EN"}</button>
</div> </div>
<table className="table table-bordered" style={{ textAlign: "center", minWidth: "200px", tableLayout: "fixed" }}> <table className="table table-bordered" style={{ textAlign: "center", minWidth: "160px", tableLayout: "fixed" }}>
<tbody> <tbody>
{pSpec.map((rw, i) => ( {pSpec.map((rw, i) => (
<tr> <tr>

View File

@ -5,6 +5,7 @@ import {
grammarUnits, grammarUnits,
getVerbBlockPosFromPerson, getVerbBlockPosFromPerson,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import { hasBaParticle, psRemove } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
type ListOfEntities = (T.PsString & { isVerbPrefix?: boolean, prefixFollowedByParticle?: boolean })[][]; type ListOfEntities = (T.PsString & { isVerbPrefix?: boolean, prefixFollowedByParticle?: boolean })[][];
@ -49,11 +50,15 @@ function compilePs(
} : {}, } : {},
}; };
} }
const { hasBa, verbEntities } = compileVerbWNegative(head, rest, negative)
const entities: ListOfEntities = [ const entities: ListOfEntities = [
...nps, ...nps,
...compileVerbWNegative(head, rest, negative), ...verbEntities,
]; ];
const entitiesWKids = putKidsInKidsSection(entities, kids); const entitiesWKids = putKidsInKidsSection(
entities,
hasBa ? [[grammarUnits.baParticle], ...kids] : kids,
);
return combineEntities(entitiesWKids); return combineEntities(entitiesWKids);
} }
@ -77,7 +82,10 @@ function shrinkEntitiesAndGatherKids(VP: VPRendered, form: FormVersion): { kids:
(VP.king === "object" && !removeKing && king) || (VP.servant === "object" && !shrinkServant) (VP.king === "object" && !removeKing && king) || (VP.servant === "object" && !shrinkServant)
); );
return { return {
kids: [...toShrink ? [shrink(toShrink)] : []], kids: [
...toShrink
? [shrink(toShrink)] : [],
],
NPs: [ NPs: [
...showSubject ? [main.subject] : [], ...showSubject ? [main.subject] : [],
...(showObject && main.object) ? [main.object] : [], ...(showObject && main.object) ? [main.object] : [],
@ -86,11 +94,7 @@ function shrinkEntitiesAndGatherKids(VP: VPRendered, form: FormVersion): { kids:
} }
function shrink(np: Rendered<NPSelection>): T.PsString[] { function shrink(np: Rendered<NPSelection>): T.PsString[] {
const person: T.Person = np.type === "participle" const [row, col] = getVerbBlockPosFromPerson(np.person);
? T.Person.ThirdPlurMale
// @ts-ignore
: np.person;
const [row, col] = getVerbBlockPosFromPerson(person);
return grammarUnits.pronouns.mini[row][col]; return grammarUnits.pronouns.mini[row][col];
} }
@ -124,27 +128,43 @@ function combineEntities(loe: ListOfEntities): T.PsString[] {
} }
function compileVerbWNegative(head: T.PsString | undefined, rest: T.PsString[], negative: boolean): ListOfEntities { function compileVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], negative: boolean): {
hasBa: boolean,
verbEntities: ListOfEntities,
} {
const hasBa = hasBaParticle(restRaw[0]);
const rest = hasBa
? restRaw.map(ps => psRemove(ps, concatPsString(grammarUnits.baParticle, " ")))
: restRaw;
if (!negative) { if (!negative) {
return [ return {
...head ? [[{...head, isVerbPrefix: true}]] : [], hasBa,
rest, verbEntities: [
]; ...head ? [[{...head, isVerbPrefix: true}]] : [],
rest,
],
};
} }
const nu: T.PsString = { p: "نه", f: "nú" }; const nu: T.PsString = { p: "نه", f: "nú" };
if (!head) { if (!head) {
return [ return {
[nu], hasBa,
rest.map(r => removeAccents(r)), verbEntities: [
]; [nu],
rest.map(r => removeAccents(r)),
],
};
} }
// const regularPrefix = head.p === "و" || head.p === "وا"; // const regularPrefix = head.p === "و" || head.p === "وا";
// if (regularPrefix) { // if (regularPrefix) {
// dashes for oo-nu etc // dashes for oo-nu etc
return [ return {
[{ ...removeAccents(head), isVerbPrefix: true }], hasBa,
rest.map(r => concatPsString(nu, " ", removeAccents(r))) verbEntities: [
]; [{ ...removeAccents(head), isVerbPrefix: true }],
rest.map(r => concatPsString(nu, " ", removeAccents(r))),
],
};
} }
function compileEnglish(VP: VPRendered): string[] | undefined { function compileEnglish(VP: VPRendered): string[] | undefined {

View File

@ -8,9 +8,11 @@ import {
conjugateVerb, conjugateVerb,
concatPsString, concatPsString,
removeAccents, removeAccents,
getPersonNumber,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import { import {
psStringFromEntry, psStringFromEntry,
getLong,
} from "../text-tools"; } from "../text-tools";
import { import {
getPersonFromNP, getPersonFromNP,
@ -30,7 +32,7 @@ export function renderVP(VP: VPSelection): VPRendered {
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 && !isSingularAnimatePattern4(VP.subject); const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(VP.subject);
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object); const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
// Render Elements // Render Elements
return { return {
@ -88,6 +90,7 @@ function renderNounSelection(n: NounSelection, inflected: boolean): Rendered<Nou
})(); })();
return { return {
...n, ...n,
person: getPersonNumber(n.gender, n.number),
inflected, inflected,
ps: pashto, ps: pashto,
e: english, e: english,
@ -108,6 +111,7 @@ function renderParticipleSelection(p: ParticipleSelection, inflected: boolean):
return { return {
...p, ...p,
inflected, inflected,
person: T.Person.ThirdPlurMale,
// TODO: More robust inflection of inflecting pariticiples - get from the conjugation engine // 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), ps: [psStringFromEntry(p.verb.entry)].map(ps => inflected ? concatPsString(ps, { p: "و", f: "o" }) : ps),
e: getEnglishParticiple(p.verb.entry), e: getEnglishParticiple(p.verb.entry),
@ -155,6 +159,9 @@ function renderEnglishVPBase({ subjectPerson, object, vs }: {
function isToBe(v: T.EnglishVerbConjugationEc): boolean { function isToBe(v: T.EnglishVerbConjugationEc): boolean {
return (v[2] === "being"); return (v[2] === "being");
} }
const futureEngBuilder: T.EnglishBuilder = (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
]);
const builders: Record< const builders: Record<
VerbTense, VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[] (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
@ -169,6 +176,8 @@ function renderEnglishVPBase({ subjectPerson, object, vs }: {
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(ec) ? "be" : ec[0]}`, `that $SUBJ ${n ? " won't" : " will"} ${isToBe(ec) ? "be" : ec[0]}`,
`should $SUBJ ${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`, `should $SUBJ ${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
]), ]),
imperfectiveFuture: futureEngBuilder,
perfectiveFuture: futureEngBuilder,
imperfectivePast: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ imperfectivePast: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
// - subj pastEquative (N && "not") ec.2 obj // - subj pastEquative (N && "not") ec.2 obj
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${ec[2]}`, `$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${ec[2]}`,
@ -180,7 +189,8 @@ function renderEnglishVPBase({ subjectPerson, object, vs }: {
perfectivePast: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ perfectivePast: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ${isToBe(ec) `$SUBJ${isToBe(ec)
? ` ${engEquative("past", s)}${n ? " not" : ""}` ? ` ${engEquative("past", s)}${n ? " not" : ""}`
: `${n ? " did not" : ""} ${ec[3]}`}`, : (n ? ` did not ${ec[0]}` : ` ${ec[3]}`)
}`
]), ]),
}; };
const base = builders[tense](subjectPerson, ec, vs.negative); const base = builders[tense](subjectPerson, ec, vs.negative);
@ -252,12 +262,6 @@ function removeHead(head: T.PsString, rest: T.SingleOrLengthOpts<T.PsString[]>):
}); });
} }
function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
if ("long" in x) {
return x.long;
}
return x;
}
function getMatrixBlock<U>(f: { function getMatrixBlock<U>(f: {
mascSing: T.SingleOrLengthOpts<U>; mascSing: T.SingleOrLengthOpts<U>;
mascPlur: T.SingleOrLengthOpts<U>; mascPlur: T.SingleOrLengthOpts<U>;
@ -291,6 +295,12 @@ function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm
if (tense === "subjunctive") { if (tense === "subjunctive") {
return conj.perfective.nonImperative; return conj.perfective.nonImperative;
} }
if (tense === "imperfectiveFuture") {
return conj.imperfective.future;
}
if (tense === "perfectiveFuture") {
return conj.perfective.future;
}
if (tense === "imperfectivePast") { if (tense === "imperfectivePast") {
return conj.imperfective.past; return conj.imperfective.past;
} }
@ -371,18 +381,21 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur
} }
function isPerfective(t: VerbTense): boolean { function isPerfective(t: VerbTense): boolean {
if (t === "present" || t === "imperfectivePast") { if (t === "present" || t === "imperfectiveFuture" || t === "imperfectivePast") {
return false; return false;
} }
if (t === "perfectivePast" || t === "subjunctive") { if (t === "perfectiveFuture" || t === "subjunctive" || t === "perfectivePast") {
return true; return true;
} }
throw new Error("tense not implemented yet"); throw new Error("tense not implemented yet");
} }
function isSingularAnimatePattern4(np: NPSelection): boolean { function isMascSingAnimatePattern4(np: NPSelection): boolean {
if (np.type !== "noun") { if (np.type !== "noun") {
return false; return false;
} }
return isPattern4Entry(np.entry) && np.entry.c.includes("anim.") && (np.number === "singular"); return isPattern4Entry(np.entry)
&& np.entry.c.includes("anim.")
&& (np.number === "singular")
&& (np.gender === "masc");
} }

View File

@ -14,6 +14,13 @@ export function psStringFromEntry(entry: T.PsString): T.PsString {
}; };
} }
export function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
if ("long" in x) {
return x.long;
}
return x;
}
export function capitalizeFirstLetter(string: string) { export function capitalizeFirstLetter(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);
} }

View File

@ -25,7 +25,7 @@ type VPRendered = {
englishBase?: string[], englishBase?: string[],
} }
type VerbTense = "present" | "subjunctive" | "perfectivePast" | "imperfectivePast"; type VerbTense = "present" | "subjunctive" | "perfectiveFuture" | "imperfectiveFuture" | "perfectivePast" | "imperfectivePast";
type VerbSelection = { type VerbSelection = {
type: "verb", type: "verb",
@ -104,6 +104,7 @@ type Rendered<T extends NPSelection> = ReplaceKey<
ps: import("@lingdocs/pashto-inflector").Types.PsString[], ps: import("@lingdocs/pashto-inflector").Types.PsString[],
e?: string, e?: string,
inflected: boolean, inflected: boolean,
person: T.Person,
}; };
// TODO: recursive changing this down into the possesor etc. // TODO: recursive changing this down into the possesor etc.