From f8964c67994ddd54309abebdc86011180ae44ac6 Mon Sep 17 00:00:00 2001 From: lingdocs <71590811+lingdocs@users.noreply.github.com> Date: Wed, 30 Mar 2022 15:47:22 +0500 Subject: [PATCH] got perfect working! (I think) --- src/components/VerbPicker.tsx | 88 +++++++++++++++---- src/lib/phrase-building/compile-vp.ts | 2 +- .../phrase-building/english-vp-rendering.ts | 57 ++++++++++-- src/lib/phrase-building/render-vp.ts | 51 ++++++++--- src/lib/phrase-building/vp-tools.ts | 10 ++- src/types/gen-g.d.ts | 14 +-- 6 files changed, 178 insertions(+), 44 deletions(-) diff --git a/src/components/VerbPicker.tsx b/src/components/VerbPicker.tsx index 66d468b..b4dfdd7 100644 --- a/src/components/VerbPicker.tsx +++ b/src/components/VerbPicker.tsx @@ -9,14 +9,15 @@ import { ButtonSelect, getVerbInfo, } from "@lingdocs/pashto-inflector"; +import { isEquativeTense } from "../lib/phrase-building/vp-tools"; // import { useState } from "react"; const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{ label:
present
, - value: "present", + value: "presentVerb", }, { label:
subjunctive
, - value: "subjunctive", + value: "subjunctiveVerb", }, { label:
imperf. future
, value: "imperfectiveFuture", @@ -37,6 +38,29 @@ const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{ value: "habitualPerfectivePast", }]; +const equativeTenseOptions: { label: string | JSX.Element, value: EquativeTense }[] = [{ + label: "Present Perfect", + value: "present", +}, { + label: "Habitual Perfect", + value: "habitual", +}, { + label: "Subjunctive Perfect", + value: "subjunctive", +}, { + label: "Future Perfect", + value: "future", +}, { + label: "Past Perfect", + value: "past", +}, { + label: "Would Be Perfect", + value: "wouldBe", +}, { + label: "Past Subjunctive Perfect", + value: "pastSubjunctive", +}]; + // type Filters = { // stative: boolean, // dynamic: boolean, @@ -62,12 +86,21 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS } onChange(makeVerbSelection(v, verb)); } - function onTenseSelect({ value }: { label: string, value: VerbTense }) { + function onTenseSelect({ value }: { label: string, value: VerbTense | EquativeTense }) { if (verb) { - onChange({ - ...verb, - tense: value, - }); + if (isEquativeTense(value)) { + onChange({ + ...verb, + tense: value, + tenseCategory: "perfect", + }); + } else { + onChange({ + ...verb, + tense: value, + tenseCategory: verb.tenseCategory === "perfect" ? "basic" : verb.tenseCategory, + }); + } } } function onPosNegSelect(value: string) { @@ -78,12 +111,21 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS }); } } - function onTenseCategorySelect(value: "basic" | "modal") { + function onTenseCategorySelect(value: "basic" | "modal" | "perfect") { if (verb) { - onChange({ - ...verb, - tenseCategory: value, - }); + if (value === "perfect") { + onChange({ + ...verb, + tenseCategory: value, + tense: isEquativeTense(verb.tense) ? verb.tense : "present", + }); + } else { + onChange({ + ...verb, + tenseCategory: value, + tense: isEquativeTense(verb.tense) ? "presentVerb" : verb.tense, + }); + } } } function notInstransitive(t: "transitive" | "intransitive" | "grammatically transitive"): "transitive" | "grammatically transitive" { @@ -123,6 +165,9 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS }, { label: "Modal", value: "modal", + }, { + label: "Perfect", + value: "perfect", }]} handleChange={onTenseCategorySelect} /> @@ -135,8 +180,13 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS onChange={onTenseSelect} className="mb-2" // @ts-ignore - options={tenseOptions} - placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."} + options={verb?.tenseCategory === "perfect" ? equativeTenseOptions : tenseOptions} + placeholder={verb ? (() => { + const label = (verb.tenseCategory === "perfect") + ? equativeTenseOptions.find(o => o.value === verb.tense)?.label + : tenseOptions.find(o => o.value === verb.tense)?.label; + return label || "Select Tense..."; + })() : undefined} {...zIndexProps} /> {verb &&
@@ -223,11 +273,17 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V type: "verb", verb: verb, dynAuxVerb, - tense: oldVerbSelection ? oldVerbSelection.tense : "present", + ...oldVerbSelection ? { + // TODO: carry it over from the old selection!! + tense: "presentVerb", + tenseCategory: "basic", + } : { + tense: "presentVerb", + tenseCategory: "basic", + }, object, transitivity, isCompound, - tenseCategory: oldVerbSelection ? oldVerbSelection.tenseCategory : "basic", negative: oldVerbSelection ? oldVerbSelection.negative : false, ...("grammaticallyTransitive" in info) ? { changeTransitivity: function (t) { diff --git a/src/lib/phrase-building/compile-vp.ts b/src/lib/phrase-building/compile-vp.ts index 6082b64..afbf14a 100644 --- a/src/lib/phrase-building/compile-vp.ts +++ b/src/lib/phrase-building/compile-vp.ts @@ -20,7 +20,7 @@ export function compileVP(VP: VPRendered, form: Form, combineLengths?: true): { NPs, kids, verb, - hasLeapfrog: VP.verb.tenseCategory === "modal", + hasLeapfrog: VP.verb.tenseCategory !== "basic", negative: VP.verb.negative, isCompound: VP.isCompound, }); diff --git a/src/lib/phrase-building/english-vp-rendering.ts b/src/lib/phrase-building/english-vp-rendering.ts index 014f7da..6481c4a 100644 --- a/src/lib/phrase-building/english-vp-rendering.ts +++ b/src/lib/phrase-building/english-vp-rendering.ts @@ -5,6 +5,16 @@ import { parseEc, } from "@lingdocs/pashto-inflector"; +function engHave(s: T.Person): string { + function isThirdPersonSing(p: T.Person): boolean { + return ( + p === T.Person.ThirdSingMale || + p === T.Person.ThirdSingFemale + ); + } + return isThirdPersonSing(s) ? "has" : "have"; +} + export function renderEnglishVPBase({ subjectPerson, object, vs }: { subjectPerson: T.Person, object: NPSelection | ObjectNP, @@ -12,7 +22,6 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: { }): string[] { const ec = parseEc(vs.verb.entry.ec || ""); const ep = vs.verb.entry.ep; - const tense = vs.tense; function engEquative(tense: "past" | "present", s: T.Person): string { const [row, col] = getVerbBlockPosFromPerson(s); return grammarUnits.englishEquative[tense][row][col]; @@ -33,17 +42,17 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: { `$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`, ]); // TODO: Pull these out to a seperate entity and import it - const builders: Record< + const basicBuilders: Record< VerbTense, (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[] > = { - present: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ + presentVerb: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ `$SUBJ ${isToBe(ec) ? `${engEquative("present", s)}${n ? " not" : ""}` : `${n ? engPresC(s, ["don't", "doesn't"]) : ""} ${n ? ec[0] : engPresC(s, ec)}`}`, `$SUBJ ${engEquative("present", s)}${n ? " not" : ""} ${ec[2]}`, ]), - subjunctive: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ + subjunctiveVerb: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([ `that $SUBJ ${n ? " won't" : " will"} ${isToBe(ec) ? "be" : ec[0]}`, `should $SUBJ ${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`, ]), @@ -76,10 +85,10 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: { VerbTense, (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[] > = { - present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + presentVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ `$SUBJ can${n ? "'t" : ""} ${isToBe(v) ? "be" : v[0]}`, ]), - subjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + subjunctiveVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ `that $SUBJ can${n ? "'t" : ""} ${isToBe(v) ? "be" : v[0]}`, ]), imperfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ @@ -105,6 +114,38 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: { `$SUBJ would ${n ? " not" : ""} be able to ${isToBe(v) ? "be" : v[0]}`, ]), }; - const base = (vs.tenseCategory === "basic" ? builders : modalBuilders)[tense](subjectPerson, ec, vs.negative); + const perfectBuilders: Record< + EquativeTense, + (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[] + > = { + present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ ${engHave(s)}${n ? " not" : ""} ${v[4]}`, + ]), + past: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ had${n ? " not" : ""} ${v[4]}`, + ]), + habitual: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ ${engHave(s)}${n ? " not" : ""} ${v[4]}`, + ]), + subjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `that $SUBJ will have${n ? " not" : ""} ${v[4]}`, + ]), + future: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ will${n ? " not" : ""} have ${v[4]}`, + ]), + wouldBe: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ would${n ? " not" : ""} have ${v[4]}`, + ]), + pastSubjunctive: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([ + `$SUBJ would${n ? " not" : ""} have ${v[4]}`, + `$SUBJ should${n ? " not" : ""} have ${v[4]}`, + ]), + } + const base = ( + (vs.tenseCategory === "perfect") + ? perfectBuilders[vs.tense] + : vs.tenseCategory === "basic" + ? basicBuilders[vs.tense] + : modalBuilders[vs.tense])(subjectPerson, ec, vs.negative); return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`); -} \ No newline at end of file +} diff --git a/src/lib/phrase-building/render-vp.ts b/src/lib/phrase-building/render-vp.ts index 3f561af..3bff533 100644 --- a/src/lib/phrase-building/render-vp.ts +++ b/src/lib/phrase-building/render-vp.ts @@ -19,6 +19,7 @@ import { getPersonFromNP, removeBa, isPastTense, + isEquativeTense, } from "./vp-tools"; import { isPattern4Entry } from "../type-predicates"; import { renderEnglishVPBase } from "./english-vp-rendering"; @@ -140,24 +141,24 @@ function renderVerbSelection(vs: VerbSelection, person: T.Person, objectPerson: return { ...vs, person, - ...getPsVerbConjugation(conj, vs.tense, vs.tenseCategory, person, objectPerson), + ...getPsVerbConjugation(conj, vs, person, objectPerson), } } -function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, tenseCategory: "basic" | "modal", person: T.Person, objectPerson: T.Person | undefined): { +function getPsVerbConjugation(conj: T.VerbConjugation, vs: VerbSelection, person: T.Person, objectPerson: T.Person | undefined): { ps: { head: T.PsString | undefined, rest: T.SingleOrLengthOpts, }, hasBa: boolean, } { - const f = getTenseVerbForm(conj, tense, tenseCategory); + const f = getTenseVerbForm(conj, vs.tense, vs.tenseCategory); const block = getMatrixBlock(f, objectPerson, person); - const perfective = isPerfective(tense); + const perfective = isPerfective(vs.tense); const verbForm = getVerbFromBlock(block, person); const hasBa = hasBaParticle(getLong(verbForm)[0]); if (perfective) { - const past = isPastTense(tense); + const past = isPastTense(vs.tense); const splitInfo = conj.info[past ? "root" : "stem"].perfectiveSplit; if (!splitInfo) return { ps: { head: undefined, rest: verbForm }, hasBa }; // TODO: Either solve this in the inflector or here, it seems silly (or redundant) @@ -253,12 +254,12 @@ function getMatrixBlock(f: { return f[personToLabel(person)]; } -function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense, tenseCategory: "basic" | "modal"): T.VerbForm { +function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense | EquativeTense, tenseCategory: "basic" | "modal" | "perfect"): T.VerbForm { if (tenseCategory === "basic") { - if (tense === "present") { + if (tense === "presentVerb") { return conj.imperfective.nonImperative; } - if (tense === "subjunctive") { + if (tense === "subjunctiveVerb") { return conj.perfective.nonImperative; } if (tense === "imperfectiveFuture") { @@ -280,11 +281,34 @@ function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense, tenseCatego return conj.perfective.habitualPast; } } - if (tenseCategory === "modal") { + if (tenseCategory === "perfect") { if (tense === "present") { - return conj.imperfective.modal.nonImperative; + return conj.perfect.present; + } + if (tense === "past") { + return conj.perfect.past; + } + if (tense === "future") { + return conj.perfect.future; + } + if (tense === "habitual") { + return conj.perfect.habitual; } if (tense === "subjunctive") { + return conj.perfect.subjunctive; + } + if (tense === "wouldBe") { + return conj.perfect.affirmational; + } + if (tense === "pastSubjunctive") { + return conj.perfect.pastSubjunctiveHypothetical; + } + } + if (tenseCategory === "modal") { + if (tense === "presentVerb") { + return conj.imperfective.modal.nonImperative; + } + if (tense === "subjunctiveVerb") { return conj.perfective.modal.nonImperative; } if (tense === "imperfectiveFuture") { @@ -376,11 +400,12 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur return [0,1,2,3,6,7,8,9].includes(o.person); } -function isPerfective(t: VerbTense): boolean { - if (t === "present" || t === "imperfectiveFuture" || t === "imperfectivePast" || t === "habitualImperfectivePast") { +function isPerfective(t: VerbTense | EquativeTense): boolean { + if (isEquativeTense(t)) return false; + if (t === "presentVerb" || t === "imperfectiveFuture" || t === "imperfectivePast" || t === "habitualImperfectivePast") { return false; } - if (t === "perfectiveFuture" || t === "subjunctive" || t === "perfectivePast" || t === "habitualPerfectivePast") { + if (t === "perfectiveFuture" || t === "subjunctiveVerb" || t === "perfectivePast" || t === "habitualPerfectivePast") { return true; } throw new Error("tense not implemented yet"); diff --git a/src/lib/phrase-building/vp-tools.ts b/src/lib/phrase-building/vp-tools.ts index e371d70..63f34c2 100644 --- a/src/lib/phrase-building/vp-tools.ts +++ b/src/lib/phrase-building/vp-tools.ts @@ -27,6 +27,14 @@ export function removeBa(ps: T.PsString): T.PsString { return psRemove(ps, concatPsString(grammarUnits.baParticle, " ")); } -export function isPastTense(tense: VerbTense): boolean { +export function isEquativeTense(t: VerbTense | EquativeTense): t is EquativeTense { + return (t === "present" || t === "future" || t === "habitual" || t === "past" || t === "wouldBe" || t === "subjunctive" || t === "pastSubjunctive"); +} + +export function isPastTense(tense: VerbTense | EquativeTense): boolean { + if (isEquativeTense(tense)) { + // equative tenses are used HERE for the perfect forms, which are all considered past tense + return true; + } return tense.toLowerCase().includes("past"); } \ No newline at end of file diff --git a/src/types/gen-g.d.ts b/src/types/gen-g.d.ts index d68d87d..9f40127 100644 --- a/src/types/gen-g.d.ts +++ b/src/types/gen-g.d.ts @@ -26,8 +26,8 @@ type VPRendered = { englishBase?: string[], } -type VerbTense = "present" - | "subjunctive" +type VerbTense = "presentVerb" + | "subjunctiveVerb" | "perfectiveFuture" | "imperfectiveFuture" | "perfectivePast" @@ -39,8 +39,6 @@ type VerbSelection = { type: "verb", verb: VerbEntry, dynAuxVerb?: VerbEntry, - tense: VerbTense, - tenseCategory: "basic" | "modal", object: VerbObject, // TODO: should have a locked in (but number changeable noun) here for dynamic compounds transitivity: import("@lingdocs/pashto-inflector").Types.Transitivity, isCompound: "stative" | "dynamic" | false, @@ -49,7 +47,13 @@ type VerbSelection = { // TODO: changeStativeDynamic // TODO: add in aspect element here?? negative: boolean, -}; +} & ({ + tense: VerbTense, + tenseCategory: "basic" | "modal", +} | { + tense: EquativeTense, + tenseCategory: "perfect" +}); type VerbRendered = Omit & { ps: {