fix not-allowed pronoun combos
This commit is contained in:
parent
a000731a4a
commit
5d632f095e
|
@ -7,12 +7,18 @@ import {
|
||||||
Types as T,
|
Types as T,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
const tenseOptions = [{
|
const tenseOptions: { label: string, value: VerbTense }[] = [{
|
||||||
label: "present",
|
label: "present",
|
||||||
value: "present",
|
value: "present",
|
||||||
}, {
|
}, {
|
||||||
label: "subjunctive",
|
label: "subjunctive",
|
||||||
value: "subjunctive",
|
value: "subjunctive",
|
||||||
|
}, {
|
||||||
|
label: "simple past",
|
||||||
|
value: "perfectivePast",
|
||||||
|
}, {
|
||||||
|
label: "continuous past",
|
||||||
|
value: "imperfectivePast",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): VerbSelection {
|
function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): VerbSelection {
|
||||||
|
@ -49,7 +55,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
|
||||||
}
|
}
|
||||||
onChange(makeVerbSelection(v, verb));
|
onChange(makeVerbSelection(v, verb));
|
||||||
}
|
}
|
||||||
function onTenseSelect({ value }: { label: string, value: "present" | "subjunctive" }) {
|
function onTenseSelect({ value }: { label: string, value: VerbTense }) {
|
||||||
if (verb) {
|
if (verb) {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...verb,
|
||||||
|
@ -80,7 +86,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
options={tenseOptions}
|
options={tenseOptions}
|
||||||
isSearchable
|
isSearchable
|
||||||
placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.value : "Select Tense..."}
|
placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."}
|
||||||
{...zIndexProps}
|
{...zIndexProps}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -4,6 +4,6 @@ title: Phrase Builder
|
||||||
|
|
||||||
import PhraseBuilder from "../../components/phrase-builder/PhraseBuilder";
|
import PhraseBuilder from "../../components/phrase-builder/PhraseBuilder";
|
||||||
|
|
||||||
This is under construction... It's not quite working yet. 👷🚧
|
##### This is under construction... It's not fully working yet. 👷🚧
|
||||||
|
|
||||||
<PhraseBuilder />
|
<PhraseBuilder />
|
|
@ -12,13 +12,39 @@ import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
randomPerson,
|
randomPerson,
|
||||||
randomSubjObj,
|
randomSubjObj,
|
||||||
|
isInvalidSubjObjCombo,
|
||||||
} from "../../lib/np-tools";
|
} from "../../lib/np-tools";
|
||||||
|
|
||||||
export function RPicker() {
|
export function RPicker() {
|
||||||
|
// TODO: Pull this into a type safe file
|
||||||
const startSubjObj = randomSubjObj();
|
const startSubjObj = randomSubjObj();
|
||||||
const [subject, setSubject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.subj });
|
const [subject, setSubject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.subj });
|
||||||
const [object, setObject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.obj });
|
const [object, setObject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.obj });
|
||||||
const [mode, setMode] = useState("single");
|
const [mode, setMode] = useState("single");
|
||||||
|
function handleSetSubject(incoming) {
|
||||||
|
if (mode !== "single" && isInvalidSubjObjCombo(incoming.person, object.person)) {
|
||||||
|
alert("That combination of pronouns is not allowed");
|
||||||
|
return;
|
||||||
|
// let newP = 0;
|
||||||
|
// do {
|
||||||
|
// newP = randomPerson();
|
||||||
|
// } while (isInvalidSubjObjCombo(newP, object.person));
|
||||||
|
// return setSubject({ ...incoming, person: newP });
|
||||||
|
}
|
||||||
|
return setSubject(incoming);
|
||||||
|
}
|
||||||
|
function handleSetObject(incoming) {
|
||||||
|
if (isInvalidSubjObjCombo(subject.person, incoming.person)) {
|
||||||
|
alert("That combination of pronouns is not allowed");
|
||||||
|
return;
|
||||||
|
// let newP = 0;
|
||||||
|
// do {
|
||||||
|
// newP = randomPerson();
|
||||||
|
// } while (isInvalidSubjObjCombo(newP, subject.person));
|
||||||
|
// return setObject({ ...incoming, person: newP });
|
||||||
|
}
|
||||||
|
return setObject(incoming);
|
||||||
|
}
|
||||||
function setRandomSubjObj() {
|
function setRandomSubjObj() {
|
||||||
const { subj, obj } = randomSubjObj();
|
const { subj, obj } = randomSubjObj();
|
||||||
setSubject(s => ({
|
setSubject(s => ({
|
||||||
|
@ -64,12 +90,12 @@ export function RPicker() {
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col my-2" style={{ maxWidth: "375px", margin: "0 auto" }}>
|
<div className="col my-2" style={{ maxWidth: "375px", margin: "0 auto" }}>
|
||||||
{mode === "subjObj" && <h5>Subject</h5>}
|
{mode === "subjObj" && <h5>Subject</h5>}
|
||||||
<PronounPicker pronoun={subject} onChange={setSubject} />
|
<PronounPicker pronoun={subject} onChange={handleSetSubject} />
|
||||||
</div>
|
</div>
|
||||||
{mode === "subjObj" &&
|
{mode === "subjObj" &&
|
||||||
<div className="col my-2" style={{ maxWidth: "375px", margin: "0 auto" }}>
|
<div className="col my-2" style={{ maxWidth: "375px", margin: "0 auto" }}>
|
||||||
<h5>Object</h5>
|
<h5>Object</h5>
|
||||||
<PronounPicker pronoun={object} onChange={setObject} isObject />
|
<PronounPicker pronoun={object} onChange={handleSetObject} isObject />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,22 +14,25 @@ import {
|
||||||
|
|
||||||
export function renderVP(VP: VPSelection): VPRendered {
|
export function renderVP(VP: VPSelection): VPRendered {
|
||||||
// TODO: Will be based on past tense etc
|
// TODO: Will be based on past tense etc
|
||||||
const king = "subject";
|
const isPast = isPastTense(VP.verb.tense);
|
||||||
// const servant = VP.object ? "object" : undefined;
|
const isTransitive = VP.object !== "none";
|
||||||
|
const { king, /* servant */ } = getKingAndServant(isPast, isTransitive);
|
||||||
|
console.log({ king, isPast, isTransitive });
|
||||||
const verbPerson = getPersonFromNP(VP[king]);
|
const verbPerson = getPersonFromNP(VP[king]);
|
||||||
const subjectPerson = getPersonFromNP(VP.subject);
|
const subjectPerson = getPersonFromNP(VP.subject);
|
||||||
|
// TODO: also don't inflect if it's a pattern one animate noun
|
||||||
|
const inflectSubject = isPast && isTransitive;
|
||||||
|
console.log({ inflectSubject });
|
||||||
const subject: Rendered<NPSelection> = {
|
const subject: Rendered<NPSelection> = {
|
||||||
...VP.subject,
|
...VP.subject,
|
||||||
inflected: false,
|
inflected: inflectSubject,
|
||||||
// TODO: possibility for inflecting
|
...textOfNP(VP.subject, inflectSubject, false),
|
||||||
...textOfNP(VP.subject, false, false),
|
|
||||||
};
|
};
|
||||||
const inflectObject = isFirstOrSecondPersPronoun(VP.object);
|
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
|
||||||
const object: "none" | Rendered<NPSelection> | T.Person.ThirdPlurMale = typeof VP.object === "object"
|
const object: "none" | Rendered<NPSelection> | T.Person.ThirdPlurMale = typeof VP.object === "object"
|
||||||
? {
|
? {
|
||||||
...VP.subject,
|
...VP.subject,
|
||||||
inflected: inflectObject,
|
inflected: inflectObject,
|
||||||
// TODO: possibility for inflecting
|
|
||||||
...textOfNP(VP.object, inflectObject, true),
|
...textOfNP(VP.object, inflectObject, true),
|
||||||
} : VP.object;
|
} : VP.object;
|
||||||
// TODO: error handle this?
|
// TODO: error handle this?
|
||||||
|
@ -64,11 +67,20 @@ export function compileVP(VP: VPRendered | VPSelection): { ps: T.SingleOrLengthO
|
||||||
if (VP.type === "VPSelection") {
|
if (VP.type === "VPSelection") {
|
||||||
return compileVP(renderVP(VP));
|
return compileVP(renderVP(VP));
|
||||||
}
|
}
|
||||||
|
function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
|
||||||
|
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 vPs = "long" in VP.verb.ps ? VP.verb.ps.long : VP.verb.ps;
|
||||||
// const vE = VP.verb.e;
|
const engSubj = VP.subject.e || undefined;
|
||||||
|
const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
|
||||||
|
// require all English parts for making the English phrase
|
||||||
|
const e = (VP.verb.e && engSubj && engObj) ? VP.verb.e.map(e => insertEWords(e, {
|
||||||
|
subject: engSubj,
|
||||||
|
object: engObj,
|
||||||
|
})) : undefined;
|
||||||
const obj = typeof VP.object === "object" ? VP.object : undefined;
|
const obj = typeof VP.object === "object" ? VP.object : undefined;
|
||||||
const ps = VP.subject.ps.flatMap(s => (
|
const ps = VP.subject.ps.flatMap(s => (
|
||||||
// TODO: fix double space thing
|
|
||||||
obj ? obj.ps.flatMap(o => (
|
obj ? obj.ps.flatMap(o => (
|
||||||
vPs.flatMap(v => (
|
vPs.flatMap(v => (
|
||||||
concatPsString(s, " ", o, " ", v)
|
concatPsString(s, " ", o, " ", v)
|
||||||
|
@ -77,7 +89,27 @@ export function compileVP(VP: VPRendered | VPSelection): { ps: T.SingleOrLengthO
|
||||||
concatPsString(s, " ", v)
|
concatPsString(s, " ", v)
|
||||||
))
|
))
|
||||||
));
|
));
|
||||||
return { ps };
|
return { ps, e };
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPastTense(tense: VerbTense): boolean {
|
||||||
|
return tense.toLowerCase().includes("past");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getKingAndServant(isPast: boolean, isTransitive: boolean):
|
||||||
|
{ king: "subject", servant: "object" } |
|
||||||
|
{ king: "object", servant: "subject" } |
|
||||||
|
{ king: "subject", servant: undefined } {
|
||||||
|
if (!isTransitive) {
|
||||||
|
return { king: "subject", servant: undefined };
|
||||||
|
}
|
||||||
|
return isPast ? {
|
||||||
|
king: "object",
|
||||||
|
servant: "subject",
|
||||||
|
} : {
|
||||||
|
king: "subject",
|
||||||
|
servant: "object",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlurMale): boolean {
|
function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlurMale): boolean {
|
||||||
|
@ -86,8 +118,8 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur
|
||||||
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 getPsVerbConjugation(conj: T.VerbConjugation, tense: "present" | "subjunctive", person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
const f = conj[tense === "present" ? "imperfective" : "perfective"].nonImperative;
|
const f = getTenseVerbForm(conj, tense);
|
||||||
// TODO: ability to grab the correct part of matrix
|
// TODO: ability to grab the correct part of matrix
|
||||||
const block = "mascSing" in f
|
const block = "mascSing" in f
|
||||||
? f.mascSing
|
? f.mascSing
|
||||||
|
@ -108,12 +140,28 @@ function getPsVerbConjugation(conj: T.VerbConjugation, tense: "present" | "subju
|
||||||
return grabFromBlock(block, pos);
|
return grabFromBlock(block, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm {
|
||||||
|
if (tense === "present") {
|
||||||
|
return conj.imperfective.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "subjunctive") {
|
||||||
|
return conj.perfective.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "imperfectivePast") {
|
||||||
|
return conj.imperfective.past;
|
||||||
|
}
|
||||||
|
if (tense === "perfectivePast") {
|
||||||
|
return conj.perfective.past;
|
||||||
|
}
|
||||||
|
throw new Error("unknown tense");
|
||||||
|
}
|
||||||
|
|
||||||
function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
|
function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
|
||||||
subjectPerson: T.Person,
|
subjectPerson: T.Person,
|
||||||
object: "none" | NPSelection | T.Person.ThirdPlurMale,
|
object: "none" | NPSelection | T.Person.ThirdPlurMale,
|
||||||
v: T.EnglishVerbConjugationEc,
|
v: T.EnglishVerbConjugationEc,
|
||||||
ep: string | undefined,
|
ep: string | undefined,
|
||||||
tense: "present" | "subjunctive",
|
tense: VerbTense,
|
||||||
n: boolean,
|
n: boolean,
|
||||||
}): string[] {
|
}): string[] {
|
||||||
function engEquative(tense: "past" | "present", s: T.Person): string {
|
function engEquative(tense: "past" | "present", s: T.Person): string {
|
||||||
|
@ -133,7 +181,7 @@ function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
|
||||||
return (v[2] === "being");
|
return (v[2] === "being");
|
||||||
}
|
}
|
||||||
const builders: Record<
|
const builders: Record<
|
||||||
string,
|
VerbTense,
|
||||||
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
|
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
|
||||||
> = {
|
> = {
|
||||||
present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
|
present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||||
|
@ -146,12 +194,28 @@ function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
|
||||||
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(v) ? "be" : v[0]}`,
|
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(v) ? "be" : v[0]}`,
|
||||||
`should $SUBJ ${n ? " not" : ""} ${isToBe(v) ? "be" : v[0]}`,
|
`should $SUBJ ${n ? " not" : ""} ${isToBe(v) ? "be" : v[0]}`,
|
||||||
]),
|
]),
|
||||||
|
imperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||||
|
// - subj pastEquative (N && "not") v.2 obj
|
||||||
|
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${v[2]}`,
|
||||||
|
// - subj "would" (N && "not") v.0 obj
|
||||||
|
`$SUBJ would${n ? " not" : ""} ${isToBe(v) ? "be" : v[0]}`,
|
||||||
|
// - subj pastEquative (N && "not") going to" v.0 obj
|
||||||
|
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} going to ${isToBe(v) ? "be" : v[0]}`,
|
||||||
|
]),
|
||||||
|
perfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||||
|
`$SUBJ${isToBe(v)
|
||||||
|
? ` ${engEquative("past", s)}${n ? " not" : ""}`
|
||||||
|
: `${n ? " did not" : ""} ${v[3]}`}`,
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
const base = builders[tense](subjectPerson, v, n);
|
const base = builders[tense](subjectPerson, v, n);
|
||||||
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
|
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale): T.Person {
|
function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale | "none"): T.Person {
|
||||||
|
if (np === "none") {
|
||||||
|
throw new Error("empty entity");
|
||||||
|
}
|
||||||
if (typeof np === "number") return np;
|
if (typeof np === "number") return np;
|
||||||
if (np.type === "participle") {
|
if (np.type === "participle") {
|
||||||
return T.Person.ThirdPlurMale;
|
return T.Person.ThirdPlurMale;
|
||||||
|
@ -166,20 +230,19 @@ function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale): T.Person {
|
||||||
|
|
||||||
function textOfNP(np: NPSelection, inflected: boolean, englishInflected: boolean): { ps: T.PsString[], e: string } {
|
function textOfNP(np: NPSelection, inflected: boolean, englishInflected: boolean): { ps: T.PsString[], e: string } {
|
||||||
if (np.type === "participle") {
|
if (np.type === "participle") {
|
||||||
// TODO: Implement ability to inflect participles
|
|
||||||
return textOfParticiple(np, inflected);
|
return textOfParticiple(np, inflected);
|
||||||
}
|
}
|
||||||
if (np.type === "pronoun") {
|
if (np.type === "pronoun") {
|
||||||
return textOfPronoun(np, inflected, englishInflected);
|
return textOfPronoun(np, inflected, englishInflected);
|
||||||
}
|
}
|
||||||
// TODO: Implement ability to inflect nouns
|
|
||||||
return textOfNoun(np, inflected);
|
return textOfNoun(np, inflected);
|
||||||
}
|
}
|
||||||
|
|
||||||
function textOfParticiple({ verb: { entry }}: ParticipleSelection, inflected: boolean): { ps: T.PsString[], e: string } {
|
function textOfParticiple({ verb: { entry }}: ParticipleSelection, inflected: boolean): { ps: T.PsString[], e: string } {
|
||||||
// TODO: ability to inflect participles
|
// TODO: ability to inflect participles
|
||||||
return {
|
return {
|
||||||
ps: [psStringFromEntry(entry)],
|
// 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),
|
e: getEnglishParticiple(entry),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -218,11 +281,11 @@ function textOfNoun(n: NounSelection, inflected: boolean): { ps: T.PsString[], e
|
||||||
const pashto = ((): T.PsString[] => {
|
const pashto = ((): T.PsString[] => {
|
||||||
const infs = inflectWord(n.entry);
|
const infs = inflectWord(n.entry);
|
||||||
const ps = n.number === "singular"
|
const ps = n.number === "singular"
|
||||||
? getInf(infs, "inflections", n.gender, false)
|
? getInf(infs, "inflections", n.gender, false, inflected)
|
||||||
: [
|
: [
|
||||||
...getInf(infs, "plural", n.gender, true),
|
...getInf(infs, "plural", n.gender, true, inflected),
|
||||||
...getInf(infs, "arabicPlural", n.gender, true),
|
...getInf(infs, "arabicPlural", n.gender, true, inflected),
|
||||||
...getInf(infs, "inflections", n.gender, true),
|
...getInf(infs, "inflections", n.gender, true, inflected),
|
||||||
];
|
];
|
||||||
return ps.length > 0
|
return ps.length > 0
|
||||||
? ps
|
? ps
|
||||||
|
@ -231,13 +294,14 @@ function textOfNoun(n: NounSelection, inflected: boolean): { ps: T.PsString[], e
|
||||||
return { ps: pashto, e: english };
|
return { ps: pashto, e: english };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: boolean): T.PsString[] {
|
function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: boolean, inflected: boolean): T.PsString[] {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (infs && t in infs && infs[t] !== undefined && gender in infs[t] && infs[t][gender] !== undefined) {
|
if (infs && t in infs && infs[t] !== undefined && gender in infs[t] && infs[t][gender] !== undefined) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const iset = infs[t][gender] as T.InflectionSet;
|
const iset = infs[t][gender] as T.InflectionSet;
|
||||||
const ipick = iset[(t === "inflections" && plural) ? 1 : 0];
|
const inflectionNumber = (inflected ? 1 : 0) + ((t === "inflections" && plural) ? 1 : 0);
|
||||||
return ipick;
|
console.log({ t, plural, inflectionNumber });
|
||||||
|
return iset[inflectionNumber];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export function randomPerson(p?: T.Person) {
|
||||||
return newP;
|
return newP;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
||||||
const firstPeople = [
|
const firstPeople = [
|
||||||
T.Person.FirstSingMale,
|
T.Person.FirstSingMale,
|
||||||
T.Person.FirstSingFemale,
|
T.Person.FirstSingFemale,
|
||||||
|
|
|
@ -20,10 +20,12 @@ type VPRendered = {
|
||||||
verb: VerbRendered,
|
verb: VerbRendered,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VerbTense = "present" | "subjunctive" | "perfectivePast" | "imperfectivePast";
|
||||||
|
|
||||||
type VerbSelection = {
|
type VerbSelection = {
|
||||||
type: "verb",
|
type: "verb",
|
||||||
verb: VerbEntry,
|
verb: VerbEntry,
|
||||||
tense: "present" | "subjunctive",
|
tense: VerbTense,
|
||||||
object: VerbObject,
|
object: VerbObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue