diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..d949d6d
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "typescript.preferences.autoImportFileExcludePatterns": [
+ "../../library.ts"
+ ],
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 3f860a5..059d31c 100644
--- a/package.json
+++ b/package.json
@@ -76,6 +76,8 @@
]
},
"dependencies": {
+ "fp-ts": "^2.16.0",
+ "react-media-hook": "^0.5.0",
"react-select": "^5.4.0"
}
}
diff --git a/src/components/src/PersInfsPicker.tsx b/src/components/src/PersInfsPicker.tsx
index 24c7321..34c1e9a 100644
--- a/src/components/src/PersInfsPicker.tsx
+++ b/src/components/src/PersInfsPicker.tsx
@@ -9,50 +9,64 @@
import * as T from "../../types";
const persInfs: {
- label: string;
- value: T.PersonInflectionsField;
+ label: string;
+ value: T.PersonInflectionsField;
}[] = [
- {
- label: "masc. sing.",
- value: "mascSing",
- },
- {
- label: "fem. sing.",
- value: "femSing",
- },
- {
- label: "masc. plur.",
- value: "mascPlur",
- },
- {
- label: "fem. plur",
- value: "femPlur",
- }
+ {
+ label: "masc. sing.",
+ value: "mascSing",
+ },
+ {
+ label: "fem. sing.",
+ value: "femSing",
+ },
+ {
+ label: "masc. plur.",
+ value: "mascPlur",
+ },
+ {
+ label: "fem. plur",
+ value: "femPlur",
+ },
];
function PersInfsPicker(props: {
- transitivity: T.Transitivity,
- persInf: T.PersonInflectionsField,
- handleChange: (persInf: T.PersonInflectionsField) => void,
+ subjOrObj: "subject" | "object";
+ persInf: T.PersonInflectionsField;
+ handleChange: (persInf: T.PersonInflectionsField) => void;
}) {
- function hChange(e: any) {
- const newValue = e.target.value as T.PersonInflectionsField;
- props.handleChange(newValue);
- }
- return
-
- When the {props.transitivity === "intransitive" ? "subject" : "object"} is
-
-
-
-
-
;
+ function hChange(e: any) {
+ const newValue = e.target.value as T.PersonInflectionsField;
+ props.handleChange(newValue);
+ }
+ return (
+
+
+ When the {props.subjOrObj} is
+
+
+
+
+
+ );
}
-export default PersInfsPicker;
\ No newline at end of file
+export default PersInfsPicker;
diff --git a/src/components/src/TableCell.tsx b/src/components/src/TableCell.tsx
index f38bfce..88a4b46 100644
--- a/src/components/src/TableCell.tsx
+++ b/src/components/src/TableCell.tsx
@@ -3,50 +3,79 @@ import * as T from "../../types";
import Pashto from "./Pashto";
import Phonetics from "./Phonetics";
-const arrowDown = ;
+const arrowDown = (
+
+);
-function TableCell({ item, textOptions, center, noBorder }: {
- item: T.ArrayOneOrMore,
- textOptions: T.TextOptions,
- center?: boolean,
- noBorder?: boolean,
+function TableCell({
+ item,
+ textOptions,
+ center,
+ noBorder,
+}: {
+ item: T.PsString[];
+ textOptions: T.TextOptions;
+ center?: boolean;
+ noBorder?: boolean;
}) {
- const [version, setVersion] = useState(0);
- useEffect(() => setVersion(0), [item]);
- function advanceVersion() {
- setVersion((version + 1) % item.length);
- }
- const w = item[version] || item[0];
- return (
-
-
-
-
-
- {w.e && (Array.isArray(w.e)
- ? w.e.map(e => {e} )
- : {w.e} )}
+ const [version, setVersion] = useState(0);
+ useEffect(() => setVersion(0), [item]);
+ function advanceVersion() {
+ setVersion((version + 1) % item.length);
+ }
+ const w = item[version] || item[0];
+ return (
+
+
+
+
+
+ {w.e &&
+ (Array.isArray(w.e) ? (
+ w.e.map((e) => (
+
+ {e}
- {item.length > 1 &&
-
- }
-
- |
- );
+ ))
+ ) : (
+ {w.e}
+ ))}
+
+ {item.length > 1 && (
+
+ )}
+
+ |
+ );
}
-export default TableCell;
\ No newline at end of file
+export default TableCell;
diff --git a/src/components/src/VerbFormDisplay.tsx b/src/components/src/VerbFormDisplay.tsx
index abf5cfc..9e1e730 100644
--- a/src/components/src/VerbFormDisplay.tsx
+++ b/src/components/src/VerbFormDisplay.tsx
@@ -13,107 +13,157 @@ import SingleItemDisplay from "./SingleItemDisplay";
import ButtonSelect from "./ButtonSelect";
import VerbTable from "./VerbTable";
import {
- getEnglishPersonInfo,
- isSentenceForm,
+ getEnglishPersonInfo,
+ isSentenceForm,
} from "../../lib/src/misc-helpers";
-import {
- isAllOne,
-} from "../../lib/src/p-text-helpers";
+import { isAllOne } from "../../lib/src/p-text-helpers";
import * as T from "../../types";
-function agreementInfo(info: T.NonComboVerbInfo, displayForm: T.DisplayForm): React.ReactNode {
- if (!displayForm.past) {
- return null;
- }
- const beginning = "Verb agrees with the ";
- const agreesWith = (info.transitivity !== "intransitive" && displayForm.past && !displayForm.passive)
- ? "object"
- : "subject";
- const extraExplanation = (!displayForm.past)
- ? ""
- : (info.transitivity === "grammatically transitive")
- ? " which is an unwritten 3rd pers. masc. object."
- : (info.type === "generative stative compound" || info.type === "dynamic compound")
- ? ` which is the complement ${info.objComplement.plural ? info.objComplement.plural.p : info.objComplement.entry.p} (${getEnglishPersonInfo(info.objComplement.person)})`
- : ""
- return <>Note: {beginning}{agreesWith}{extraExplanation}>
+function agreementInfo(
+ info: T.NonComboVerbInfo,
+ displayForm: T.DisplayForm
+): React.ReactNode {
+ if (!displayForm.past) {
+ return null;
+ }
+ const beginning = "Verb agrees with the ";
+ const agreesWith =
+ info.transitivity !== "intransitive" &&
+ displayForm.past &&
+ !displayForm.passive
+ ? "object"
+ : "subject";
+ const extraExplanation = !displayForm.past
+ ? ""
+ : info.transitivity === "grammatically transitive"
+ ? " which is an unwritten 3rd pers. masc. object."
+ : info.type === "generative stative compound" ||
+ info.type === "dynamic compound"
+ ? ` which is the complement ${
+ info.objComplement.plural
+ ? info.objComplement.plural.p
+ : info.objComplement.entry.p
+ } (${getEnglishPersonInfo(info.objComplement.person)})`
+ : "";
+ return (
+ <>
+ Note: {beginning}
+ {agreesWith}
+ {extraExplanation}
+ >
+ );
}
-function VerbFormDisplay({ displayForm, textOptions, info, showingFormInfo, english, shortDefault }: {
- displayForm: T.DisplayForm | T.VerbForm | T.ImperativeForm,
- english?: T.EnglishBlock | string,
- textOptions: T.TextOptions,
- showingFormInfo: boolean,
- info?: T.NonComboVerbInfo,
- shortDefault?: boolean,
+function VerbFormDisplay({
+ displayForm,
+ textOptions,
+ info,
+ showingFormInfo,
+ english,
+ shortDefault,
+}: {
+ displayForm: T.DisplayForm | T.VerbForm | T.ImperativeForm;
+ english?: T.EnglishBlock | string;
+ textOptions: T.TextOptions;
+ showingFormInfo: boolean;
+ info?: T.NonComboVerbInfo;
+ shortDefault?: boolean;
}) {
- const defaultLength = shortDefault ? "short" : "long";
- const [persInf, setPersInf] = useState("mascSing");
- const [length, setLength] = useState(defaultLength);
- const [showingExplanation, setShowingExplanation] = useState(false);
- const block = "label" in displayForm ? displayForm.form : displayForm;
- const chosenPersInf = "mascSing" in block
- ? block[persInf]
- : block;
- const form = "long" in chosenPersInf
- ? chosenPersInf[length] || chosenPersInf.short
- : chosenPersInf;
- useEffect(() => {
- if (length === "mini" && !("mini" in chosenPersInf)) {
- setLength(defaultLength);
- }
- // setPersInf("mascSing");
- // setShowingExplanation(false);
- }, [block, length, chosenPersInf, defaultLength]);
- // TODO: This could be handled better to avoid the react-hooks/exhaustive-deps warning ?
- useEffect(() => {
- setShowingExplanation(false);
- }, [block]);
- const hasVariations = (!("masc" in form)) && (!("p" in form)) && (!isSentenceForm(form)) && !isAllOne(form as T.VerbBlock | T.ImperativeBlock);
- return <>
- {(("label" in displayForm && info) && showingFormInfo) && <>
- {(hasVariations || displayForm.past) &&
- {agreementInfo(info, displayForm)}
-
}
-
- Formula: {displayForm.formula}
-
-
- {showingExplanation &&
- {displayForm.explanation}
-
}
- >}
- {"long" in chosenPersInf &&
-
- setLength(p as T.Length)}
- />
-
- }
- {("mascSing" in block && info) && setPersInf(p)}
- transitivity={info.transitivity}
- />}
- {"masc" in form ?
-
- : "p" in form ?
-
- :
-
- }
+ const defaultLength = shortDefault ? "short" : "long";
+ const [persInf, setPersInf] = useState("mascSing");
+ const [length, setLength] = useState(defaultLength);
+ const [showingExplanation, setShowingExplanation] = useState(false);
+ const block = "label" in displayForm ? displayForm.form : displayForm;
+ const chosenPersInf = "mascSing" in block ? block[persInf] : block;
+ const form =
+ "long" in chosenPersInf
+ ? chosenPersInf[length] || chosenPersInf.short
+ : chosenPersInf;
+ useEffect(() => {
+ if (length === "mini" && !("mini" in chosenPersInf)) {
+ setLength(defaultLength);
+ }
+ // setPersInf("mascSing");
+ // setShowingExplanation(false);
+ }, [block, length, chosenPersInf, defaultLength]);
+ // TODO: This could be handled better to avoid the react-hooks/exhaustive-deps warning ?
+ useEffect(() => {
+ setShowingExplanation(false);
+ }, [block]);
+ const hasVariations =
+ !("masc" in form) &&
+ !("p" in form) &&
+ !isSentenceForm(form) &&
+ !isAllOne(form as T.VerbBlock | T.ImperativeBlock);
+ return (
+ <>
+ {"label" in displayForm && info && showingFormInfo && (
+ <>
+ {(hasVariations || displayForm.past) && (
+
+ {agreementInfo(info, displayForm)}
+
+ )}
+
+ Formula: {displayForm.formula}
+
+
+ {showingExplanation && (
+ {displayForm.explanation}
+ )}
+ >
+ )}
+ {"long" in chosenPersInf && (
+
+ setLength(p as T.Length)}
+ />
+
+ )}
+ {"mascSing" in block && info && (
+ setPersInf(p)}
+ subjOrObj={info.transitivity === "transitive" ? "object" : "subject"}
+ />
+ )}
+ {"masc" in form ? (
+
+ ) : "p" in form ? (
+
+ ) : (
+
+ )}
>
+ );
}
export default VerbFormDisplay;
diff --git a/src/components/src/verb-info/VerbInfo.tsx b/src/components/src/verb-info/VerbInfo.tsx
index 2024958..a6f76ce 100644
--- a/src/components/src/verb-info/VerbInfo.tsx
+++ b/src/components/src/verb-info/VerbInfo.tsx
@@ -6,14 +6,11 @@
*
*/
+import { CSSProperties, useState } from "react";
import {
- CSSProperties,
- useState,
-} from "react";
-import {
- pickPersInf,
- hasPersInfs,
- noPersInfs,
+ pickPersInf,
+ hasPersInfs,
+ noPersInfs,
} from "../../../lib/src/misc-helpers";
import VerbInfoItemDisplay from "./VerbInfoItemDisplay";
import PersonInfsPicker from "../PersInfsPicker";
@@ -26,56 +23,75 @@ import fadedTree from "./faded-tree.svg";
// import video from "../icons/camera-video-fill";
const indentR = {
- paddingLeft: "1rem",
+ paddingLeft: "1rem",
};
const highlight = {
- background: "rgba(255, 227, 10, 0.6)",
+ background: "rgba(255, 227, 10, 0.6)",
};
const title: CSSProperties = {
- fontWeight: "bolder",
- marginBottom: "0.5rem",
- marginTop: "0.5rem",
+ fontWeight: "bolder",
+ marginBottom: "0.5rem",
+ marginTop: "0.5rem",
};
-export function RootsAndStems({ textOptions, info, hidePastParticiple, highlighted, noTails }: {
- textOptions: T.TextOptions,
- info: T.NonComboVerbInfo | T.PassiveRootsAndStems | T.AbilityRootsAndStems,
- hidePastParticiple?: boolean,
- highlighted?: T.RootsOrStemsToHighlight,
- noTails?: boolean,
+export function RootsAndStems({
+ textOptions,
+ info,
+ hidePastParticiple,
+ highlighted,
+ noTails,
+}: {
+ textOptions: T.TextOptions;
+ info: T.NonComboVerbInfo | T.PassiveRootsAndStems | T.AbilityRootsAndStems;
+ hidePastParticiple?: boolean;
+ highlighted?: T.RootsOrStemsToHighlight;
+ noTails?: boolean;
}) {
- const hasPerfectiveSplit = ("perfectiveSplit" in info.root && "perfectiveSplit" in info.stem)
- && !!(info.root.perfectiveSplit || info.stem.perfectiveSplit);
- const showPersInf = hasPersInfs(info);
- const [persInf, setPersInf] = useState("mascSing");
- const [split, setSplit] = useState(false);
- const perfectiveStem = (info.stem.perfectiveSplit && split)
- ? info.stem.perfectiveSplit
- : info.stem.perfective;
- const perfectiveRoot = (info.root.perfectiveSplit && split)
- ? info.root.perfectiveSplit
- : info.root.perfective;
- const colClass = "col col-md-5 px-0 mb-1";
- const rowClass = "row justify-content-between";
- return (
-
- {showPersInf &&
setPersInf(p)}
- transitivity={"transitivity" in info ? info.transitivity : "intransitive"}
- />}
-
- {/*
("mascSing");
+ const [split, setSplit] = useState
(false);
+ const perfectiveStem =
+ info.stem.perfectiveSplit && split
+ ? info.stem.perfectiveSplit
+ : info.stem.perfective;
+ const perfectiveRoot =
+ info.root.perfectiveSplit && split
+ ? info.root.perfectiveSplit
+ : info.root.perfective;
+ const colClass = "col col-md-5 px-0 mb-1";
+ const rowClass = "row justify-content-between";
+ return (
+
+ {showPersInf && (
+
setPersInf(p)}
+ subjOrObj={
+ "transitivity" in info && info.transitivity === "intransitive"
+ ? "subject"
+ : "object"
+ }
+ />
+ )}
+
+ {/*
{info.def}
@@ -85,127 +101,158 @@ export function RootsAndStems({ textOptions, info, hidePastParticiple, highlight
{info.subDef}
} */}
-
-
-
-
-
-
-
-
-
-
- {hasPerfectiveSplit &&
-
-
}
-
-
-
-
-
- {!hidePastParticiple && "participle" in info &&
}
-
+
+
- );
-}
-
-function VerbInfo({ info, textOptions, showingStemsAndRoots, toggleShowingSar, highlightInRootsAndStems, hidePastParticiple, hideTypeInfo }: {
- info: T.NonComboVerbInfo,
- textOptions: T.TextOptions,
- showingStemsAndRoots: boolean,
- highlightInRootsAndStems?: T.RootsOrStemsToHighlight,
- toggleShowingSar: () => void,
- hidePastParticiple?: boolean,
- hideTypeInfo?: boolean,
-}) {
- const inf = noPersInfs(info.root.imperfective).long;
- return (
-
- {!hideTypeInfo &&
}
-
+
+
+
+
+ {hasPerfectiveSplit && (
+
+
+
+ )}
+
+
+
+
+
+
+
+ {!hidePastParticiple && "participle" in info && (
+
+ )}
- );
+
+
+ );
}
-export default VerbInfo;
\ No newline at end of file
+function VerbInfo({
+ info,
+ textOptions,
+ showingStemsAndRoots,
+ toggleShowingSar,
+ highlightInRootsAndStems,
+ hidePastParticiple,
+ hideTypeInfo,
+}: {
+ info: T.NonComboVerbInfo;
+ textOptions: T.TextOptions;
+ showingStemsAndRoots: boolean;
+ highlightInRootsAndStems?: T.RootsOrStemsToHighlight;
+ toggleShowingSar: () => void;
+ hidePastParticiple?: boolean;
+ hideTypeInfo?: boolean;
+}) {
+ const inf = noPersInfs(info.root.imperfective).long;
+ return (
+
+ {!hideTypeInfo && }
+
+
+
+
+ );
+}
+
+export default VerbInfo;
diff --git a/src/components/src/vp-explorer/AllTensesDisplay.tsx b/src/components/src/vp-explorer/AllTensesDisplay.tsx
index 2a44780..0d17f5c 100644
--- a/src/components/src/vp-explorer/AllTensesDisplay.tsx
+++ b/src/components/src/vp-explorer/AllTensesDisplay.tsx
@@ -1,59 +1,101 @@
-import { abilityTenseOptions, imperativeTenseOptions, perfectTenseOptions, verbTenseOptions } from "./verbTenseOptions";
+import {
+ abilityTenseOptions,
+ imperativeTenseOptions,
+ perfectTenseOptions,
+ verbTenseOptions,
+} from "./verbTenseOptions";
import ChartDisplay from "./VPChartDisplay";
import Hider from "../Hider";
import * as T from "../../../types";
import useStickyState from "../useStickyState";
-import { conjugateVerb } from "../../../lib/src/verb-conjugation";
+import { isImperativeTense } from "../../../lib/src/type-predicates";
+// import { conjugateVerb } from "../../../lib/src/verb-conjugation";
-function AllTensesDisplay({ VS, opts }: { VS: T.VerbSelection, opts: T.TextOptions }) {
- const [showing, setShowing] = useStickyState([], "VPTensesShowing");
- const [showFormulas, setShowFormulas] = useStickyState(false, "showFormulasWithCharts");
- const adjustShowing = (v: string) => {
- if (showing.includes(v)) {
- setShowing(os => os.filter(x => x !== v));
- } else {
- setShowing(os => [v, ...os]);
- }
+function AllTensesDisplay({
+ VS,
+ opts,
+}: {
+ VS: T.VerbSelection;
+ opts: T.TextOptions;
+}) {
+ const [showing, setShowing] = useStickyState([], "VPTensesShowing");
+ const [showFormulas, setShowFormulas] = useStickyState(
+ false,
+ "showFormulasWithCharts"
+ );
+ const adjustShowing = (v: string) => {
+ if (showing.includes(v)) {
+ setShowing((os) => os.filter((x) => x !== v));
+ } else {
+ setShowing((os) => [v, ...os]);
}
- const options = VS.tenseCategory === "basic"
- ? verbTenseOptions
- : VS.tenseCategory === "perfect"
- ? perfectTenseOptions
- : VS.tenseCategory === "modal"
- ? abilityTenseOptions
- : imperativeTenseOptions;
- const rawConjugations = conjugateVerb(VS.verb.entry, VS.verb.complement);
- const conjugations = ("stative" in rawConjugations)
- ? rawConjugations[VS.isCompound === "stative" ? "stative" : "dynamic"]
- : ("transitive" in rawConjugations)
- ? rawConjugations[VS.transitivity === "grammatically transitive" ? "grammaticallyTransitive" : "transitive"]
- : rawConjugations;
- function getTense(baseTense: T.VerbTense | T.PerfectTense | T.ImperativeTense): T.VerbTense | T.PerfectTense | T.ImperativeTense | T.AbilityTense {
- return VS.tenseCategory === "modal" ? `${baseTense}Modal` as T.AbilityTense : baseTense;
- }
- return
-
setShowFormulas(x => !x)}>
- 🧪 {!showFormulas ? "Show" : "Hide"} Formulas
-
- {options.map((tense) =>
+ };
+ const options =
+ VS.tenseCategory === "basic"
+ ? verbTenseOptions
+ : VS.tenseCategory === "perfect"
+ ? perfectTenseOptions
+ : VS.tenseCategory === "modal"
+ ? abilityTenseOptions
+ : imperativeTenseOptions;
+ // const rawConjugations = conjugateVerb(VS.verb.entry, VS.verb.complement);
+ // const conjugations =
+ // "stative" in rawConjugations
+ // ? rawConjugations[VS.isCompound === "stative" ? "stative" : "dynamic"]
+ // : "transitive" in rawConjugations
+ // ? rawConjugations[
+ // VS.transitivity === "grammatically transitive"
+ // ? "grammaticallyTransitive"
+ // : "transitive"
+ // ]
+ // : rawConjugations;
+ function getTense(
+ baseTense: T.VerbTense | T.PerfectTense | T.ImperativeTense
+ ): T.VerbTense | T.PerfectTense | T.ImperativeTense | T.AbilityTense {
+ return VS.tenseCategory === "modal"
+ ? (`${baseTense}Modal` as T.AbilityTense)
+ : baseTense;
+ }
+ return (
+
+
setShowFormulas((x) => !x)}
+ >
+ 🧪 {!showFormulas ? "Show" : "Hide"} Formulas
+
+ {options.map((tense) => {
+ const t = getTense(tense.value);
+ return (
+
adjustShowing(tense.value)}
- hLevel={5}
+ label={tense.label}
+ showing={showing.includes(tense.value)}
+ handleChange={() => adjustShowing(tense.value)}
+ hLevel={5}
>
- {showFormulas &&
- {tense.formula}
-
}
+ {showFormulas && (
+
+ {tense.formula}
+
+ )}
+ {showing && (
+ )}
-
)}
-
;
+
+ );
+ })}
+
+ );
}
-export default AllTensesDisplay;
\ No newline at end of file
+export default AllTensesDisplay;
diff --git a/src/components/src/vp-explorer/NewVerbFormDisplay.tsx b/src/components/src/vp-explorer/NewVerbFormDisplay.tsx
new file mode 100644
index 0000000..c26c989
--- /dev/null
+++ b/src/components/src/vp-explorer/NewVerbFormDisplay.tsx
@@ -0,0 +1,255 @@
+import { useEffect, useState } from "react";
+import ButtonSelect from "../ButtonSelect";
+import { combineIntoText } from "../../../lib/src/phrase-building/compile";
+import { insertNegative } from "../../../lib/src/phrase-building/render-vp";
+import * as T from "../../../types";
+import TableCell from "../TableCell";
+import { choosePersInf, getLength } from "../../../lib/src/p-text-helpers";
+import genderColors from "../gender-colors";
+import { eqPsStringWVars } from "../../../lib/src/fp-ps";
+import PersInfsPicker from "../PersInfsPicker";
+import { useMediaPredicate } from "react-media-hook";
+
+export const roleIcon = {
+ king: ,
+ servant: ,
+};
+
+function VerbChartDisplay({
+ chart,
+ opts,
+ shortDefault,
+ transitivity,
+ past,
+}: {
+ chart: T.OptionalPersonInflections<
+ T.SingleOrLengthOpts
+ >;
+ opts: T.TextOptions;
+ shortDefault?: boolean;
+ transitivity: T.Transitivity;
+ past: boolean;
+}) {
+ const [length, setLength] = useState(
+ shortDefault ? "short" : "long"
+ );
+ const [persInf, setPersInf] = useState("mascSing");
+ useEffect(() => {
+ setLength("long");
+ }, [chart]);
+ const desktop = useMediaPredicate("(min-width: 600px)");
+ const chartWPers = choosePersInf(chart, persInf);
+ const chartWLength = getLength(chartWPers, length);
+
+ const x = chartWLength.map(renderVerbOutputToText(false));
+ const verbBlock =
+ x.length === 12
+ ? [
+ // 1st pers
+ [
+ [x[0], x[6]],
+ [x[1], x[7]],
+ ],
+ // 2nd pers
+ [
+ [x[2], x[8]],
+ [x[3], x[9]],
+ ],
+ // 3rd pers
+ [
+ [x[4], x[10]],
+ [x[5], x[11]],
+ ],
+ ]
+ : [
+ // 2nd pers
+ [
+ [x[0], x[2]],
+ [x[1], x[3]],
+ ],
+ ];
+ return (
+ <>
+
+ {"mascSing" in chart ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {"long" in chartWPers && (
+
+ )}
+
+ {desktop &&
}
+
+
+
+
+
+ Pers.
+ |
+ Singular |
+ Plural |
+
+
+
+ {verbBlock.map((personRow, i) => (
+
+ ))}
+
+
+ >
+ );
+}
+
+function PersonRow({
+ person,
+ item,
+ opts,
+}: {
+ person: number;
+ item: T.PsString[][][];
+ opts: T.TextOptions;
+}) {
+ const [singM, singF] = [item[0][0], item[1][0]];
+ const [plurM, plurF] = [item[0][1], item[1][1]];
+ // just show one single, ungendered row if the gender doesn't make a difference
+ if (
+ eqPsStringWVars.equals(singM, singF) &&
+ eqPsStringWVars.equals(plurM, plurF)
+ ) {
+ return (
+
+ );
+ }
+ return (
+ <>
+
+
+ >
+ );
+}
+
+function GenderedPersonRow({
+ person,
+ line,
+ gender,
+ opts,
+}: {
+ person: number;
+ line: T.PsString[][];
+ gender: T.Gender | undefined;
+ opts: T.TextOptions;
+}) {
+ const pers = ["1st", "2nd", "3rd"]; // arr.length > 1 ? ["1st", "2nd", "3rd"] : ["2nd"];
+ const rowLabel = `${pers[person]}${
+ gender ? (gender === "masc" ? " m." : " f.") : ""
+ }`;
+ const color = !gender ? "inherit" : genderColors[gender];
+ return (
+
+
+ {rowLabel}
+ |
+
+
+
+ );
+}
+
+function LengthSelection({
+ value,
+ onChange,
+ hasMini,
+}: {
+ hasMini: boolean;
+ value: T.Length;
+ onChange: (v: T.Length) => void;
+}) {
+ return (
+
+ onChange(p as T.Length)}
+ />
+
+ );
+}
+
+function renderVerbOutputToText(negative: boolean) {
+ return function (v: T.RenderVerbOutput): T.PsString[] {
+ const blocks = insertNegative(
+ v.vbs,
+ negative,
+ false /* TODO: apply imperative */
+ );
+ return combineIntoText(blocks, 0 /* TODO: why is this needed */);
+ };
+}
+
+function AgreementInfo({
+ transitivity,
+ past,
+}: {
+ transitivity: T.Transitivity;
+ past: boolean;
+}) {
+ return (
+
+ {roleIcon.king} agrees w/{" "}
+
+ {transitivity !== "intransitive" && past ? "object" : "subject"}
+
+
+ );
+}
+
+export default VerbChartDisplay;
diff --git a/src/components/src/vp-explorer/VPChartDisplay.tsx b/src/components/src/vp-explorer/VPChartDisplay.tsx
index 46b5c6d..f93315d 100644
--- a/src/components/src/vp-explorer/VPChartDisplay.tsx
+++ b/src/components/src/vp-explorer/VPChartDisplay.tsx
@@ -1,24 +1,43 @@
-import {
- getTenseVerbForm,
-} from "../../../lib/src/phrase-building/vp-tools";
-import VerbFormDisplay from "../VerbFormDisplay";
+import NewVerbFormDisplay from "./NewVerbFormDisplay";
import * as T from "../../../types";
+import { buildVerbChart } from "./chart-builder";
+import { isPastTense } from "../../library";
-function ChartDisplay({ conjugations, tense, opts, voice }: {
- conjugations: T.VerbConjugation,
- tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense,
- opts: T.TextOptions,
- voice: T.VerbSelection["voice"],
+function ChartDisplay({
+ verb,
+ tense,
+ opts,
+ voice,
+ imperative,
+ negative,
+ transitivity,
+}: {
+ verb: T.VerbEntry;
+ tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
+ opts: T.TextOptions;
+ voice: T.VerbSelection["voice"];
+ imperative: boolean;
+ negative: boolean;
+ transitivity: T.Transitivity;
}) {
- const form = getTenseVerbForm(conjugations, tense, voice, "charts", false);
- return
-
-
;
+ const verbChart = buildVerbChart({
+ verb,
+ tense,
+ voice,
+ negative,
+ transitivity,
+ imperative,
+ });
+ return (
+
+
+
+ );
}
-export default ChartDisplay;
\ No newline at end of file
+export default ChartDisplay;
diff --git a/src/components/src/vp-explorer/chart-builder.tsx b/src/components/src/vp-explorer/chart-builder.tsx
new file mode 100644
index 0000000..a6c17b6
--- /dev/null
+++ b/src/components/src/vp-explorer/chart-builder.tsx
@@ -0,0 +1,157 @@
+import { renderVerb } from "../../../lib/src/new-verb-engine/render-verb";
+import * as T from "../../../types";
+import { equals } from "rambda";
+import { isPastTense } from "../../library";
+
+export function buildVerbChart({
+ verb,
+ tense,
+ transitivity,
+ voice,
+ imperative,
+ negative,
+}: {
+ verb: T.VerbEntry;
+ tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
+ transitivity: T.Transitivity;
+ imperative: boolean;
+ voice: T.VerbSelection["voice"];
+ negative: boolean;
+}): T.OptionalPersonInflections> {
+ const allPersons = imperative
+ ? [
+ T.Person.SecondSingMale,
+ T.Person.SecondSingFemale,
+ T.Person.SecondPlurMale,
+ T.Person.SecondPlurFemale,
+ ]
+ : ([...Array(12).keys()] as T.Person[]);
+ const isPast = isPastTense(tense);
+ function conjugateAllPers(
+ p?: T.Person
+ ): T.SingleOrLengthOpts {
+ const ps = allPersons.map((person) => {
+ const { subject, object } =
+ transitivity === "intransitive"
+ ? { subject: person, object: undefined }
+ : transitivity === "transitive" && isPast
+ ? { object: person, subject: 0 }
+ : { subject: person, object: p ?? 0 };
+ return renderVerb({
+ verb,
+ tense,
+ subject,
+ object,
+ voice,
+ negative,
+ });
+ });
+ const hasLengths = vIsLength("long")(ps[0]);
+ const hasMini = vIsLength("mini")(ps[0]);
+ return pullOutLengths(hasLengths, hasMini, ps);
+ }
+ if (transitivity === "transitive" && !isPast) {
+ return conflateIfNoCompGenNumDiff({
+ mascSing: conjugateAllPers(T.Person.FirstSingMale),
+ mascPlur: conjugateAllPers(T.Person.FirstPlurMale),
+ femSing: conjugateAllPers(T.Person.FirstSingFemale),
+ femPlur: conjugateAllPers(T.Person.FirstPlurFemale),
+ });
+ } else {
+ return conjugateAllPers();
+ }
+}
+
+const vIsLength =
+ (length: T.Length) =>
+ ({ vbs: [ph, [v]] }: T.RenderVerbOutput): boolean => {
+ // there are a number of parts of the verb that could be considered
+ // to be length variations
+ // but we will take the first main verb block as the point of length variation
+ // w reg verbs - wahúlm vs. wahúm
+ // (when welded, the right side of the block)
+ // w ability or perfect - kawúley shum vs. kawéy shum
+ function checkVBForLengths(v: T.VB): boolean {
+ if (v.type === "welded") {
+ return checkVBForLengths(v.right);
+ }
+ if (length === "mini" && "mini" in v.ps && v.ps.mini) {
+ return true;
+ }
+ return length in v.ps;
+ }
+ return checkVBForLengths(v);
+ };
+
+function grabLength(
+ length: T.Length,
+ { hasBa, vbs: [ph, v] }: T.RenderVerbOutput
+): T.RenderVerbOutput {
+ function grabVBLength(vb: V): V {
+ if (vb.type === "welded") {
+ return {
+ ...vb,
+ right: grabVBLength(vb.right) as T.VBBasic | T.VBGenNum,
+ };
+ }
+ if (!(length in vb.ps)) {
+ return vb;
+ }
+ return {
+ ...vb,
+ // @ts-ignore
+ ps: vb.ps[length],
+ };
+ }
+ if (v.length === 2) {
+ const [vb, vbe] = v;
+ return {
+ objComp: undefined,
+ hasBa,
+ vbs: [ph, [grabVBLength(vb), vbe]],
+ };
+ }
+ return {
+ objComp: undefined,
+ hasBa,
+ vbs: [ph, [grabVBLength(v[0])]],
+ };
+}
+
+function pullOutLengths(
+ hasLengths: boolean,
+ hasMini: boolean,
+ ps: T.RenderVerbOutput[]
+): T.SingleOrLengthOpts {
+ if (!hasLengths) {
+ return ps;
+ }
+ const wLengths: T.LengthOptions = {
+ long: [],
+ short: [],
+ };
+ ps.forEach((x) => {
+ wLengths.long.push(grabLength("long", x));
+ wLengths.short.push(grabLength("short", x));
+ });
+ if (hasMini) {
+ wLengths.mini = [];
+ ps.forEach((x) => {
+ // @ts-ignore
+ wLengths.mini.push(grabLength("mini", x));
+ });
+ }
+ return wLengths;
+}
+
+function conflateIfNoCompGenNumDiff(
+ v: T.PersonInflections>
+): T.OptionalPersonInflections> {
+ const toCheck = [
+ "femSing",
+ "femPlur",
+ "mascPlur",
+ ] as T.PersonInflectionsField[];
+ const diffExists = toCheck.some((f) => !equals(v[f], v.mascSing));
+ return diffExists ? v : v.mascSing;
+}
diff --git a/src/lib/src/fp-ps.ts b/src/lib/src/fp-ps.ts
new file mode 100644
index 0000000..f26caa7
--- /dev/null
+++ b/src/lib/src/fp-ps.ts
@@ -0,0 +1,43 @@
+import { Eq, struct } from "fp-ts/Eq";
+import { Semigroup } from "fp-ts/Semigroup";
+import { Monoid } from "fp-ts/Monoid";
+import * as S from "fp-ts/string";
+import * as T from "../../types";
+
+export const eqPsString: Eq = struct({
+ p: S.Eq,
+ f: S.Eq,
+});
+
+export const eqPsStringWVars: Eq = {
+ equals: (x, y) => {
+ return (
+ x.length === y.length && x.every((a, i) => eqPsString.equals(a, y[i]))
+ );
+ },
+};
+
+export const semigroupPsStringWVars: Semigroup = {
+ concat: (x, y) =>
+ x.flatMap((a) => y.map((b) => semigroupPsString.concat(a, b))),
+};
+
+export const semigroupPsString: Semigroup = {
+ concat: (x, y) => ({
+ p: x.p + y.p,
+ f: x.f + y.f,
+ }),
+};
+
+export const monoidPsString: Monoid = {
+ concat: semigroupPsString.concat,
+ empty: {
+ p: "",
+ f: "",
+ },
+};
+
+export const monoidPsStringWVars: Monoid = {
+ concat: semigroupPsStringWVars.concat,
+ empty: [monoidPsString.empty],
+};
diff --git a/src/lib/src/misc-helpers.ts b/src/lib/src/misc-helpers.ts
index 7e473b4..ab20bed 100644
--- a/src/lib/src/misc-helpers.ts
+++ b/src/lib/src/misc-helpers.ts
@@ -10,50 +10,51 @@ import * as T from "../../types";
import { fmapSingleOrLengthOpts } from "./fmaps";
export const blank: T.PsString = {
- p: "_____",
- f: "_____",
+ p: "_____",
+ f: "_____",
};
export const kidsBlank: T.PsString = { p: "___", f: "___" };
/**
* returns the main entry of a VerbEntry or just the entry of a DictionaryEntry
- *
+ *
* @param e FullEntry
* @returns DictionaryEntry
*/
export function entryOfFull(e: T.FullEntry): T.DictionaryEntry {
- return "entry" in e ? e.entry : e;
+ return "entry" in e ? e.entry : e;
}
// just for type safety
-export function noPersInfs(s: T.OptionalPersonInflections): S {
- if ("mascSing" in s) {
- // this path shouldn't be used, just for type safety
- return s.mascSing;
- }
- return s;
+export function noPersInfs(
+ s: T.OptionalPersonInflections
+): S {
+ if ("mascSing" in s) {
+ // this path shouldn't be used, just for type safety
+ return s.mascSing;
+ }
+ return s;
}
export function ensureNonComboVerbInfo(i: T.VerbInfo): T.NonComboVerbInfo {
- return "stative" in i
- ? i.stative
- : "transitive" in i
- ? i.transitive
- : i;
+ return "stative" in i ? i.stative : "transitive" in i ? i.transitive : i;
}
-export function pickPersInf(s: T.OptionalPersonInflections, persInf: T.PersonInflectionsField): T {
- // @ts-ignore
- if ("mascSing" in s) {
- return s[persInf];
- }
- return s;
+export function pickPersInf(
+ s: T.OptionalPersonInflections,
+ persInf: T.PersonInflectionsField
+): T {
+ // @ts-ignore
+ if ("mascSing" in s) {
+ return s[persInf];
+ }
+ return s;
}
export function getFirstSecThird(p: T.Person): 1 | 2 | 3 {
- if ([0, 1, 6, 7].includes(p)) return 1;
- if ([2, 3, 8, 9].includes(p)) return 2;
- return 3;
+ if ([0, 1, 6, 7].includes(p)) return 1;
+ if ([2, 3, 8, 9].includes(p)) return 2;
+ return 3;
}
// export function pickPersInf(
@@ -82,140 +83,169 @@ export function getFirstSecThird(p: T.Person): 1 | 2 | 3 {
// return s;
// }
-export function hasPersInfs(info: T.NonComboVerbInfo | T.PassiveRootsAndStems | T.AbilityRootsAndStems): boolean {
- if ("participle" in info) {
- return (
- "mascSing" in info.root.perfective ||
- "mascSing" in info.stem.perfective ||
- ("present" in info.participle && "mascSing" in info.participle.present) ||
- "mascSing" in info.participle.past
- );
- }
+export function hasPersInfs(
+ info: T.NonComboVerbInfo | T.PassiveRootsAndStems | T.AbilityRootsAndStems
+): boolean {
+ if ("participle" in info) {
return (
- "mascSing" in info.root.perfective ||
- "mascSing" in info.stem.perfective
+ "mascSing" in info.root.perfective ||
+ "mascSing" in info.stem.perfective ||
+ ("present" in info.participle && "mascSing" in info.participle.present) ||
+ "mascSing" in info.participle.past
);
+ }
+ return (
+ "mascSing" in info.root.perfective || "mascSing" in info.stem.perfective
+ );
}
// TODO: deprecated using new verb rendering thing
export function chooseParticipleInflection(
- pPartInfs: T.SingleOrLengthOpts | T.SingleOrLengthOpts,
- person: T.Person,
+ pPartInfs:
+ | T.SingleOrLengthOpts
+ | T.SingleOrLengthOpts,
+ person: T.Person
): T.SingleOrLengthOpts {
- if ("long" in pPartInfs) {
- return {
- short: chooseParticipleInflection(pPartInfs.short, person) as T.PsString,
- long: chooseParticipleInflection(pPartInfs.long, person) as T.PsString,
- };
- }
- if ("masc" in pPartInfs) {
- const gender = personGender(person);
- const infNum = personIsPlural(person) ? 1 : 0;
- return pPartInfs[gender][infNum][0];
- }
- return pPartInfs; // already just one thing
+ if ("long" in pPartInfs) {
+ return {
+ short: chooseParticipleInflection(pPartInfs.short, person) as T.PsString,
+ long: chooseParticipleInflection(pPartInfs.long, person) as T.PsString,
+ };
+ }
+ if ("masc" in pPartInfs) {
+ const gender = personGender(person);
+ const infNum = personIsPlural(person) ? 1 : 0;
+ return pPartInfs[gender][infNum][0];
+ }
+ return pPartInfs; // already just one thing
}
-export function getPersonNumber(gender: T.Gender, number: T.NounNumber): T.Person {
- const base = gender === "masc" ? 4 : 5;
- return base + (number === "singular" ? 0 : 6);
+export function getPersonNumber(
+ gender: T.Gender,
+ number: T.NounNumber
+): T.Person {
+ const base = gender === "masc" ? 4 : 5;
+ return base + (number === "singular" ? 0 : 6);
}
export function personFromVerbBlockPos(pos: [number, number]): T.Person {
- return pos[0] + (pos[1] === 1 ? 6 : 0);
+ return pos[0] + (pos[1] === 1 ? 6 : 0);
}
-export function getPersonInflectionsKey(person: T.Person): T.PersonInflectionsField {
- return `${personGender(person)}${personIsPlural(person) ? "Plur" : "Sing"}` as T.PersonInflectionsField;
+export function getPersonInflectionsKey(
+ person: T.Person
+): T.PersonInflectionsField {
+ return `${personGender(person)}${
+ personIsPlural(person) ? "Plur" : "Sing"
+ }` as T.PersonInflectionsField;
}
export function spaceInForm(form: T.FullForm): boolean {
- if ("mascSing" in form) {
- return spaceInForm(form.mascSing);
- }
- if ("long" in form) {
- return spaceInForm(form.long);
- }
- return form.p.includes(" ");
+ if ("mascSing" in form) {
+ return spaceInForm(form.mascSing);
+ }
+ if ("long" in form) {
+ return spaceInForm(form.long);
+ }
+ return form.p.includes(" ");
}
-export function getPersonFromVerbForm(form: T.SingleOrLengthOpts, person: T.Person): T.SentenceForm {
- return fmapSingleOrLengthOpts(x => {
- const [row, col] = getVerbBlockPosFromPerson(person);
- return x[row][col];
- }, form);
+export function getPersonFromVerbForm(
+ form: T.SingleOrLengthOpts,
+ person: T.Person
+): T.SentenceForm {
+ return fmapSingleOrLengthOpts((x) => {
+ const [row, col] = getVerbBlockPosFromPerson(person);
+ return x[row][col];
+ }, form);
}
-export function getVerbBlockPosFromPerson(person: T.Person): [0 | 1 | 2 | 3 | 4 | 5, 0 | 1] {
- const plural = personIsPlural(person)
- const row = (plural ? (person - 6) : person) as 0 | 1 | 2 | 3 | 4 | 5;
- const col = plural ? 1 : 0;
- return [row, col];
+export function getVerbBlockPosFromPerson(
+ person: T.Person
+): [0 | 1 | 2 | 3 | 4 | 5, 0 | 1] {
+ const plural = personIsPlural(person);
+ const row = (plural ? person - 6 : person) as 0 | 1 | 2 | 3 | 4 | 5;
+ const col = plural ? 1 : 0;
+ return [row, col];
}
-export function getAuxTransitivity(trans: T.Transitivity): "transitive" | "intransitive" {
- return trans === "intransitive" ? "intransitive" : "transitive";
+export function getAuxTransitivity(
+ trans: T.Transitivity
+): "transitive" | "intransitive" {
+ return trans === "intransitive" ? "intransitive" : "transitive";
}
export function personGender(person: T.Person): T.Gender {
- return person % 2 === 0 ? "masc" : "fem";
+ return person % 2 === 0 ? "masc" : "fem";
}
export function personNumber(person: T.Person): T.NounNumber {
- return personIsPlural(person) ? "plural" : "singular";
+ return personIsPlural(person) ? "plural" : "singular";
}
export function personIsPlural(person: T.Person): boolean {
- return person > 5;
+ return person > 5;
}
-export function getEnglishPersonInfo(person: T.Person, version?: "short" | "long"): string {
- const p = ([0,1,6,7].includes(person)
- ? "1st"
- : [2,3,8,9].includes(person)
- ? "2nd"
- : "3rd") + " pers.";
- const number = personIsPlural(person) ? "plur" : "sing";
- const n = version === "short"
- ? (number === "plur" ? "pl" : "sg") : number;
- const gender = personGender(person);
- const g = version === "short"
- ? (gender === "masc" ? "m" : "f")
- : gender;
- return `${p} ${n}. ${g}.`;
+export function getEnglishPersonInfo(
+ person: T.Person,
+ version?: "short" | "long"
+): string {
+ const p =
+ ([0, 1, 6, 7].includes(person)
+ ? "1st"
+ : [2, 3, 8, 9].includes(person)
+ ? "2nd"
+ : "3rd") + " pers.";
+ const number = personIsPlural(person) ? "plur" : "sing";
+ const n = version === "short" ? (number === "plur" ? "pl" : "sg") : number;
+ const gender = personGender(person);
+ const g = version === "short" ? (gender === "masc" ? "m" : "f") : gender;
+ return `${p} ${n}. ${g}.`;
}
-export function getEnglishGenNumInfo(gender: T.Gender, number: T.NounNumber): string {
- return `${gender === "masc" ? "masc" : "fem"} ${number === "plural" ? "plur." : "sing."}`;
+export function getEnglishGenNumInfo(
+ gender: T.Gender,
+ number: T.NounNumber
+): string {
+ return `${gender === "masc" ? "masc" : "fem"} ${
+ number === "plural" ? "plur." : "sing."
+ }`;
}
export function personToGenNum(p: T.Person): {
- gender: T.Gender,
- number: T.NounNumber,
+ gender: T.Gender;
+ number: T.NounNumber;
} {
- return {
- gender: personGender(p),
- number: personNumber(p),
- };
+ return {
+ gender: personGender(p),
+ number: personNumber(p),
+ };
}
-export function getEnglishParticipleInflection(person: T.Person, version?: "short" | "long"): string {
- const number = personIsPlural(person) ? "plural" : "singular";
- const n = version === "short"
- ? (number === "plural" ? "plur." : "sing.") : number;
- const gender = personGender(person);
- const g = gender;
- return `${g}. ${n}`;
+export function getEnglishParticipleInflection(
+ person: T.Person,
+ version?: "short" | "long"
+): string {
+ const number = personIsPlural(person) ? "plural" : "singular";
+ const n =
+ version === "short" ? (number === "plural" ? "plur." : "sing.") : number;
+ const gender = personGender(person);
+ const g = gender;
+ return `${g}. ${n}`;
}
-export function randomNumber(minInclusive: number, maxExclusive: number): number {
- return Math.floor(Math.random() * (maxExclusive - minInclusive) + minInclusive);
+export function randomNumber(
+ minInclusive: number,
+ maxExclusive: number
+): number {
+ return Math.floor(
+ Math.random() * (maxExclusive - minInclusive) + minInclusive
+ );
}
-export function randFromArray(arr: M[]): M {
- return arr[
- Math.floor(Math.random()*arr.length)
- ];
+export function randFromArray(arr: Readonly): M {
+ return arr[Math.floor(Math.random() * arr.length)];
}
export const isFirstPerson = (p: T.Person) => [0, 1, 6, 7].includes(p);
@@ -223,87 +253,92 @@ export const isSecondPerson = (p: T.Person) => [2, 3, 8, 9].includes(p);
export const isThirdPerson = (p: T.Person) => [4, 5, 10, 11].includes(p);
export function incrementPerson(p: T.Person): T.Person {
- return (p + 1) % 12;
+ return (p + 1) % 12;
}
export function isSentenceForm(f: any): boolean {
- if ("long" in f) {
- return isSentenceForm(f.long);
- }
- return Array.isArray(f) && "p" in f[0];
+ if ("long" in f) {
+ return isSentenceForm(f.long);
+ }
+ return Array.isArray(f) && "p" in f[0];
}
-export function isNounAdjOrVerb(entry: T.DictionaryEntry): "nounAdj" | "verb" | false {
- if (!entry.c) {
- return false;
- }
- if (entry.c.includes("adj.") || entry.c.includes("n. m.") || entry.c.includes("n. f.")) {
- return "nounAdj";
- }
- if (entry.c.slice(0, 3) === "v. ") {
- return "verb";
- }
+export function isNounAdjOrVerb(
+ entry: T.DictionaryEntry
+): "nounAdj" | "verb" | false {
+ if (!entry.c) {
return false;
+ }
+ if (
+ entry.c.includes("adj.") ||
+ entry.c.includes("n. m.") ||
+ entry.c.includes("n. f.")
+ ) {
+ return "nounAdj";
+ }
+ if (entry.c.slice(0, 3) === "v. ") {
+ return "verb";
+ }
+ return false;
}
/**
* takes the ec field from a dictionary entry and produces an array of an EnglishVerbConjugation
* for use with the conjugations display for showing English translation sentences of various verb
* forms and conjugations
- *
- * @param ec
- * @returns
+ *
+ * @param ec
+ * @returns
*/
export function parseEc(ec: string): T.EnglishVerbConjugationEc {
- function isVowel(s: string): boolean {
- return ["a", "e", "i", "o", "u"].includes(s);
+ function isVowel(s: string): boolean {
+ return ["a", "e", "i", "o", "u"].includes(s);
+ }
+ function makeRegularConjugations(s: string): T.EnglishVerbConjugationEc {
+ if (s === "get") {
+ return ["get", "gets", "getting", "got", "gotten"];
}
- function makeRegularConjugations(s: string): T.EnglishVerbConjugationEc {
- if (s === "get") {
- return ["get","gets","getting","got","gotten"];
- }
- if (s === "become") {
- return ["become","becomes","becoming","became","become"];
- }
- if (s === "make") {
- return ["make","makes","making","made","made"];
- }
- if (s === "have") {
- return ["have","has","having","had","had"];
- }
- if (s === "be") {
- return ["am","is","being","was","been"];
- }
- if ((s.slice(-1) === "y") && !isVowel(s.slice(-2)[0])) {
- const b = s.slice(0, -1);
- return [`${s}`, `${b}ies`, `${s}ing`, `${b}ied`, `${b}ied`];
- }
- if (s.slice(-2) === "ss") {
- return [`${s}`, `${s}es`, `${s}ing`, `${s}ed`, `${s}ed`];
- }
- if (s.slice(-2) === "ie" && !isVowel(s.slice(-3)[0])) {
- const b = s.slice(0, -2);
- return [`${s}`, `${s}s`, `${b}ying`, `${s}d`, `${s}d`];
- }
- const b = s === ""
- ? "VERB"
- : (s.slice(-1) === "e")
- ? s.slice(0, -1)
- : s;
- return [`${s}`, `${s}s`, `${b}ing`, `${b}ed`, `${b}ed`];
+ if (s === "become") {
+ return ["become", "becomes", "becoming", "became", "become"];
}
- const items = ec.split(",").map(x => x.trim());
- return (items.length === 4)
- ? [items[0], items[1], items[2], items[3], items[3]]
- : (items.length === 5)
- ? [items[0], items[1], items[2], items[3], items[4]]
- : makeRegularConjugations(items[0]);
+ if (s === "make") {
+ return ["make", "makes", "making", "made", "made"];
+ }
+ if (s === "have") {
+ return ["have", "has", "having", "had", "had"];
+ }
+ if (s === "be") {
+ return ["am", "is", "being", "was", "been"];
+ }
+ if (s.slice(-1) === "y" && !isVowel(s.slice(-2)[0])) {
+ const b = s.slice(0, -1);
+ return [`${s}`, `${b}ies`, `${s}ing`, `${b}ied`, `${b}ied`];
+ }
+ if (s.slice(-2) === "ss") {
+ return [`${s}`, `${s}es`, `${s}ing`, `${s}ed`, `${s}ed`];
+ }
+ if (s.slice(-2) === "ie" && !isVowel(s.slice(-3)[0])) {
+ const b = s.slice(0, -2);
+ return [`${s}`, `${s}s`, `${b}ying`, `${s}d`, `${s}d`];
+ }
+ const b = s === "" ? "VERB" : s.slice(-1) === "e" ? s.slice(0, -1) : s;
+ return [`${s}`, `${s}s`, `${b}ing`, `${b}ed`, `${b}ed`];
+ }
+ const items = ec.split(",").map((x) => x.trim());
+ return items.length === 4
+ ? [items[0], items[1], items[2], items[3], items[3]]
+ : items.length === 5
+ ? [items[0], items[1], items[2], items[3], items[4]]
+ : makeRegularConjugations(items[0]);
}
-export function chooseLength(x: T.SingleOrLengthOpts, length: "long" | "short"): N {
- // @ts-ignore
- if ("long" in x) {
- return x[length];
- }
- return x;
-}
\ No newline at end of file
+export function chooseLength(
+ x: T.SingleOrLengthOpts,
+ length: "long" | "short"
+): N {
+ // @ts-ignore
+ if ("long" in x) {
+ return x[length];
+ }
+ return x;
+}
diff --git a/src/lib/src/new-verb-engine/render-verb.test.ts b/src/lib/src/new-verb-engine/render-verb.test.ts
index c07109e..229ee7b 100644
--- a/src/lib/src/new-verb-engine/render-verb.test.ts
+++ b/src/lib/src/new-verb-engine/render-verb.test.ts
@@ -3,1070 +3,1664 @@ import { vEntry } from "./rs-helpers";
import * as T from "../../../types";
import { negate } from "rambda";
import { personToGenNum } from "../misc-helpers";
+import { getTransitivity } from "../verb-info";
-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 raawrul = vEntry({"ts":1527815214,"i":6954,"p":"راوړل","f":"raawRúl","g":"raawRul","e":"to bring, deliver (inanimate objects)","r":4,"c":"v. trans.","tppp":"راووړ","tppf":"raawoR","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"bring,brings,bringing,brought,brought"});
-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"});
-const ganul = vEntry({"ts":1527812000,"i":11398,"p":"ګڼل","f":"gaNul, guNul","g":"gaNul,guNul","e":"to count, consider, reckon, suppose, assume","r":4,"c":"v. trans.","tppp":"ګاڼه","tppf":"gaaNu","ec":"deem"});
-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 kawulDyn = vEntry({"ts":1527812752,"i":11031,"p":"کول","f":"kawul","g":"kawul","e":"to do (an action or activity)","r":4,"c":"v. trans./gramm. trans.","ssp":"وکړ","ssf":"óokR","prp":"وکړل","prf":"óokRul","pprtp":"کړی","pprtf":"kúRey","diacExcept":true,"ec":"do,does,doing,did,done","separationAtP":1,"separationAtF":2});
-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 kedulDyn = vEntry({"ts":1527812754,"i":11101,"p":"کېدل","f":"kedul","g":"kedul","e":"to happen, occur","r":2,"c":"v. intrans.","ssp":"وش","ssf":"óosh","prp":"وشول","prf":"óoshwul","pprtp":"شوی","pprtf":"shúwey","diacExcept":true,"ec":"happen","separationAtP":1,"separationAtF":2});
-const raatlul = vEntry({"ts":1527815216,"i":6875,"p":"راتلل","f":"raatlúl","g":"raatlul","e":"to come","r":4,"c":"v. intrans.","psp":"راځ","psf":"raadz","ssp":"راش","ssf":"ráash","prp":"راغلل","prf":"ráaghlul","pprtp":"راغلی","pprtf":"raaghúley","tppp":"راغی","tppf":"ráaghey","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"come,comes,coming,came,come"});
-const wartlul = vEntry({"ts":1585228579997,"i":14821,"p":"ورتلل","f":"wărtlul","g":"wartlul","e":"to come / go over to (third person or place)","r":4,"c":"v. intrans.","psp":"ورځ","psf":"wărdz","ssp":"ورش","ssf":"wársh","prp":"ورغلل","prf":"wárghlul","pprtp":"ورغلی","pprtf":"wărghúley","tppp":"ورغی","tppf":"wărghey","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"come,comes,coming,came,come"});
-const osedul = vEntry({"ts":1527815139,"i":1127,"p":"اوسېدل","f":"osedul","g":"osedul","e":"to live, reside, stay, be","r":4,"c":"v. intrans.","shortIntrans":true,"diacExcept":true});
-const tlul = vEntry({"ts":1527815348,"i":3791,"p":"تلل","f":"tlul","g":"tlul","e":"to go","r":4,"c":"v. intrans.","psp":"ځ","psf":"dz","ssp":"لاړ ش","ssf":"láaR sh","prp":"لاړ","prf":"láaR","ec":"go,goes,going,went,gone"});
-const awuxtul = vEntry({"ts":1527814012,"i":1133,"p":"اوښتل","f":"awUxtul","g":"awUxtul","e":"to pass over, overturn, be flipped over, spill over, shift, change, diverge, pass, cross, abandon; to be sprained","r":4,"c":"v. intrans.","psp":"اوړ","psf":"awR","ec":"pass","ep":"over"});
-const khorul = vEntry({"ts":1527812790,"i":6002,"p":"خوړل","f":"khoRul","g":"khoRul","e":"to eat, to bite","r":4,"c":"v. trans.","psp":"خور","psf":"khor","tppp":"خوړ","tppf":"khoR","ec":"eat,eats,eating,ate,eaten"});
-const azmoyul = vEntry({"ts":1527811605,"i":468,"p":"ازمویل","f":"azmoyul","g":"azmoyul","e":"to attempt, try; to experiment, test","r":4,"c":"v. trans.","sepOo":true,"ec":"try"});
-const khatul = vEntry({"ts":1527814025,"i":5677,"p":"ختل","f":"khatul","g":"khatul","e":"to climb, ascend, rise, go up; to fall out, to fall off, to leave/dissapear; to turn out to be ...; to give a sentence (in law)","r":3,"c":"v. intrans.","psp":"خېژ","psf":"khejz","tppp":"خوت","tppf":"khot","ec":"climb"});
-const rasedul = vEntry({"ts":1527813573,"i":7057,"p":"رسېدل","f":"rasedul","g":"rasedul","e":"arrive, reach; (fig.) understand, attain to; mature, ripen","r":4,"c":"v. intrans.","shortIntrans":true,"ec":"arrive"});
-const weshul = vEntry({"ts":1527811701,"i":15106,"p":"وېشل","f":"weshul","g":"weshul","e":"divide, distribute, share","r":4,"c":"v. trans.","ec":"divide"});
-const watul = vEntry({"ts":1527823376,"i":14759,"p":"وتل","f":"watul","g":"watul","e":"to go out, exit, leave, emerge","r":4,"c":"v. intrans.","psp":"وځ","psf":"oodz","tppp":"واته","tppf":"waatu","ec":"go,goes,going,went,gone","ep":"out"});
-const wurul = vEntry({"ts":1527816865,"i":14903,"p":"وړل","f":"wuRúl, oRúl, wRul","g":"wuRul,oRul,wRul","e":"to take, carry, bear, move (inanimate objects); to win, earn (subjunctive یوسي - yósee or ویسي - wéesee, simple past یو یې وړلو - yo ye wRulo)","r":3,"c":"v. trans.","ssp":"یوس","ssf":"yos","prp":"یوړل","prf":"yóRul","tppp":"یوړ","tppf":"yoR","noOo":true,"separationAtP":2,"separationAtF":2,"diacExcept":true,"ec":"take,takes,taking,took,taken"});
-const kexodul = vEntry({"ts":1527812284,"i":11113,"p":"کېښودل","f":"kexodul","g":"kexodul","e":"to put, to put down, to set in place","r":4,"c":"v. trans.","psp":"ږد","psf":"Gd","ssp":"کېږد","ssf":"kéGd","noOo":true,"separationAtP":2,"separationAtF":2,"ec":"put,puts,putting,put,put"});
-const kenaastul = vEntry({"ts":1527812759,"i":11124,"p":"کېناستل","f":"kenaastul","g":"kenaastul","e":"to sit down, to have a seat","r":4,"c":"v. intrans.","psp":"کېن","psf":"ken","noOo":true,"separationAtP":2,"separationAtF":2,"ec":"sit,sits,sitting,sat","ep":"down"});
-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 leedul = vEntry({"ts":1527812275,"i":12049,"p":"لیدل","f":"leedul","g":"leedul","e":"to see","r":4,"c":"v. trans./gramm. trans.","psp":"وین","psf":"ween","tppp":"لید","tppf":"leed","ec":"see,sees,seeing,saw,seen"});
+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 raawrul = vEntry({
+ ts: 1527815214,
+ i: 6954,
+ p: "راوړل",
+ f: "raawRúl",
+ g: "raawRul",
+ e: "to bring, deliver (inanimate objects)",
+ r: 4,
+ c: "v. trans.",
+ tppp: "راووړ",
+ tppf: "raawoR",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 3,
+ ec: "bring,brings,bringing,brought,brought",
+});
+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",
+});
+const ganul = vEntry({
+ ts: 1527812000,
+ i: 11398,
+ p: "ګڼل",
+ f: "gaNul, guNul",
+ g: "gaNul,guNul",
+ e: "to count, consider, reckon, suppose, assume",
+ r: 4,
+ c: "v. trans.",
+ tppp: "ګاڼه",
+ tppf: "gaaNu",
+ ec: "deem",
+});
+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 kawulDyn = vEntry({
+ ts: 1527812752,
+ i: 11031,
+ p: "کول",
+ f: "kawul",
+ g: "kawul",
+ e: "to do (an action or activity)",
+ r: 4,
+ c: "v. trans./gramm. trans.",
+ ssp: "وکړ",
+ ssf: "óokR",
+ prp: "وکړل",
+ prf: "óokRul",
+ pprtp: "کړی",
+ pprtf: "kúRey",
+ diacExcept: true,
+ ec: "do,does,doing,did,done",
+ separationAtP: 1,
+ separationAtF: 2,
+});
+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 kedulDyn = vEntry({
+ ts: 1527812754,
+ i: 11101,
+ p: "کېدل",
+ f: "kedul",
+ g: "kedul",
+ e: "to happen, occur",
+ r: 2,
+ c: "v. intrans.",
+ ssp: "وش",
+ ssf: "óosh",
+ prp: "وشول",
+ prf: "óoshwul",
+ pprtp: "شوی",
+ pprtf: "shúwey",
+ diacExcept: true,
+ ec: "happen",
+ separationAtP: 1,
+ separationAtF: 2,
+});
+const raatlul = vEntry({
+ ts: 1527815216,
+ i: 6875,
+ p: "راتلل",
+ f: "raatlúl",
+ g: "raatlul",
+ e: "to come",
+ r: 4,
+ c: "v. intrans.",
+ psp: "راځ",
+ psf: "raadz",
+ ssp: "راش",
+ ssf: "ráash",
+ prp: "راغلل",
+ prf: "ráaghlul",
+ pprtp: "راغلی",
+ pprtf: "raaghúley",
+ tppp: "راغی",
+ tppf: "ráaghey",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 3,
+ ec: "come,comes,coming,came,come",
+});
+const wartlul = vEntry({
+ ts: 1585228579997,
+ i: 14821,
+ p: "ورتلل",
+ f: "wărtlul",
+ g: "wartlul",
+ e: "to come / go over to (third person or place)",
+ r: 4,
+ c: "v. intrans.",
+ psp: "ورځ",
+ psf: "wărdz",
+ ssp: "ورش",
+ ssf: "wársh",
+ prp: "ورغلل",
+ prf: "wárghlul",
+ pprtp: "ورغلی",
+ pprtf: "wărghúley",
+ tppp: "ورغی",
+ tppf: "wărghey",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 3,
+ ec: "come,comes,coming,came,come",
+});
+const osedul = vEntry({
+ ts: 1527815139,
+ i: 1127,
+ p: "اوسېدل",
+ f: "osedul",
+ g: "osedul",
+ e: "to live, reside, stay, be",
+ r: 4,
+ c: "v. intrans.",
+ shortIntrans: true,
+ diacExcept: true,
+});
+const tlul = vEntry({
+ ts: 1527815348,
+ i: 3791,
+ p: "تلل",
+ f: "tlul",
+ g: "tlul",
+ e: "to go",
+ r: 4,
+ c: "v. intrans.",
+ psp: "ځ",
+ psf: "dz",
+ ssp: "لاړ ش",
+ ssf: "láaR sh",
+ prp: "لاړ",
+ prf: "láaR",
+ ec: "go,goes,going,went,gone",
+});
+const awuxtul = vEntry({
+ ts: 1527814012,
+ i: 1133,
+ p: "اوښتل",
+ f: "awUxtul",
+ g: "awUxtul",
+ e: "to pass over, overturn, be flipped over, spill over, shift, change, diverge, pass, cross, abandon; to be sprained",
+ r: 4,
+ c: "v. intrans.",
+ psp: "اوړ",
+ psf: "awR",
+ ec: "pass",
+ ep: "over",
+});
+const khorul = vEntry({
+ ts: 1527812790,
+ i: 6002,
+ p: "خوړل",
+ f: "khoRul",
+ g: "khoRul",
+ e: "to eat, to bite",
+ r: 4,
+ c: "v. trans.",
+ psp: "خور",
+ psf: "khor",
+ tppp: "خوړ",
+ tppf: "khoR",
+ ec: "eat,eats,eating,ate,eaten",
+});
+const azmoyul = vEntry({
+ ts: 1527811605,
+ i: 468,
+ p: "ازمویل",
+ f: "azmoyul",
+ g: "azmoyul",
+ e: "to attempt, try; to experiment, test",
+ r: 4,
+ c: "v. trans.",
+ sepOo: true,
+ ec: "try",
+});
+const khatul = vEntry({
+ ts: 1527814025,
+ i: 5677,
+ p: "ختل",
+ f: "khatul",
+ g: "khatul",
+ e: "to climb, ascend, rise, go up; to fall out, to fall off, to leave/dissapear; to turn out to be ...; to give a sentence (in law)",
+ r: 3,
+ c: "v. intrans.",
+ psp: "خېژ",
+ psf: "khejz",
+ tppp: "خوت",
+ tppf: "khot",
+ ec: "climb",
+});
+const rasedul = vEntry({
+ ts: 1527813573,
+ i: 7057,
+ p: "رسېدل",
+ f: "rasedul",
+ g: "rasedul",
+ e: "arrive, reach; (fig.) understand, attain to; mature, ripen",
+ r: 4,
+ c: "v. intrans.",
+ shortIntrans: true,
+ ec: "arrive",
+});
+const weshul = vEntry({
+ ts: 1527811701,
+ i: 15106,
+ p: "وېشل",
+ f: "weshul",
+ g: "weshul",
+ e: "divide, distribute, share",
+ r: 4,
+ c: "v. trans.",
+ ec: "divide",
+});
+const watul = vEntry({
+ ts: 1527823376,
+ i: 14759,
+ p: "وتل",
+ f: "watul",
+ g: "watul",
+ e: "to go out, exit, leave, emerge",
+ r: 4,
+ c: "v. intrans.",
+ psp: "وځ",
+ psf: "oodz",
+ tppp: "واته",
+ tppf: "waatu",
+ ec: "go,goes,going,went,gone",
+ ep: "out",
+});
+const wurul = vEntry({
+ ts: 1527816865,
+ i: 14903,
+ p: "وړل",
+ f: "wuRúl, oRúl, wRul",
+ g: "wuRul,oRul,wRul",
+ e: "to take, carry, bear, move (inanimate objects); to win, earn (subjunctive یوسي - yósee or ویسي - wéesee, simple past یو یې وړلو - yo ye wRulo)",
+ r: 3,
+ c: "v. trans.",
+ ssp: "یوس",
+ ssf: "yos",
+ prp: "یوړل",
+ prf: "yóRul",
+ tppp: "یوړ",
+ tppf: "yoR",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ diacExcept: true,
+ ec: "take,takes,taking,took,taken",
+});
+const kexodul = vEntry({
+ ts: 1527812284,
+ i: 11113,
+ p: "کېښودل",
+ f: "kexodul",
+ g: "kexodul",
+ e: "to put, to put down, to set in place",
+ r: 4,
+ c: "v. trans.",
+ psp: "ږد",
+ psf: "Gd",
+ ssp: "کېږد",
+ ssf: "kéGd",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ ec: "put,puts,putting,put,put",
+});
+const kenaastul = vEntry({
+ ts: 1527812759,
+ i: 11124,
+ p: "کېناستل",
+ f: "kenaastul",
+ g: "kenaastul",
+ e: "to sit down, to have a seat",
+ r: 4,
+ c: "v. intrans.",
+ psp: "کېن",
+ psf: "ken",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ ec: "sit,sits,sitting,sat",
+ ep: "down",
+});
+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 leedul = vEntry({
+ ts: 1527812275,
+ i: 12049,
+ p: "لیدل",
+ f: "leedul",
+ g: "leedul",
+ e: "to see",
+ r: 4,
+ c: "v. trans./gramm. trans.",
+ psp: "وین",
+ psf: "ween",
+ tppp: "لید",
+ tppf: "leed",
+ ec: "see,sees,seeing,saw,seen",
+});
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."},
+ {
+ 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."},
+ {
+ 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."},
+ {
+ 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."},
+ {
+ 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" }};
+const ooPh: T.PH = { type: "PH", ps: { p: "و", f: "óo" } };
test("basic tenses", () => {
- expect(renderVerb({
- verb: wahul,
- tense: "presentVerb",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
-
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهم", f: "wahum" }], person: T.Person.FirstSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "subjunctiveVerb",
- person: T.Person.SecondSingMale,
- complementGenNum: personToGenNum(T.Person.SecondSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [{ type: "PH", ps: { f: "óo", p: "و" }}],
- [
- { type: "VB", ps: [{ p: "وهې", f: "wahe" }], person: T.Person.SecondSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "habitualPerfectivePast",
- person: T.Person.ThirdSingFemale,
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: true,
- vbs: [
- [{ type: "PH", ps: { f: "óo", p: "و" }}],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "وهله", f: "wahula" }],
- short: [{ p: "وهه", f: "waha" }],
- },
- person: T.Person.ThirdSingFemale
- },
- ],
- ],
- });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "presentVerb",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهم", f: "wahum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "subjunctiveVerb",
+ subject: T.Person.SecondSingMale,
+ object: T.Person.ThirdPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [{ type: "PH", ps: { f: "óo", p: "و" } }],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهې", f: "wahe" }],
+ person: T.Person.SecondSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "habitualPerfectivePast",
+ subject: T.Person.ThirdSingMale,
+ object: T.Person.ThirdSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: true,
+ vbs: [
+ [{ type: "PH", ps: { f: "óo", p: "و" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "وهله", f: "wahula" }],
+ short: [{ p: "وهه", f: "waha" }],
+ },
+ person: T.Person.ThirdSingFemale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "presentVerb",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهم", f: "wahum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "subjunctiveVerb",
+ subject: T.Person.SecondSingMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [{ type: "PH", ps: { f: "óo", p: "و" } }],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهې", f: "wahe" }],
+ person: T.Person.SecondSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "habitualPerfectivePast",
+ subject: T.Person.FirstSingFemale,
+ object: T.Person.ThirdSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: true,
+ vbs: [
+ [{ type: "PH", ps: { f: "óo", p: "و" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "وهله", f: "wahula" }],
+ short: [{ p: "وهه", f: "waha" }],
+ },
+ person: T.Person.ThirdSingFemale,
+ },
+ ],
+ ],
+ });
});
test("basic tenses with inflecting roots/stems", () => {
- expect(renderVerb({
- verb: bandawul,
- tense: "subjunctiveVerb",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [
- {
- type: "NComp",
- comp: {
- type: "AdjComp",
- ps: { p: "بنده", f: "bánda" },
- gender: "fem",
- number: "singular",
- },
- },
- ],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "کړم", f: "kRum" }],
- short: [{ p: "کم", f: "kum" }],
- },
- person: T.Person.FirstSingMale,
- },
- ],
- ],
- });
+ expect(
+ renderVerb({
+ verb: bandawul,
+ tense: "subjunctiveVerb",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [
+ {
+ type: "NComp",
+ comp: {
+ type: "AdjComp",
+ ps: { p: "بنده", f: "bánda" },
+ gender: "fem",
+ number: "singular",
+ },
+ },
+ ],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "کړم", f: "kRum" }],
+ short: [{ p: "کم", f: "kum" }],
+ },
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
});
test("special endings", () => {
- const tests: {
- verb: T.VerbEntryNoFVars,
- tense: "perfectivePast" | "imperfectivePast",
- result: T.VerbRenderedOutput,
- }[] = [
- // verbs ending in -awul
- {
- verb: achawul,
- tense: "perfectivePast",
- result: [
- [{ type: "PH", ps: { p: "وا", f: "wáa" }}],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "چولو", f: "chawulo" }],
- short: [{ p: "چاوه", f: "chaawu" }],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: achawul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "اچولو", f: "achawúlo" }],
- short: [{ p: "اچاوه", f: "achaawú" }],
- },
- person: 4,
- },
- ],
- ],
- },
- // verbs with special tppp
- {
- verb: ganul,
- tense: "perfectivePast",
- result: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "ګڼلو", f: "gaNulo" }],
- short: [{ p: "ګاڼه", f: "gaaNu" }],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: ganul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "ګڼلو", f: "gaNúlo" }],
- short: [{ p: "ګاڼه", f: "gaaNú" }],
- },
- person: 4,
- },
- ],
- ],
- },
- // verbs with special tppp ending in a consonant
- {
- verb: khatul,
- tense: "perfectivePast",
- result: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "ختلو", f: "khatulo" }],
- short: [
- { p: "خوت", f: "khot" },
- // // TODO: is this even right?
- // { p: "خوته", f: "khotu" },
- // { p: "خوتو", f: "khoto" },
- ],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: leedul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "لیدلو", f: "leedúlo" }],
- short: [
- { p: "لید", f: "léed" },
- // // TODO: is this even right?
- // { p: "خوته", f: "khotu" },
- // { p: "خوتو", f: "khoto" },
- ],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: raawrul,
- tense: "perfectivePast",
- result: [
- [{ type: "PH", ps: { p: "را", f: "ráa" }}],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "وړلو", f: "wRulo" }],
- short: [{ p: "ووړ", f: "woR" }],
- },
- person: 4,
- },
- ],
- ],
- },
- // verbs ending in a dental ت or د
- {
- verb: rasedul,
- tense: "perfectivePast",
- result: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "رسېدلو", f: "rasedulo" }],
- short: [
- { p: "رسېد", f: "rased" },
- { p: "رسېده", f: "rasedu" },
- { p: "رسېدو", f: "rasedo" },
- ],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: awuxtul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "اوښتلو", f: "awUxtúlo" }],
- short: [
- { p: "اوښت", f: "awÚxt" },
- { p: "اوښته", f: "awUxtú" },
- { p: "اوښتو", f: "awUxtó" },
- ],
- },
- person: 4,
- },
- ],
- ],
- },
- // other verbs
- {
- verb: weshul,
- tense: "perfectivePast",
- result: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "وېشلو", f: "weshulo" }],
- short: [
- { p: "وېشه", f: "weshu" },
- { p: "وېشو", f: "wesho" },
- ],
- },
- person: 4,
- },
- ],
- ],
- },
- {
- verb: kedulStat,
- tense: "perfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "شولو", f: "shwulo" }],
- short: [{ p: "شو", f: "sho" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: kedulStat,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "کېدلو", f: "kedúlo" }],
- short: [{ p: "کېده", f: "kedú" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: kawulStat,
- tense: "perfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "کړلو", f: "kRulo" }],
- short: [
- { p: "کړ", f: "kuR" },
- { p: "کړه", f: "kRu" },
- { p: "کړو", f: "kRo" },
- ],
- mini: [{ p: "که", f: "ku" }, { p: "کو", f: "ko" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: kawulDyn,
- tense: "perfectivePast",
- result: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "کړلو", f: "kRulo" }],
- short: [
- { p: "کړ", f: "kuR" },
- { p: "کړه", f: "kRu" },
- { p: "کړو", f: "kRo" },
- ],
- mini: [{ p: "که", f: "ku" }, { p: "کو", f: "ko" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: kawulDyn,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "کولو", f: "kawúlo" }],
- short: [{ p: "کاوه", f: "kaawú" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: tlul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "تللو", f: "tlúlo" }],
- short: [{ p: "ته", f: "tú" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: tlul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "تللو", f: "tlúlo" }],
- short: [{ p: "ته", f: "tú" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: raatlul,
- tense: "imperfectivePast",
- result: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "راتللو", f: "raatlúlo" }],
- short: [{ p: "راته", f: "raatú" }],
- },
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: raatlul,
- tense: "perfectivePast",
- result: [
- [{ type: "PH", ps: { p: "را", f: "ráa" }}],
- [
- {
- type: "VB",
- ps: [{ p: "غی", f: "ghey" }],
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- {
- verb: wartlul,
- tense: "perfectivePast",
- result: [
- [{ type: "PH", ps: { p: "ور", f: "wár" }}],
- [
- {
- type: "VB",
- ps: [{ p: "غی", f: "ghey" }],
- person: T.Person.ThirdSingMale,
- },
- ],
- ],
- },
- ];
- tests.forEach(x => {
- expect(renderVerb({
- verb: x.verb,
- tense: x.tense,
+ const tests: {
+ verb: T.VerbEntryNoFVars;
+ tense: "perfectivePast" | "imperfectivePast";
+ result: T.VerbRenderedOutput;
+ }[] = [
+ // verbs ending in -awul
+ {
+ verb: achawul,
+ tense: "perfectivePast",
+ result: [
+ [{ type: "PH", ps: { p: "وا", f: "wáa" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "چولو", f: "chawulo" }],
+ short: [{ p: "چاوه", f: "chaawu" }],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: achawul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "اچولو", f: "achawúlo" }],
+ short: [{ p: "اچاوه", f: "achaawú" }],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ // verbs with special tppp
+ {
+ verb: ganul,
+ tense: "perfectivePast",
+ result: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ګڼلو", f: "gaNulo" }],
+ short: [{ p: "ګاڼه", f: "gaaNu" }],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: ganul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ګڼلو", f: "gaNúlo" }],
+ short: [{ p: "ګاڼه", f: "gaaNú" }],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ // verbs with special tppp ending in a consonant
+ {
+ verb: khatul,
+ tense: "perfectivePast",
+ result: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ختلو", f: "khatulo" }],
+ short: [
+ { p: "خوت", f: "khot" },
+ // // TODO: is this even right?
+ // { p: "خوته", f: "khotu" },
+ // { p: "خوتو", f: "khoto" },
+ ],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: leedul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "لیدلو", f: "leedúlo" }],
+ short: [
+ { p: "لید", f: "léed" },
+ // // TODO: is this even right?
+ // { p: "خوته", f: "khotu" },
+ // { p: "خوتو", f: "khoto" },
+ ],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: raawrul,
+ tense: "perfectivePast",
+ result: [
+ [{ type: "PH", ps: { p: "را", f: "ráa" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "وړلو", f: "wRulo" }],
+ short: [{ p: "ووړ", f: "woR" }],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ // verbs ending in a dental ت or د
+ {
+ verb: rasedul,
+ tense: "perfectivePast",
+ result: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "رسېدلو", f: "rasedulo" }],
+ short: [
+ { p: "رسېد", f: "rased" },
+ { p: "رسېده", f: "rasedu" },
+ { p: "رسېدو", f: "rasedo" },
+ ],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: awuxtul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "اوښتلو", f: "awUxtúlo" }],
+ short: [
+ { p: "اوښت", f: "awÚxt" },
+ { p: "اوښته", f: "awUxtú" },
+ { p: "اوښتو", f: "awUxtó" },
+ ],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ // other verbs
+ {
+ verb: weshul,
+ tense: "perfectivePast",
+ result: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "وېشلو", f: "weshulo" }],
+ short: [
+ { p: "وېشه", f: "weshu" },
+ { p: "وېشو", f: "wesho" },
+ ],
+ },
+ person: 4,
+ },
+ ],
+ ],
+ },
+ {
+ verb: kedulStat,
+ tense: "perfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "شولو", f: "shwulo" }],
+ short: [{ p: "شو", f: "sho" }],
+ },
person: T.Person.ThirdSingMale,
- complementGenNum: personToGenNum(T.Person.ThirdSingMale),
- voice: "active",
- negative: false,
- })).toEqual({ hasBa: false, vbs: x.result });
- });
+ },
+ ],
+ ],
+ },
+ {
+ verb: kedulStat,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "کېدلو", f: "kedúlo" }],
+ short: [{ p: "کېده", f: "kedú" }],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: kawulStat,
+ tense: "perfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "کړلو", f: "kRulo" }],
+ short: [
+ { p: "کړ", f: "kuR" },
+ { p: "کړه", f: "kRu" },
+ { p: "کړو", f: "kRo" },
+ ],
+ mini: [
+ { p: "که", f: "ku" },
+ { p: "کو", f: "ko" },
+ ],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: kawulDyn,
+ tense: "perfectivePast",
+ result: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "کړلو", f: "kRulo" }],
+ short: [
+ { p: "کړ", f: "kuR" },
+ { p: "کړه", f: "kRu" },
+ { p: "کړو", f: "kRo" },
+ ],
+ mini: [
+ { p: "که", f: "ku" },
+ { p: "کو", f: "ko" },
+ ],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: kawulDyn,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "کولو", f: "kawúlo" }],
+ short: [{ p: "کاوه", f: "kaawú" }],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: tlul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "تللو", f: "tlúlo" }],
+ short: [
+ { p: "ته", f: "tú" },
+ {
+ p: "تلو",
+ f: "tló",
+ },
+ ],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: raatlul,
+ tense: "imperfectivePast",
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "راتللو", f: "raatlúlo" }],
+ short: [
+ { p: "راته", f: "raatú" },
+ { p: "راتلو", f: "raatló" },
+ ],
+ },
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: raatlul,
+ tense: "perfectivePast",
+ result: [
+ [{ type: "PH", ps: { p: "را", f: "ráa" } }],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "غی", f: "ghey" }],
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ {
+ verb: wartlul,
+ tense: "perfectivePast",
+ result: [
+ [{ type: "PH", ps: { p: "ور", f: "wár" } }],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "غی", f: "ghey" }],
+ person: T.Person.ThirdSingMale,
+ },
+ ],
+ ],
+ },
+ ];
+ tests.forEach((x) => {
+ expect(
+ renderVerb({
+ verb: x.verb,
+ tense: x.tense,
+ subject: T.Person.ThirdSingMale,
+ object: x.verb.entry.c.includes("intrans.")
+ ? undefined
+ : T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({ hasBa: false, vbs: x.result });
+ });
- expect(renderVerb({
- verb: kedulStat,
- tense: "perfectivePast",
- person: T.Person.FirstPlurMale,
- complementGenNum: personToGenNum(T.Person.FirstPlurMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "شولو", f: "shwuloo" }],
- short: [{ p: "شو", f: "shoo" }],
- },
- person: T.Person.FirstPlurMale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: tlul,
- tense: "imperfectivePast",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "تللم", f: "tlúlum" }],
- // TODO: Shouldn't be accent here on single syllable
- short: [{ p: "تلم", f: "tlúm" }],
- },
- person: T.Person.FirstSingMale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: tlul,
- tense: "imperfectivePast",
- person: T.Person.ThirdSingFemale,
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "تلله", f: "tlúla" }],
- // TODO: Shouldn't be accent here on single syllable
- short: [{ p: "تله", f: "tlá" }],
- },
- person: T.Person.ThirdSingFemale,
- },
- ],
- ],
- });
- // avoid redundant ل ending
- expect(renderVerb({
- verb: khorul,
- tense: "imperfectivePast",
- person: T.Person.ThirdPlurMale,
- complementGenNum: personToGenNum(T.Person.ThirdPlurMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "خوړل", f: "khoRúl" }],
- short: [{ p: "خوړل", f: "khoRúl" }],
- },
- person: T.Person.ThirdPlurMale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: khorul,
- tense: "perfectivePast",
- person: T.Person.ThirdPlurMale,
- complementGenNum: personToGenNum(T.Person.ThirdPlurMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [ooPh],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "خوړل", f: "khoRul" }],
- short: [{ p: "خوړل", f: "khoRul" }],
- },
- person: T.Person.ThirdPlurMale,
- },
- ],
- ],
- });
+ expect(
+ renderVerb({
+ verb: kedulStat,
+ tense: "perfectivePast",
+ subject: T.Person.FirstPlurMale,
+ object: undefined,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "شولو", f: "shwuloo" }],
+ short: [{ p: "شو", f: "shoo" }],
+ },
+ person: T.Person.FirstPlurMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: tlul,
+ tense: "imperfectivePast",
+ subject: T.Person.FirstSingMale,
+ object: undefined,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "تللم", f: "tlúlum" }],
+ // TODO: Shouldn't be accent here on single syllable
+ short: [{ p: "تلم", f: "tlúm" }],
+ },
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: tlul,
+ tense: "imperfectivePast",
+ subject: T.Person.ThirdSingFemale,
+ object: undefined,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "تلله", f: "tlúla" }],
+ // TODO: Shouldn't be accent here on single syllable
+ short: [{ p: "تله", f: "tlá" }],
+ },
+ person: T.Person.ThirdSingFemale,
+ },
+ ],
+ ],
+ });
+ // avoid redundant ل ending
+ expect(
+ renderVerb({
+ verb: khorul,
+ tense: "imperfectivePast",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "خوړل", f: "khoRúl" }],
+ short: [{ p: "خوړل", f: "khoRúl" }],
+ },
+ person: T.Person.ThirdPlurMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: khorul,
+ tense: "perfectivePast",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [ooPh],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "خوړل", f: "khoRul" }],
+ short: [{ p: "خوړل", f: "khoRul" }],
+ },
+ person: T.Person.ThirdPlurMale,
+ },
+ ],
+ ],
+ });
});
test("imperative tenses", () => {
- expect(renderVerb({
- verb: wahul,
- tense: "imperfectiveImperative",
- person: T.Person.SecondSingMale,
- complementGenNum: personToGenNum(T.Person.SecondSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهه", f: "wahá" } ], person: 2},
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "perfectiveImperative",
- person: T.Person.SecondSingFemale,
- complementGenNum: personToGenNum(T.Person.SecondSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [ooPh],
- [
- { type: "VB", ps: [{ p: "وهه", f: "waha" }], person: 3 },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "imperfectiveImperative",
- person: T.Person.SecondPlurMale,
- complementGenNum: personToGenNum(T.Person.SecondPlurMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهئ", f: "wahéyy" } ], person: 8 },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "perfectiveImperative",
- person: T.Person.SecondPlurFemale,
- complementGenNum: personToGenNum(T.Person.SecondPlurFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [ooPh],
- [
- { type: "VB", ps: [{ p: "وهئ", f: "waheyy" }], person: 9 },
- ],
- ],
- });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "imperfectiveImperative",
+ subject: T.Person.SecondSingMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [[], [{ type: "VB", ps: [{ p: "وهه", f: "wahá" }], person: 2 }]],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "perfectiveImperative",
+ subject: T.Person.SecondSingFemale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [[ooPh], [{ type: "VB", ps: [{ p: "وهه", f: "waha" }], person: 3 }]],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "imperfectiveImperative",
+ subject: T.Person.SecondPlurMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [[], [{ type: "VB", ps: [{ p: "وهئ", f: "wahéyy" }], person: 8 }]],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "perfectiveImperative",
+ subject: T.Person.SecondPlurFemale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [[ooPh], [{ type: "VB", ps: [{ p: "وهئ", f: "waheyy" }], person: 9 }]],
+ });
});
test("ability tenses", () => {
- expect(renderVerb({
- verb: wahul,
- tense: "presentVerbModal",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "VB",
- ps: {
- long: [
- { p: "وهلی", f: "wahúley" },
- { p: "وهلای", f: "wahúlaay" },
- ],
- short: [
- { p: "وهی", f: "wahéy" },
- { p: "وهای", f: "waháay" },
- ],
- },
- },
- {
- type: "VB",
- ps: [{ p: "شم", f: "shum" }],
- person: T.Person.FirstSingMale,
- },
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "presentVerbModal",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [
+ { p: "وهلی", f: "wahúley" },
+ { p: "وهلای", f: "wahúlaay" },
],
- ],
- });
-});
-
-test("basic tenses", () => {
- expect(renderVerb({
- verb: wahul,
- tense: "presentVerb",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
-
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهم", f: "wahum" }], person: T.Person.FirstSingMale },
+ short: [
+ { p: "وهی", f: "wahéy" },
+ { p: "وهای", f: "waháay" },
],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "subjunctiveVerb",
- person: T.Person.SecondSingMale,
- complementGenNum: personToGenNum(T.Person.SecondSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [{ type: "PH", ps: { f: "óo", p: "و" }}],
- [
- { type: "VB", ps: [{ p: "وهې", f: "wahe" }], person: T.Person.SecondSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "habitualPerfectivePast",
- person: T.Person.ThirdSingFemale,
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: true,
- vbs: [
- [{ type: "PH", ps: { f: "óo", p: "و" }}],
- [
- {
- type: "VB",
- ps: {
- long: [{ p: "وهله", f: "wahula" }],
- short: [{ p: "وهه", f: "waha" }],
- },
- person: T.Person.ThirdSingFemale
- },
- ],
- ],
- });
+ },
+ },
+ {
+ type: "VB",
+ ps: [{ p: "شم", f: "shum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
});
test("perfect tenses", () => {
- expect(renderVerb({
- verb: wahul,
- tense: "presentPerfect",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" },
- { type: "VB", ps: [{ p: "یم", f: "yum" }], person: T.Person.FirstSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "subjunctivePerfect",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" },
- { type: "VB", ps: [{ p: "وم", f: "wum" }], person: T.Person.FirstSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "habitualPerfect",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" },
- { type: "VB", ps: [{ p: "یم", f: "yum" }], person: T.Person.FirstSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "habitualPerfect",
- person: T.Person.ThirdPlurMale,
- complementGenNum: personToGenNum(T.Person.ThirdPlurMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلي", f: "wahúlee" }], gender: "masc", number: "plural" },
- { type: "VB", ps: [{ p: "وي", f: "wee" }], person: T.Person.ThirdPlurMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "futurePerfect",
- person: T.Person.FirstSingMale,
- complementGenNum: personToGenNum(T.Person.FirstSingMale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: true,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلی", f: "wahúley" }], gender: "masc", number: "singular" },
- { type: "VB", ps: [{ p: "یم", f: "yum" }], person: T.Person.FirstSingMale },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "pastPerfect",
- person: T.Person.SecondSingFemale,
- complementGenNum: personToGenNum(T.Person.SecondSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" },
- {
- type: "VB",
- ps: {
- long: [{ p: "ولې", f: "wule" }],
- short: [{ p: "وې", f: "we" }],
- },
- person: T.Person.SecondSingFemale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "wouldBePerfect",
- person: T.Person.SecondSingFemale,
- complementGenNum: personToGenNum(T.Person.SecondSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: true,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" },
- {
- type: "VB",
- ps: {
- long: [{ p: "ولې", f: "wule" }],
- short: [{ p: "وې", f: "we" }],
- },
- person: T.Person.SecondSingFemale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "pastSubjunctivePerfect",
- person: T.Person.SecondSingFemale,
- complementGenNum: personToGenNum(T.Person.SecondSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" },
- {
- type: "VB",
- ps: [{ p: "وای", f: "waay" }, { p: "وی", f: "wey" }],
- person: T.Person.SecondSingFemale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: wahul,
- tense: "wouldHaveBeenPerfect",
- person: T.Person.SecondSingFemale,
- complementGenNum: personToGenNum(T.Person.SecondSingFemale),
- voice: "active",
- negative: false,
- })).toEqual({
- hasBa: true,
- vbs: [
- [],
- [
- { type: "VB", ps: [{ p: "وهلې", f: "wahúle" }], gender: "fem", number: "singular" },
- {
- type: "VB",
- ps: [{ p: "وای", f: "waay" }, { p: "وی", f: "wey" }],
- person: T.Person.SecondSingFemale,
- },
- ],
- ],
- });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "presentPerfect",
+ subject: T.Person.SecondSingMale,
+ object: T.Person.FirstSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلی", f: "wahúley" }],
+ gender: "masc",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [{ p: "یم", f: "yum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "subjunctivePerfect",
+ subject: T.Person.ThirdPlurFemale,
+ object: T.Person.FirstSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلی", f: "wahúley" }],
+ gender: "masc",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [{ p: "وم", f: "wum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "habitualPerfect",
+ object: T.Person.FirstSingMale,
+ subject: T.Person.ThirdSingMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلی", f: "wahúley" }],
+ gender: "masc",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [{ p: "یم", f: "yum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "habitualPerfect",
+ subject: T.Person.FirstPlurMale,
+ object: T.Person.ThirdPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلي", f: "wahúlee" }],
+ gender: "masc",
+ number: "plural",
+ },
+ {
+ type: "VB",
+ ps: [{ p: "وي", f: "wee" }],
+ person: T.Person.ThirdPlurMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "futurePerfect",
+ object: T.Person.FirstSingMale,
+ subject: T.Person.ThirdPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: true,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلی", f: "wahúley" }],
+ gender: "masc",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [{ p: "یم", f: "yum" }],
+ person: T.Person.FirstSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "pastPerfect",
+ subject: T.Person.FirstPlurFemale,
+ object: T.Person.SecondSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلې", f: "wahúle" }],
+ gender: "fem",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ولې", f: "wule" }],
+ short: [{ p: "وې", f: "we" }],
+ },
+ person: T.Person.SecondSingFemale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "wouldBePerfect",
+ subject: T.Person.ThirdSingMale,
+ object: T.Person.SecondSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: true,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلې", f: "wahúle" }],
+ gender: "fem",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ولې", f: "wule" }],
+ short: [{ p: "وې", f: "we" }],
+ },
+ person: T.Person.SecondSingFemale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "pastSubjunctivePerfect",
+ object: T.Person.SecondSingFemale,
+ subject: T.Person.FirstPlurMale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلې", f: "wahúle" }],
+ gender: "fem",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [
+ { p: "وای", f: "waay" },
+ { p: "وی", f: "wey" },
+ ],
+ person: T.Person.SecondSingFemale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: wahul,
+ tense: "wouldHaveBeenPerfect",
+ subject: T.Person.FirstSingMale,
+ object: T.Person.SecondSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: true,
+ vbs: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: [{ p: "وهلې", f: "wahúle" }],
+ gender: "fem",
+ number: "singular",
+ },
+ {
+ type: "VB",
+ ps: [
+ { p: "وای", f: "waay" },
+ { p: "وی", f: "wey" },
+ ],
+ person: T.Person.SecondSingFemale,
+ },
+ ],
+ ],
+ });
});
test("ending on complex verbs", () => {
- expect(renderVerb({
- verb: stureyKawul,
- tense: "presentVerbModal",
- person: T.Person.SecondSingMale,
- voice: "active",
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "welded",
- left: {
- type: "NComp",
- comp: {
- type: "AdjComp",
- ps: { p: "ستړې", f: "stuRe" },
- gender: "fem",
- number: "singular",
- },
- },
- right: {
- type: "VB",
- ps: {
- long: [
- { p: "کولی", f: "kawúley" },
- { p: "کولای", f: "kawúlaay" },
- ],
- short: [
- { p: "کوی", f: "kawéy" },
- { p: "کوای", f: "kawáay" },
- ],
- },
- },
- },
- {
- type: "VB",
- ps: [{ p: "شې", f: "she" }],
- person: T.Person.SecondSingMale,
- },
- ],
- ],
- });
- expect(renderVerb({
- verb: stureyKawul,
- tense: "presentVerb",
- person: T.Person.SecondSingMale,
- voice: "active",
- complementGenNum: personToGenNum(T.Person.ThirdSingFemale),
- negative: false,
- })).toEqual({
- hasBa: false,
- vbs: [
- [],
- [
- {
- type: "welded",
- left: {
- type: "NComp",
- comp: {
- type: "AdjComp",
- ps: { p: "ستړې", f: "stuRe" },
- gender: "fem",
- number: "singular",
- },
- },
- right: {
- type: "VB",
- ps: [{ p: "کوې", f: "kawé" }],
- },
- person: T.Person.SecondSingMale,
- },
- ],
- ],
- });
-});
\ No newline at end of file
+ expect(
+ renderVerb({
+ verb: stureyKawul,
+ tense: "presentVerbModal",
+ subject: T.Person.SecondSingMale,
+ object: T.Person.ThirdSingFemale,
+ voice: "active",
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "welded",
+ left: {
+ type: "NComp",
+ comp: {
+ type: "AdjComp",
+ ps: { p: "ستړې", f: "stuRe" },
+ gender: "fem",
+ number: "singular",
+ },
+ },
+ right: {
+ type: "VB",
+ ps: {
+ long: [
+ { p: "کولی", f: "kawúley" },
+ { p: "کولای", f: "kawúlaay" },
+ ],
+ short: [
+ { p: "کوی", f: "kawéy" },
+ { p: "کوای", f: "kawáay" },
+ ],
+ },
+ },
+ },
+ {
+ type: "VB",
+ ps: [{ p: "شې", f: "she" }],
+ person: T.Person.SecondSingMale,
+ },
+ ],
+ ],
+ });
+ expect(
+ renderVerb({
+ verb: stureyKawul,
+ tense: "presentVerb",
+ subject: T.Person.SecondSingMale,
+ voice: "active",
+ object: T.Person.ThirdSingFemale,
+ negative: false,
+ })
+ ).toEqual({
+ hasBa: false,
+ vbs: [
+ [],
+ [
+ {
+ type: "welded",
+ left: {
+ type: "NComp",
+ comp: {
+ type: "AdjComp",
+ ps: { p: "ستړې", f: "stuRe" },
+ gender: "fem",
+ number: "singular",
+ },
+ },
+ right: {
+ type: "VB",
+ ps: [{ p: "کوې", f: "kawé" }],
+ },
+ person: T.Person.SecondSingMale,
+ },
+ ],
+ ],
+ });
+});
diff --git a/src/lib/src/new-verb-engine/render-verb.ts b/src/lib/src/new-verb-engine/render-verb.ts
index 815c7c3..6828a3e 100644
--- a/src/lib/src/new-verb-engine/render-verb.ts
+++ b/src/lib/src/new-verb-engine/render-verb.ts
@@ -1,310 +1,367 @@
import * as T from "../../../types";
import {
- getVerbBlockPosFromPerson,
- isSecondPerson,
- personGender,
- personNumber,
- personToGenNum,
+ getVerbBlockPosFromPerson,
+ isSecondPerson,
+ personNumber,
+ personToGenNum,
} from "../misc-helpers";
+import { fmapSingleOrLengthOpts } from "../fmaps";
+import { concatPsString, getLength } from "../p-text-helpers";
import {
- fmapSingleOrLengthOpts,
-} from "../fmaps";
-import {
- concatPsString,
- getLength,
-} from "../p-text-helpers";
-import {
- presentEndings,
- pastEndings,
- equativeEndings,
- imperativeEndings,
+ presentEndings,
+ pastEndings,
+ equativeEndings,
+ imperativeEndings,
} from "../grammar-units";
-import { isKawulVerb, isAbilityTense, isPerfectTense, isTlulVerb, isImperativeTense } from "../type-predicates";
+import {
+ isKawulVerb,
+ isAbilityTense,
+ isPerfectTense,
+ isTlulVerb,
+} from "../type-predicates";
import { perfectTenseHasBa } from "../phrase-building/vp-tools";
import { makePsString, removeFVarients } from "../accent-and-ps-utils";
import { getPastParticiple, getRootStem } from "./roots-and-stems";
-import { isKedul, perfectTenseToEquative, verbEndingConcat } from "./rs-helpers";
-import { accentOnNFromEnd, accentPsSyllable, removeAccents } from "../accent-helpers";
+import {
+ isKedul,
+ perfectTenseToEquative,
+ verbEndingConcat,
+} from "./rs-helpers";
+import {
+ accentOnNFromEnd,
+ accentPsSyllable,
+ removeAccents,
+} from "../accent-helpers";
-const formulas: Record = {
- "presentVerb": {
- aspect: "imperfective",
- tenseC: "present",
- hasBa: false,
- },
- "subjunctiveVerb": {
- aspect: "imperfective",
- tenseC: "present",
- hasBa: false,
- },
- "perfectiveFuture": {
- aspect: "perfective",
- tenseC: "present",
- hasBa: true,
- },
- "imperfectiveFuture": {
- aspect: "imperfective",
- tenseC: "present",
- hasBa: true,
- },
- "perfectivePast": {
- aspect: "perfective",
- tenseC: "past",
- hasBa: false,
- },
- "imperfectivePast": {
- aspect: "imperfective",
- tenseC: "past",
- hasBa: false,
- },
- "habitualImperfectivePast": {
- aspect: "imperfective",
- tenseC: "past",
- hasBa: true,
- },
- "habitualPerfectivePast": {
- aspect: "perfective",
- tenseC: "past",
- hasBa: true,
- },
- "perfectiveImperative": {
- aspect: "perfective",
- tenseC: "imperative",
- hasBa: false,
- },
- "imperfectiveImperative": {
- aspect: "imperfective",
- tenseC: "imperative",
- hasBa: false,
- },
-}
+const formulas: Record<
+ T.VerbTense | T.ImperativeTense,
+ {
+ aspect: T.Aspect;
+ tenseC: "past" | "present" | "imperative";
+ hasBa: boolean;
+ }
+> = {
+ presentVerb: {
+ aspect: "imperfective",
+ tenseC: "present",
+ hasBa: false,
+ },
+ subjunctiveVerb: {
+ aspect: "perfective",
+ tenseC: "present",
+ hasBa: false,
+ },
+ perfectiveFuture: {
+ aspect: "perfective",
+ tenseC: "present",
+ hasBa: true,
+ },
+ imperfectiveFuture: {
+ aspect: "imperfective",
+ tenseC: "present",
+ hasBa: true,
+ },
+ perfectivePast: {
+ aspect: "perfective",
+ tenseC: "past",
+ hasBa: false,
+ },
+ imperfectivePast: {
+ aspect: "imperfective",
+ tenseC: "past",
+ hasBa: false,
+ },
+ habitualImperfectivePast: {
+ aspect: "imperfective",
+ tenseC: "past",
+ hasBa: true,
+ },
+ habitualPerfectivePast: {
+ aspect: "perfective",
+ tenseC: "past",
+ hasBa: true,
+ },
+ perfectiveImperative: {
+ aspect: "perfective",
+ tenseC: "imperative",
+ hasBa: false,
+ },
+ imperfectiveImperative: {
+ aspect: "imperfective",
+ tenseC: "imperative",
+ hasBa: false,
+ },
+};
-// to get the chart of conjugations:
-// 1. get the conjugation for all persons
-// 2. if transitive present tense, check (or do all the conjugation) the conjugation with all different complement person stuff
-// if necessary pull out the object option
-//
-
-// to make the verbs displayable for the charts
-// - take the output of renderVerb { hasBa, VerbRenderedOutput }
-// - filter out a long and short version etc if necessary
-// - pass it into combineIntoText
-
-// PROBLEM: how to handle when to specify the object
-// present tense
-
-// TODO: problem with laaR - no perfective split
-export function renderVerb({ verb, tense: tense, person, voice, negative, complementGenNum }: {
- verb: T.VerbEntry,
- negative: boolean,
- tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense, // TODO: make T.Tense
- person: T.Person,
- complementGenNum: { gender: T.Gender, number: T.NounNumber },
- voice: T.Voice,
-}): {
- hasBa: boolean,
- vbs: T.VerbRenderedOutput,
-} {
- if (isPerfectTense(tense)) {
- return renderPerfectVerb({ verb, tense, voice, person });
- }
- const { aspect, tenseC, hasBa } = formulas[removeAbility(tense)];
- const isPast = tenseC === "past";
- const type = isAbilityTense(tense) ? "ability" : "basic";
-
- // #1 get the appropriate root / stem
- const [vHead, rest] = getRootStem({
- verb,
- rs: isPast ? "root" : "stem",
- aspect,
- voice,
- type,
- genderNumber: complementGenNum,
+// TODO: dynamic and stative compounds
+export function renderVerb({
+ verb,
+ tense,
+ subject,
+ object,
+ voice,
+}: {
+ verb: T.VerbEntry;
+ negative: boolean;
+ tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense; // TODO: make T.Tense
+ subject: T.Person;
+ object: T.Person | undefined;
+ voice: T.Voice;
+}): T.RenderVerbOutput {
+ if (isPerfectTense(tense)) {
+ return renderPerfectVerb({
+ verb,
+ tense,
+ voice,
+ person: object ?? subject,
});
- // #2 add the verb ending to it
- const ending = getEnding(person, tenseC, aspect);
- return {
- hasBa,
- vbs: [
- vHead,
- addEnding({
- rs: rest,
- ending,
- verb,
- person,
- pastThird: isPast && person === T.Person.ThirdSingMale,
- aspect,
- basicForm: type === "basic" && voice === "active",
- }),
- ],
- };
+ }
+ const { aspect, tenseC, hasBa } = formulas[removeAbility(tense)];
+ const isPast = tenseC === "past";
+ const type = isAbilityTense(tense) ? "ability" : "basic";
+ const transitive = object !== undefined;
+ const king = transitive && isPast ? object : subject;
+
+ // #1 get the appropriate root / stem
+ const [vHead, rest] = getRootStem({
+ verb,
+ rs: isPast ? "root" : "stem",
+ aspect,
+ voice,
+ type,
+ genderNumber: personToGenNum(transitive ? object : subject),
+ });
+
+ // #2 add the verb ending to it
+ const ending = getEnding(king, tenseC, aspect);
+ return {
+ hasBa,
+ objComp: undefined,
+ vbs: [
+ vHead,
+ addEnding({
+ rs: rest,
+ ending,
+ verb,
+ person: king,
+ pastThird: isPast && king === T.Person.ThirdSingMale,
+ aspect,
+ basicForm: type === "basic" && voice === "active",
+ }),
+ ],
+ };
}
-function renderPerfectVerb({ tense, verb, voice, person }: {
- tense: T.PerfectTense,
- verb: T.VerbEntry,
- voice: T.Voice,
- person: T.Person,
- // TODO: Tighter typing on the output for T.VB (enforce genderNumber?)
-}): { hasBa: boolean, vbs: [[], [T.VB, T.VBE]] } {
- const hasBa = perfectTenseHasBa(tense);
- // #1 get the past participle
- const pp = getPastParticiple(verb, voice, personToGenNum(person));
- // #2 get the right equative
- const equative = equativeEndings[perfectTenseToEquative(tense)];
- const [row, col] = getVerbBlockPosFromPerson(person);
- const equativeBlock: T.VBE = {
- type: "VB",
- person,
- ps: fmapSingleOrLengthOpts(x => x[row][col], equative),
- };
- return {
- hasBa,
- vbs: [[], [pp, equativeBlock]],
- };
+function renderPerfectVerb({
+ tense,
+ verb,
+ voice,
+ person,
+}: {
+ person: T.Person;
+ tense: T.PerfectTense;
+ verb: T.VerbEntry;
+ voice: T.Voice;
+}): {
+ hasBa: boolean;
+ vbs: [[], [T.VB, T.VBE]];
+ objComp: T.Rendered | undefined;
+} {
+ const hasBa = perfectTenseHasBa(tense);
+ // #1 get the past participle
+ const pp = getPastParticiple(verb, voice, personToGenNum(person));
+ // #2 get the right equative
+ const equative = equativeEndings[perfectTenseToEquative(tense)];
+ const [row, col] = getVerbBlockPosFromPerson(person);
+ const equativeBlock: T.VBE = {
+ type: "VB",
+ person,
+ ps: fmapSingleOrLengthOpts((x) => x[row][col], equative),
+ };
+ return {
+ hasBa,
+ objComp: undefined,
+ vbs: [[], [pp, equativeBlock]],
+ };
}
-function addEnding({ verb, rs, ending, person, pastThird, aspect, basicForm }: {
- rs: [T.VB, T.VBA] | [T.VBA],
- ending: T.SingleOrLengthOpts,
- person: T.Person,
- verb: T.VerbEntry,
- pastThird: boolean,
- aspect: T.Aspect,
- basicForm: boolean,
+function addEnding({
+ verb,
+ rs,
+ ending,
+ person,
+ pastThird,
+ aspect,
+ basicForm,
+}: {
+ rs: [T.VB, T.VBA] | [T.VBA];
+ ending: T.SingleOrLengthOpts;
+ person: T.Person;
+ verb: T.VerbEntry;
+ pastThird: boolean;
+ aspect: T.Aspect;
+ basicForm: boolean;
}): [T.VB, T.VBE] | [T.VBE] {
- return rs.length === 2
- ? [rs[0], addEnd(rs[1], ending)]
- : [addEnd(rs[0], ending)];
- function addEnd(vba: T.VBA, ending: T.SingleOrLengthOpts): T.VBE {
- if (vba.type === "welded") {
- return {
- ...vba,
- right: addToVBBasicEnd(vba.right, ending),
- person,
- };
- }
- return {
- ...addToVBBasicEnd(vba, ending),
- person,
- }
+ return rs.length === 2
+ ? [rs[0], addEnd(rs[1], ending)]
+ : [addEnd(rs[0], ending)];
+ function addEnd(
+ vba: T.VBA,
+ ending: T.SingleOrLengthOpts
+ ): T.VBE {
+ if (vba.type === "welded") {
+ return {
+ ...vba,
+ right: addToVBBasicEnd(vba.right, ending),
+ person,
+ };
}
- function addToVBBasicEnd(vb: T.VBBasic, end: T.SingleOrLengthOpts): T.VBBasic {
- if ("long" in vb.ps) {
- if (vb.ps.short[0].f === "ghl" && pastThird && basicForm) {
- return {
- ...vb,
- ps: [{ p: "غی", f: "ghey" }],
- };
- }
- const endLong = getLength(end, "long");
- const endShort = getLength(end, "short");
- // TODO: this is hacky
- return {
- ...vb,
- ps: {
- long: verbEndingConcat(vb.ps.long, endLong),
- short: pastThird && basicForm
- ? ensure3rdPast(vb.ps.short, endShort, verb, aspect)
- : verbEndingConcat(vb.ps.short, endShort),
- ...vb.ps.mini ? {
- mini: verbEndingConcat(vb.ps.mini, endShort),
- } : {},
- },
- };
- }
- /* istanbul ignore next */
- if ("long" in end) {
- throw new Error("should not be using verb stems with long and short endings");
- }
+ return {
+ ...addToVBBasicEnd(vba, ending),
+ person,
+ };
+ }
+ function addToVBBasicEnd(
+ vb: T.VBBasic,
+ end: T.SingleOrLengthOpts
+ ): T.VBBasic {
+ if ("long" in vb.ps) {
+ if (vb.ps.short[0].f === "ghl" && pastThird && basicForm) {
return {
- ...vb,
- ps: verbEndingConcat(vb.ps, end),
+ ...vb,
+ ps: [{ p: "غی", f: "ghey" }],
};
+ }
+ const endLong = getLength(end, "long");
+ const endShort = getLength(end, "short");
+ // TODO: this is hacky
+ return {
+ ...vb,
+ ps: {
+ long: verbEndingConcat(vb.ps.long, endLong),
+ short:
+ pastThird && basicForm
+ ? ensure3rdPast(vb.ps.short, endShort, verb, aspect)
+ : verbEndingConcat(vb.ps.short, endShort),
+ ...(vb.ps.mini
+ ? {
+ mini: verbEndingConcat(vb.ps.mini, endShort),
+ }
+ : {}),
+ },
+ };
}
+ /* istanbul ignore next */
+ if ("long" in end) {
+ throw new Error(
+ "should not be using verb stems with long and short endings"
+ );
+ }
+ return {
+ ...vb,
+ ps: verbEndingConcat(vb.ps, end),
+ };
+ }
}
-function getEnding(person: T.Person, tenseC: "present" | "past" | "imperative", aspect: T.Aspect) {
- if (tenseC === "imperative") {
- if (!isSecondPerson(person)) {
- throw new Error("imperative forms must be second person");
- }
- const number = personNumber(person);
- const ends = imperativeEndings[0][number === "singular" ? 0 : 1];
- return aspect === "imperfective"
- ? ends.map(e => accentPsSyllable(e))
- : ends;
+function getEnding(
+ person: T.Person,
+ tenseC: "present" | "past" | "imperative",
+ aspect: T.Aspect
+) {
+ if (tenseC === "imperative") {
+ if (!isSecondPerson(person)) {
+ throw new Error("imperative forms must be second person");
}
- const [row, col] = getVerbBlockPosFromPerson(person);
- return tenseC === "past" ? {
+ const number = personNumber(person);
+ const ends = imperativeEndings[0][number === "singular" ? 0 : 1];
+ return aspect === "imperfective"
+ ? ends.map((e) => accentPsSyllable(e))
+ : ends;
+ }
+ const [row, col] = getVerbBlockPosFromPerson(person);
+ return tenseC === "past"
+ ? {
long: pastEndings.long[row][col],
short: pastEndings.short[row][col],
- } : presentEndings[row][col];
+ }
+ : presentEndings[row][col];
}
// TODO: THIS IS PROBABLY SKEEEETCH
-function ensure3rdPast(rs: T.PsString[], ending: T.PsString[], verb: T.VerbEntry, aspect: T.Aspect): T.PsString[] {
- if (isKedul(verb)) {
- return aspect === "perfective"
- ? [{ p: "شو", f: "sho" }]
- : [{ p: "کېده", f: "kedú" }];
- }
- if (isKawulVerb(verb) && rs[0].p === "کړ") {
- return [
- { p: "کړ", f: "kuR" },
- { p: "کړه", f: "kRu" },
- { p: "کړو", f: "kRo" },
- ];
- }
- if (isTlulVerb(verb)) {
- // should be imperfective at this point
- // the perfective غی should already be covered in the function this is coming from
- return [{
- p: rs[0].p.slice(0, -1) + "ه",
- f: rs[0].f.slice(0, -2) + "ú",
- }];
- }
- if (verb.entry.tppp && verb.entry.tppf) {
- const tip = removeAccents(verb.entry.separationAtP !== undefined
- ? makePsString(verb.entry.tppp.slice(verb.entry.separationAtP), verb.entry.tppf.slice(verb.entry.separationAtF))
- : makePsString(verb.entry.tppp, verb.entry.tppf));
- const aTip = aspect === "imperfective"
- ? accentOnNFromEnd(tip, 0)
- : tip;
- return [aTip];
- // if it ends in a consonant, the special form will also have another
- // variation ending with a ه - u
- // const endsInAConsonant = (pashtoConsonants.includes(tip.p.slice(-1)) || tip.f.slice(-1) === "w");
- // return [
- // aTip,
- // ...endsInAConsonant ? [
- // ...verbEndingConcat([aTip], [{ p: "ه", f: "u" }, { p: "و", f: "o" }]),
- // ] : [],
- // ];
- }
- const endsInAwul = (
- (["awul", "awúl"].includes(removeFVarients(verb.entry.f).slice(-4)))
- &&
- (verb.entry.p.slice(-2) === "ول")
+function ensure3rdPast(
+ rs: T.PsString[],
+ ending: T.PsString[],
+ verb: T.VerbEntry,
+ aspect: T.Aspect
+): T.PsString[] {
+ if (isKedul(verb)) {
+ return aspect === "perfective"
+ ? [{ p: "شو", f: "sho" }]
+ : [{ p: "کېده", f: "kedú" }];
+ }
+ if (isKawulVerb(verb) && rs[0].p === "کړ") {
+ return [
+ { p: "کړ", f: "kuR" },
+ { p: "کړه", f: "kRu" },
+ { p: "کړو", f: "kRo" },
+ ];
+ }
+ if (isTlulVerb(verb)) {
+ // should be imperfective at this point
+ // the perfective غی should already be covered in the function this is coming from
+ return [
+ {
+ p: rs[0].p.slice(0, -1) + "ه",
+ f: rs[0].f.slice(0, -2) + "ú",
+ },
+ {
+ p: rs[0].p + "و",
+ f: rs[0].f.slice(0, -1) + "ó",
+ },
+ ];
+ }
+ if (verb.entry.tppp && verb.entry.tppf) {
+ const tip = removeAccents(
+ verb.entry.separationAtP !== undefined
+ ? makePsString(
+ verb.entry.tppp.slice(verb.entry.separationAtP),
+ verb.entry.tppf.slice(verb.entry.separationAtF)
+ )
+ : makePsString(verb.entry.tppp, verb.entry.tppf)
);
- // TODO: check about verbs like tawul (if they exist)
- if (endsInAwul) {
- const base = { p: rs[0].p.slice(0, -1), f: rs[0].f.slice(0, -2) };
- const aawuEnd = concatPsString(base, { p: "اوه", f: base.f.charAt(base.f.length-1) === "a" ? "awu" : "aawu" });
- return [aspect === "imperfective"
- ? accentOnNFromEnd(aawuEnd, 0)
- : aawuEnd];
- }
- const endsInDental = ["د", "ت"].includes(rs[0].p.slice(-1));
- // short endings like ورسېد
- const ends = endsInDental ? [{ p: "", f: "" }, ...ending] : ending;
- return verbEndingConcat(rs, ends);
+ const aTip = aspect === "imperfective" ? accentOnNFromEnd(tip, 0) : tip;
+ return [aTip];
+ // if it ends in a consonant, the special form will also have another
+ // variation ending with a ه - u
+ // const endsInAConsonant = (pashtoConsonants.includes(tip.p.slice(-1)) || tip.f.slice(-1) === "w");
+ // return [
+ // aTip,
+ // ...endsInAConsonant ? [
+ // ...verbEndingConcat([aTip], [{ p: "ه", f: "u" }, { p: "و", f: "o" }]),
+ // ] : [],
+ // ];
+ }
+ const endsInAwul =
+ ["awul", "awúl"].includes(removeFVarients(verb.entry.f).slice(-4)) &&
+ verb.entry.p.slice(-2) === "ول";
+ // TODO: check about verbs like tawul (if they exist)
+ if (endsInAwul) {
+ const base = { p: rs[0].p.slice(0, -1), f: rs[0].f.slice(0, -2) };
+ const aawuEnd = concatPsString(base, {
+ p: "اوه",
+ f: base.f.charAt(base.f.length - 1) === "a" ? "awu" : "aawu",
+ });
+ return [aspect === "imperfective" ? accentOnNFromEnd(aawuEnd, 0) : aawuEnd];
+ }
+ const endsInDental = ["د", "ت"].includes(rs[0].p.slice(-1));
+ // short endings like ورسېد
+ const ends = endsInDental ? [{ p: "", f: "" }, ...ending] : ending;
+ return verbEndingConcat(rs, ends);
}
-function removeAbility(tense: T.VerbTense | T.AbilityTense | T.ImperativeTense): T.VerbTense | T.ImperativeTense {
- return tense.replace("Modal", "") as T.VerbTense | T.ImperativeTense;
-}
\ No newline at end of file
+function removeAbility(
+ tense: T.VerbTense | T.AbilityTense | T.ImperativeTense
+): T.VerbTense | T.ImperativeTense {
+ return tense.replace("Modal", "") as T.VerbTense | T.ImperativeTense;
+}
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 546398e..779d1c9 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
@@ -2,76 +2,560 @@ import * as T from "../../../types";
import { getPastParticiple, getRootStem } from "./roots-and-stems";
import { vEntry } 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"});
-const ganul = vEntry({"ts":1527812000,"i":11398,"p":"ګڼل","f":"gaNul, guNul","g":"gaNul,guNul","e":"to count, consider, reckon, suppose, assume","r":4,"c":"v. trans.","tppp":"ګاڼه","tppf":"gaaNu","ec":"deem"});
-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 kawulDyn = vEntry({"ts":1527812752,"i":11031,"p":"کول","f":"kawul","g":"kawul","e":"to do (an action or activity)","r":4,"c":"v. trans./gramm. trans.","ssp":"وکړ","ssf":"óokR","prp":"وکړل","prf":"óokRul","pprtp":"کړی","pprtf":"kúRey","diacExcept":true,"ec":"do,does,doing,did,done","separationAtP":1,"separationAtF":2});
-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 kedulDyn = vEntry({"ts":1527812754,"i":11101,"p":"کېدل","f":"kedul","g":"kedul","e":"to happen, occur","r":2,"c":"v. intrans.","ssp":"وش","ssf":"óosh","prp":"وشول","prf":"óoshwul","pprtp":"شوی","pprtf":"shúwey","diacExcept":true,"ec":"happen","separationAtP":1,"separationAtF":2});
-const raatlul = vEntry({"ts":1527815216,"i":6875,"p":"راتلل","f":"raatlúl","g":"raatlul","e":"to come","r":4,"c":"v. intrans.","psp":"راځ","psf":"raadz","ssp":"راش","ssf":"ráash","prp":"راغلل","prf":"ráaghlul","pprtp":"راغلی","pprtf":"raaghúley","tppp":"راغی","tppf":"ráaghey","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"come,comes,coming,came,come"});
-const wartlul = vEntry({"ts":1585228579997,"i":14821,"p":"ورتلل","f":"wărtlul","g":"wartlul","e":"to come / go over to (third person or place)","r":4,"c":"v. intrans.","psp":"ورځ","psf":"wărdz","ssp":"ورش","ssf":"wársh","prp":"ورغلل","prf":"wárghlul","pprtp":"ورغلی","pprtf":"wărghúley","tppp":"ورغی","tppf":"wărghey","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"come,comes,coming,came,come"});
-const osedul = vEntry({"ts":1527815139,"i":1127,"p":"اوسېدل","f":"osedul","g":"osedul","e":"to live, reside, stay, be","r":4,"c":"v. intrans.","shortIntrans":true,"diacExcept":true});
-const tlul = vEntry({"ts":1527815348,"i":3791,"p":"تلل","f":"tlul","g":"tlul","e":"to go","r":4,"c":"v. intrans.","psp":"ځ","psf":"dz","ssp":"لاړ ش","ssf":"láaR sh","prp":"لاړ","prf":"láaR","ec":"go,goes,going,went,gone"});
-const awuxtul = vEntry({"ts":1527814012,"i":1133,"p":"اوښتل","f":"awUxtul","g":"awUxtul","e":"to pass over, overturn, be flipped over, spill over, shift, change, diverge, pass, cross, abandon; to be sprained","r":4,"c":"v. intrans.","psp":"اوړ","psf":"awR","ec":"pass","ep":"over"});
-const khorul = vEntry({"ts":1527812790,"i":6002,"p":"خوړل","f":"khoRul","g":"khoRul","e":"to eat, to bite","r":4,"c":"v. trans.","psp":"خور","psf":"khor","tppp":"خوړ","tppf":"khoR","ec":"eat,eats,eating,ate,eaten"});
-const azmoyul = vEntry({"ts":1527811605,"i":468,"p":"ازمویل","f":"azmoyul","g":"azmoyul","e":"to attempt, try; to experiment, test","r":4,"c":"v. trans.","sepOo":true,"ec":"try"});
-const khatul = vEntry({"ts":1527814025,"i":5677,"p":"ختل","f":"khatul","g":"khatul","e":"to climb, ascend, rise, go up; to fall out, to fall off, to leave/dissapear; to turn out to be ...; to give a sentence (in law)","r":3,"c":"v. intrans.","psp":"خېژ","psf":"khejz","tppp":"خوت","tppf":"khot","ec":"climb"});
-const rasedul = vEntry({"ts":1527813573,"i":7057,"p":"رسېدل","f":"rasedul","g":"rasedul","e":"arrive, reach; (fig.) understand, attain to; mature, ripen","r":4,"c":"v. intrans.","shortIntrans":true,"ec":"arrive"});
-const weshul = vEntry({"ts":1527811701,"i":15106,"p":"وېشل","f":"weshul","g":"weshul","e":"divide, distribute, share","r":4,"c":"v. trans.","ec":"divide"});
-const watul = vEntry({"ts":1527823376,"i":14759,"p":"وتل","f":"watul","g":"watul","e":"to go out, exit, leave, emerge","r":4,"c":"v. intrans.","psp":"وځ","psf":"oodz","tppp":"واته","tppf":"waatu","ec":"go,goes,going,went,gone","ep":"out"});
-const wurul = vEntry({"ts":1527816865,"i":14903,"p":"وړل","f":"wuRúl, oRúl, wRul","g":"wuRul,oRul,wRul","e":"to take, carry, bear, move (inanimate objects); to win, earn (subjunctive یوسي - yósee or ویسي - wéesee, simple past یو یې وړلو - yo ye wRulo)","r":3,"c":"v. trans.","ssp":"یوس","ssf":"yos","prp":"یوړل","prf":"yóRul","tppp":"یوړ","tppf":"yoR","noOo":true,"separationAtP":2,"separationAtF":2,"diacExcept":true,"ec":"take,takes,taking,took,taken"});
-const kexodul = vEntry({"ts":1527812284,"i":11113,"p":"کېښودل","f":"kexodul","g":"kexodul","e":"to put, to put down, to set in place","r":4,"c":"v. trans.","psp":"ږد","psf":"Gd","ssp":"کېږد","ssf":"kéGd","noOo":true,"separationAtP":2,"separationAtF":2,"ec":"put,puts,putting,put,put"});
-const kenaastul = vEntry({"ts":1527812759,"i":11124,"p":"کېناستل","f":"kenaastul","g":"kenaastul","e":"to sit down, to have a seat","r":4,"c":"v. intrans.","psp":"کېن","psf":"ken","noOo":true,"separationAtP":2,"separationAtF":2,"ec":"sit,sits,sitting,sat","ep":"down"});
-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 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",
+});
+const ganul = vEntry({
+ ts: 1527812000,
+ i: 11398,
+ p: "ګڼل",
+ f: "gaNul, guNul",
+ g: "gaNul,guNul",
+ e: "to count, consider, reckon, suppose, assume",
+ r: 4,
+ c: "v. trans.",
+ tppp: "ګاڼه",
+ tppf: "gaaNu",
+ ec: "deem",
+});
+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 kawulDyn = vEntry({
+ ts: 1527812752,
+ i: 11031,
+ p: "کول",
+ f: "kawul",
+ g: "kawul",
+ e: "to do (an action or activity)",
+ r: 4,
+ c: "v. trans./gramm. trans.",
+ ssp: "وکړ",
+ ssf: "óokR",
+ prp: "وکړل",
+ prf: "óokRul",
+ pprtp: "کړی",
+ pprtf: "kúRey",
+ diacExcept: true,
+ ec: "do,does,doing,did,done",
+ separationAtP: 1,
+ separationAtF: 2,
+});
+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 kedulDyn = vEntry({
+ ts: 1527812754,
+ i: 11101,
+ p: "کېدل",
+ f: "kedul",
+ g: "kedul",
+ e: "to happen, occur",
+ r: 2,
+ c: "v. intrans.",
+ ssp: "وش",
+ ssf: "óosh",
+ prp: "وشول",
+ prf: "óoshwul",
+ pprtp: "شوی",
+ pprtf: "shúwey",
+ diacExcept: true,
+ ec: "happen",
+ separationAtP: 1,
+ separationAtF: 2,
+});
+const raatlul = vEntry({
+ ts: 1527815216,
+ i: 6875,
+ p: "راتلل",
+ f: "raatlúl",
+ g: "raatlul",
+ e: "to come",
+ r: 4,
+ c: "v. intrans.",
+ psp: "راځ",
+ psf: "raadz",
+ ssp: "راش",
+ ssf: "ráash",
+ prp: "راغلل",
+ prf: "ráaghlul",
+ pprtp: "راغلی",
+ pprtf: "raaghúley",
+ tppp: "راغی",
+ tppf: "ráaghey",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 3,
+ ec: "come,comes,coming,came,come",
+});
+const wartlul = vEntry({
+ ts: 1585228579997,
+ i: 14821,
+ p: "ورتلل",
+ f: "wărtlul",
+ g: "wartlul",
+ e: "to come / go over to (third person or place)",
+ r: 4,
+ c: "v. intrans.",
+ psp: "ورځ",
+ psf: "wărdz",
+ ssp: "ورش",
+ ssf: "wársh",
+ prp: "ورغلل",
+ prf: "wárghlul",
+ pprtp: "ورغلی",
+ pprtf: "wărghúley",
+ tppp: "ورغی",
+ tppf: "wărghey",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 3,
+ ec: "come,comes,coming,came,come",
+});
+const osedul = vEntry({
+ ts: 1527815139,
+ i: 1127,
+ p: "اوسېدل",
+ f: "osedul",
+ g: "osedul",
+ e: "to live, reside, stay, be",
+ r: 4,
+ c: "v. intrans.",
+ shortIntrans: true,
+ diacExcept: true,
+});
+const awuxtul = vEntry({
+ ts: 1527814012,
+ i: 1133,
+ p: "اوښتل",
+ f: "awUxtul",
+ g: "awUxtul",
+ e: "to pass over, overturn, be flipped over, spill over, shift, change, diverge, pass, cross, abandon; to be sprained",
+ r: 4,
+ c: "v. intrans.",
+ psp: "اوړ",
+ psf: "awR",
+ ec: "pass",
+ ep: "over",
+});
+const khorul = vEntry({
+ ts: 1527812790,
+ i: 6002,
+ p: "خوړل",
+ f: "khoRul",
+ g: "khoRul",
+ e: "to eat, to bite",
+ r: 4,
+ c: "v. trans.",
+ psp: "خور",
+ psf: "khor",
+ tppp: "خوړ",
+ tppf: "khoR",
+ ec: "eat,eats,eating,ate,eaten",
+});
+const azmoyul = vEntry({
+ ts: 1527811605,
+ i: 468,
+ p: "ازمویل",
+ f: "azmoyul",
+ g: "azmoyul",
+ e: "to attempt, try; to experiment, test",
+ r: 4,
+ c: "v. trans.",
+ sepOo: true,
+ ec: "try",
+});
+const khatul = vEntry({
+ ts: 1527814025,
+ i: 5677,
+ p: "ختل",
+ f: "khatul",
+ g: "khatul",
+ e: "to climb, ascend, rise, go up; to fall out, to fall off, to leave/dissapear; to turn out to be ...; to give a sentence (in law)",
+ r: 3,
+ c: "v. intrans.",
+ psp: "خېژ",
+ psf: "khejz",
+ tppp: "خوت",
+ tppf: "khot",
+ ec: "climb",
+});
+const rasedul = vEntry({
+ ts: 1527813573,
+ i: 7057,
+ p: "رسېدل",
+ f: "rasedul",
+ g: "rasedul",
+ e: "arrive, reach; (fig.) understand, attain to; mature, ripen",
+ r: 4,
+ c: "v. intrans.",
+ shortIntrans: true,
+ ec: "arrive",
+});
+const weshul = vEntry({
+ ts: 1527811701,
+ i: 15106,
+ p: "وېشل",
+ f: "weshul",
+ g: "weshul",
+ e: "divide, distribute, share",
+ r: 4,
+ c: "v. trans.",
+ ec: "divide",
+});
+const watul = vEntry({
+ ts: 1527823376,
+ i: 14759,
+ p: "وتل",
+ f: "watul",
+ g: "watul",
+ e: "to go out, exit, leave, emerge",
+ r: 4,
+ c: "v. intrans.",
+ psp: "وځ",
+ psf: "oodz",
+ tppp: "واته",
+ tppf: "waatu",
+ ec: "go,goes,going,went,gone",
+ ep: "out",
+});
+const wurul = vEntry({
+ ts: 1527816865,
+ i: 14903,
+ p: "وړل",
+ f: "wuRúl, oRúl, wRul",
+ g: "wuRul,oRul,wRul",
+ e: "to take, carry, bear, move (inanimate objects); to win, earn (subjunctive یوسي - yósee or ویسي - wéesee, simple past یو یې وړلو - yo ye wRulo)",
+ r: 3,
+ c: "v. trans.",
+ ssp: "یوس",
+ ssf: "yos",
+ prp: "یوړل",
+ prf: "yóRul",
+ tppp: "یوړ",
+ tppf: "yoR",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ diacExcept: true,
+ ec: "take,takes,taking,took,taken",
+});
+const kexodul = vEntry({
+ ts: 1527812284,
+ i: 11113,
+ p: "کېښودل",
+ f: "kexodul",
+ g: "kexodul",
+ e: "to put, to put down, to set in place",
+ r: 4,
+ c: "v. trans.",
+ psp: "ږد",
+ psf: "Gd",
+ ssp: "کېږد",
+ ssf: "kéGd",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ ec: "put,puts,putting,put,put",
+});
+const kenaastul = vEntry({
+ ts: 1527812759,
+ i: 11124,
+ p: "کېناستل",
+ f: "kenaastul",
+ g: "kenaastul",
+ e: "to sit down, to have a seat",
+ r: 4,
+ c: "v. intrans.",
+ psp: "کېن",
+ psf: "ken",
+ noOo: true,
+ separationAtP: 2,
+ separationAtF: 2,
+ ec: "sit,sits,sitting,sat",
+ ep: "down",
+});
+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 tlul = vEntry({
+ ts: 1527815348,
+ i: 3804,
+ p: "تلل",
+ f: "tlul",
+ g: "tlul",
+ e: "to go",
+ r: 4,
+ c: "v. intrans.",
+ psp: "ځ",
+ psf: "dz",
+ ssp: "لاړ ش",
+ ssf: "láaR sh",
+ prp: "لاړ",
+ prf: "láaR",
+ ec: "go,goes,going,went,gone",
+});
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."},
+ {
+ 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."},
+ {
+ 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."},
+ {
+ 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."},
+ {
+ 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 bayaanedul = vEntry(
- {"ts":1659037345120,"i":2055,"p":"بیانېدل","f":"bayaanedúl","g":"bayaanedul","e":"to be described, told, narrated, explained, declared","r":4,"c":"v. stat. comp. intrans.","l":1527814259},
- {"ts":1527814259,"i":2052,"p":"بیان","f":"bayáan","g":"bayaan","e":"description, statement, speaking, narration, sermon","r":4,"c":"n. m.","app":"بیانات","apf":"bayaanaat"},
+ {
+ ts: 1659037345120,
+ i: 2055,
+ p: "بیانېدل",
+ f: "bayaanedúl",
+ g: "bayaanedul",
+ e: "to be described, told, narrated, explained, declared",
+ r: 4,
+ c: "v. stat. comp. intrans.",
+ l: 1527814259,
+ },
+ {
+ ts: 1527814259,
+ i: 2052,
+ p: "بیان",
+ f: "bayáan",
+ g: "bayaan",
+ e: "description, statement, speaking, narration, sermon",
+ r: 4,
+ c: "n. m.",
+ app: "بیانات",
+ apf: "bayaanaat",
+ }
);
const khufaKedul = vEntry(
- {"ts":1577898920635,"i":5845,"p":"خفه کېدل","f":"khufa kedul","g":"khufakedul","e":"to become sad, grieved, annoyed, upset; to be choked, to suffocate","r":4,"c":"v. stat. comp. intrans.","l":1527812798,"ec":"become","ep":"sad"},
- {"ts":1527812798,"i":5843,"p":"خفه","f":"khufa","g":"khufa","e":"sad, upset, angry; choked, suffocated","r":4,"c":"adj."},
+ {
+ ts: 1577898920635,
+ i: 5845,
+ p: "خفه کېدل",
+ f: "khufa kedul",
+ g: "khufakedul",
+ e: "to become sad, grieved, annoyed, upset; to be choked, to suffocate",
+ r: 4,
+ c: "v. stat. comp. intrans.",
+ l: 1527812798,
+ ec: "become",
+ ep: "sad",
+ },
+ {
+ ts: 1527812798,
+ i: 5843,
+ p: "خفه",
+ f: "khufa",
+ g: "khufa",
+ e: "sad, upset, angry; choked, suffocated",
+ r: 4,
+ c: "adj.",
+ }
);
-const ooPH: T.PH= { type: "PH", ps: { p: "و", f: "óo" }};
+const ooPH: T.PH = { type: "PH", ps: { p: "و", f: "óo" } };
describe("imperfective stems", () => {
const tests: {
- title: string,
+ title: string;
tests: {
- verb: T.VerbEntry,
- genderNumber?: T.GenderNumber,
- result: T.RootsStemsOutput,
- }[],
+ 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" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "ګڼ", f: "gaN" }] }]],
},
{
verb: wahul,
- result: [[], [{ type: "VB", ps: [{ p: "وه", f: "wah" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "وه", f: "wah" }] }]],
},
],
},
@@ -98,31 +582,41 @@ describe("imperfective stems", () => {
tests: [
{
verb: ghadzedul,
- result: [[], [{ type: "VB", ps: [{ p: "غځېږ", f: "ghadzéG" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "غځېږ", f: "ghadzéG" }] }]],
},
{
verb: rasedul,
- result: [[], [{
- type: "VB",
- ps: {
- long: [{ p: "رسېږ", f: "raséG" }],
- short: [{ p: "رس", f: "ras" }],
- },
- }]],
+ 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",
+ title:
+ "is the special imperfective stem for irregular verbs with a special imperfective stem",
tests: [
{
verb: khorul,
- result: [[], [{ type: "VB", ps: [{ p: "خور", f: "khor" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "خور", f: "khor" }] }]],
},
{
verb: kexodul,
result: [[], [{ type: "VB", ps: [{ p: "ږد", f: "Gd" }] }]],
},
+ {
+ verb: tlul,
+ result: [[], [{ type: "VB", ps: [{ p: "ځ", f: "dz" }] }]],
+ },
],
},
{
@@ -131,101 +625,134 @@ describe("imperfective stems", () => {
{
verb: bandawul,
genderNumber: { gender: "masc", number: "singular" },
- result: [[], [{ type: "VB", ps: [{ p: "بندو", f: "bandawX" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "بندو", f: "bandawX" }] }]],
},
{
verb: bandedul,
genderNumber: { gender: "masc", number: "singular" },
- result: [[], [{ type: "VB", ps: [{ p: "بندېږ", f: "bandéG" }]}]],
+ result: [[], [{ type: "VB", ps: [{ p: "بندېږ", f: "bandéG" }] }]],
},
],
},
{
- title: "is welded together with the complement on seperated stative compounds",
+ 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",
+ result: [
+ [],
+ [
+ {
+ type: "welded",
+ left: {
+ type: "NComp",
+ comp: {
+ type: "AdjComp",
+ ps: { p: "ستړې", f: "stuRe" },
+ number: "singular",
+ gender: "fem",
+ },
+ },
+ right: {
+ type: "VB",
+ ps: [{ p: "کو", f: "kawX" }],
+ },
},
- },
- 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",
+ 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" }],
+ },
},
- },
- right: {
- type: "VB",
- ps: [{ p: "کېږ", f: "kéG" }],
- },
- }]],
+ ],
+ ],
},
- ]
- }
+ ],
+ },
];
- tests.forEach(x => {
+ 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);
+ 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,
+ title: string;
tests: {
- verb: T.VerbEntry,
- genderNumber?: T.GenderNumber,
- result: T.RootsStemsOutput,
- }[],
+ 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",
+ 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" }],
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "وهل", f: "wahúl" }],
+ short: [{ p: "وه", f: "wahX" }],
+ },
},
- }]
+ ],
+ ],
+ },
+ {
+ verb: tlul,
+ result: [
+ [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "تلل", f: "tlúl" }],
+ short: [{ p: "تل", f: "tlX" }],
+ },
+ },
+ ],
],
},
],
@@ -239,12 +766,12 @@ describe("imperfective roots", () => {
result: [
[],
[
- {
+ {
type: "VB",
ps: {
long: [{ p: "بندول", f: "bandawúl" }],
short: [{ p: "بندو", f: "bandawX" }],
- }
+ },
},
],
],
@@ -259,7 +786,7 @@ describe("imperfective roots", () => {
type: "VB",
ps: {
long: [{ p: "بندېدل", f: "bandedúl" }],
- short: [{ p: "بندېد", f: "bandedX" }]
+ short: [{ p: "بندېد", f: "bandedX" }],
},
},
],
@@ -268,98 +795,108 @@ describe("imperfective roots", () => {
],
},
{
- title: "is welded together with the complement on seperated stative compounds",
+ 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",
+ 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" }],
+ },
+ },
},
- },
- 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",
+ 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" }],
+ },
+ },
},
- },
- right: {
- type: "VB",
- ps: {
- long: [{ p: "کېدل", f: "kedúl" }],
- short: [{ p: "کېد", f: "kedX" }],
- },
- },
- }]],
+ ],
+ ],
},
- ]
- }
+ ],
+ },
];
- tests.forEach(x => {
+ 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);
+ 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,
+ title: string;
tests: {
- verb: T.VerbEntry,
- genderNumber?: T.GenderNumber,
- result: T.RootsStemsOutput,
- }[],
+ 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" }]}],
- ],
+ result: [[ooPH], [{ type: "VB", ps: [{ p: "ګڼ", f: "gaN" }] }]],
},
{
verb: wahul,
- result: [[ooPH], [{ type: "VB", ps: [{ p: "وه", f: "wah" }]}]],
+ result: [[ooPH], [{ type: "VB", ps: [{ p: "وه", f: "wah" }] }]],
},
],
},
@@ -368,7 +905,7 @@ describe("perfective stems", () => {
tests: [
{
verb: ghadzedul,
- result: [[ooPH], [{ type: "VB", ps: [{ p: "غځېږ", f: "ghadzeG" }]}]],
+ result: [[ooPH], [{ type: "VB", ps: [{ p: "غځېږ", f: "ghadzeG" }] }]],
},
{
verb: rasedul,
@@ -388,11 +925,12 @@ describe("perfective stems", () => {
],
},
{
- title: "the imperfective stem the perfective stem is regularly built off could be irregular",
+ 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" }]}]],
+ result: [[ooPH], [{ type: "VB", ps: [{ p: "خور", f: "khor" }] }]],
},
],
},
@@ -402,11 +940,11 @@ describe("perfective stems", () => {
{
verb: wurul,
result: [
- [{ type: "PH", ps: { p: "یو", f: "yó" }}],
- [{ type: "VB", ps: [{ p: "س", f: "s" }]}],
+ [{ type: "PH", ps: { p: "یو", f: "yó" } }],
+ [{ type: "VB", ps: [{ p: "س", f: "s" }] }],
],
- }
- ]
+ },
+ ],
},
{
title: "includes extra irregular short roots for kawul verbs",
@@ -423,7 +961,7 @@ describe("perfective stems", () => {
short: [{ p: "ک", f: "k" }],
},
},
- ]
+ ],
],
},
],
@@ -443,7 +981,7 @@ describe("perfective stems", () => {
short: [{ p: "ک", f: "k" }],
},
},
- ]
+ ],
],
},
],
@@ -475,30 +1013,24 @@ describe("perfective stems", () => {
verb: tlul,
genderNumber: { gender: "fem", number: "singular" },
result: [
- [{ type: "PH", ps: { p: "لاړه ", f: "láaRa " }}],
- [
- { type: "VB", ps: [{ p: "ش", f: "sh" }]},
- ],
+ [{ 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" }]},
- ],
+ [{ 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" }]},
- ],
+ [{ type: "PH", ps: { p: "لاړ ", f: "láaR " } }],
+ [{ type: "VB", ps: [{ p: "ش", f: "sh" }] }],
],
},
],
@@ -633,9 +1165,7 @@ describe("perfective stems", () => {
verb: azmoyul,
genderNumber: { gender: "masc", number: "plural" },
result: [
- [
- { type: "PH", ps: { p: "و ", f: "óo`" }},
- ],
+ [{ type: "PH", ps: { p: "و ", f: "óo`" } }],
[
{
type: "VB",
@@ -648,9 +1178,7 @@ describe("perfective stems", () => {
verb: achawul,
genderNumber: { gender: "masc", number: "plural" },
result: [
- [
- { type: "PH", ps: { p: "وا", f: "wáa" }},
- ],
+ [{ type: "PH", ps: { p: "وا", f: "wáa" } }],
[
{
type: "VB",
@@ -663,21 +1191,15 @@ describe("perfective stems", () => {
verb: watul,
genderNumber: { gender: "masc", number: "plural" },
result: [
- [
- { type: "PH", ps: { p: "و", f: "wÚ" }},
- ],
- [
- { type: "VB", ps: [{ p: "وځ", f: "oodz" }]},
- ],
+ [{ type: "PH", ps: { p: "و", f: "wÚ" } }],
+ [{ type: "VB", ps: [{ p: "وځ", f: "oodz" }] }],
],
},
{
verb: osedul,
genderNumber: { gender: "masc", number: "plural" },
result: [
- [
- { type: "PH", ps: { p: "و", f: "óo`" }},
- ],
+ [{ type: "PH", ps: { p: "و", f: "óo`" } }],
[
{
type: "VB",
@@ -692,33 +1214,35 @@ describe("perfective stems", () => {
],
},
];
- tests.forEach(x => {
+ 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);
+ 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,
+ title: string;
tests: {
- verb: T.VerbEntry,
- genderNumber?: T.GenderNumber,
- result: T.RootsStemsOutput,
- }[],
+ verb: T.VerbEntry;
+ genderNumber?: T.GenderNumber;
+ result: T.RootsStemsOutput;
+ }[];
}[] = [
{
title: "is the imprefective root with an oo- prefix for regular verbs",
@@ -743,7 +1267,7 @@ describe("perfective roots", () => {
result: [
[ooPH],
[
- {
+ {
type: "VB",
ps: {
long: [{ p: "وهل", f: "wahul" }],
@@ -761,14 +1285,34 @@ describe("perfective roots", () => {
{
verb: wurul,
result: [
- [{ type: "PH", ps: { p: "یو", f: "yó" }}],
+ [{ type: "PH", ps: { p: "یو", f: "yó" } }],
[
{
type: "VB",
ps: {
long: [{ p: "ړل", f: "Rul" }],
short: [{ p: "ړ", f: "R" }],
- }
+ },
+ },
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ title: "is the special form with tlul",
+ tests: [
+ {
+ verb: tlul,
+ result: [
+ [{ type: "PH", ps: { p: "لا", f: "láa" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ړل", f: "Rul" }],
+ short: [{ p: "ړ", f: "R" }],
+ },
},
],
],
@@ -812,7 +1356,7 @@ describe("perfective roots", () => {
mini: [{ p: "ک", f: "k" }],
},
},
- ]
+ ],
],
},
],
@@ -889,7 +1433,7 @@ describe("perfective roots", () => {
ps: {
long: [{ p: "شول", f: "shwul" }],
short: [{ p: "شو", f: "shw" }],
- }
+ },
},
],
],
@@ -915,7 +1459,7 @@ describe("perfective roots", () => {
ps: {
long: [{ p: "شول", f: "shwul" }],
short: [{ p: "شو", f: "shw" }],
- }
+ },
},
],
],
@@ -923,159 +1467,279 @@ describe("perfective roots", () => {
],
},
];
- tests.forEach(x => {
+ 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);
+ 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", () => {
- expect(getPastParticiple(rasedul, "active", { gender: "masc", number: "singular" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "رسېدلی", f: "rasedúley" }],
+ expect(
+ getPastParticiple(rasedul, "active", {
gender: "masc",
number: "singular",
- });
- expect(getPastParticiple(ganul, "active", { gender: "fem", number: "singular" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "ګڼلې", f: "gaNúle" }],
- gender: "fem",
- number: "singular",
- });
+ })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "رسېدلی", f: "rasedúley" }],
+ gender: "masc",
+ number: "singular",
+ });
+ expect(
+ getPastParticiple(ganul, "active", { gender: "fem", number: "singular" })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "ګڼلې", f: "gaNúle" }],
+ gender: "fem",
+ number: "singular",
+ });
});
test("for verbs like اېښودل and پرېښودل they have a short version shortened taking off after ښ", () => {
- expect(getPastParticiple(prexodul, "active", { gender: "masc", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: {
- long: [{ p: "پرېښودلي", f: "prexodúlee" }],
- short: [{ p: "پرېښي", f: "préxee" }],
- },
+ expect(
+ getPastParticiple(prexodul, "active", {
gender: "masc",
number: "plural",
- });
+ })
+ ).toEqual({
+ type: "VB",
+ ps: {
+ long: [{ p: "پرېښودلي", f: "prexodúlee" }],
+ short: [{ p: "پرېښي", f: "préxee" }],
+ },
+ gender: "masc",
+ number: "plural",
+ });
});
test("verbs ending in ستل ښتل وتل or وړل verbs also have a short version", () => {
- expect(getPastParticiple(raawustul, "active", { gender: "fem", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: {
- long: [{ p: "راوستلې", f: "raawustúle" }],
- short: [{ p: "راوستې", f: "raawúste" }],
- },
+ expect(
+ getPastParticiple(raawustul, "active", {
gender: "fem",
number: "plural",
- });
- expect(getPastParticiple(awuxtul, "active", { gender: "masc", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: {
- long: [{ p: "اوښتلي", f: "awUxtúlee" }],
- short: [{ p: "اوښتي", f: "awÚxtee" }],
- },
- gender: "masc",
- number: "plural",
- });
- expect(getPastParticiple(watul, "active", { gender: "fem", number: "singular" }))
- .toEqual({
- type: "VB",
- ps: {
- long: [{ p: "وتلې", f: "watúle" }],
- short: [{ p: "وتې", f: "wáte" }],
- },
- gender: "fem",
- number: "singular",
- });
+ })
+ ).toEqual({
+ type: "VB",
+ ps: {
+ long: [{ p: "راوستلې", f: "raawustúle" }],
+ short: [{ p: "راوستې", f: "raawúste" }],
+ },
+ gender: "fem",
+ number: "plural",
+ });
+ expect(
+ getPastParticiple(awuxtul, "active", { gender: "masc", number: "plural" })
+ ).toEqual({
+ type: "VB",
+ ps: {
+ long: [{ p: "اوښتلي", f: "awUxtúlee" }],
+ short: [{ p: "اوښتي", f: "awÚxtee" }],
+ },
+ gender: "masc",
+ number: "plural",
+ });
+ expect(
+ getPastParticiple(watul, "active", { gender: "fem", number: "singular" })
+ ).toEqual({
+ type: "VB",
+ ps: {
+ long: [{ p: "وتلې", f: "watúle" }],
+ short: [{ p: "وتې", f: "wáte" }],
+ },
+ gender: "fem",
+ number: "singular",
+ });
});
test("but not verbs ending with استل", () => {
- expect(getPastParticiple(kenaastul, "active", { gender: "fem", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "کېناستلې", f: "kenaastúle" }],
+ expect(
+ getPastParticiple(kenaastul, "active", {
gender: "fem",
number: "plural",
- });
+ })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "کېناستلې", f: "kenaastúle" }],
+ gender: "fem",
+ number: "plural",
+ });
});
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",
- });
+ 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",
- ps: [{ p: "کړی", f: "kúRey" }],
+ expect(
+ getPastParticiple(kawulDyn, "active", {
gender: "masc",
number: "singular",
- });
- expect(getPastParticiple(kawulStat, "active", { gender: "masc", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "کړي", f: "kúRee" }],
+ })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "کړی", f: "kúRey" }],
+ gender: "masc",
+ number: "singular",
+ });
+ expect(
+ getPastParticiple(kawulStat, "active", {
gender: "masc",
number: "plural",
- });
- expect(getPastParticiple(kedulStat, "active", { gender: "fem", number: "singular" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "شوې", f: "shúwe" }],
+ })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "کړي", f: "kúRee" }],
+ gender: "masc",
+ number: "plural",
+ });
+ expect(
+ getPastParticiple(kedulStat, "active", {
gender: "fem",
number: "singular",
- });
- expect(getPastParticiple(kedulDyn, "active", { gender: "fem", number: "plural" }))
- .toEqual({
- type: "VB",
- ps: [{ p: "شوې", f: "shúwe" }],
- gender: "fem",
- number: "plural",
- });
+ })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "شوې", f: "shúwe" }],
+ gender: "fem",
+ number: "singular",
+ });
+ expect(
+ getPastParticiple(kedulDyn, "active", { gender: "fem", number: "plural" })
+ ).toEqual({
+ type: "VB",
+ ps: [{ p: "شوې", f: "shúwe" }],
+ gender: "fem",
+ 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" }],
+ 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",
},
- });
- expect(getPastParticiple(bandedul, "active", { gender: "fem", number: "plural" }))
- .toEqual({
+ },
+ 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",
@@ -1087,101 +1751,35 @@ describe("past participles", () => {
},
},
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"
- },
- });
- })
+ },
+ right: {
+ type: "VB",
+ ps: [{ p: "شوې", f: "shúwe" }],
+ gender: "fem",
+ number: "plural",
+ },
+ });
+ });
});
describe("ability roots and stems", () => {
const tests: {
- title: string,
+ title: string;
tests: {
- verb: T.VerbEntry,
- aspect: T.Aspect,
- rs: "root" | "stem",
- genderNumber?: T.GenderNumber,
- result: T.RootsStemsOutput,
- voice: T.Voice,
- }[],
+ verb: T.VerbEntry;
+ aspect: T.Aspect;
+ rs: "root" | "stem";
+ genderNumber?: T.GenderNumber;
+ result: T.RootsStemsOutput;
+ voice: T.Voice;
+ }[];
}[] = [
{
- title: "is the aspect's root with the ability endings and then the perfective kedul modal verb stem or root",
+ title:
+ "is the aspect's root with the ability endings and then the perfective kedul modal verb stem or root",
tests: [
{
verb: khatul,
@@ -1327,8 +1925,8 @@ describe("ability roots and stems", () => {
],
},
},
- {
- type: "VB",
+ {
+ type: "VB",
ps: [{ p: "ش", f: "sh" }],
},
],
@@ -1355,8 +1953,8 @@ describe("ability roots and stems", () => {
],
},
},
- {
- type: "VB",
+ {
+ type: "VB",
ps: [{ p: "ش", f: "sh" }],
},
],
@@ -1388,8 +1986,8 @@ describe("ability roots and stems", () => {
],
},
},
- {
- type: "VB",
+ {
+ type: "VB",
ps: [{ p: "ش", f: "sh" }],
},
],
@@ -1398,7 +1996,8 @@ describe("ability roots and stems", () => {
],
},
{
- title: "passive takes the long imperfective passive root (loses aspect), and adds the ability endings",
+ title:
+ "passive takes the long imperfective passive root (loses aspect), and adds the ability endings",
tests: [
{
verb: achawul,
@@ -1420,16 +2019,16 @@ describe("ability roots and stems", () => {
long: [
{ p: "کېدلی", f: "kedúley" },
{ p: "کېدلای", f: "kedúlaay" },
- ],
+ ],
short: [
{ p: "کېدی", f: "kedéy" },
{ p: "کېدای", f: "kedáay" },
- ],
+ ],
},
},
},
- {
- type: "VB",
+ {
+ type: "VB",
ps: [{ p: "ش", f: "sh" }],
},
],
@@ -1441,32 +2040,39 @@ describe("ability roots and stems", () => {
tests.forEach((x) => {
test(x.title, () => {
x.tests.forEach((y) => {
- expect(getRootStem({
- verb: y.verb,
- aspect: y.aspect,
- rs: y.rs,
- genderNumber: y.genderNumber || { gender: "masc", number: "plural" },
- type: "ability",
- voice: y.voice,
- })).toEqual(y.result);
- })
- })
+ expect(
+ getRootStem({
+ verb: y.verb,
+ aspect: y.aspect,
+ rs: y.rs,
+ genderNumber: y.genderNumber || {
+ gender: "masc",
+ number: "plural",
+ },
+ type: "ability",
+ voice: y.voice,
+ })
+ ).toEqual(y.result);
+ });
+ });
});
});
describe("passive roots and stems", () => {
test("root plus kedul", () => {
- expect(getRootStem({
- verb: wahul,
- aspect: "imperfective",
- type: "basic",
- rs: "stem",
- genderNumber: {
- gender: "masc",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: wahul,
+ aspect: "imperfective",
+ type: "basic",
+ rs: "stem",
+ genderNumber: {
+ gender: "masc",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[],
[
{
@@ -1482,17 +2088,19 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: wahul,
- aspect: "imperfective",
- type: "basic",
- rs: "root",
- genderNumber: {
- gender: "masc",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: wahul,
+ aspect: "imperfective",
+ type: "basic",
+ rs: "root",
+ genderNumber: {
+ gender: "masc",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[],
[
{
@@ -1511,17 +2119,19 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: wahul,
- aspect: "perfective",
- type: "basic",
- rs: "stem",
- genderNumber: {
- gender: "masc",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: wahul,
+ aspect: "perfective",
+ type: "basic",
+ rs: "stem",
+ genderNumber: {
+ gender: "masc",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[ooPH],
[
{
@@ -1537,17 +2147,19 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: wahul,
- aspect: "perfective",
- type: "basic",
- rs: "root",
- genderNumber: {
- gender: "masc",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: wahul,
+ aspect: "perfective",
+ type: "basic",
+ rs: "root",
+ genderNumber: {
+ gender: "masc",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[ooPH],
[
{
@@ -1566,17 +2178,19 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: bandawul,
- aspect: "perfective",
- type: "basic",
- rs: "root",
- genderNumber: {
- gender: "fem",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: bandawul,
+ aspect: "perfective",
+ type: "basic",
+ rs: "root",
+ genderNumber: {
+ gender: "fem",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[
{
type: "NComp",
@@ -1605,17 +2219,19 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: bandawul,
- aspect: "imperfective",
- type: "basic",
- rs: "root",
- genderNumber: {
- gender: "fem",
- number: "singular",
- },
- voice: "passive",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: bandawul,
+ aspect: "imperfective",
+ type: "basic",
+ rs: "root",
+ genderNumber: {
+ gender: "fem",
+ number: "singular",
+ },
+ voice: "passive",
+ })
+ ).toEqual([
[],
[
{
@@ -1634,56 +2250,58 @@ describe("passive roots and stems", () => {
},
],
]);
- expect(getRootStem({
- verb: stureyKawul,
- aspect: "imperfective",
- type: "basic",
- voice: "passive",
- genderNumber: {
- gender: "masc",
- number: "singular",
- },
- rs: "stem",
- })).toEqual([
+ expect(
+ getRootStem({
+ verb: stureyKawul,
+ aspect: "imperfective",
+ type: "basic",
+ voice: "passive",
+ genderNumber: {
+ gender: "masc",
+ number: "singular",
+ },
+ rs: "stem",
+ })
+ ).toEqual([
[],
[
{
- "type": "welded",
- "left": {
- "type": "welded",
- "left": {
- "type": "NComp",
- "comp": {
- "type": "AdjComp",
- "ps": {
- "p": "ستړی",
- "f": "stuRey"
+ type: "welded",
+ left: {
+ type: "welded",
+ left: {
+ type: "NComp",
+ comp: {
+ type: "AdjComp",
+ ps: {
+ p: "ستړی",
+ f: "stuRey",
},
- "gender": "masc",
- "number": "singular"
- }
+ gender: "masc",
+ number: "singular",
+ },
},
- "right": {
- "type": "VB",
- "ps": [
+ right: {
+ type: "VB",
+ ps: [
{
- "p": "کول",
- "f": "kawul"
- }
- ]
- }
+ p: "کول",
+ f: "kawul",
+ },
+ ],
+ },
},
- "right": {
- "type": "VB",
- "ps": [
+ right: {
+ type: "VB",
+ ps: [
{
- "p": "کېږ",
- "f": "kéG"
- }
- ]
+ p: "کېږ",
+ f: "kéG",
+ },
+ ],
},
- }
- ]
+ },
+ ],
]);
});
});
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 c9e0f20..c8a4f5a 100644
--- a/src/lib/src/new-verb-engine/roots-and-stems.ts
+++ b/src/lib/src/new-verb-engine/roots-and-stems.ts
@@ -6,360 +6,471 @@
*
*/
-import {
- concatPsString, trimOffPs,
-} from "../p-text-helpers";
+import { concatPsString, trimOffPs } from "../p-text-helpers";
import * as T from "../../../types";
import { makePsString, removeFVarientsFromVerb } from "../accent-and-ps-utils";
-import { accentOnNFromEnd, countSyllables, 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, vTransitivity, isKedul } from "./rs-helpers";
+import {
+ vEntry,
+ addAbilityEnding,
+ weld,
+ removeL,
+ addTrailingAccent,
+ tlulPerfectiveStem,
+ getLongVB,
+ possiblePPartLengths,
+ isStatComp,
+ statCompImperfectiveSpace,
+ makeComplement,
+ vTransitivity,
+ isKedul,
+} from "./rs-helpers";
import { inflectPattern3 } from "./new-inflectors";
import { fmapSingleOrLengthOpts } from "../fmaps";
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"}),
+ 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",
- ps: {
- long: [{ p: "شول", f: "shwul" }],
- short: [{ p: "شو", f: "shw" }],
- },
-}
+ type: "VB",
+ ps: {
+ long: [{ p: "شول", f: "shwul" }],
+ short: [{ p: "شو", f: "shw" }],
+ },
+};
const shVB: T.VBBasic = {
- type: "VB",
- ps: [{ p: "ش", f: "sh" }],
-}
+ type: "VB",
+ ps: [{ p: "ش", f: "sh" }],
+};
// TODO: figure out how to handle dynamic / stative verbs
-export function getRootStem({ verb, rs, aspect, type, genderNumber, voice }: {
- verb: T.VerbEntry,
- rs: "root" | "stem",
- aspect: T.Aspect,
- voice: T.Voice,
- type: "basic" | "ability",
- genderNumber: {
- gender: T.Gender,
- number: T.NounNumber,
- },
+export function getRootStem({
+ verb,
+ rs,
+ aspect,
+ type,
+ genderNumber,
+ voice,
+}: {
+ verb: T.VerbEntry;
+ rs: "root" | "stem";
+ aspect: T.Aspect;
+ voice: T.Voice;
+ type: "basic" | "ability";
+ genderNumber: {
+ gender: T.Gender;
+ number: T.NounNumber;
+ };
}): T.RootsStemsOutput {
- const v = removeFVarientsFromVerb(verb);
- if (type === "ability") {
- return getAbilityRs(v, aspect, rs, voice, genderNumber);
- }
- if (voice === "passive") {
- return getPassiveRs(v, aspect, rs, genderNumber);
- }
- return rs === "stem"
- ? getStem(v, genderNumber, aspect)
- : getRoot(v, genderNumber, aspect);
+ const v = removeFVarientsFromVerb(verb);
+ if (type === "ability") {
+ return getAbilityRs(v, aspect, rs, voice, genderNumber);
+ }
+ if (voice === "passive") {
+ return getPassiveRs(v, aspect, rs, genderNumber);
+ }
+ return rs === "stem"
+ ? getStem(v, genderNumber, aspect)
+ : getRoot(v, genderNumber, aspect);
}
function getAbilityRs(
- verb: T.VerbEntryNoFVars,
- aspect: T.Aspect,
- rs: "root" | "stem",
- voice: T.Voice,
- genderNum: T.GenderNumber,
+ verb: T.VerbEntryNoFVars,
+ aspect: T.Aspect,
+ rs: "root" | "stem",
+ voice: T.Voice,
+ genderNum: T.GenderNumber
): [[] | [T.VHead], [T.VB, T.VBA]] {
- const losesAspect = isTlulVerb(verb) || (isStatComp(verb) && vTransitivity(verb) === "intransitive");
- const [vhead, [basicroot]] = voice === "passive"
- ? getPassiveRs(verb, "imperfective", "root", genderNum)
- : getRoot(verb, genderNum, losesAspect ? "imperfective" : aspect);
- return [
- vhead,
- [
- addAbilityEnding(basicroot),
- rs === "root" ? shwulVB : shVB,
- ],
- ];
+ const losesAspect =
+ isTlulVerb(verb) ||
+ (isStatComp(verb) && vTransitivity(verb) === "intransitive");
+ const [vhead, [basicroot]] =
+ voice === "passive"
+ ? getPassiveRs(verb, "imperfective", "root", genderNum)
+ : getRoot(verb, genderNum, losesAspect ? "imperfective" : aspect);
+ return [vhead, [addAbilityEnding(basicroot), rs === "root" ? shwulVB : shVB]];
}
-export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, number }: { gender: T.Gender, number: T.NounNumber }): T.VBGenNum | T.WeldedGN {
- const v = removeFVarientsFromVerb(verb);
- 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 {
- type: "VB",
- ps: inflectPattern3(base, { gender, number }),
- gender,
- number,
- };
- }
- 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) {
- throw new Error("should not have welded here");
- }
- return {
- ...rootWLengths,
- ps: addTail(rootWLengths.ps),
+export function getPastParticiple(
+ verb: T.VerbEntry,
+ voice: T.Voice,
+ { gender, number }: { gender: T.Gender; number: T.NounNumber }
+): T.VBGenNum | T.WeldedGN {
+ const v = removeFVarientsFromVerb(verb);
+ 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 {
+ type: "VB",
+ ps: inflectPattern3(base, { gender, number }),
+ gender,
+ number,
};
-
- function addTail(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts {
- return fmapSingleOrLengthOpts((x) => {
- const withTail = concatPsString(x[0], { p: "ی", f: "ey"});
- return inflectPattern3(withTail, { gender, number });
- }, ps);
- }
+ }
+ 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) {
+ throw new Error("should not have welded here");
+ }
+ return {
+ ...rootWLengths,
+ ps: addTail(rootWLengths.ps),
+ gender,
+ number,
+ };
+
+ function addTail(
+ ps: T.SingleOrLengthOpts
+ ): T.SingleOrLengthOpts {
+ return fmapSingleOrLengthOpts((x) => {
+ const withTail = concatPsString(x[0], { p: "ی", f: "ey" });
+ return inflectPattern3(withTail, { gender, number });
+ }, ps);
+ }
}
-function getPassivePp(verb: T.VerbEntryNoFVars, genderNumber: T.GenderNumber): T.WeldedGN {
- if (isStatComp(verb) && verb.complement) {
- return weld(
- makeComplement(verb.complement, genderNumber),
- getPassivePp(statVerb.transitive, genderNumber),
+function getPassivePp(
+ verb: T.VerbEntryNoFVars,
+ genderNumber: T.GenderNumber
+): T.WeldedGN {
+ 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(
+ statVerb.intransitive,
+ "active",
+ genderNumber
+ ) as T.VBGenNum;
+ return weld(longRoot, kedulVb);
+}
+
+function getPassiveRs(
+ verb: T.VerbEntryNoFVars,
+ aspect: T.Aspect,
+ rs: "root" | "stem",
+ genderNumber: T.GenderNumber
+): [[] | [T.VHead], [T.VBA]] {
+ const [vHead, [basicRoot]] = getRoot(verb, genderNumber, aspect);
+ const longRoot = getLongVB(basicRoot);
+ 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 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 complement = makeComplement(verb.complement, genderNum);
+ return aspect === "perfective"
+ ? [[complement], [auxStem]]
+ : [[], [weld(complement, auxStem)]];
+ }
+ 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 basicRoot = getRoot(verb, genderNumber, isKawulVerb(verb) ? "perfective" : "imperfective")[1][0];
- const longRoot = getLongVB(basicRoot);
- const kedulVb: T.VBGenNum = getPastParticiple(statVerb.intransitive, "active", genderNumber) as T.VBGenNum;
- return weld(longRoot, kedulVb);
-}
-
-function getPassiveRs(verb: T.VerbEntryNoFVars, aspect: T.Aspect, rs: "root" | "stem", genderNumber: T.GenderNumber): [[] | [T.VHead], [T.VBA]] {
- const [vHead, [basicRoot]] = getRoot(verb, genderNumber, aspect);
- const longRoot = getLongVB(basicRoot);
- const kedulVba = getRootStem({ verb: statVerb.intransitive, aspect, rs, type: "basic", voice: "active", genderNumber: { gender: "masc", number: "singular" }})[1][0] as T.VBBasic;
+ const [perfectiveHead, rest] =
+ aspect === "perfective" ? getPerfectiveHead(base, verb) : [undefined, base];
+ if (verb.entry.f === "tlul" && aspect === "perfective") {
return [
- vHead,
- [weld(longRoot, kedulVba)],
+ [{ type: "PH", ps: { p: "لا", f: "láa" } }],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [{ p: "ړل", f: "Rul" }],
+ short: [{ p: "ړ", f: "R" }],
+ },
+ },
+ ],
];
-}
-
-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 complement = makeComplement(verb.complement, genderNum);
- return aspect === "perfective"
- ? [[complement], [auxStem]]
- : [[], [weld(complement, auxStem)]];
- }
- 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: aspect === "imperfective"
- ? {
- long: [rest],
- short: [addTrailingAccent(removeL(rest))],
+ }
+ return [
+ perfectiveHead ? [perfectiveHead] : [],
+ [
+ {
+ type: "VB",
+ ps:
+ aspect === "imperfective"
+ ? {
+ long: [rest],
+ short: [addTrailingAccent(removeL(rest))],
+ }
+ : {
+ long: [rest],
+ short: [removeL(rest)],
+ ...(aspect === "perfective" && isKawulVerb(verb)
+ ? {
+ mini: [{ p: "ک", f: "k" }],
}
- : {
- long: [rest],
- short: [removeL(rest)],
- ...(aspect === "perfective" && isKawulVerb(verb)) ? {
- mini: [{ p: "ک", f: "k" }],
- } : {},
- },
- },
- ],
- ];
+ : {}),
+ },
+ },
+ ],
+ ];
}
-function getStem(verb: T.VerbEntryNoFVars, genderNum: T.GenderNumber, aspect: T.Aspect): [[T.VHead] | [], [T.VB]] {
- const statComp = isStatComp(verb);
- if (verb.complement && statComp && (aspect === "perfective" || statCompImperfectiveSpace(verb))) {
- const auxStem = getStem(
- statVerb[vTransitivity(verb)],
- genderNum,
- aspect,
- )[1][0] as T.VBBasic;
- const complement = makeComplement(verb.complement, genderNum);
- return aspect === "perfective"
- ? [[complement], [auxStem]]
- : [[], [weld(complement, auxStem)]];
+function getStem(
+ verb: T.VerbEntryNoFVars,
+ genderNum: T.GenderNumber,
+ aspect: T.Aspect
+): [[T.VHead] | [], [T.VB]] {
+ const statComp = isStatComp(verb);
+ if (
+ verb.complement &&
+ statComp &&
+ (aspect === "perfective" || statCompImperfectiveSpace(verb))
+ ) {
+ const auxStem = getStem(
+ statVerb[vTransitivity(verb)],
+ genderNum,
+ aspect
+ )[1][0] as T.VBBasic;
+ const complement = makeComplement(verb.complement, genderNum);
+ return aspect === "perfective"
+ ? [[complement], [auxStem]]
+ : [[], [weld(complement, auxStem)]];
+ }
+ if (aspect === "perfective") {
+ if (verb.entry.f === "tlul") {
+ return tlulPerfectiveStem(genderNum);
}
- if (aspect === "perfective") {
- if (verb.entry.f === "tlul") {
- return tlulPerfectiveStem(genderNum);
- }
- if (!isKedul(verb) && vTransitivity(verb) === "intransitive" && verb.entry.p.endsWith("ېدل")) {
- return splitEdulIntans(edulIntransBase(verb))
- }
- const base: T.PsString = (verb.entry.ssp && verb.entry.ssf)
- // with irregular perfective stem
- ? makePsString(verb.entry.ssp, verb.entry.ssf)
- : (verb.entry.psp && verb.entry.psf)
- // with perfective stem based on irregular perfective root
- ? makePsString(verb.entry.psp, verb.entry.psf)
- // with regular infinitive based perfective stem
- : removeL(makePsString(verb.entry.p, verb.entry.f));
- const [perfectiveHead, rest] = getPerfectiveHead(base, verb);
- return [
- perfectiveHead ? [perfectiveHead] : [],
- [
- {
- type: "VB",
- ps: isKawulVerb(verb) ? kawulSpecialPerfective : [rest],
- },
- ],
- ];
+ if (
+ !isKedul(verb) &&
+ vTransitivity(verb) === "intransitive" &&
+ verb.entry.p.endsWith("ېدل")
+ ) {
+ return splitEdulIntans(edulIntransBase(verb));
}
- const rawBase = removeL(makePsString(verb.entry.p, verb.entry.f));
- const base = verb.entry.psp && verb.entry.psf
- ? [makePsString(verb.entry.psp, verb.entry.psf)]
- : (vTransitivity(verb) === "intransitive" && rawBase.p.endsWith("ېد"))
- ? edulIntransBase(verb)
- : isKawulVerb(verb) || statComp || (countSyllables(rawBase) > 1 && rawBase.f.endsWith("aw"))
- ? [addTrailingAccent(rawBase)]
- : [rawBase];
+ const base: T.PsString =
+ verb.entry.ssp && verb.entry.ssf
+ ? // with irregular perfective stem
+ makePsString(verb.entry.ssp, verb.entry.ssf)
+ : verb.entry.psp && verb.entry.psf
+ ? // with perfective stem based on irregular perfective root
+ makePsString(verb.entry.psp, verb.entry.psf)
+ : // with regular infinitive based perfective stem
+ removeL(makePsString(verb.entry.p, verb.entry.f));
+ const [perfectiveHead, rest] = getPerfectiveHead(base, verb);
return [
- [],
- [
- {
- type: "VB",
- ps: base,
- },
- ],
+ perfectiveHead ? [perfectiveHead] : [],
+ [
+ {
+ type: "VB",
+ ps: isKawulVerb(verb) ? kawulSpecialPerfective : [rest],
+ },
+ ],
];
- function splitEdulIntans(ps: T.SingleOrLengthOpts): [[T.PH] | [], [T.VB]] {
- const [ph, long] = ("long" in ps)
- ? getPerfectiveHead(ps.long[0], verb)
- : getPerfectiveHead(ps[0], verb)
- const short = ("long" in ps)
- ? getPerfectiveHead(ps.short[0], verb)
- : undefined;
- if (short) {
- return [
- ph ? [ph] : [],
- [
- {
- type: "VB",
- ps: {
- long: [long],
- short: [short[1]],
- },
- },
- ],
- ];
- }
- return [
- ph ? [ph] : [],
- [
- { type: "VB", ps: [long] },
- ],
- ];
+ }
+ const rawBase = removeL(makePsString(verb.entry.p, verb.entry.f));
+ const base =
+ verb.entry.psp && verb.entry.psf
+ ? [makePsString(verb.entry.psp, verb.entry.psf)]
+ : vTransitivity(verb) === "intransitive" && rawBase.p.endsWith("ېد")
+ ? edulIntransBase(verb)
+ : isKawulVerb(verb) ||
+ statComp ||
+ (countSyllables(rawBase) > 1 && rawBase.f.endsWith("aw"))
+ ? [addTrailingAccent(rawBase)]
+ : [rawBase];
+ return [
+ [],
+ [
+ {
+ type: "VB",
+ ps: base,
+ },
+ ],
+ ];
+ function splitEdulIntans(
+ ps: T.SingleOrLengthOpts
+ ): [[T.PH] | [], [T.VB]] {
+ const [ph, long] =
+ "long" in ps
+ ? getPerfectiveHead(ps.long[0], verb)
+ : getPerfectiveHead(ps[0], verb);
+ const short =
+ "long" in ps ? getPerfectiveHead(ps.short[0], verb) : undefined;
+ if (short) {
+ return [
+ ph ? [ph] : [],
+ [
+ {
+ type: "VB",
+ ps: {
+ long: [long],
+ short: [short[1]],
+ },
+ },
+ ],
+ ];
}
+ return [ph ? [ph] : [], [{ type: "VB", ps: [long] }]];
+ }
}
// TODO: This is a nasty and messy way to do it with the length options included
-function getPerfectiveHead(base: T.PsString, v: T.VerbEntryNoFVars): [T.PH, T.PsString] | [undefined, T.PsString] {
- // if ((verb.entry.ssp && verb.entry.ssf) || verb.entry.separationAtP) {
- // // handle split
- // }
- if (v.entry.separationAtP && v.entry.separationAtF) {
- const ph: T.PH = {
- type: "PH",
- ps: accentOnNFromEnd({
- p: base.p.slice(0, v.entry.separationAtP),
- f: base.f.slice(0, v.entry.separationAtF),
- }, 0),
- };
- const rest = {
- p: base.p.slice(v.entry.separationAtP),
- f: base.f.slice(v.entry.separationAtF),
- };
- return [ph, rest];
- }
- const [ph, rest]: [T.PH | undefined, T.PsString] = v.entry.noOo
- ? [undefined, base]
- : v.entry.sepOo
- ? [
- { type: "PH", ps: { p: "و ", f: "óo`"}},
- base,
- ]
- : ["آ", "ا"].includes(base.p.charAt(0)) && base.f.charAt(0) === "a"
- ? [
- { type: "PH", ps: { p: "وا", f: "wáa" }},
- removeAStart(base),
- ]
- : ["óo", "oo"].includes(base.f.slice(0, 2))
- ? [
- { type: "PH", ps: { p: "و", f: "wÚ" }},
- base,
- ]
- : ["ée", "ee"].includes(base.f.slice(0, 2)) && base.p.slice(0, 2) === "ای"
- ? [
- { type: "PH", ps: { p: "وي", f: "wée" }},
- {
- p: base.p.slice(2),
- f: base.f.slice(2),
- },
- ] : ["é", "e"].includes(base.f.slice(0, 2)) && base.p.slice(0, 2) === "اې"
- ? [
- { type: "PH", ps: { p: "وي", f: "wé" }},
- {
- p: base.p.slice(2),
- f: base.f.slice(1),
- },
- ] : ["ó", "o"].includes(base.f[0]) && base.p.slice(0, 2) === "او"
- ? [
- { type: "PH", ps: { p: "و", f: "óo`"}},
- base,
- ] : [
- { type: "PH", ps: { p: "و", f: "óo" }},
- base,
- ];
- return [
- ph,
- removeAccents(rest),
- ];
- function removeAStart(ps: T.PsString) {
- return {
- p: ps.p.slice(1),
- f: ps.f.slice(ps.f[1] === "a" ? 2 : 1),
- };
- }
+function getPerfectiveHead(
+ base: T.PsString,
+ v: T.VerbEntryNoFVars
+): [T.PH, T.PsString] | [undefined, T.PsString] {
+ // if ((verb.entry.ssp && verb.entry.ssf) || verb.entry.separationAtP) {
+ // // handle split
+ // }
+ if (v.entry.separationAtP && v.entry.separationAtF) {
+ const ph: T.PH = {
+ type: "PH",
+ ps: accentOnNFromEnd(
+ {
+ p: base.p.slice(0, v.entry.separationAtP),
+ f: base.f.slice(0, v.entry.separationAtF),
+ },
+ 0
+ ),
+ };
+ const rest = {
+ p: base.p.slice(v.entry.separationAtP),
+ f: base.f.slice(v.entry.separationAtF),
+ };
+ return [ph, rest];
+ }
+ const [ph, rest]: [T.PH | undefined, T.PsString] = v.entry.noOo
+ ? [undefined, base]
+ : v.entry.sepOo
+ ? [{ type: "PH", ps: { p: "و ", f: "óo`" } }, base]
+ : ["آ", "ا"].includes(base.p.charAt(0)) && base.f.charAt(0) === "a"
+ ? [{ type: "PH", ps: { p: "وا", f: "wáa" } }, removeAStart(base)]
+ : ["óo", "oo"].includes(base.f.slice(0, 2))
+ ? [{ type: "PH", ps: { p: "و", f: "wÚ" } }, base]
+ : ["ée", "ee"].includes(base.f.slice(0, 2)) && base.p.slice(0, 2) === "ای"
+ ? [
+ { type: "PH", ps: { p: "وي", f: "wée" } },
+ {
+ p: base.p.slice(2),
+ f: base.f.slice(2),
+ },
+ ]
+ : ["é", "e"].includes(base.f.slice(0, 2)) && base.p.slice(0, 2) === "اې"
+ ? [
+ { type: "PH", ps: { p: "وي", f: "wé" } },
+ {
+ p: base.p.slice(2),
+ f: base.f.slice(1),
+ },
+ ]
+ : ["ó", "o"].includes(base.f[0]) && base.p.slice(0, 2) === "او"
+ ? [{ type: "PH", ps: { p: "و", f: "óo`" } }, base]
+ : [{ type: "PH", ps: { p: "و", f: "óo" } }, base];
+ return [ph, removeAccents(rest)];
+ function removeAStart(ps: T.PsString) {
+ return {
+ p: ps.p.slice(1),
+ f: ps.f.slice(ps.f[1] === "a" ? 2 : 1),
+ };
+ }
}
-function edulIntransBase(v: T.VerbEntryNoFVars): T.SingleOrLengthOpts {
- const base = trimOffPs(makePsString(v.entry.p, v.entry.f), 3, 4);
- const long: T.PsString[] = [concatPsString(
- base,
- { p: "ېږ", f: "éG" },
- )];
- const short: T.PsString[] | undefined = (v.entry.shortIntrans)
- ? [base]
- : undefined;
- return short ? { short, long } : long;
+function edulIntransBase(
+ v: T.VerbEntryNoFVars
+): T.SingleOrLengthOpts {
+ const base = trimOffPs(makePsString(v.entry.p, v.entry.f), 3, 4);
+ const long: T.PsString[] = [concatPsString(base, { p: "ېږ", f: "éG" })];
+ const short: T.PsString[] | undefined = v.entry.shortIntrans
+ ? [base]
+ : undefined;
+ return short ? { short, long } : long;
}
const kawulSpecialPerfective: T.LengthOptions = {
- long: [{ p: "کړ", f: "kR" }],
- short: [{ p: "ک", f: "k" }],
-};
\ No newline at end of file
+ long: [{ p: "کړ", f: "kR" }],
+ short: [{ p: "ک", f: "k" }],
+};
diff --git a/src/lib/src/phrase-building/compile.ts b/src/lib/src/phrase-building/compile.ts
index baef606..f6adca1 100644
--- a/src/lib/src/phrase-building/compile.ts
+++ b/src/lib/src/phrase-building/compile.ts
@@ -1,39 +1,35 @@
import * as T from "../../../types";
import {
- capitalizeFirstLetter,
- concatPsString, getLong,
+ capitalizeFirstLetter,
+ concatPsString,
+ getLong,
} from "../p-text-helpers";
import { negativeParticle } from "../grammar-units";
import * as grammarUnits from "../grammar-units";
-import {
- removeDuplicates,
-} from "./vp-tools";
+import { removeDuplicates } from "./vp-tools";
import { getEnglishFromRendered, getPashtoFromRendered } from "./np-tools";
import { completeEPSelection, renderEP } from "./render-ep";
import { completeVPSelection } from "./vp-tools";
import { renderVP } from "./render-vp";
import {
- getAPsFromBlocks,
- getComplementFromBlocks,
- getObjectSelectionFromBlocks,
- getPredicateSelectionFromBlocks,
- getSubjectSelectionFromBlocks,
- hasEquativeWithLengths,
- isRenderedVerbB,
- specifyEquativeLength,
+ getAPsFromBlocks,
+ getComplementFromBlocks,
+ getObjectSelectionFromBlocks,
+ getPredicateSelectionFromBlocks,
+ getSubjectSelectionFromBlocks,
+ hasEquativeWithLengths,
+ isRenderedVerbB,
+ specifyEquativeLength,
} from "./blocks-utils";
-import {
- blank,
- kidsBlank,
-} from "../misc-helpers";
+import { blank, kidsBlank } from "../misc-helpers";
type BlankoutOptions = {
- equative?: boolean,
- ba?: boolean,
- kidsSection?: boolean,
- verb?: boolean,
- negative?: boolean,
- predicate?: boolean,
+ equative?: boolean;
+ ba?: boolean;
+ kidsSection?: boolean;
+ verb?: boolean;
+ negative?: boolean;
+ predicate?: boolean;
};
// function compilePs({ blocks, kids, verb: { head, rest }, VP }: CompilePsInput): T.SingleOrLengthOpts {
@@ -61,357 +57,506 @@ type BlankoutOptions = {
// }));
// }
-export function compileEP(EP: T.EPRendered): { ps: T.SingleOrLengthOpts, e?: string[] };
-export function compileEP(EP: T.EPRendered, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string[] };
-export function compileEP(EP: T.EPRendered, combineLengths?: boolean, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts, e?: string[] } {
- const psResult = compileEPPs(EP.blocks, EP.kids, EP.omitSubject, blankOut);
+export function compileEP(EP: T.EPRendered): {
+ ps: T.SingleOrLengthOpts;
+ e?: string[];
+};
+export function compileEP(
+ EP: T.EPRendered,
+ combineLengths: true,
+ blankOut?: BlankoutOptions
+): { ps: T.PsString[]; e?: string[] };
+export function compileEP(
+ EP: T.EPRendered,
+ combineLengths?: boolean,
+ blankOut?: BlankoutOptions
+): { ps: T.SingleOrLengthOpts; e?: string[] } {
+ const psResult = compileEPPs(EP.blocks, EP.kids, EP.omitSubject, blankOut);
+ return {
+ ps: combineLengths ? flattenLengths(psResult) : psResult,
+ e: compileEnglishEP(EP),
+ };
+}
+
+export function compileVP(
+ VP: T.VPRendered,
+ form: T.FormVersion
+): { ps: T.SingleOrLengthOpts; e?: string[] };
+export function compileVP(
+ VP: T.VPRendered,
+ form: T.FormVersion,
+ combineLengths: true,
+ blankOut?: BlankoutOptions
+): { ps: T.PsString[]; e?: string[] };
+export function compileVP(
+ VP: T.VPRendered,
+ form: T.FormVersion,
+ combineLengths?: true,
+ blankOut?: BlankoutOptions
+): { ps: T.SingleOrLengthOpts; e?: string[] } {
+ // const verb = getVerbFromBlocks(VP.blocks).block;
+ const psResult = compileVPPs(VP.blocks, VP.kids, form, VP.king, blankOut);
+ return {
+ ps: combineLengths ? flattenLengths(psResult) : psResult,
+ // TODO: English doesn't quite work for dynamic compounds in passive voice
+ e: /* (verb.voice === "passive" && VP.isCompound === "dynamic") ? undefined : */ compileEnglishVP(
+ VP
+ ),
+ };
+}
+
+function compileVPPs(
+ blocks: T.Block[][],
+ kids: T.Kid[],
+ form: T.FormVersion,
+ king: "subject" | "object",
+ blankOut?: BlankoutOptions
+): T.PsString[] {
+ const subjectPerson =
+ getSubjectSelectionFromBlocks(blocks).selection.selection.person;
+ const blocksWKids = putKidsInKidsSection(
+ filterForVisibleBlocksVP(blocks, form, king),
+ kids,
+ !!blankOut?.ba
+ );
+ return removeDuplicates(
+ combineIntoText(blocksWKids, subjectPerson, blankOut)
+ );
+}
+
+function compileEPPs(
+ blocks: T.Block[][],
+ kids: T.Kid[],
+ omitSubject: boolean,
+ blankOut?: BlankoutOptions
+): T.SingleOrLengthOpts {
+ if (hasEquativeWithLengths(blocks)) {
return {
- ps: combineLengths ? flattenLengths(psResult) : psResult,
- e: compileEnglishEP(EP),
+ long: compileEPPs(
+ specifyEquativeLength(blocks, "long"),
+ kids,
+ omitSubject,
+ blankOut
+ ) as T.PsString[],
+ short: compileEPPs(
+ specifyEquativeLength(blocks, "short"),
+ kids,
+ omitSubject,
+ blankOut
+ ) as T.PsString[],
};
+ }
+ const subjectPerson =
+ getSubjectSelectionFromBlocks(blocks).selection.selection.person;
+ const blocksWKids = putKidsInKidsSection(
+ omitSubject
+ ? blocks.map((blks) =>
+ blks.filter((b) => b.block.type !== "subjectSelection")
+ )
+ : blocks,
+ kids,
+ !!blankOut?.kidsSection
+ );
+ return removeDuplicates(
+ combineIntoText(blocksWKids, subjectPerson, blankOut)
+ );
}
-export function compileVP(VP: T.VPRendered, form: T.FormVersion): { ps: T.SingleOrLengthOpts, e?: string [] };
-export function compileVP(VP: T.VPRendered, form: T.FormVersion, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string [] };
-export function compileVP(VP: T.VPRendered, form: T.FormVersion, combineLengths?: true, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts, e?: string [] } {
- // const verb = getVerbFromBlocks(VP.blocks).block;
- const psResult = compileVPPs(VP.blocks, VP.kids, form, VP.king, blankOut);
+export function filterForVisibleBlocksVP(
+ blocks: T.Block[][],
+ form: T.FormVersion,
+ king: "subject" | "object"
+): T.Block[][] {
+ const servant = king === "object" ? "subject" : "object";
+ return blocks.map((blks) =>
+ blks.filter((block) => {
+ if (form.removeKing) {
+ if (
+ (king === "subject" && block.block.type === "subjectSelection") ||
+ (king === "object" && block.block.type === "objectSelection")
+ )
+ return false;
+ }
+ if (form.shrinkServant) {
+ if (
+ (servant === "subject" && block.block.type === "subjectSelection") ||
+ (servant === "object" && block.block.type === "objectSelection")
+ )
+ return false;
+ }
+ if (
+ block.block.type === "objectSelection" &&
+ typeof block.block.selection !== "object"
+ ) {
+ return false;
+ }
+ return true;
+ })
+ );
+}
+
+export function filterForVisibleBlocksEP(
+ blocks: T.Block[][],
+ omitSubject: boolean
+): T.Block[][] {
+ if (!omitSubject) return blocks;
+ return blocks.map((blks) =>
+ blks.filter(({ block }) => {
+ if (block.type === "subjectSelection") {
+ return false;
+ }
+ return true;
+ })
+ );
+}
+
+export function combineIntoText(
+ piecesWVars: (T.Block | T.Kid | T.PsString)[][],
+ subjectPerson: T.Person,
+ blankOut?: BlankoutOptions
+): T.PsString[] {
+ function removeDoubleBlanks(x: T.PsString): T.PsString {
return {
- ps: combineLengths ? flattenLengths(psResult) : psResult,
- // TODO: English doesn't quite work for dynamic compounds in passive voice
- e: /* (verb.voice === "passive" && VP.isCompound === "dynamic") ? undefined : */ compileEnglishVP(VP),
+ p: x.p.replace(blank.p + blank.p, blank.p),
+ f: x.f.replace(blank.f + blank.f, blank.f),
};
-}
-
-function compileVPPs(blocks: T.Block[][], kids: T.Kid[], form: T.FormVersion, king: "subject" | "object", blankOut?: BlankoutOptions): T.PsString[] {
- const subjectPerson = getSubjectSelectionFromBlocks(blocks)
- .selection.selection.person;
- const blocksWKids = putKidsInKidsSection(
- filterForVisibleBlocksVP(blocks, form, king),
- kids,
- !!blankOut?.ba
- );
- return removeDuplicates(combineIntoText(blocksWKids, subjectPerson, blankOut));
-}
-
-function compileEPPs(blocks: T.Block[][], kids: T.Kid[], omitSubject: boolean, blankOut?: BlankoutOptions): T.SingleOrLengthOpts {
- if (hasEquativeWithLengths(blocks)) {
- return {
- long: compileEPPs(specifyEquativeLength(blocks, "long"), kids, omitSubject, blankOut) as T.PsString[],
- short: compileEPPs(specifyEquativeLength(blocks, "short"), kids, omitSubject, blankOut) as T.PsString[],
- };
+ }
+ function combine(pieces: (T.Block | T.Kid | T.PsString)[]): T.PsString[] {
+ const first = pieces[0];
+ const next = pieces[1];
+ const rest = pieces.slice(1);
+ // better to do map-reduce
+ // map the blocks into monoids [T.PsString] (with appropriate space blocks) and then concat them all together
+ const firstPs =
+ "p" in first
+ ? [first]
+ : (blankOut?.equative &&
+ "block" in first &&
+ first.block.type === "equative") ||
+ (blankOut?.verb && "block" in first && isRenderedVerbB(first)) ||
+ (blankOut?.predicate &&
+ "block" in first &&
+ first.block.type === "predicateSelection")
+ ? [blank]
+ : blankOut?.ba && "kid" in first && first.kid.type === "ba"
+ ? [kidsBlank]
+ : blankOut?.negative &&
+ "block" in first &&
+ first.block.type === "negative"
+ ? [{ p: "", f: "" }]
+ : getPsFromPiece(first, subjectPerson);
+ if (!rest.length) {
+ return firstPs;
}
- const subjectPerson = getSubjectSelectionFromBlocks(blocks)
- .selection.selection.person;
- const blocksWKids = putKidsInKidsSection(
- omitSubject ? blocks.map(blks => blks.filter(b => b.block.type !== "subjectSelection")) : blocks,
- kids,
- !!blankOut?.kidsSection
- );
- return removeDuplicates(combineIntoText(blocksWKids, subjectPerson, blankOut));
+ return combine(rest)
+ .flatMap((r) =>
+ firstPs.map((fPs) =>
+ concatPsString(
+ fPs,
+ // TODO: this spacing is a mess and not accurate
+ !("p" in first) &&
+ "block" in first &&
+ first.block.type === "PH" &&
+ !("p" in next) &&
+ (("block" in next &&
+ (isRenderedVerbB(next) || next.block.type === "negative")) ||
+ ("kid" in next && next.kid.type === "mini-pronoun"))
+ ? ("block" in next && next.block.type === "negative") ||
+ ("kid" in next && next.kid.type === "mini-pronoun")
+ ? { p: "", f: " " }
+ : ""
+ : " ",
+ r
+ )
+ )
+ )
+ .map(removeDoubleBlanks);
+ }
+ return piecesWVars.flatMap(combine);
}
-export function filterForVisibleBlocksVP(blocks: T.Block[][], form: T.FormVersion, king: "subject" | "object"): T.Block[][] {
- const servant = king === "object" ? "subject" : "object";
- return blocks.map(blks => blks.filter((block) => {
- if (form.removeKing) {
- if (
- (king === "subject" && block.block.type === "subjectSelection")
- ||
- (king === "object" && block.block.type === "objectSelection")
- ) return false;
- }
- if (form.shrinkServant) {
- if (
- (servant === "subject" && block.block.type === "subjectSelection")
- ||
- (servant === "object" && block.block.type === "objectSelection")
- ) return false;
- }
- if (block.block.type === "objectSelection" && typeof block.block.selection !== "object") {
- return false;
- }
- return true;
- }));
-}
-
-export function filterForVisibleBlocksEP(blocks: T.Block[][], omitSubject: boolean): T.Block[][] {
- if (!omitSubject) return blocks;
- return blocks.map(blks => blks.filter(({ block }) => {
- if (block.type === "subjectSelection") {
- return false;
- }
- return true;
- }));
-}
-
-function combineIntoText(piecesWVars: (T.Block | T.Kid | T.PsString)[][], subjectPerson: T.Person, blankOut?: BlankoutOptions): T.PsString[] {
- function removeDoubleBlanks(x: T.PsString): T.PsString {
- return {
- p: x.p.replace(blank.p+blank.p, blank.p),
- f: x.f.replace(blank.f+blank.f, blank.f),
- };
+function getPsFromPiece(
+ piece: T.Block | T.Kid,
+ subjectPerson: T.Person
+): T.PsString[] {
+ if ("block" in piece) {
+ if (piece.block.type === "negative") {
+ return [
+ negativeParticle[
+ piece.block.imperative ? "imperative" : "nonImperative"
+ ],
+ ];
}
- function combine(pieces: (T.Block | T.Kid | T.PsString)[]): T.PsString[] {
- const first = pieces[0];
- const next = pieces[1];
- const rest = pieces.slice(1);
- const firstPs = ("p" in first)
- ? [first]
- : (
- (blankOut?.equative && "block" in first && first.block.type === "equative") ||
- (blankOut?.verb && "block" in first && isRenderedVerbB(first)) ||
- (blankOut?.predicate && "block" in first && first.block.type === "predicateSelection")
- )
- ? [blank]
- : ((blankOut?.ba) && "kid" in first && first.kid.type === "ba")
- ? [kidsBlank]
- : (blankOut?.negative && "block" in first && first.block.type === "negative")
- ? [{ p: "", f: "" }]
- : getPsFromPiece(first, subjectPerson);
- if (!rest.length) {
- return firstPs;
- }
- return combine(rest).flatMap(r => (
- firstPs.map(fPs => concatPsString(
- fPs,
- // TODO: this spacing is a mess and not accurate
- (!("p" in first) && "block" in first && first.block.type === "PH" && !("p" in next) && (("block" in next && (isRenderedVerbB(next) || next.block.type === "negative")) || ("kid" in next && next.kid.type === "mini-pronoun")))
- ? ((("block" in next && next.block.type === "negative") || ("kid" in next && next.kid.type === "mini-pronoun")) ? { p: "", f: " " } : "")
- : " ",
- r,
- ))
- )
- ).map(removeDoubleBlanks);
+ if (piece.block.type === "equative") {
+ // length will already be specified in compileEPPs - this is just for type safety
+ return getLong(piece.block.equative.ps);
}
- return piecesWVars.flatMap(combine);
-}
-
-function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsString[] {
- if ("block" in piece) {
- if (piece.block.type === "negative") {
- return [
- negativeParticle[piece.block.imperative ? "imperative" : "nonImperative"],
- ];
- }
- if (piece.block.type === "equative") {
- // length will already be specified in compileEPPs - this is just for type safety
- return getLong(piece.block.equative.ps);
- }
- if (piece.block.type === "subjectSelection" || piece.block.type === "predicateSelection") {
- return getPashtoFromRendered(piece.block.selection, subjectPerson);
- }
- if (piece.block.type === "AP") {
- return getPashtoFromRendered(piece.block, subjectPerson);
- }
- if (piece.block.type === "PH") {
- return [piece.block.ps];
- }
- if (piece.block.type === "VB") {
- return flattenLengths(piece.block.ps);
- }
- if (piece.block.type === "objectSelection") {
- if (typeof piece.block.selection !== "object") {
- return [{ p: "", f: "" }];
- }
- return getPashtoFromRendered(piece.block.selection, subjectPerson);
- }
- if (piece.block.type === "NComp") {
- return [piece.block.comp.ps];
- }
- if (piece.block.type === "complement") {
- if (piece.block.selection.type === "sandwich") {
- // TODO: Kinda cheating
- return getPashtoFromRendered({ type: "AP", selection: piece.block.selection }, false);
- }
- return piece.block.selection.ps;
- }
- // welded
- return getPsFromWelded(piece.block);
+ if (
+ piece.block.type === "subjectSelection" ||
+ piece.block.type === "predicateSelection"
+ ) {
+ return getPashtoFromRendered(piece.block.selection, subjectPerson);
}
- if ("kid" in piece) {
- if (piece.kid.type === "ba") {
- return [grammarUnits.baParticle];
- }
- if (piece.kid.type === "mini-pronoun") {
- return [piece.kid.ps];
- }
+ if (piece.block.type === "AP") {
+ return getPashtoFromRendered(piece.block, subjectPerson);
}
- throw new Error("unrecognized piece type");
+ if (piece.block.type === "PH") {
+ return [piece.block.ps];
+ }
+ if (piece.block.type === "VB") {
+ return flattenLengths(piece.block.ps);
+ }
+ if (piece.block.type === "objectSelection") {
+ if (typeof piece.block.selection !== "object") {
+ return [{ p: "", f: "" }];
+ }
+ return getPashtoFromRendered(piece.block.selection, subjectPerson);
+ }
+ if (piece.block.type === "NComp") {
+ return [piece.block.comp.ps];
+ }
+ if (piece.block.type === "complement") {
+ if (piece.block.selection.type === "sandwich") {
+ // TODO: Kinda cheating
+ return getPashtoFromRendered(
+ { type: "AP", selection: piece.block.selection },
+ false
+ );
+ }
+ return piece.block.selection.ps;
+ }
+ // welded
+ return getPsFromWelded(piece.block);
+ }
+ if ("kid" in piece) {
+ if (piece.kid.type === "ba") {
+ return [grammarUnits.baParticle];
+ }
+ if (piece.kid.type === "mini-pronoun") {
+ return [piece.kid.ps];
+ }
+ }
+ throw new Error("unrecognized piece type");
}
function getPsFromWelded(v: T.Welded): T.PsString[] {
- function getPsFromSide(v: T.VBBasic | T.Welded | T.NComp | T.VBGenNum): T.PsString[] {
- if (v.type === "VB") {
- return flattenLengths(v.ps);
- }
- if (v.type === "NComp") {
- return [v.comp.ps];
- }
- return getPsFromWelded(v);
+ function getPsFromSide(
+ v: T.VBBasic | T.Welded | T.NComp | T.VBGenNum
+ ): T.PsString[] {
+ if (v.type === "VB") {
+ return flattenLengths(v.ps);
}
- const left = getPsFromSide(v.left);
- const right = getPsFromSide(v.right);
- return left.flatMap(leftVar => (
- right.flatMap(rightVar => (
- concatPsString(leftVar, " ", rightVar)
- ))
- ));
+ if (v.type === "NComp") {
+ return [v.comp.ps];
+ }
+ return getPsFromWelded(v);
+ }
+ const left = getPsFromSide(v.left);
+ const right = getPsFromSide(v.right);
+ return left.flatMap((leftVar) =>
+ right.flatMap((rightVar) => concatPsString(leftVar, " ", rightVar))
+ );
}
function getEngAPs(blocks: T.Block[][]): string {
- return getAPsFromBlocks(blocks).reduce((accum, curr) => {
- const e = getEnglishFromRendered(curr);
- if (!e) return accum;
- return `${accum} ${e}`;
- }, "");
+ return getAPsFromBlocks(blocks).reduce((accum, curr) => {
+ const e = getEnglishFromRendered(curr);
+ if (!e) return accum;
+ return `${accum} ${e}`;
+ }, "");
}
function getEngComplement(blocks: T.Block[][]): string | undefined {
- const comp = getComplementFromBlocks(blocks);
- if (!comp) return undefined;
- if (comp.selection.type === "unselected") {
- return "____";
- }
- if (comp.selection.type === "sandwich") {
- return getEnglishFromRendered({ type: "AP", selection: comp.selection });
- }
- return comp.selection.e;
+ const comp = getComplementFromBlocks(blocks);
+ if (!comp) return undefined;
+ if (comp.selection.type === "unselected") {
+ return "____";
+ }
+ if (comp.selection.type === "sandwich") {
+ return getEnglishFromRendered({ type: "AP", selection: comp.selection });
+ }
+ return comp.selection.e;
}
-function putKidsInKidsSection(blocksWVars: T.Block[][], kids: T.Kid[], enforceKidsSectionBlankout: boolean): (T.Block | T.Kid | T.PsString)[][] {
- function insert(blocks: T.Block[]): (T.Block | T.Kid | T.PsString)[] {
- const first = blocks[0];
- const rest = blocks.slice(1);
- return [
- first,
- ...enforceKidsSectionBlankout ? [kidsBlank] : kids,
- ...rest,
- ];
- }
- return blocksWVars.map(insert);
+function putKidsInKidsSection(
+ blocksWVars: T.Block[][],
+ kids: T.Kid[],
+ enforceKidsSectionBlankout: boolean
+): (T.Block | T.Kid | T.PsString)[][] {
+ function insert(blocks: T.Block[]): (T.Block | T.Kid | T.PsString)[] {
+ const first = blocks[0];
+ const rest = blocks.slice(1);
+ return [
+ first,
+ ...(enforceKidsSectionBlankout ? [kidsBlank] : kids),
+ ...rest,
+ ];
+ }
+ return blocksWVars.map(insert);
}
function compileEnglishVP(VP: T.VPRendered): string[] | undefined {
- function insertEWords(e: string, { subject, object, APs, complement }: { subject: string, object?: string, APs: string, complement: string | undefined }): string {
- return e
- .replace("$SUBJ", subject)
- .replace("$OBJ", object || "")
- // add the complement in English if it's an external complement from a helper verb (kawul/kedul)
- // TODO!
- + (complement /* && isStativeHelper(getVerbFromBlocks(VP.blocks).block.verb))*/
- ? ` ${complement}`
- : "")
- + APs;
+ function insertEWords(
+ e: string,
+ {
+ subject,
+ object,
+ APs,
+ complement,
+ }: {
+ subject: string;
+ object?: string;
+ APs: string;
+ complement: string | undefined;
}
- const engSubj = getSubjectSelectionFromBlocks(VP.blocks).selection;
- const obj = getObjectSelectionFromBlocks(VP.blocks).selection;
- const engObj = typeof obj === "object"
- ? obj
- : (obj === "none" || obj === T.Person.ThirdPlurMale)
- ? ""
- : undefined;
- const engAPs = getEngAPs(VP.blocks);
- const engComplement = getEngComplement(VP.blocks);
- // require all English parts for making the English phrase
- return (VP.englishBase && engSubj && engObj !== undefined)
- ? VP.englishBase.map(e => insertEWords(e, {
+ ): string {
+ return (
+ e.replace("$SUBJ", subject).replace("$OBJ", object || "") +
+ // add the complement in English if it's an external complement from a helper verb (kawul/kedul)
+ // TODO!
+ (complement /* && isStativeHelper(getVerbFromBlocks(VP.blocks).block.verb))*/
+ ? ` ${complement}`
+ : "") +
+ APs
+ );
+ }
+ const engSubj = getSubjectSelectionFromBlocks(VP.blocks).selection;
+ const obj = getObjectSelectionFromBlocks(VP.blocks).selection;
+ const engObj =
+ typeof obj === "object"
+ ? obj
+ : obj === "none" || obj === T.Person.ThirdPlurMale
+ ? ""
+ : undefined;
+ const engAPs = getEngAPs(VP.blocks);
+ const engComplement = getEngComplement(VP.blocks);
+ // require all English parts for making the English phrase
+ return VP.englishBase && engSubj && engObj !== undefined
+ ? VP.englishBase
+ .map((e) =>
+ insertEWords(e, {
// TODO: make sure we actually have the english
subject: getEnglishFromRendered(engSubj) || "",
object: engObj ? getEnglishFromRendered(engObj) : "",
APs: engAPs,
complement: engComplement,
- })).map(capitalizeFirstLetter)
- : undefined;
+ })
+ )
+ .map(capitalizeFirstLetter)
+ : undefined;
}
function compileEnglishEP(EP: T.EPRendered): string[] | undefined {
- function insertEWords(e: string, { subject, predicate, APs }: { subject: string, predicate: string, APs: string }): string {
- return e.replace("$SUBJ", subject).replace("$PRED", predicate || "") + APs;
- }
- const engSubjR = getSubjectSelectionFromBlocks(EP.blocks).selection;
- const engPredR = getPredicateSelectionFromBlocks(EP.blocks).selection;
- const engSubj = getEnglishFromRendered(engSubjR);
- const engPred = getEnglishFromRendered(engPredR);
- const engAPs = getEngAPs(EP.blocks);
- // require all English parts for making the English phrase
- const b = (EP.englishBase && engSubj && engPred)
- ? EP.englishBase.map(e => insertEWords(e, {
+ function insertEWords(
+ e: string,
+ {
+ subject,
+ predicate,
+ APs,
+ }: { subject: string; predicate: string; APs: string }
+ ): string {
+ return e.replace("$SUBJ", subject).replace("$PRED", predicate || "") + APs;
+ }
+ const engSubjR = getSubjectSelectionFromBlocks(EP.blocks).selection;
+ const engPredR = getPredicateSelectionFromBlocks(EP.blocks).selection;
+ const engSubj = getEnglishFromRendered(engSubjR);
+ const engPred = getEnglishFromRendered(engPredR);
+ const engAPs = getEngAPs(EP.blocks);
+ // require all English parts for making the English phrase
+ const b =
+ EP.englishBase && engSubj && engPred
+ ? EP.englishBase.map((e) =>
+ insertEWords(e, {
subject: engSubj,
predicate: engPred,
APs: engAPs,
- }))
- : undefined;
- return b?.map(capitalizeFirstLetter);
+ })
+ )
+ : undefined;
+ return b?.map(capitalizeFirstLetter);
}
-export function checkForMiniPronounsError(s: T.EPSelectionState | T.VPSelectionState): undefined | string {
- function findDuplicateMiniP(mp: T.MiniPronoun[]): T.MiniPronoun | undefined {
- const duplicates = mp.filter((item, index) => (
- mp.findIndex(m => item.ps.p === m.ps.p) !== index
- ));
- if (duplicates.length === 0) return undefined;
- return duplicates[0];
+export function checkForMiniPronounsError(
+ s: T.EPSelectionState | T.VPSelectionState
+): undefined | string {
+ function findDuplicateMiniP(mp: T.MiniPronoun[]): T.MiniPronoun | undefined {
+ const duplicates = mp.filter(
+ (item, index) => mp.findIndex((m) => item.ps.p === m.ps.p) !== index
+ );
+ if (duplicates.length === 0) return undefined;
+ return duplicates[0];
+ }
+ const kids = (() => {
+ if ("predicate" in s) {
+ const EPS = completeEPSelection(s);
+ if (!EPS) return undefined;
+ return renderEP(EPS).kids;
}
- const kids = (() => {
- if ("predicate" in s) {
- const EPS = completeEPSelection(s);
- if (!EPS) return undefined;
- return renderEP(EPS).kids;
- };
- const VPS = completeVPSelection(s);
- if (!VPS) return undefined;
- return renderVP(VPS).kids;
- })();
- if (!kids) return undefined;
- const miniPronouns = kids.filter(x => x.kid.type === "mini-pronoun").map(m => m.kid) as T.MiniPronoun[];
- if (miniPronouns.length > 2) {
- return "can't add another mini-pronoun, there are alread two";
- }
- const duplicateMiniPronoun = findDuplicateMiniP(miniPronouns);
- if (duplicateMiniPronoun) {
- return `there's already a ${duplicateMiniPronoun.ps.p} - ${duplicateMiniPronoun.ps.f} mini-pronoun in use, can't have two of those`;
- }
- return undefined;
+ const VPS = completeVPSelection(s);
+ if (!VPS) return undefined;
+ return renderVP(VPS).kids;
+ })();
+ if (!kids) return undefined;
+ const miniPronouns = kids
+ .filter((x) => x.kid.type === "mini-pronoun")
+ .map((m) => m.kid) as T.MiniPronoun[];
+ if (miniPronouns.length > 2) {
+ return "can't add another mini-pronoun, there are alread two";
+ }
+ const duplicateMiniPronoun = findDuplicateMiniP(miniPronouns);
+ if (duplicateMiniPronoun) {
+ return `there's already a ${duplicateMiniPronoun.ps.p} - ${duplicateMiniPronoun.ps.f} mini-pronoun in use, can't have two of those`;
+ }
+ return undefined;
}
-function findPossesivesInNP(NP: T.Rendered | T.ObjectNP | undefined): T.Rendered[] {
- if (NP === undefined) return [];
- if (typeof NP !== "object") return [];
- if (!NP.selection.possesor) return [];
- if (NP.selection.adjectives) {
- const { adjectives, ...rest } = NP.selection;
- return [
- ...findPossesivesInAdjectives(adjectives),
- ...findPossesivesInNP({ type: "NP", selection: rest }),
- ];
- }
- if (NP.selection.possesor.shrunken) {
- return [NP.selection.possesor.np];
- }
- return findPossesivesInNP(NP.selection.possesor.np);
+function findPossesivesInNP(
+ NP: T.Rendered | T.ObjectNP | undefined
+): T.Rendered[] {
+ if (NP === undefined) return [];
+ if (typeof NP !== "object") return [];
+ if (!NP.selection.possesor) return [];
+ if (NP.selection.adjectives) {
+ const { adjectives, ...rest } = NP.selection;
+ return [
+ ...findPossesivesInAdjectives(adjectives),
+ ...findPossesivesInNP({ type: "NP", selection: rest }),
+ ];
+ }
+ if (NP.selection.possesor.shrunken) {
+ return [NP.selection.possesor.np];
+ }
+ return findPossesivesInNP(NP.selection.possesor.np);
}
-function findPossesivesInAdjectives(a: T.Rendered[]): T.Rendered[] {
- return a.reduce((accum, curr): T.Rendered[] => ([
- ...accum,
- ...findPossesivesInAdjective(curr),
- ]), [] as T.Rendered[])
+function findPossesivesInAdjectives(
+ a: T.Rendered[]
+): T.Rendered[] {
+ return a.reduce(
+ (accum, curr): T.Rendered[] => [
+ ...accum,
+ ...findPossesivesInAdjective(curr),
+ ],
+ [] as T.Rendered[]
+ );
}
-function findPossesivesInAdjective(a: T.Rendered): T.Rendered[] {
- if (!a.sandwich) return [];
- return findPossesivesInNP(a.sandwich.inside);
+function findPossesivesInAdjective(
+ a: T.Rendered
+): T.Rendered[] {
+ if (!a.sandwich) return [];
+ return findPossesivesInNP(a.sandwich.inside);
}
-export function flattenLengths(r: T.SingleOrLengthOpts): T.PsString[] {
- if ("long" in r) {
- return Object.values(r).flat();
+export function flattenLengths(
+ r: T.SingleOrLengthOpts
+): T.PsString[] {
+ if ("long" in r) {
+ // because we want to use the short shwul and past equatives as the default
+ if (r.long[0].p.startsWith("شول") || r.long[0].p.startsWith("ول")) {
+ return [...r.short, ...r.long];
}
- if (Array.isArray(r)) {
- return r;
- }
- return [r];
+ return [...r.long, ...r.short, ...("mini" in r && r.mini ? r.mini : [])];
+ }
+ return r;
}
-
-
diff --git a/src/lib/src/phrase-building/render-vp.ts b/src/lib/src/phrase-building/render-vp.ts
index 397dc1b..4f74d0f 100644
--- a/src/lib/src/phrase-building/render-vp.ts
+++ b/src/lib/src/phrase-building/render-vp.ts
@@ -1,285 +1,339 @@
import * as T from "../../../types";
-import {
- mapVerbRenderedOutput,
-} from "../fmaps";
+import { mapVerbRenderedOutput } from "../fmaps";
import { removeAccents } from "../accent-helpers";
-import {
- getPersonFromNP,
- isPastTense,
-} from "./vp-tools";
-import {
- isImperativeTense,
- isPattern4Entry,
-} from "../type-predicates";
+import { getPersonFromNP, isPastTense } from "./vp-tools";
+import { isImperativeTense, isPattern4Entry } from "../type-predicates";
import { renderVerb } from "../new-verb-engine/render-verb";
import { renderEnglishVPBase } from "./english-vp-rendering";
import { renderNPSelection } from "./render-np";
-import { getObjectSelection, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
+import {
+ getObjectSelection,
+ getSubjectSelection,
+ makeBlock,
+ makeKid,
+} from "./blocks-utils";
import { renderAPSelection } from "./render-ap";
-import { findPossesivesToShrink, orderKids, getMiniPronounPs } from "./render-common";
+import {
+ findPossesivesToShrink,
+ orderKids,
+ getMiniPronounPs,
+} from "./render-common";
import { renderComplementSelection } from "./render-complement";
-import { personToGenNum } from "../misc-helpers";
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
- const subject = getSubjectSelection(VP.blocks).selection;
- const object = getObjectSelection(VP.blocks).selection;
- // Sentence Rules Logic
- const isPast = isPastTense(VP.verb.tense);
- const isTransitive = object !== "none";
- const { king, servant } = getKingAndServant(isPast, isTransitive);
- const kingPerson = getPersonFromNP(
- king === "subject" ? subject : object,
- );
- const complementPerson = getPersonFromNP(object ? object : subject)
- // TODO: more elegant way of handling this type safety
- if (kingPerson === undefined) {
- throw new Error("king of sentance does not exist");
+ const subject = getSubjectSelection(VP.blocks).selection;
+ const object = getObjectSelection(VP.blocks).selection;
+ // Sentence Rules Logic
+ const isPast = isPastTense(VP.verb.tense);
+ const isTransitive = object !== "none";
+ const { king, servant } = getKingAndServant(isPast, isTransitive);
+ const kingPerson = getPersonFromNP(king === "subject" ? subject : object);
+ const complementPerson = getPersonFromNP(object ? object : subject);
+ // TODO: more elegant way of handling this type safety
+ if (kingPerson === undefined) {
+ throw new Error("king of sentance does not exist");
+ }
+ const subjectPerson = getPersonFromNP(subject);
+ const objectPerson = getPersonFromNP(object);
+ const inflectSubject =
+ isPast && isTransitive && !isMascSingAnimatePattern4(subject);
+ const inflectObject = !isPast && isFirstOrSecondPersPronoun(object);
+ // Render Elements
+ const firstBlocks = renderVPBlocks(VP.blocks, VP.externalComplement, {
+ inflectSubject,
+ inflectObject,
+ king,
+ complementPerson,
+ });
+ const { vbs, hasBa } = renderVerb({
+ verb: VP.verb.verb,
+ tense: VP.verb.tense,
+ subject: subjectPerson,
+ object: objectPerson,
+ voice: VP.verb.voice,
+ negative: VP.verb.negative,
+ });
+ const VBwNeg = insertNegative(
+ vbs,
+ VP.verb.negative,
+ isImperativeTense(VP.verb.tense)
+ );
+ // just enter the negative in the verb blocks
+ return {
+ type: "VPRendered",
+ king,
+ servant,
+ isPast,
+ isTransitive,
+ isCompound: VP.verb.isCompound,
+ blocks: VBwNeg.map((VBvars) => [...firstBlocks, ...VBvars]),
+ kids: getVPKids(hasBa, VP.blocks, VP.form, king),
+ englishBase: renderEnglishVPBase({
+ subjectPerson,
+ object: VP.verb.isCompound === "dynamic" ? "none" : object,
+ vs: VP.verb,
+ }),
+ form: VP.form,
+ whatsAdjustable: whatsAdjustable(VP),
+ };
+}
+
+function getVPKids(
+ hasBa: boolean,
+ blocks: T.VPSBlockComplete[],
+ form: T.FormVersion,
+ king: "subject" | "object"
+): T.Kid[] {
+ const subject = getSubjectSelection(blocks).selection;
+ const objectS = getObjectSelection(blocks).selection;
+ const object = typeof objectS === "object" ? objectS : undefined;
+ const servantNP = king === "subject" ? object : subject;
+ const shrunkenServant =
+ form.shrinkServant && servantNP
+ ? makeKid(shrinkServant(servantNP))
+ : undefined;
+ const shrunkenPossesives = findPossesivesToShrink(
+ removeAbbreviated(blocks, form, king)
+ ).map(makeKid);
+ return orderKids([
+ ...(hasBa ? [makeKid({ type: "ba" })] : []),
+ ...(shrunkenServant ? [shrunkenServant] : []),
+ ...(shrunkenPossesives ? shrunkenPossesives : []),
+ ]);
+}
+
+function removeAbbreviated(
+ blocks: T.VPSBlockComplete[],
+ form: T.FormVersion,
+ king: "subject" | "object"
+): T.VPSBlockComplete[] {
+ return blocks.filter(({ block }) => {
+ if (block.type === "subjectSelection") {
+ if (form.shrinkServant && king === "object") return false;
+ if (form.removeKing && king === "subject") return false;
}
- const subjectPerson = getPersonFromNP(subject);
- const objectPerson = getPersonFromNP(object);
- const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(subject);
- const inflectObject = !isPast && isFirstOrSecondPersPronoun(object);
- // Render Elements
- const firstBlocks = renderVPBlocks(VP.blocks, VP.externalComplement, {
- inflectSubject,
- inflectObject,
- king,
- complementPerson,
- });
- const { vbs, hasBa } = renderVerb({
- verb: VP.verb.verb,
- tense: VP.verb.tense,
- person: kingPerson,
- complementGenNum: personToGenNum(objectPerson || kingPerson),
- voice: VP.verb.voice,
- negative: VP.verb.negative,
- });
- const VBwNeg = insertNegative(vbs, VP.verb.negative, isImperativeTense(VP.verb.tense));
- // just enter the negative in the verb blocks
- return {
- type: "VPRendered",
- king,
- servant,
- isPast,
- isTransitive,
- isCompound: VP.verb.isCompound,
- blocks: VBwNeg.map(VBvars => [...firstBlocks, ...VBvars]),
- kids: getVPKids(hasBa, VP.blocks, VP.form, king),
- englishBase: renderEnglishVPBase({
- subjectPerson,
- object: VP.verb.isCompound === "dynamic" ? "none" : object,
- vs: VP.verb,
- }),
- form: VP.form,
- whatsAdjustable: whatsAdjustable(VP),
- };
-}
-
-function getVPKids(hasBa: boolean, blocks: T.VPSBlockComplete[], form: T.FormVersion, king: "subject" | "object"): T.Kid[] {
- const subject = getSubjectSelection(blocks).selection;
- const objectS = getObjectSelection(blocks).selection;
- const object = typeof objectS === "object" ? objectS : undefined;
- const servantNP = king === "subject" ? object : subject;
- const shrunkenServant = (form.shrinkServant && servantNP)
- ? makeKid(shrinkServant(servantNP))
- : undefined;
- const shrunkenPossesives = findPossesivesToShrink(removeAbbreviated(blocks, form, king)).map(makeKid);
- return orderKids([
- ...hasBa ? [makeKid({ type: "ba" })] : [],
- ...shrunkenServant ? [shrunkenServant] : [],
- ...shrunkenPossesives ? shrunkenPossesives : [],
- ]);
-}
-
-function removeAbbreviated(blocks: T.VPSBlockComplete[], form: T.FormVersion, king: "subject" | "object"): T.VPSBlockComplete[] {
- return blocks.filter(({ block }) => {
- if (block.type === "subjectSelection") {
- if (form.shrinkServant && king === "object") return false;
- if (form.removeKing && king === "subject") return false;
- }
- if (block.type === "objectSelection") {
- if (form.shrinkServant && king === "subject") return false;
- if (form.removeKing && king === "object") return false;
- }
- return true;
- });
-}
-
-function insertNegative(blocks: T.VerbRenderedOutput, negative: boolean, imperative: boolean): T.Block[][] {
- if (!negative) {
- return [blocks.flat().map(makeBlock)];
- };
- const blocksA = blocks.flat().map(makeBlock);
- const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks).flat().map(makeBlock);
- const neg = makeBlock({ type: "negative", imperative });
- const nonStandPerfectiveSplit = hasNonStandardPerfectiveSplit(blocks);
- if (blocks[1].length === 2) {
- // swapped ending with negative for ability and perfect verb forms
- if (nonStandPerfectiveSplit) {
- return [
- insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
- insertFromEnd(swapEndingBlocks(blocksA, 2), neg, 3),
- insertFromEnd(blocksNoAccentA, neg, 1),
- ]
- }
- return [
- insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
- insertFromEnd(blocksNoAccentA, neg, 1),
- ];
+ if (block.type === "objectSelection") {
+ if (form.shrinkServant && king === "subject") return false;
+ if (form.removeKing && king === "object") return false;
}
+ return true;
+ });
+}
+
+export function insertNegative(
+ blocks: T.VerbRenderedOutput,
+ negative: boolean,
+ imperative: boolean
+): T.Block[][] {
+ if (!negative) {
+ return [blocks.flat().map(makeBlock)];
+ }
+ const blocksA = blocks.flat().map(makeBlock);
+ const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks)
+ .flat()
+ .map(makeBlock);
+ const neg = makeBlock({ type: "negative", imperative });
+ const nonStandPerfectiveSplit = hasNonStandardPerfectiveSplit(blocks);
+ if (blocks[1].length === 2) {
+ // swapped ending with negative for ability and perfect verb forms
if (nonStandPerfectiveSplit) {
- return [
- insertFromEnd(blocksNoAccentA, neg, 1),
- insertFromEnd(blocksNoAccentA, neg, 2),
- ];
- } else {
- return [insertFromEnd(blocksNoAccentA, neg, 1)];
+ return [
+ insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
+ insertFromEnd(swapEndingBlocks(blocksA, 2), neg, 3),
+ insertFromEnd(blocksNoAccentA, neg, 1),
+ ];
}
+ return [
+ insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
+ insertFromEnd(blocksNoAccentA, neg, 1),
+ ];
+ }
+ if (nonStandPerfectiveSplit) {
+ return [
+ insertFromEnd(blocksNoAccentA, neg, 1),
+ insertFromEnd(blocksNoAccentA, neg, 2),
+ ];
+ } else {
+ return [insertFromEnd(blocksNoAccentA, neg, 1)];
+ }
}
function swapEndingBlocks(arr: X[], n: number = 1): X[] {
- return [
- ...arr.slice(0, arr.length - (n + 1)),
- ...arr.slice(-n),
- ...arr.slice(-(n + 1), -n),
- ];
+ return [
+ ...arr.slice(0, arr.length - (n + 1)),
+ ...arr.slice(-n),
+ ...arr.slice(-(n + 1), -n),
+ ];
}
function insertFromEnd(arr: X[], x: X, n: number): X[] {
- if (n === 0) {
- return [...arr, x];
- }
- return [
- ...arr.slice(0, arr.length - n),
- x,
- ...arr.slice(-n),
- ];
+ if (n === 0) {
+ return [...arr, x];
+ }
+ return [...arr.slice(0, arr.length - n), x, ...arr.slice(-n)];
}
function hasNonStandardPerfectiveSplit([[ph]]: T.VerbRenderedOutput): boolean {
- if (!ph) {
- return false;
- }
- if (ph.type !== "PH") {
- return false;
- }
- return !["و", "وا"].includes(ph.ps.p);
+ if (!ph) {
+ return false;
+ }
+ if (ph.type !== "PH") {
+ return false;
+ }
+ return !["و", "وا"].includes(ph.ps.p);
}
function shrinkServant(np: T.NPSelection): T.MiniPronoun {
- const person = getPersonFromNP(np);
- return {
- type: "mini-pronoun",
- person,
- ps: getMiniPronounPs(person),
- source: "servant",
- np,
- };
+ const person = getPersonFromNP(np);
+ return {
+ type: "mini-pronoun",
+ person,
+ ps: getMiniPronounPs(person),
+ source: "servant",
+ np,
+ };
}
-
-function renderVPBlocks(blocks: T.VPSBlockComplete[], externalComplement: T.VPSelectionComplete["externalComplement"], config: {
- inflectSubject: boolean,
- inflectObject: boolean,
- king: "subject" | "object",
- complementPerson: T.Person | undefined,
-}): T.Block[] {
- const object = getObjectSelection(blocks);
- const subject = getSubjectSelection(blocks);
- const adverbPerson = typeof object.selection === "object"
- ? getPersonFromNP(object.selection)
- : getPersonFromNP(subject.selection);
- const b = externalComplement ? [...blocks, { block: externalComplement }] : blocks
- return b.reduce((blocks, { block }): T.Block[] => {
- if (block.type === "subjectSelection") {
- return [
- ...blocks,
- makeBlock({
- type: "subjectSelection",
- selection: renderNPSelection(block.selection, config.inflectSubject, false, "subject", config.king === "subject" ? "king" : "servant", false),
- }),
- ];
- }
- if (block.type === "objectSelection") {
- const object = typeof block === "object" ? block.selection : block;
- if (typeof object !== "object") {
- return [
- ...blocks,
- makeBlock({
- type: "objectSelection",
- selection: object,
- }),
- ];
- }
- const selection = renderNPSelection(object, config.inflectObject, true, "object", config.king === "object" ? "king" : "servant", false);
- return [
- ...blocks,
- makeBlock({
- type: "objectSelection",
- selection,
- }),
- ];
- }
- if (block.type === "AP") {
- return [
- ...blocks,
- makeBlock(renderAPSelection(block, adverbPerson ?? 0)),
- ];
- }
- return [
- ...blocks,
- makeBlock(
- renderComplementSelection(
- block,
- // just for typesafety // TODO: only include the person if we're doing an adjective
- config.complementPerson || T.Person.FirstSingMale,
- )),
- ];
- }, [] as T.Block[]);
-}
-
-function whatsAdjustable(VP: T.VPSelectionComplete): "both" | "king" | "servant" {
- // TODO: intransitive dynamic compounds?
- return (VP.verb.isCompound === "dynamic" && VP.verb.transitivity === "transitive")
- ? (isPastTense(VP.verb.tense) ? "servant" : "king")
- : VP.verb.transitivity === "transitive"
- ? (VP.verb.voice === "active" ? "both" : "king")
- : VP.verb.transitivity === "intransitive"
- ? "king"
- // grammTrans
- : isPastTense(VP.verb.tense)
- ? "servant"
- : "king";
-}
-
-export 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 };
+function renderVPBlocks(
+ blocks: T.VPSBlockComplete[],
+ externalComplement: T.VPSelectionComplete["externalComplement"],
+ config: {
+ inflectSubject: boolean;
+ inflectObject: boolean;
+ king: "subject" | "object";
+ complementPerson: T.Person | undefined;
+ }
+): T.Block[] {
+ const object = getObjectSelection(blocks);
+ const subject = getSubjectSelection(blocks);
+ const adverbPerson =
+ typeof object.selection === "object"
+ ? getPersonFromNP(object.selection)
+ : getPersonFromNP(subject.selection);
+ const b = externalComplement
+ ? [...blocks, { block: externalComplement }]
+ : blocks;
+ return b.reduce((blocks, { block }): T.Block[] => {
+ if (block.type === "subjectSelection") {
+ return [
+ ...blocks,
+ makeBlock({
+ type: "subjectSelection",
+ selection: renderNPSelection(
+ block.selection,
+ config.inflectSubject,
+ false,
+ "subject",
+ config.king === "subject" ? "king" : "servant",
+ false
+ ),
+ }),
+ ];
}
- return isPast ? {
+ if (block.type === "objectSelection") {
+ const object = typeof block === "object" ? block.selection : block;
+ if (typeof object !== "object") {
+ return [
+ ...blocks,
+ makeBlock({
+ type: "objectSelection",
+ selection: object,
+ }),
+ ];
+ }
+ const selection = renderNPSelection(
+ object,
+ config.inflectObject,
+ true,
+ "object",
+ config.king === "object" ? "king" : "servant",
+ false
+ );
+ return [
+ ...blocks,
+ makeBlock({
+ type: "objectSelection",
+ selection,
+ }),
+ ];
+ }
+ if (block.type === "AP") {
+ return [
+ ...blocks,
+ makeBlock(renderAPSelection(block, adverbPerson ?? 0)),
+ ];
+ }
+ return [
+ ...blocks,
+ makeBlock(
+ renderComplementSelection(
+ block,
+ // just for typesafety // TODO: only include the person if we're doing an adjective
+ config.complementPerson || T.Person.FirstSingMale
+ )
+ ),
+ ];
+ }, [] as T.Block[]);
+}
+
+function whatsAdjustable(
+ VP: T.VPSelectionComplete
+): "both" | "king" | "servant" {
+ // TODO: intransitive dynamic compounds?
+ return VP.verb.isCompound === "dynamic" &&
+ VP.verb.transitivity === "transitive"
+ ? isPastTense(VP.verb.tense)
+ ? "servant"
+ : "king"
+ : VP.verb.transitivity === "transitive"
+ ? VP.verb.voice === "active"
+ ? "both"
+ : "king"
+ : VP.verb.transitivity === "intransitive"
+ ? "king"
+ : // grammTrans
+ isPastTense(VP.verb.tense)
+ ? "servant"
+ : "king";
+}
+
+export 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" | T.NPSelection | T.Person.ThirdPlurMale): boolean {
- if (typeof o !== "object") return false;
- if (o.selection.type !== "pronoun") return false;
- return [0,1,2,3,6,7,8,9].includes(o.selection.person);
+function isFirstOrSecondPersPronoun(
+ o: "none" | T.NPSelection | T.Person.ThirdPlurMale
+): boolean {
+ if (typeof o !== "object") return false;
+ if (o.selection.type !== "pronoun") return false;
+ return [0, 1, 2, 3, 6, 7, 8, 9].includes(o.selection.person);
}
function isMascSingAnimatePattern4(np: T.NPSelection): boolean {
- if (np.selection.type !== "noun") {
- return false;
- }
- return isPattern4Entry(np.selection.entry)
- && np.selection.entry.c.includes("anim.")
- && (np.selection.number === "singular")
- && (np.selection.gender === "masc");
+ if (np.selection.type !== "noun") {
+ return false;
+ }
+ return (
+ isPattern4Entry(np.selection.entry) &&
+ np.selection.entry.c.includes("anim.") &&
+ np.selection.number === "singular" &&
+ np.selection.gender === "masc"
+ );
}
diff --git a/src/lib/src/phrase-building/vp-tools.ts b/src/lib/src/phrase-building/vp-tools.ts
index 4930055..e32634e 100644
--- a/src/lib/src/phrase-building/vp-tools.ts
+++ b/src/lib/src/phrase-building/vp-tools.ts
@@ -1,338 +1,361 @@
import * as T from "../../../types";
-import {
- concatPsString,
- psRemove,
- psStringEquals,
-} from "../p-text-helpers";
-import { isImperativeTense, isPerfectTense } from "../type-predicates";
+import { concatPsString, psRemove, psStringEquals } from "../p-text-helpers";
+import { isPerfectTense } from "../type-predicates";
import * as grammarUnits from "../grammar-units";
import { isSecondPerson, randomNumber } from "../misc-helpers";
-import { adjustObjectSelection, adjustSubjectSelection, getObjectSelection, getSubjectSelection, VPSBlocksAreComplete } from "./blocks-utils";
+import {
+ adjustObjectSelection,
+ adjustSubjectSelection,
+ getObjectSelection,
+ getSubjectSelection,
+ VPSBlocksAreComplete,
+} from "./blocks-utils";
export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
- const firstPeople = [
- T.Person.FirstSingMale,
- T.Person.FirstSingFemale,
- T.Person.FirstPlurMale,
- T.Person.FirstPlurFemale,
- ];
- const secondPeople = [
- T.Person.SecondSingMale,
- T.Person.SecondSingFemale,
- T.Person.SecondPlurMale,
- T.Person.SecondPlurFemale,
- ];
- return (
- (firstPeople.includes(subj) && firstPeople.includes(obj))
- ||
- (secondPeople.includes(subj) && secondPeople.includes(obj))
- );
+ const firstPeople = [
+ T.Person.FirstSingMale,
+ T.Person.FirstSingFemale,
+ T.Person.FirstPlurMale,
+ T.Person.FirstPlurFemale,
+ ];
+ const secondPeople = [
+ T.Person.SecondSingMale,
+ T.Person.SecondSingFemale,
+ T.Person.SecondPlurMale,
+ T.Person.SecondPlurFemale,
+ ];
+ return (
+ (firstPeople.includes(subj) && firstPeople.includes(obj)) ||
+ (secondPeople.includes(subj) && secondPeople.includes(obj))
+ );
}
-/**
- * @param conjR
- * @param tense
- * @param voice
- * @param negative
- * @returns
- */
-export function getTenseVerbForm(
- conjR: T.VerbConjugation,
- tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense,
- voice: "active" | "passive",
- mode: "charts" | "phrase-building",
- negative: boolean,
-): T.VerbForm | T.ImperativeForm {
- const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
- if (isImperativeTense(tense)) {
- const impPassError = new Error("can't use imperative tenses with passive voice")
- if (voice === "passive") {
- throw impPassError;
- }
- if (!conj.imperfective.imperative || !conj.perfective.imperative) throw impPassError;
- // charts can't display negative form
- return (tense === "perfectiveImperative" && (!negative || mode === "charts"))
- ? conj.perfective.imperative
- : conj.imperfective.imperative;
- }
- if (tense === "presentVerb") {
- return conj.imperfective.nonImperative;
- }
- if (tense === "subjunctiveVerb") {
- return conj.perfective.nonImperative;
- }
- if (tense === "imperfectiveFuture") {
- return conj.imperfective.future;
- }
- if (tense === "perfectiveFuture") {
- return conj.perfective.future;
- }
- if (tense === "imperfectivePast") {
- return conj.imperfective.past;
- }
- if (tense === "perfectivePast") {
- return conj.perfective.past;
- }
- if (tense === "habitualImperfectivePast") {
- return conj.imperfective.habitualPast;
- }
- if (tense === "habitualPerfectivePast") {
- return conj.perfective.habitualPast;
- }
- if (tense === "presentVerbModal") {
- return conj.imperfective.modal.nonImperative;
- }
- if (tense === "subjunctiveVerbModal") {
- return conj.perfective.modal.nonImperative;
- }
- if (tense === "imperfectiveFutureModal") {
- return conj.imperfective.modal.future;
- }
- if (tense === "perfectiveFutureModal") {
- return conj.perfective.modal.future;
- }
- if (tense === "imperfectivePastModal") {
- return conj.imperfective.modal.past;
- }
- if (tense === "perfectivePastModal") {
- return conj.perfective.modal.past;
- }
- if (tense === "habitualImperfectivePastModal") {
- return conj.imperfective.modal.habitualPast;
- }
- if (tense === "habitualPerfectivePastModal") {
- return conj.perfective.modal.habitualPast;
- }
- if (tense === "presentPerfect") {
- return conj.perfect.present;
- }
- if (tense === "pastPerfect") {
- return conj.perfect.past;
- }
- if (tense === "futurePerfect") {
- return conj.perfect.future;
- }
- if (tense === "habitualPerfect") {
- return conj.perfect.habitual;
- }
- if (tense === "subjunctivePerfect") {
- return conj.perfect.subjunctive;
- }
- if (tense === "wouldBePerfect") {
- return conj.perfect.wouldBe;
- }
- if (tense === "pastSubjunctivePerfect") {
- return conj.perfect.pastSubjunctive;
- }
- if (tense === "wouldHaveBeenPerfect") {
- return conj.perfect.wouldHaveBeen;
- }
- throw new Error("unknown tense");
-}
+// DEPRECATED
+// /**
+// * @param conjR
+// * @param tense
+// * @param voice
+// * @param negative
+// * @returns
+// */
+// export function getTenseVerbForm(
+// conjR: T.VerbConjugation,
+// tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense,
+// voice: "active" | "passive",
+// mode: "charts" | "phrase-building",
+// negative: boolean,
+// ): T.VerbForm | T.ImperativeForm {
+// const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
+// if (isImperativeTense(tense)) {
+// const impPassError = new Error("can't use imperative tenses with passive voice")
+// if (voice === "passive") {
+// throw impPassError;
+// }
+// if (!conj.imperfective.imperative || !conj.perfective.imperative) throw impPassError;
+// // charts can't display negative form
+// return (tense === "perfectiveImperative" && (!negative || mode === "charts"))
+// ? conj.perfective.imperative
+// : conj.imperfective.imperative;
+// }
+// if (tense === "presentVerb") {
+// return conj.imperfective.nonImperative;
+// }
+// if (tense === "subjunctiveVerb") {
+// return conj.perfective.nonImperative;
+// }
+// if (tense === "imperfectiveFuture") {
+// return conj.imperfective.future;
+// }
+// if (tense === "perfectiveFuture") {
+// return conj.perfective.future;
+// }
+// if (tense === "imperfectivePast") {
+// return conj.imperfective.past;
+// }
+// if (tense === "perfectivePast") {
+// return conj.perfective.past;
+// }
+// if (tense === "habitualImperfectivePast") {
+// return conj.imperfective.habitualPast;
+// }
+// if (tense === "habitualPerfectivePast") {
+// return conj.perfective.habitualPast;
+// }
+// if (tense === "presentVerbModal") {
+// return conj.imperfective.modal.nonImperative;
+// }
+// if (tense === "subjunctiveVerbModal") {
+// return conj.perfective.modal.nonImperative;
+// }
+// if (tense === "imperfectiveFutureModal") {
+// return conj.imperfective.modal.future;
+// }
+// if (tense === "perfectiveFutureModal") {
+// return conj.perfective.modal.future;
+// }
+// if (tense === "imperfectivePastModal") {
+// return conj.imperfective.modal.past;
+// }
+// if (tense === "perfectivePastModal") {
+// return conj.perfective.modal.past;
+// }
+// if (tense === "habitualImperfectivePastModal") {
+// return conj.imperfective.modal.habitualPast;
+// }
+// if (tense === "habitualPerfectivePastModal") {
+// return conj.perfective.modal.habitualPast;
+// }
+// if (tense === "presentPerfect") {
+// return conj.perfect.present;
+// }
+// if (tense === "pastPerfect") {
+// return conj.perfect.past;
+// }
+// if (tense === "futurePerfect") {
+// return conj.perfect.future;
+// }
+// if (tense === "habitualPerfect") {
+// return conj.perfect.habitual;
+// }
+// if (tense === "subjunctivePerfect") {
+// return conj.perfect.subjunctive;
+// }
+// if (tense === "wouldBePerfect") {
+// return conj.perfect.wouldBe;
+// }
+// if (tense === "pastSubjunctivePerfect") {
+// return conj.perfect.pastSubjunctive;
+// }
+// if (tense === "wouldHaveBeenPerfect") {
+// return conj.perfect.wouldHaveBeen;
+// }
+// throw new Error("unknown tense");
+// }
export function getPersonFromNP(np: T.NPSelection): T.Person;
-export function getPersonFromNP(np: T.NPSelection | T.ObjectNP): T.Person | undefined;
-export function getPersonFromNP(np: T.NPSelection | T.ObjectNP): T.Person | undefined {
- if (np === "none") {
- return undefined;
- }
- if (typeof np === "number") return np;
- if (np.selection.type === "participle") {
- return T.Person.ThirdPlurMale;
- }
- if (np.selection.type === "pronoun") {
- return np.selection.person;
- }
- return np.selection.number === "plural"
- ? (np.selection.gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
- : (np.selection.gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
+export function getPersonFromNP(
+ np: T.NPSelection | T.ObjectNP
+): T.Person | undefined;
+export function getPersonFromNP(
+ np: T.NPSelection | T.ObjectNP
+): T.Person | undefined {
+ if (np === "none") {
+ return undefined;
+ }
+ if (typeof np === "number") return np;
+ if (np.selection.type === "participle") {
+ return T.Person.ThirdPlurMale;
+ }
+ if (np.selection.type === "pronoun") {
+ return np.selection.person;
+ }
+ return np.selection.number === "plural"
+ ? np.selection.gender === "masc"
+ ? T.Person.ThirdPlurMale
+ : T.Person.ThirdPlurFemale
+ : np.selection.gender === "masc"
+ ? T.Person.ThirdSingMale
+ : T.Person.ThirdSingFemale;
}
export function removeBa(ps: T.PsString): T.PsString {
- return psRemove(ps, concatPsString(grammarUnits.baParticle, " "));
+ return psRemove(ps, concatPsString(grammarUnits.baParticle, " "));
}
-export function getTenseFromVerbSelection(vs: T.VerbSelection): T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense {
- function verbTenseToModalTense(tn: T.VerbTense): T.AbilityTense {
- if (tn === "presentVerb") {
- return "presentVerbModal";
- }
- if (tn === "subjunctiveVerb") {
- return "subjunctiveVerbModal";
- }
- if (tn === "imperfectiveFuture") {
- return "imperfectiveFutureModal";
- }
- if (tn === "perfectiveFuture") {
- return "perfectiveFutureModal";
- }
- if (tn === "perfectivePast") {
- return "perfectivePastModal";
- }
- if (tn === "imperfectivePast") {
- return "imperfectivePastModal";
- }
- if (tn === "habitualImperfectivePast") {
- return "habitualImperfectivePastModal";
- }
- if (tn === "habitualPerfectivePast") {
- return "habitualPerfectivePastModal";
- }
- throw new Error("can't convert non verbTense to modalTense");
+export function getTenseFromVerbSelection(
+ vs: T.VerbSelection
+): T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense {
+ function verbTenseToModalTense(tn: T.VerbTense): T.AbilityTense {
+ if (tn === "presentVerb") {
+ return "presentVerbModal";
}
- if (vs.tenseCategory === "basic") {
- return vs.verbTense;
+ if (tn === "subjunctiveVerb") {
+ return "subjunctiveVerbModal";
}
- if (vs.tenseCategory === "perfect") {
- return vs.perfectTense;
+ if (tn === "imperfectiveFuture") {
+ return "imperfectiveFutureModal";
}
- if (vs.tenseCategory === "imperative") {
- return vs.imperativeTense;
+ if (tn === "perfectiveFuture") {
+ return "perfectiveFutureModal";
}
- // vs.tenseCategory === "modal"
- return verbTenseToModalTense(vs.verbTense);
+ if (tn === "perfectivePast") {
+ return "perfectivePastModal";
+ }
+ if (tn === "imperfectivePast") {
+ return "imperfectivePastModal";
+ }
+ if (tn === "habitualImperfectivePast") {
+ return "habitualImperfectivePastModal";
+ }
+ if (tn === "habitualPerfectivePast") {
+ return "habitualPerfectivePastModal";
+ }
+ throw new Error("can't convert non verbTense to modalTense");
+ }
+ if (vs.tenseCategory === "basic") {
+ return vs.verbTense;
+ }
+ if (vs.tenseCategory === "perfect") {
+ return vs.perfectTense;
+ }
+ if (vs.tenseCategory === "imperative") {
+ return vs.imperativeTense;
+ }
+ // vs.tenseCategory === "modal"
+ return verbTenseToModalTense(vs.verbTense);
}
export function isPastTense(tense: T.Tense): boolean {
- if (isPerfectTense(tense)) return true;
- return tense.toLowerCase().includes("past");
+ if (isPerfectTense(tense)) return true;
+ return tense.toLowerCase().includes("past");
}
export function perfectTenseHasBa(tense: T.PerfectTense): boolean {
- const withBa: Parameters[0][] = [
- "futurePerfect",
- "wouldBePerfect",
- "wouldHaveBeenPerfect",
- ];
- return withBa.includes(tense);
+ const withBa: Parameters[0][] = [
+ "futurePerfect",
+ "wouldBePerfect",
+ "wouldHaveBeenPerfect",
+ ];
+ return withBa.includes(tense);
}
export function removeDuplicates(psv: T.PsString[]): T.PsString[] {
- return psv.filter((ps, i, arr) => (
- i === arr.findIndex(t => (
- psStringEquals(t, ps)
- ))
- ));
+ return psv.filter(
+ (ps, i, arr) => i === arr.findIndex((t) => psStringEquals(t, ps))
+ );
}
-export function switchSubjObj(vps: V): V {
- const subject = getSubjectSelection(vps.blocks).selection;
- const object = getObjectSelection(vps.blocks).selection;
- if ("tenseCategory" in vps.verb) {
- if (!subject || !(typeof object === "object") || (vps.verb.tenseCategory === "imperative")) {
- return vps;
- }
- return {
- ...vps,
- blocks: adjustObjectSelection(
- adjustSubjectSelection(vps.blocks, object),
- subject,
- ),
- };
- }
- if (!subject|| !vps.verb || !(typeof object === "object")) {
- return vps;
+export function switchSubjObj<
+ V extends T.VPSelectionState | T.VPSelectionComplete
+>(vps: V): V {
+ const subject = getSubjectSelection(vps.blocks).selection;
+ const object = getObjectSelection(vps.blocks).selection;
+ if ("tenseCategory" in vps.verb) {
+ if (
+ !subject ||
+ !(typeof object === "object") ||
+ vps.verb.tenseCategory === "imperative"
+ ) {
+ return vps;
}
return {
- ...vps,
- blocks: adjustObjectSelection(
- adjustSubjectSelection(vps.blocks, object),
- subject,
- ),
+ ...vps,
+ blocks: adjustObjectSelection(
+ adjustSubjectSelection(vps.blocks, object),
+ subject
+ ),
};
+ }
+ if (!subject || !vps.verb || !(typeof object === "object")) {
+ return vps;
+ }
+ return {
+ ...vps,
+ blocks: adjustObjectSelection(
+ adjustSubjectSelection(vps.blocks, object),
+ subject
+ ),
+ };
}
-export function completeVPSelection(vps: T.VPSelectionState): T.VPSelectionComplete | undefined {
- if (!VPSBlocksAreComplete(vps.blocks)) {
- return undefined;
- }
- // necessary for this version on typscript ...
- const verb: T.VerbSelectionComplete = {
- ...vps.verb,
- tense: getTenseFromVerbSelection(vps.verb),
- };
- return {
- ...vps,
- verb,
- blocks: vps.blocks,
- };
+export function completeVPSelection(
+ vps: T.VPSelectionState
+): T.VPSelectionComplete | undefined {
+ if (!VPSBlocksAreComplete(vps.blocks)) {
+ return undefined;
+ }
+ // necessary for this version on typscript ...
+ const verb: T.VerbSelectionComplete = {
+ ...vps.verb,
+ tense: getTenseFromVerbSelection(vps.verb),
+ };
+ return {
+ ...vps,
+ verb,
+ blocks: vps.blocks,
+ };
}
export function isThirdPerson(p: T.Person): boolean {
- return (
- p === T.Person.ThirdSingMale ||
- p === T.Person.ThirdSingFemale ||
- p === T.Person.ThirdPlurMale ||
- p === T.Person.ThirdPlurFemale
- );
+ return (
+ p === T.Person.ThirdSingMale ||
+ p === T.Person.ThirdSingFemale ||
+ p === T.Person.ThirdPlurMale ||
+ p === T.Person.ThirdPlurFemale
+ );
}
-export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelectionState): T.VPSelectionState {
- const subject = getSubjectSelection(vps.blocks).selection;
- const object = getObjectSelection(vps.blocks).selection;
- const subjIs2ndPerson = (subject?.selection.type === "pronoun") && isSecondPerson(subject.selection.person);
- const objIs2ndPerson = (typeof object === "object")
- && (object.selection.type === "pronoun")
- && isSecondPerson(object.selection.person);
- const default2ndPersSubject: T.NPSelection = {
+export function ensure2ndPersSubjPronounAndNoConflict(
+ vps: T.VPSelectionState
+): T.VPSelectionState {
+ const subject = getSubjectSelection(vps.blocks).selection;
+ const object = getObjectSelection(vps.blocks).selection;
+ const subjIs2ndPerson =
+ subject?.selection.type === "pronoun" &&
+ isSecondPerson(subject.selection.person);
+ const objIs2ndPerson =
+ typeof object === "object" &&
+ object.selection.type === "pronoun" &&
+ isSecondPerson(object.selection.person);
+ const default2ndPersSubject: T.NPSelection = {
+ type: "NP",
+ selection: {
+ type: "pronoun",
+ distance: "far",
+ person: T.Person.SecondSingMale,
+ },
+ };
+ function getNon2ndPersPronoun() {
+ let newObjPerson: T.Person;
+ do {
+ newObjPerson = randomNumber(0, 12);
+ } while (isSecondPerson(newObjPerson));
+ return newObjPerson;
+ }
+ if (subjIs2ndPerson && !objIs2ndPerson) {
+ return vps;
+ }
+ if (subjIs2ndPerson && objIs2ndPerson) {
+ if (typeof object !== "object" || object.selection.type !== "pronoun") {
+ return vps;
+ }
+ return {
+ ...vps,
+ blocks: adjustObjectSelection(vps.blocks, {
type: "NP",
selection: {
- type: "pronoun",
- distance: "far",
- person: T.Person.SecondSingMale,
+ ...object.selection,
+ person: getNon2ndPersPronoun(),
},
+ }),
};
- function getNon2ndPersPronoun() {
- let newObjPerson: T.Person;
- do {
- newObjPerson = randomNumber(0, 12);
- } while(isSecondPerson(newObjPerson));
- return newObjPerson;
+ }
+ if (!subjIs2ndPerson && objIs2ndPerson) {
+ if (typeof object !== "object" || object.selection.type !== "pronoun") {
+ return {
+ ...vps,
+ blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject),
+ };
}
- if (subjIs2ndPerson && !objIs2ndPerson) {
- return vps;
- }
- if (subjIs2ndPerson && objIs2ndPerson) {
- if (typeof object !== "object" || object.selection.type !== "pronoun") {
- return vps;
+ return {
+ ...vps,
+ blocks: adjustObjectSelection(
+ adjustSubjectSelection(vps.blocks, default2ndPersSubject),
+ {
+ type: "NP",
+ selection: {
+ ...object.selection,
+ person: getNon2ndPersPronoun(),
+ },
}
- return {
- ...vps,
- blocks: adjustObjectSelection(vps.blocks, {
- type: "NP",
- selection: {
- ...object.selection,
- person: getNon2ndPersPronoun(),
- },
- }),
- };
- }
- if (!subjIs2ndPerson && objIs2ndPerson) {
- if (typeof object !== "object" || object.selection.type !== "pronoun") {
- return {
- ...vps,
- blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject)
- };
- }
- return {
- ...vps,
- blocks: adjustObjectSelection(
- adjustSubjectSelection(vps.blocks, default2ndPersSubject),
- {
- type: "NP",
- selection: {
- ...object.selection,
- person: getNon2ndPersPronoun(),
- },
- },
- ),
- };
- }
- if (!subjIs2ndPerson && !objIs2ndPerson) {
- return {
- ...vps,
- blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject),
- };
- }
- throw new Error("error ensuring compatible VPSelection for imperative verb");
-}
\ No newline at end of file
+ ),
+ };
+ }
+ if (!subjIs2ndPerson && !objIs2ndPerson) {
+ return {
+ ...vps,
+ blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject),
+ };
+ }
+ throw new Error("error ensuring compatible VPSelection for imperative verb");
+}
diff --git a/src/lib/src/verb-info.ts b/src/lib/src/verb-info.ts
index 9309bcb..6e84516 100644
--- a/src/lib/src/verb-info.ts
+++ b/src/lib/src/verb-info.ts
@@ -7,55 +7,44 @@
*/
import {
- concatPsString,
- psStringEquals,
- removeEndingL,
- yulEndingInfinitive,
- removeRetroflexR,
- unisexInfToObjectMatrix,
- complementInflects,
- beginsWithDirectionalPronoun,
- checkForOoPrefix,
- removeStartingTick,
- ensureShortWurShwaShift,
- choosePersInf,
- isUnisexSet,
- getLong,
- getShort,
+ concatPsString,
+ psStringEquals,
+ removeEndingL,
+ yulEndingInfinitive,
+ removeRetroflexR,
+ unisexInfToObjectMatrix,
+ complementInflects,
+ beginsWithDirectionalPronoun,
+ checkForOoPrefix,
+ removeStartingTick,
+ ensureShortWurShwaShift,
+ choosePersInf,
+ isUnisexSet,
+ getLong,
+ getShort,
} from "./p-text-helpers";
+import { makePsString, removeFVarients } from "./accent-and-ps-utils";
+import { inflectYey } from "./pashto-inflector";
import {
- makePsString,
- removeFVarients,
-} from "./accent-and-ps-utils";
-import {
- inflectYey,
-} from "./pashto-inflector";
-import {
- accentOnFront,
- accentOnNFromEnd,
- removeAccents,
+ accentOnFront,
+ accentOnNFromEnd,
+ removeAccents,
} from "./accent-helpers";
+import { inflectWord } from "./pashto-inflector";
import {
- inflectWord,
-} from "./pashto-inflector";
-import {
- checkForIrregularConjugation,
- kedulStat,
- stativeAux,
+ checkForIrregularConjugation,
+ kedulStat,
+ stativeAux,
} from "./irregular-conjugations";
+import { presentParticipleSuffix } from "./grammar-units";
+import { dynamicAuxVerbs } from "./dyn-comp-aux-verbs";
import {
- presentParticipleSuffix
-} from "./grammar-units";
-import {
- dynamicAuxVerbs,
-} from "./dyn-comp-aux-verbs";
-import {
- getPersonInflectionsKey,
- getPersonNumber,
- spaceInForm,
- getAuxTransitivity,
- chooseParticipleInflection,
- noPersInfs,
+ getPersonInflectionsKey,
+ getPersonNumber,
+ spaceInForm,
+ getAuxTransitivity,
+ chooseParticipleInflection,
+ noPersInfs,
} from "./misc-helpers";
import * as T from "../../types";
import { isTlulVerb } from "./type-predicates";
@@ -66,1170 +55,1586 @@ const eyEndingUnaccented: T.PsString = { p: "ی", f: "ey" };
* Compiles the base information (roots, stems etc.) needed in order
* to make all the conjugations. This is the first step of creating
* the conjugations.
- *
+ *
* @param entry - the dictionary entry for the verb
* @param complement - the dictioanry entry for the complement of the verb if compound
*/
export function getVerbInfo(
- ent: T.DictionaryEntry,
- complmnt?: T.DictionaryEntry,
+ ent: T.DictionaryEntry,
+ complmnt?: T.DictionaryEntry
): T.VerbInfo {
- const entry = removeFVarients(ent);
- const irregularConj = checkForIrregularConjugation(entry);
- if (irregularConj) {
- return irregularConj.info;
- }
- const complement = (complmnt && ent.c?.includes("comp.")) ? removeFVarients(complmnt) : undefined;
- const type = getType(entry);
- if (type === "transitive or grammatically transitive simple") {
- return {
- type: "transitive or grammatically transitive simple",
- transitive: getVerbInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("trans./gramm. trans.", "trans.") },
- ) as T.SimpleVerbInfo,
- grammaticallyTransitive: getVerbInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("trans./gramm. trans.", "gramm. trans.") },
- ) as T.SimpleVerbInfo,
- };
- }
- const transitivity = getTransitivity(entry);
- if (type !== "simple") {
- if (!complement) {
- throw new Error("complement required for compound verb");
- }
- if (type === "dynamic compound") {
- return getDynamicCompoundInfo(entry, complement)
- }
- if (type === "dynamic or stative compound") {
- return {
- type: "dynamic or stative compound",
- transitivity,
- dynamic: getDynamicCompoundInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("dyn./stat.", "dyn.") },
- complement,
- ),
- stative: getVerbInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("dyn./stat.", "stat.") },
- complement,
- ) as T.StativeCompoundVerbInfo,
- };
- }
- if (type === "dynamic or generative stative compound") {
- return {
- type: "dynamic or generative stative compound",
- transitivity,
- dynamic: getDynamicCompoundInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("gen. stat./dyn.", "dyn.") },
- complement,
- ),
- stative: getGenerativeStativeCompoundVerbInfo(
- // @ts-ignore (will have entry.c)
- { ...entry, c: entry.c.replace("gen. stat./dyn.", "gen. stat.") },
- complement,
- ),
- }
- }
- if (type === "generative stative compound") {
- return getGenerativeStativeCompoundVerbInfo(entry, complement as T.DictionaryEntryNoFVars);
- }
- }
- const comp = complement ? ensureUnisexInf(complement) : undefined;
- const root = getVerbRoots(entry, transitivity, comp);
- const stem = getVerbStems(entry, root, transitivity, comp);
- const infinitive = "mascSing" in root.imperfective ? root.imperfective.mascSing.long : root.imperfective.long;
- const yulEnding = yulEndingInfinitive(infinitive);
- const participle = getParticiple(entry, stem, infinitive, transitivity, comp);
- const idiosyncraticThirdMascSing = getIdiosyncraticThirdMascSing(entry);
- const baseInfo: T.VerbInfoBase = {
- entry: {
- // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
- entry: entry as unknown as T.VerbDictionaryEntry,
- complement,
- },
- transitivity,
- yulEnding,
- root,
- stem,
- participle,
- ...idiosyncraticThirdMascSing ? {
- idiosyncraticThirdMascSing,
- } : {},
- };
- if (type === "stative compound") {
- return {
- ...baseInfo,
- type,
- complement: comp as T.UnisexInflections,
- };
- }
+ const entry = removeFVarients(ent);
+ const irregularConj = checkForIrregularConjugation(entry);
+ if (irregularConj) {
+ return irregularConj.info;
+ }
+ const complement =
+ complmnt && ent.c?.includes("comp.")
+ ? removeFVarients(complmnt)
+ : undefined;
+ const type = getType(entry);
+ if (type === "transitive or grammatically transitive simple") {
return {
- ...baseInfo,
- type,
+ type: "transitive or grammatically transitive simple",
+ transitive: getVerbInfo(
+ // @ts-ignore (will have entry.c)
+ { ...entry, c: entry.c.replace("trans./gramm. trans.", "trans.") }
+ ) as T.SimpleVerbInfo,
+ grammaticallyTransitive: getVerbInfo({
+ ...entry,
+ // @ts-ignore (will have entry.c)
+ c: entry.c.replace("trans./gramm. trans.", "gramm. trans."),
+ }) as T.SimpleVerbInfo,
};
+ }
+ const transitivity = getTransitivity(entry);
+ if (type !== "simple") {
+ if (!complement) {
+ throw new Error("complement required for compound verb");
+ }
+ if (type === "dynamic compound") {
+ return getDynamicCompoundInfo(entry, complement);
+ }
+ if (type === "dynamic or stative compound") {
+ return {
+ type: "dynamic or stative compound",
+ transitivity,
+ dynamic: getDynamicCompoundInfo(
+ // @ts-ignore (will have entry.c)
+ { ...entry, c: entry.c.replace("dyn./stat.", "dyn.") },
+ complement
+ ),
+ stative: getVerbInfo(
+ // @ts-ignore (will have entry.c)
+ { ...entry, c: entry.c.replace("dyn./stat.", "stat.") },
+ complement
+ ) as T.StativeCompoundVerbInfo,
+ };
+ }
+ if (type === "dynamic or generative stative compound") {
+ return {
+ type: "dynamic or generative stative compound",
+ transitivity,
+ dynamic: getDynamicCompoundInfo(
+ // @ts-ignore (will have entry.c)
+ { ...entry, c: entry.c.replace("gen. stat./dyn.", "dyn.") },
+ complement
+ ),
+ stative: getGenerativeStativeCompoundVerbInfo(
+ // @ts-ignore (will have entry.c)
+ { ...entry, c: entry.c.replace("gen. stat./dyn.", "gen. stat.") },
+ complement
+ ),
+ };
+ }
+ if (type === "generative stative compound") {
+ return getGenerativeStativeCompoundVerbInfo(
+ entry,
+ complement as T.DictionaryEntryNoFVars
+ );
+ }
+ }
+ const comp = complement ? ensureUnisexInf(complement) : undefined;
+ const root = getVerbRoots(entry, transitivity, comp);
+ const stem = getVerbStems(entry, root, transitivity, comp);
+ const infinitive =
+ "mascSing" in root.imperfective
+ ? root.imperfective.mascSing.long
+ : root.imperfective.long;
+ const yulEnding = yulEndingInfinitive(infinitive);
+ const participle = getParticiple(entry, stem, infinitive, transitivity, comp);
+ const idiosyncraticThirdMascSing = getIdiosyncraticThirdMascSing(entry);
+ const baseInfo: T.VerbInfoBase = {
+ entry: {
+ // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
+ entry: entry as unknown as T.VerbDictionaryEntry,
+ complement,
+ },
+ transitivity,
+ yulEnding,
+ root,
+ stem,
+ participle,
+ ...(idiosyncraticThirdMascSing
+ ? {
+ idiosyncraticThirdMascSing,
+ }
+ : {}),
+ };
+ if (type === "stative compound") {
+ return {
+ ...baseInfo,
+ type,
+ complement: comp as T.UnisexInflections,
+ };
+ }
+ return {
+ ...baseInfo,
+ type,
+ };
}
type Bases = {
- stem: {
- imperfective: T.FullForm,
- perfective: T.FullForm,
- perfectiveSplit?: T.SplitInfo,
- },
- root: {
- imperfective: T.FullForm,
- perfective: T.FullForm,
- perfectiveSplit?: T.SplitInfo,
- },
- participle: {
- present: T.FullForm,
- past: T.FullForm,
- },
-}
+ stem: {
+ imperfective: T.FullForm;
+ perfective: T.FullForm;
+ perfectiveSplit?: T.SplitInfo;
+ };
+ root: {
+ imperfective: T.FullForm;
+ perfective: T.FullForm;
+ perfectiveSplit?: T.SplitInfo;
+ };
+ participle: {
+ present: T.FullForm;
+ past: T.FullForm;
+ };
+};
function getGenerativeStativeCompoundVerbInfo(
- entry: T.DictionaryEntryNoFVars, comp: T.DictionaryEntryNoFVars, forceSingular?: true,
+ entry: T.DictionaryEntryNoFVars,
+ comp: T.DictionaryEntryNoFVars,
+ forceSingular?: true
): T.GenerativeStativeCompoundVerbInfo {
- const transitivity = getTransitivity(entry);
- const transitivityNoGrammTrans = transitivity === "grammatically transitive" ? "transitive" : transitivity;
- const yulEnding = null;
- const objComplement = getObjComplementInfo(entry, comp, forceSingular);
- const auxVerb = stativeAux[transitivityNoGrammTrans];
- const compUsed = objComplement.plural ? objComplement.plural : removeFVarients(objComplement.entry);
- const bases: Bases = {
- stem: {
- imperfective: auxVerb.info.stem.imperfective,
- perfective: auxVerb.info.stem.perfective,
- },
- root: {
- imperfective: auxVerb.info.root.imperfective,
- perfective: auxVerb.info.root.perfective,
- },
- participle: {
- present: auxVerb.info.participle.present,
- past: chooseParticipleInflection(
- inflectYey(
- "mascSing" in auxVerb.info.participle.past
- // purely for type saftey, will not have mascSing
- // in a non stative compound verb
- /* istanbul ignore next */
- ? auxVerb.info.participle.past.mascSing
- : auxVerb.info.participle.past
- ),
- objComplement.person,
- ),
- }
- }
- const perfectiveStem = concatPsString(compUsed, " ", bases.stem.perfective);
- const stem = {
- imperfective: concatPsString(compUsed, " ", bases.stem.imperfective),
- perfective: perfectiveStem,
- perfectiveSplit: splitPerfective(perfectiveStem, 0, 0, true),
- };
- const perfectiveRoot = concatPsString(compUsed, " ", bases.root.perfective) as T.OptionalPersonInflections>;
- const root = {
- imperfective: concatPsString(compUsed, " ", bases.root.imperfective) as T.OptionalPersonInflections>,
- perfective: perfectiveRoot,
- perfectiveSplit: splitPerfective(perfectiveRoot, 0, 0, true),
- };
- const participle = {
- present: concatPsString(compUsed, " ", auxVerb.info.participle.present),
- past: concatPsString(compUsed, " ", bases.participle.past),
- }
- return {
- entry: {
- // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
- entry: entry as unknown as T.VerbDictionaryEntry,
- complement: comp,
- },
- type: "generative stative compound",
- transitivity,
- yulEnding,
- stem,
- root,
- participle,
- objComplement,
- ...objComplement.plural ? {
- singularForm: getGenerativeStativeCompoundVerbInfo(entry, comp, true),
- } : {},
- };
-}
-
-function getDynamicCompoundInfo(entry: T.DictionaryEntryNoFVars, comp: T.DictionaryEntryNoFVars, forceSingular?: true): T.DynamicCompoundVerbInfo {
- const transitivity = getTransitivity(entry);
- const yulEnding = null;
- const objComplement = getObjComplementInfo(entry, comp, forceSingular);
- const auxVerb = getDynamicAuxVerb(entry);
- const auxVerbInfo = getVerbInfo(auxVerb.entry, auxVerb.complement) as T.NonComboVerbInfo;
- const compUsed = objComplement.plural ? objComplement.plural : objComplement.entry;
- const bases: Bases = (auxVerbInfo.type === "stative compound")
- ? getObjectMatchingBases(auxVerbInfo, objComplement.person)
- : {
- stem: {
- imperfective: auxVerbInfo.stem.imperfective,
- perfective: auxVerbInfo.stem.perfective,
- ...auxVerbInfo.stem.perfectiveSplit ? {
- perfectiveSplit: auxVerbInfo.stem.perfectiveSplit,
- } : {},
- },
- root: {
- imperfective: auxVerbInfo.root.imperfective,
- perfective: auxVerbInfo.root.perfective,
- ...auxVerbInfo.root.perfectiveSplit ? {
- perfectiveSplit: auxVerbInfo.root.perfectiveSplit,
- } : {},
- },
- participle: {
- present: auxVerbInfo.participle.present,
- past: chooseParticipleInflection(
- inflectYey(
- "mascSing" in auxVerbInfo.participle.past
- // purely for type saftey, will not have mascSing
- // in a non stative compound verb
- /* istanbul ignore next */
- ? auxVerbInfo.participle.past.mascSing
- : auxVerbInfo.participle.past
- ),
- objComplement.person,
- ),
- }
- }
- const stem = {
- imperfective: concatPsString(compUsed, " ", bases.stem.imperfective),
- perfective: concatPsString(compUsed, " ", bases.stem.perfective),
- ...bases.stem.perfectiveSplit ? {
- perfectiveSplit: makeDynamicPerfectiveSplit(compUsed, bases.stem.perfectiveSplit),
- } : {},
- };
- const root = {
- imperfective: concatPsString(compUsed, " ", bases.root.imperfective) as T.OptionalPersonInflections>,
- perfective: concatPsString(compUsed, " ", bases.root.perfective) as T.OptionalPersonInflections>,
- ...bases.root.perfectiveSplit ? {
- perfectiveSplit: makeDynamicPerfectiveSplit(compUsed, bases.root.perfectiveSplit),
- } : {},
- };
- const participle = {
- present: concatPsString(compUsed, " ", auxVerbInfo.participle.present),
- past: concatPsString(compUsed, " ", bases.participle.past),
- };
- const makeIntransitiveFormOfEntry = (e: T.DictionaryEntryNoFVars): T.DictionaryEntryNoFVars => ({
- ...e,
- p: e.p.replace(
- "کول",
- "کېدل"
+ const transitivity = getTransitivity(entry);
+ const transitivityNoGrammTrans =
+ transitivity === "grammatically transitive" ? "transitive" : transitivity;
+ const yulEnding = null;
+ const objComplement = getObjComplementInfo(entry, comp, forceSingular);
+ const auxVerb = stativeAux[transitivityNoGrammTrans];
+ const compUsed = objComplement.plural
+ ? objComplement.plural
+ : removeFVarients(objComplement.entry);
+ const bases: Bases = {
+ stem: {
+ imperfective: auxVerb.info.stem.imperfective,
+ perfective: auxVerb.info.stem.perfective,
+ },
+ root: {
+ imperfective: auxVerb.info.root.imperfective,
+ perfective: auxVerb.info.root.perfective,
+ },
+ participle: {
+ present: auxVerb.info.participle.present,
+ past: chooseParticipleInflection(
+ inflectYey(
+ "mascSing" in auxVerb.info.participle.past
+ ? // purely for type saftey, will not have mascSing
+ // in a non stative compound verb
+ /* istanbul ignore next */
+ auxVerb.info.participle.past.mascSing
+ : auxVerb.info.participle.past
),
- e: e.e.replace("to do", "to become"),
- f: e.f.replace(/kaw[u|ú]l/, "kedul"),
- c: "v. intrans. dyn. comp.",
- });
- const intransitiveFormEntry = (transitivity === "transitive" && auxVerb.entry.p === "کول")
- ? makeIntransitiveFormOfEntry(entry)
- : null;
- return {
- entry: {
- // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
- entry: entry as unknown as T.VerbDictionaryEntry,
- complement: comp,
- },
- type: "dynamic compound",
- transitivity,
- yulEnding,
- stem,
- root,
- participle,
- objComplement,
- auxVerb: auxVerb.entry,
- ...auxVerb.complement ? {
- auxVerbComplement: auxVerb.complement,
- } : {},
- ...objComplement.plural ? {
- singularForm: getDynamicCompoundInfo(entry, comp, true),
- } : {},
- ...intransitiveFormEntry ? {
- intransitiveForm: getDynamicCompoundInfo(intransitiveFormEntry, comp),
- } : {},
- };
+ objComplement.person
+ ),
+ },
+ };
+ const perfectiveStem = concatPsString(compUsed, " ", bases.stem.perfective);
+ const stem = {
+ imperfective: concatPsString(compUsed, " ", bases.stem.imperfective),
+ perfective: perfectiveStem,
+ perfectiveSplit: splitPerfective(perfectiveStem, 0, 0, true),
+ };
+ const perfectiveRoot = concatPsString(
+ compUsed,
+ " ",
+ bases.root.perfective
+ ) as T.OptionalPersonInflections>;
+ const root = {
+ imperfective: concatPsString(
+ compUsed,
+ " ",
+ bases.root.imperfective
+ ) as T.OptionalPersonInflections>,
+ perfective: perfectiveRoot,
+ perfectiveSplit: splitPerfective(perfectiveRoot, 0, 0, true),
+ };
+ const participle = {
+ present: concatPsString(compUsed, " ", auxVerb.info.participle.present),
+ past: concatPsString(compUsed, " ", bases.participle.past),
+ };
+ return {
+ entry: {
+ // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
+ entry: entry as unknown as T.VerbDictionaryEntry,
+ complement: comp,
+ },
+ type: "generative stative compound",
+ transitivity,
+ yulEnding,
+ stem,
+ root,
+ participle,
+ objComplement,
+ ...(objComplement.plural
+ ? {
+ singularForm: getGenerativeStativeCompoundVerbInfo(entry, comp, true),
+ }
+ : {}),
+ };
}
-function getObjectMatchingBases(auxInfo: T.NonComboVerbInfo, person: T.Person): Bases {
- const key = getPersonInflectionsKey(person);
- const getBase = (x: T.FullForm): T.SingleOrLengthOpts => (
- "mascSing" in x ? x[key] : x
- );
- return {
- stem: {
- imperfective: getBase(auxInfo.stem.imperfective),
- perfective: getBase(auxInfo.stem.perfective),
- ...auxInfo.stem.perfectiveSplit ? {
- perfectiveSplit: choosePersInf(auxInfo.stem.perfectiveSplit, key),
- } : {},
- },
- root: {
- imperfective: getBase(auxInfo.root.imperfective),
- perfective: getBase(auxInfo.root.perfective),
- ...auxInfo.root.perfectiveSplit ? {
- perfectiveSplit: choosePersInf(auxInfo.root.perfectiveSplit, key),
- } : {},
- },
- participle: {
- present: getBase(auxInfo.participle.present),
- past: getBase(auxInfo.participle.past),
- },
- };
+function getDynamicCompoundInfo(
+ entry: T.DictionaryEntryNoFVars,
+ comp: T.DictionaryEntryNoFVars,
+ forceSingular?: true
+): T.DynamicCompoundVerbInfo {
+ const transitivity = getTransitivity(entry);
+ const yulEnding = null;
+ const objComplement = getObjComplementInfo(entry, comp, forceSingular);
+ const auxVerb = getDynamicAuxVerb(entry);
+ const auxVerbInfo = getVerbInfo(
+ auxVerb.entry,
+ auxVerb.complement
+ ) as T.NonComboVerbInfo;
+ const compUsed = objComplement.plural
+ ? objComplement.plural
+ : objComplement.entry;
+ const bases: Bases =
+ auxVerbInfo.type === "stative compound"
+ ? getObjectMatchingBases(auxVerbInfo, objComplement.person)
+ : {
+ stem: {
+ imperfective: auxVerbInfo.stem.imperfective,
+ perfective: auxVerbInfo.stem.perfective,
+ ...(auxVerbInfo.stem.perfectiveSplit
+ ? {
+ perfectiveSplit: auxVerbInfo.stem.perfectiveSplit,
+ }
+ : {}),
+ },
+ root: {
+ imperfective: auxVerbInfo.root.imperfective,
+ perfective: auxVerbInfo.root.perfective,
+ ...(auxVerbInfo.root.perfectiveSplit
+ ? {
+ perfectiveSplit: auxVerbInfo.root.perfectiveSplit,
+ }
+ : {}),
+ },
+ participle: {
+ present: auxVerbInfo.participle.present,
+ past: chooseParticipleInflection(
+ inflectYey(
+ "mascSing" in auxVerbInfo.participle.past
+ ? // purely for type saftey, will not have mascSing
+ // in a non stative compound verb
+ /* istanbul ignore next */
+ auxVerbInfo.participle.past.mascSing
+ : auxVerbInfo.participle.past
+ ),
+ objComplement.person
+ ),
+ },
+ };
+ const stem = {
+ imperfective: concatPsString(compUsed, " ", bases.stem.imperfective),
+ perfective: concatPsString(compUsed, " ", bases.stem.perfective),
+ ...(bases.stem.perfectiveSplit
+ ? {
+ perfectiveSplit: makeDynamicPerfectiveSplit(
+ compUsed,
+ bases.stem.perfectiveSplit
+ ),
+ }
+ : {}),
+ };
+ const root = {
+ imperfective: concatPsString(
+ compUsed,
+ " ",
+ bases.root.imperfective
+ ) as T.OptionalPersonInflections>,
+ perfective: concatPsString(
+ compUsed,
+ " ",
+ bases.root.perfective
+ ) as T.OptionalPersonInflections>,
+ ...(bases.root.perfectiveSplit
+ ? {
+ perfectiveSplit: makeDynamicPerfectiveSplit(
+ compUsed,
+ bases.root.perfectiveSplit
+ ),
+ }
+ : {}),
+ };
+ const participle = {
+ present: concatPsString(compUsed, " ", auxVerbInfo.participle.present),
+ past: concatPsString(compUsed, " ", bases.participle.past),
+ };
+ const makeIntransitiveFormOfEntry = (
+ e: T.DictionaryEntryNoFVars
+ ): T.DictionaryEntryNoFVars => ({
+ ...e,
+ p: e.p.replace("کول", "کېدل"),
+ e: e.e.replace("to do", "to become"),
+ f: e.f.replace(/kaw[u|ú]l/, "kedul"),
+ c: "v. intrans. dyn. comp.",
+ });
+ const intransitiveFormEntry =
+ transitivity === "transitive" && auxVerb.entry.p === "کول"
+ ? makeIntransitiveFormOfEntry(entry)
+ : null;
+ return {
+ entry: {
+ // TODO: cleanup the type safety with the DictionaryNoFVars messing things up etc
+ entry: entry as unknown as T.VerbDictionaryEntry,
+ complement: comp,
+ },
+ type: "dynamic compound",
+ transitivity,
+ yulEnding,
+ stem,
+ root,
+ participle,
+ objComplement,
+ auxVerb: auxVerb.entry,
+ ...(auxVerb.complement
+ ? {
+ auxVerbComplement: auxVerb.complement,
+ }
+ : {}),
+ ...(objComplement.plural
+ ? {
+ singularForm: getDynamicCompoundInfo(entry, comp, true),
+ }
+ : {}),
+ ...(intransitiveFormEntry
+ ? {
+ intransitiveForm: getDynamicCompoundInfo(intransitiveFormEntry, comp),
+ }
+ : {}),
+ };
+}
+
+function getObjectMatchingBases(
+ auxInfo: T.NonComboVerbInfo,
+ person: T.Person
+): Bases {
+ const key = getPersonInflectionsKey(person);
+ const getBase = (
+ x: T.FullForm
+ ): T.SingleOrLengthOpts => ("mascSing" in x ? x[key] : x);
+ return {
+ stem: {
+ imperfective: getBase(auxInfo.stem.imperfective),
+ perfective: getBase(auxInfo.stem.perfective),
+ ...(auxInfo.stem.perfectiveSplit
+ ? {
+ perfectiveSplit: choosePersInf(auxInfo.stem.perfectiveSplit, key),
+ }
+ : {}),
+ },
+ root: {
+ imperfective: getBase(auxInfo.root.imperfective),
+ perfective: getBase(auxInfo.root.perfective),
+ ...(auxInfo.root.perfectiveSplit
+ ? {
+ perfectiveSplit: choosePersInf(auxInfo.root.perfectiveSplit, key),
+ }
+ : {}),
+ },
+ participle: {
+ present: getBase(auxInfo.participle.present),
+ past: getBase(auxInfo.participle.past),
+ },
+ };
}
function getObjComplementInfo(
- entry: T.DictionaryEntryNoFVars,
- complement: T.DictionaryEntryNoFVars,
- forceSingular?: true
+ entry: T.DictionaryEntryNoFVars,
+ complement: T.DictionaryEntryNoFVars,
+ forceSingular?: true
): T.ObjComplement {
- const complementInEntry = makePsString(
- entry.p.split(" ")[0],
- entry.f.split(" ")[0],
- );
- const usesSeperatePluralForm = !forceSingular && !psStringEquals(
- makePsString(complementInEntry.p, removeAccents(complementInEntry.f)),
- makePsString(complement.p, removeAccents(complement.f)),
+ const complementInEntry = makePsString(
+ entry.p.split(" ")[0],
+ entry.f.split(" ")[0]
+ );
+ const usesSeperatePluralForm =
+ !forceSingular &&
+ !psStringEquals(
+ makePsString(complementInEntry.p, removeAccents(complementInEntry.f)),
+ makePsString(complement.p, removeAccents(complement.f))
);
+ return {
+ entry: complement,
+ ...(usesSeperatePluralForm
+ ? {
+ plural: complementInEntry,
+ }
+ : {}),
+ person: getComplementPerson(complement, usesSeperatePluralForm),
+ };
+}
+
+export function getTransitivity(
+ entry: T.DictionaryEntryNoFVars
+): T.Transitivity {
+ if (!entry.c) {
+ throw new Error("No part of speech info");
+ }
+ if (entry.c.includes("gramm. trans.")) {
+ return "grammatically transitive";
+ }
+ if (entry.c.includes("intrans.")) {
+ return "intransitive";
+ }
+ return "transitive";
+}
+
+function getType(
+ entry: T.DictionaryEntry
+):
+ | "simple"
+ | "stative compound"
+ | "dynamic compound"
+ | "dynamic or stative compound"
+ | "dynamic or generative stative compound"
+ | "generative stative compound"
+ | "transitive or grammatically transitive simple" {
+ // error will have thrown before on the getTransitivity function if missing entry.c
+ /* istanbul ignore if */
+ if (!entry.c) {
+ throw new Error("No part of speech info");
+ }
+ if (entry.c.includes(" trans./gramm. trans.")) {
+ return "transitive or grammatically transitive simple";
+ }
+ if (entry.c.includes(" gen. stat. comp.")) {
+ return "generative stative compound";
+ }
+ if (entry.c.includes(" stat. comp.")) {
+ return "stative compound";
+ }
+ if (entry.c.includes(" dyn. comp.")) {
+ return "dynamic compound";
+ }
+ if (entry.c.includes(" dyn./stat. comp.")) {
+ return "dynamic or stative compound";
+ }
+ if (entry.c.includes(" gen. stat./dyn. comp.")) {
+ return "dynamic or generative stative compound";
+ }
+ return "simple";
+}
+
+function getIdiosyncraticThirdMascSing(
+ entry: T.DictionaryEntryNoFVars
+): T.ShortThirdPersFormSet | false {
+ if (entry.tppp && entry.tppf) {
+ const tpp = makePsString(entry.tppp, entry.tppf);
+ const ooRes = addOoPrefix(tpp, entry);
return {
- entry: complement,
- ...usesSeperatePluralForm ? {
- plural: complementInEntry,
- } : {},
- person: getComplementPerson(complement, usesSeperatePluralForm),
+ imperfective: tpp,
+ perfective: ooRes.ps as T.PsString,
};
-}
-
-function getTransitivity(entry: T.DictionaryEntryNoFVars): T.Transitivity {
- if (!entry.c) {
- throw new Error("No part of speech info");
+ }
+ if (entry.p === "کول") {
+ if (entry.e.includes("to make")) {
+ return {
+ perfective: { p: "کړ", f: "kuR" },
+ imperfective: { p: "کاوه", f: "kaawú" },
+ };
}
- if (entry.c.includes("gramm. trans.")) {
- return "grammatically transitive";
+ if (entry.e.includes("to do")) {
+ return {
+ perfective: { p: "وکړ", f: "óokuR" },
+ imperfective: { p: "کاوه", f: "kaawú" },
+ };
}
- if (entry.c.includes("intrans.")) {
- return "intransitive";
- }
- return "transitive";
-}
-
-function getType(entry: T.DictionaryEntry):
- "simple" | "stative compound" | "dynamic compound" |
- "dynamic or stative compound" | "dynamic or generative stative compound" |
- "generative stative compound" | "transitive or grammatically transitive simple"
-{
- // error will have thrown before on the getTransitivity function if missing entry.c
- /* istanbul ignore if */
- if (!entry.c) {
- throw new Error("No part of speech info");
- }
- if (entry.c.includes(" trans./gramm. trans.")) {
- return "transitive or grammatically transitive simple";
- }
- if (entry.c.includes(" gen. stat. comp.")) {
- return "generative stative compound";
- }
- if (entry.c.includes(" stat. comp.")) {
- return "stative compound";
- }
- if (entry.c.includes(" dyn. comp.")) {
- return "dynamic compound";
- }
- if (entry.c.includes(" dyn./stat. comp.")) {
- return "dynamic or stative compound";
- }
- if (entry.c.includes(" gen. stat./dyn. comp.")) {
- return "dynamic or generative stative compound";
- }
- return "simple";
-}
-
-function getIdiosyncraticThirdMascSing(entry: T.DictionaryEntryNoFVars): T.ShortThirdPersFormSet | false {
- if (entry.tppp && entry.tppf) {
- const tpp = makePsString(entry.tppp, entry.tppf);
- const ooRes = addOoPrefix(tpp, entry)
- return {
- imperfective: tpp,
- perfective: ooRes.ps as T.PsString,
- };
- }
- if (entry.p === "کول") {
- if (entry.e.includes("to make")) {
- return {
- perfective: { p: "کړ", f: "kuR" },
- imperfective: { p: "کاوه", f: "kaawú" },
- };
- }
- if (entry.e.includes("to do")) {
- return {
- perfective: { p: "وکړ", f: "óokuR" },
- imperfective: { p: "کاوه", f: "kaawú" },
- };
- }
- }
- return false;
+ }
+ return false;
}
/**
* Returns the roots (imperfective and perfective) of a given verb
- *
+ *
* @param entry - the dictionary entry for the verb
*/
-function getVerbRoots(entry: T.DictionaryEntryNoFVars, transitivity: T.Transitivity, complement?: T.UnisexInflections): T.VerbRootSet {
- // each of the roots compes with a short and long version
- // with or without the ending ل - ul
- const isKawulAux = entry.p === "کول";
- const shortAndLong = (root: T.PsString, perfective?: "perfective"): T.LengthOptions => {
- const long = perfective ? root : accentOnNFromEnd(root, yulEndingInfinitive(root) ? 1 : 0);
- const short = removeEndingL(root);
- return {
- long,
- short,
- ...(isKawulAux && perfective) ? {
- mini: removeRetroflexR(short)
- } : {},
- };
- };
- const infinitive = makePsString(entry.p, entry.f);
-
- // the imperfective root is the infinitive
- // TODO: CHECK THIS!! FOR PERSON INFLECTIONS??
- const imperfective = ((): T.OptionalPersonInflections> => {
- // if stative compound
- if (complement && spaceInForm(entry)) {
- const comp = complementInflects(complement) ? unisexInfToObjectMatrix(complement) : complement.masc[0][0];
- const t = getAuxTransitivity(transitivity);
- const aux = stativeAux[t].info.root.imperfective
- return concatPsString(removeAccentsFull(comp), " ", aux) as T.OptionalPersonInflections>;
- }
- return shortAndLong(entry);
- })();
-
- const { perfective, pSplit, fSplit } = ((): {
- perfective: T.OptionalPersonInflections>
- pSplit: number,
- fSplit: number,
- } => {
- // if stative compound
- if (complement) {
- const comp = complementInflects(complement) ? unisexInfToObjectMatrix(complement) : complement.masc[0][0];
- const t = getAuxTransitivity(transitivity);
- const aux = stativeAux[t].info.root.perfective
- return {
- pSplit: 0,
- fSplit: 0,
- perfective: concatPsString(comp, " ", aux) as T.OptionalPersonInflections>,
- };
- }
- // the perfective root is
- // - the special perfective root if it exists, or
- if (entry.prp && entry.prf) {
- const perfective = shortAndLong(makePsString(entry.prp, entry.prf), "perfective");
- const hasOoPrefix = checkForOoPrefix(perfective.long);
- return {
- perfective,
- pSplit: entry.separationAtP || (hasOoPrefix ? 1 : 0),
- fSplit: entry.separationAtF || (hasOoPrefix ? 2 : 0),
- };
- }
- // - the infinitive prefixed with oo
- const { ps, pSplit, fSplit } = addOoPrefix(infinitive, entry);
- return {
- perfective: shortAndLong(ps as T.PsString, "perfective"),
- pSplit,
- fSplit,
- };
- })();
-
- const perfectiveSplit = splitPerfective(perfective, pSplit, fSplit, !!complement);
+function getVerbRoots(
+ entry: T.DictionaryEntryNoFVars,
+ transitivity: T.Transitivity,
+ complement?: T.UnisexInflections
+): T.VerbRootSet {
+ // each of the roots compes with a short and long version
+ // with or without the ending ل - ul
+ const isKawulAux = entry.p === "کول";
+ const shortAndLong = (
+ root: T.PsString,
+ perfective?: "perfective"
+ ): T.LengthOptions => {
+ const long = perfective
+ ? root
+ : accentOnNFromEnd(root, yulEndingInfinitive(root) ? 1 : 0);
+ const short = removeEndingL(root);
return {
- imperfective,
- perfective,
- perfectiveSplit,
+ long,
+ short,
+ ...(isKawulAux && perfective
+ ? {
+ mini: removeRetroflexR(short),
+ }
+ : {}),
};
+ };
+ const infinitive = makePsString(entry.p, entry.f);
+
+ // the imperfective root is the infinitive
+ // TODO: CHECK THIS!! FOR PERSON INFLECTIONS??
+ const imperfective = ((): T.OptionalPersonInflections<
+ T.LengthOptions
+ > => {
+ // if stative compound
+ if (complement && spaceInForm(entry)) {
+ const comp = complementInflects(complement)
+ ? unisexInfToObjectMatrix(complement)
+ : complement.masc[0][0];
+ const t = getAuxTransitivity(transitivity);
+ const aux = stativeAux[t].info.root.imperfective;
+ return concatPsString(
+ removeAccentsFull(comp),
+ " ",
+ aux
+ ) as T.OptionalPersonInflections>;
+ }
+ return shortAndLong(entry);
+ })();
+
+ const { perfective, pSplit, fSplit } = ((): {
+ perfective: T.OptionalPersonInflections>;
+ pSplit: number;
+ fSplit: number;
+ } => {
+ // if stative compound
+ if (complement) {
+ const comp = complementInflects(complement)
+ ? unisexInfToObjectMatrix(complement)
+ : complement.masc[0][0];
+ const t = getAuxTransitivity(transitivity);
+ const aux = stativeAux[t].info.root.perfective;
+ return {
+ pSplit: 0,
+ fSplit: 0,
+ perfective: concatPsString(
+ comp,
+ " ",
+ aux
+ ) as T.OptionalPersonInflections>,
+ };
+ }
+ // the perfective root is
+ // - the special perfective root if it exists, or
+ if (entry.prp && entry.prf) {
+ const perfective = shortAndLong(
+ makePsString(entry.prp, entry.prf),
+ "perfective"
+ );
+ const hasOoPrefix = checkForOoPrefix(perfective.long);
+ return {
+ perfective,
+ pSplit: entry.separationAtP || (hasOoPrefix ? 1 : 0),
+ fSplit: entry.separationAtF || (hasOoPrefix ? 2 : 0),
+ };
+ }
+ // - the infinitive prefixed with oo
+ const { ps, pSplit, fSplit } = addOoPrefix(infinitive, entry);
+ return {
+ perfective: shortAndLong(ps as T.PsString, "perfective"),
+ pSplit,
+ fSplit,
+ };
+ })();
+
+ const perfectiveSplit = splitPerfective(
+ perfective,
+ pSplit,
+ fSplit,
+ !!complement
+ );
+ return {
+ imperfective,
+ perfective,
+ perfectiveSplit,
+ };
}
-function removeAccentsFull(p: T.OptionalPersonInflections): T.OptionalPersonInflections {
- if ("mascPlur" in p) {
- return {
- "mascSing": removeAccents(p.mascSing),
- "mascPlur": removeAccents(p.mascPlur),
- "femSing": removeAccents(p.femSing),
- "femPlur": removeAccents(p.femPlur),
- }
+function removeAccentsFull(
+ p: T.OptionalPersonInflections
+): T.OptionalPersonInflections {
+ if ("mascPlur" in p) {
+ return {
+ mascSing: removeAccents(p.mascSing),
+ mascPlur: removeAccents(p.mascPlur),
+ femSing: removeAccents(p.femSing),
+ femPlur: removeAccents(p.femPlur),
};
- return removeAccents(p);
+ }
+ return removeAccents(p);
}
/**
* Returns the stems (imperfective and perfective) of a given verb
- *
+ *
* @param entry - the dictionary entry for the verb
*/
-function getVerbStems(entry: T.DictionaryEntryNoFVars, root: T.VerbRootSet, transitivity: T.Transitivity, complement?: T.UnisexInflections): T.VerbStemSet {
- function isRegEdulTransitive(): boolean {
- /* istanbul ignore next */
- if ("mascSing" in root.imperfective) {
- return false;
- }
- const lastPCharacters = root.imperfective.long.p.slice(-3);
- return (
- // @ts-ignore - will always have a entry.c if we get to this point
- (entry.c.includes("intrans."))
- && (lastPCharacters === "ېدل")
- );
+function getVerbStems(
+ entry: T.DictionaryEntryNoFVars,
+ root: T.VerbRootSet,
+ transitivity: T.Transitivity,
+ complement?: T.UnisexInflections
+): T.VerbStemSet {
+ function isRegEdulTransitive(): boolean {
+ /* istanbul ignore next */
+ if ("mascSing" in root.imperfective) {
+ return false;
}
- function makeIntransImperfectiveStem() {
- const long = {
- // @ts-ignore
- p: root.imperfective.long.p.slice(0, -2) + "ږ",
- // @ts-ignore
- f: root.imperfective.long.f.slice(0, -4) + "éG",
- };
- if (entry.shortIntrans) {
- const short = makePsString(
- long.p.slice(0, -2),
- long.f.slice(0, -2),
- );
- return { long, short };
- }
- return long;
- }
-
- const imperfective = ((): T.FullForm => {
- const auxTransitivity = getAuxTransitivity(transitivity);
- if (complement && spaceInForm(root.imperfective)) {
- const comp = complementInflects(complement) ? unisexInfToObjectMatrix(complement) : complement.masc[0][0];
- return concatPsString(
- removeAccentsFull(comp),
- " ",
- stativeAux[auxTransitivity].info.stem.imperfective as T.PsString,
- );
- }
- // the imperfective stem is
- // - the special present stem if it exists, or
- if (entry.psp && entry.psf) {
- return makePsString(entry.psp, entry.psf);
- }
- // - the eG form (and short form possibly) if regular transitive, or
- if (isRegEdulTransitive()) {
- return makeIntransImperfectiveStem()
- }
- // - the infinitive minus ل
- return "mascSing" in root.imperfective
- ? root.imperfective.mascSing.short
- : root.imperfective.short;
- })();
-
- const { perfective, pSplit, fSplit } = ((): { perfective: T.FullForm, pSplit: number, fSplit: number } => {
- if (complement) {
- const comp = complementInflects(complement) ? unisexInfToObjectMatrix(complement) : complement.masc[0][0];
- const t = getAuxTransitivity(transitivity);
- return {
- perfective: concatPsString(comp, " ", stativeAux[t].info.stem.perfective),
- pSplit: 0,
- fSplit: 0,
- };
- }
- // the perfective stem is
- // - the special subjunctive stem if it exists, or
- if (entry.ssp && entry.ssf) {
- const isKawulAux = entry.p === "کول";
- const perfective = makePsString(entry.ssp, entry.ssf);
- const hasOoPrefix = checkForOoPrefix(perfective);
- if (isKawulAux) {
- return {
- perfective: {
- long: perfective,
- short: removeRetroflexR(perfective),
- },
- pSplit: hasOoPrefix ? 1 : 0,
- fSplit: hasOoPrefix ? 2 : 0,
- };
- }
- return {
- perfective,
- pSplit: entry.separationAtP || (hasOoPrefix ? 1 : 0),
- fSplit: entry.separationAtF || (hasOoPrefix ? 2 : 0),
- };
- }
- // - the perfective stem prefixed with oo (if possible)
- const res = addOoPrefix(imperfective as T.SingleOrLengthOpts, entry);
- return {
- perfective: res.ps,
- pSplit: res.pSplit,
- fSplit: res.fSplit,
- };
- })();
-
- const perfectiveSplit = splitPerfective(perfective, pSplit, fSplit, !!complement);
- return {
- imperfective,
- perfective,
- ...perfectiveSplit ? {
- perfectiveSplit,
- } : {},
- };
-}
-
-function splitPerfective(perfective: T.FullForm, pSplit: number, fSplit: number, isStativeComp: boolean): T.SplitInfo | undefined {
- if (!isStativeComp && pSplit === 0 && fSplit === 0) {
- return undefined;
- }
- if ("mascSing" in perfective) {
- // @ts-ignore
- return {
- mascSing: splitPerfective(perfective.mascSing, pSplit, fSplit, isStativeComp),
- mascPlur: splitPerfective(perfective.mascPlur, pSplit, fSplit, isStativeComp),
- femSing: splitPerfective(perfective.femSing, pSplit, fSplit, isStativeComp),
- femPlur: splitPerfective(perfective.femPlur, pSplit, fSplit, isStativeComp),
- };
- }
- if ("long" in perfective) {
- return {
- // @ts-ignore
- short: splitPerfective(perfective.short, pSplit, fSplit, isStativeComp) as [T.PsString, T.PsString],
- long: splitPerfective(perfective.long, pSplit, fSplit, isStativeComp) as [T.PsString, T.PsString],
- ..."mini" in perfective ? {
- // @ts-ignore
- mini: splitPerfective(perfective.mini, pSplit, fSplit, isStativeComp) as [T.PsString, T.PsString],
- } : {},
- };
- }
- if (isStativeComp) {
- // if it's a stative, split whatever is before the aux verb with a trailing space
- const pWords = perfective.p.split(" ");
- const fWords = perfective.f.split(" ");
- const before = makePsString(
- pWords.slice(0, -1).join(" ") + " ",
- fWords.slice(0, -1).join(" ") + " ",
- );
- const after = makePsString(
- pWords[pWords.length - 1],
- fWords[fWords.length - 1],
- );
- return [before, after];
- }
- const pBeg = perfective.p.slice(0, pSplit);
- const before = makePsString(
- pBeg.endsWith(" ") ? pBeg.slice(0, -1) : pBeg,
- perfective.f.slice(0, fSplit).replace("`", ""),
+ const lastPCharacters = root.imperfective.long.p.slice(-3);
+ return (
+ // @ts-ignore - will always have a entry.c if we get to this point
+ entry.c.includes("intrans.") && lastPCharacters === "ېدل"
);
- const beforeAccented = beginsWithDirectionalPronoun(before)
- ? before
- : accentOnFront(before);
- const after = makePsString(perfective.p.slice(pSplit), removeAccents(removeStartingTick(perfective.f.slice(fSplit))));
- return [beforeAccented, after] as T.SplitInfo;
-}
-
-function getParticiple(entry: T.DictionaryEntryNoFVars, stem: T.VerbStemSet, infinitive: T.PsString, transitivity: T.Transitivity, complement?: T.UnisexInflections): T.ParticipleSet {
- const shortParticipleRoot = ((): T.PsString | null => {
- const shortenableEndings = ["ښتل", "ستل", "وتل"];
- // special thing for اېښودل - پرېښودل
- if (infinitive.p.slice(-4) === "ښودل" && infinitive.p.length > 4 && infinitive.p !== "کېښودل" && infinitive.p !== "کښېښودل") {
- return makePsString(
- infinitive.p.slice(0, -3),
- infinitive.f.slice(0, -4),
- );
- }
- const isOrulShortenable = ["وړل", "راوړل", "وروړل"].includes(infinitive.p);
- if (isOrulShortenable || (shortenableEndings.includes(infinitive.p.slice(-3)) && infinitive.p.slice(-4) !== "استل")) {
- return makePsString(
- infinitive.p.slice(0, -1),
- infinitive.f.slice(0, -2),
- )
- }
- return null;
- })();
-
- const makeSepStativePart = (complement: T.UnisexInflections, tense: "present" | "past"): T.FullForm => {
- const compInflects = complementInflects(complement);
- const comp = compInflects ? unisexInfToObjectMatrix(complement) : complement.masc[0][0];
- const aux = stativeAux[auxTransitivity].info.participle[tense] as T.PsString;
- return concatPsString(
- removeAccentsFull(comp),
- " ",
- compInflects
- ? unisexInfToObjectMatrix(inflectYey(aux) as T.UnisexInflections)
- : aux,
- );
+ }
+ function makeIntransImperfectiveStem() {
+ const long = {
+ // @ts-ignore
+ p: root.imperfective.long.p.slice(0, -2) + "ږ",
+ // @ts-ignore
+ f: root.imperfective.long.f.slice(0, -4) + "éG",
};
+ if (entry.shortIntrans) {
+ const short = makePsString(long.p.slice(0, -2), long.f.slice(0, -2));
+ return { long, short };
+ }
+ return long;
+ }
- const accentPastPart = (pp: T.PsString): T.PsString => (
- accentOnNFromEnd(pp, yulEndingInfinitive(infinitive) ? 2 : 1)
- );
+ const imperfective = ((): T.FullForm => {
const auxTransitivity = getAuxTransitivity(transitivity);
- const past = (entry.pprtp && entry.pprtf)
- ? makePsString(entry.pprtp, entry.pprtf)
- : complement
- ? makeSepStativePart(complement, "past")
- : shortParticipleRoot
- ? {
- short: accentPastPart(
- concatPsString(ensureShortWurShwaShift(shortParticipleRoot), eyEndingUnaccented),
- ),
- long: accentPastPart(
- concatPsString(infinitive, eyEndingUnaccented),
- ),
- }
- : accentPastPart(concatPsString(infinitive, eyEndingUnaccented));
+ if (complement && spaceInForm(root.imperfective)) {
+ const comp = complementInflects(complement)
+ ? unisexInfToObjectMatrix(complement)
+ : complement.masc[0][0];
+ return concatPsString(
+ removeAccentsFull(comp),
+ " ",
+ stativeAux[auxTransitivity].info.stem.imperfective as T.PsString
+ );
+ }
+ // the imperfective stem is
+ // - the special present stem if it exists, or
+ if (entry.psp && entry.psf) {
+ return makePsString(entry.psp, entry.psf);
+ }
+ // - the eG form (and short form possibly) if regular transitive, or
+ if (isRegEdulTransitive()) {
+ return makeIntransImperfectiveStem();
+ }
+ // - the infinitive minus ل
+ return "mascSing" in root.imperfective
+ ? root.imperfective.mascSing.short
+ : root.imperfective.short;
+ })();
- // TODO: make this into a rule?
- const shortImperfectiveRoot = (entry.p === "وتل") ? { p: "وتل", f: "watl" } : removeEndingL(infinitive);
- const accentPresPart = (pp: T.PsString): T.PsString => (
- accentOnNFromEnd(pp, 1)
+ const { perfective, pSplit, fSplit } = ((): {
+ perfective: T.FullForm;
+ pSplit: number;
+ fSplit: number;
+ } => {
+ if (complement) {
+ const comp = complementInflects(complement)
+ ? unisexInfToObjectMatrix(complement)
+ : complement.masc[0][0];
+ const t = getAuxTransitivity(transitivity);
+ return {
+ perfective: concatPsString(
+ comp,
+ " ",
+ stativeAux[t].info.stem.perfective
+ ),
+ pSplit: 0,
+ fSplit: 0,
+ };
+ }
+ // the perfective stem is
+ // - the special subjunctive stem if it exists, or
+ if (entry.ssp && entry.ssf) {
+ const isKawulAux = entry.p === "کول";
+ const perfective = makePsString(entry.ssp, entry.ssf);
+ const hasOoPrefix = checkForOoPrefix(perfective);
+ if (isKawulAux) {
+ return {
+ perfective: {
+ long: perfective,
+ short: removeRetroflexR(perfective),
+ },
+ pSplit: hasOoPrefix ? 1 : 0,
+ fSplit: hasOoPrefix ? 2 : 0,
+ };
+ }
+ return {
+ perfective,
+ pSplit: entry.separationAtP || (hasOoPrefix ? 1 : 0),
+ fSplit: entry.separationAtF || (hasOoPrefix ? 2 : 0),
+ };
+ }
+ // - the perfective stem prefixed with oo (if possible)
+ const res = addOoPrefix(
+ imperfective as T.SingleOrLengthOpts,
+ entry
);
- const present = (complement && spaceInForm(infinitive))
- ? makeSepStativePart(complement, "present")
- : (shortParticipleRoot && (!psStringEquals(shortParticipleRoot, shortImperfectiveRoot) || (entry.p === "وتل")))
- ? {
- short: accentPresPart(
- concatPsString(shortParticipleRoot, presentParticipleSuffix),
- ),
- long: accentPresPart(
- concatPsString(shortImperfectiveRoot, presentParticipleSuffix),
- ),
+ return {
+ perfective: res.ps,
+ pSplit: res.pSplit,
+ fSplit: res.fSplit,
+ };
+ })();
+
+ const perfectiveSplit = splitPerfective(
+ perfective,
+ pSplit,
+ fSplit,
+ !!complement
+ );
+ return {
+ imperfective,
+ perfective,
+ ...(perfectiveSplit
+ ? {
+ perfectiveSplit,
}
- : ("short" in stem.imperfective && entry.shortIntrans && entry.p !== "اوسېدل")
+ : {}),
+ };
+}
+
+function splitPerfective(
+ perfective: T.FullForm,
+ pSplit: number,
+ fSplit: number,
+ isStativeComp: boolean
+): T.SplitInfo | undefined {
+ if (!isStativeComp && pSplit === 0 && fSplit === 0) {
+ return undefined;
+ }
+ if ("mascSing" in perfective) {
+ // @ts-ignore
+ return {
+ mascSing: splitPerfective(
+ perfective.mascSing,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ),
+ mascPlur: splitPerfective(
+ perfective.mascPlur,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ),
+ femSing: splitPerfective(
+ perfective.femSing,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ),
+ femPlur: splitPerfective(
+ perfective.femPlur,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ),
+ };
+ }
+ if ("long" in perfective) {
+ return {
+ // @ts-ignore
+ short: splitPerfective(
+ perfective.short,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ) as [T.PsString, T.PsString],
+ long: splitPerfective(perfective.long, pSplit, fSplit, isStativeComp) as [
+ T.PsString,
+ T.PsString
+ ],
+ ...("mini" in perfective
? {
- short: accentPresPart(
- concatPsString(stem.imperfective.short, presentParticipleSuffix),
- ),
- long: accentPresPart(
- concatPsString(shortImperfectiveRoot, presentParticipleSuffix),
- ),
- }
- : accentPresPart(
+ mini: splitPerfective(
+ // @ts-ignore
+ perfective.mini,
+ pSplit,
+ fSplit,
+ isStativeComp
+ ) as [T.PsString, T.PsString],
+ }
+ : {}),
+ };
+ }
+ if (isStativeComp) {
+ // if it's a stative, split whatever is before the aux verb with a trailing space
+ const pWords = perfective.p.split(" ");
+ const fWords = perfective.f.split(" ");
+ const before = makePsString(
+ pWords.slice(0, -1).join(" ") + " ",
+ fWords.slice(0, -1).join(" ") + " "
+ );
+ const after = makePsString(
+ pWords[pWords.length - 1],
+ fWords[fWords.length - 1]
+ );
+ return [before, after];
+ }
+ const pBeg = perfective.p.slice(0, pSplit);
+ const before = makePsString(
+ pBeg.endsWith(" ") ? pBeg.slice(0, -1) : pBeg,
+ perfective.f.slice(0, fSplit).replace("`", "")
+ );
+ const beforeAccented = beginsWithDirectionalPronoun(before)
+ ? before
+ : accentOnFront(before);
+ const after = makePsString(
+ perfective.p.slice(pSplit),
+ removeAccents(removeStartingTick(perfective.f.slice(fSplit)))
+ );
+ return [beforeAccented, after] as T.SplitInfo;
+}
+
+function getParticiple(
+ entry: T.DictionaryEntryNoFVars,
+ stem: T.VerbStemSet,
+ infinitive: T.PsString,
+ transitivity: T.Transitivity,
+ complement?: T.UnisexInflections
+): T.ParticipleSet {
+ const shortParticipleRoot = ((): T.PsString | null => {
+ const shortenableEndings = ["ښتل", "ستل", "وتل"];
+ // special thing for اېښودل - پرېښودل
+ if (
+ infinitive.p.slice(-4) === "ښودل" &&
+ infinitive.p.length > 4 &&
+ infinitive.p !== "کېښودل" &&
+ infinitive.p !== "کښېښودل"
+ ) {
+ return makePsString(infinitive.p.slice(0, -3), infinitive.f.slice(0, -4));
+ }
+ const isOrulShortenable = ["وړل", "راوړل", "وروړل"].includes(infinitive.p);
+ if (
+ isOrulShortenable ||
+ (shortenableEndings.includes(infinitive.p.slice(-3)) &&
+ infinitive.p.slice(-4) !== "استل")
+ ) {
+ return makePsString(infinitive.p.slice(0, -1), infinitive.f.slice(0, -2));
+ }
+ return null;
+ })();
+
+ const makeSepStativePart = (
+ complement: T.UnisexInflections,
+ tense: "present" | "past"
+ ): T.FullForm => {
+ const compInflects = complementInflects(complement);
+ const comp = compInflects
+ ? unisexInfToObjectMatrix(complement)
+ : complement.masc[0][0];
+ const aux = stativeAux[auxTransitivity].info.participle[
+ tense
+ ] as T.PsString;
+ return concatPsString(
+ removeAccentsFull(comp),
+ " ",
+ compInflects
+ ? unisexInfToObjectMatrix(inflectYey(aux) as T.UnisexInflections)
+ : aux
+ );
+ };
+
+ const accentPastPart = (pp: T.PsString): T.PsString =>
+ accentOnNFromEnd(pp, yulEndingInfinitive(infinitive) ? 2 : 1);
+ const auxTransitivity = getAuxTransitivity(transitivity);
+ const past =
+ entry.pprtp && entry.pprtf
+ ? makePsString(entry.pprtp, entry.pprtf)
+ : complement
+ ? makeSepStativePart(complement, "past")
+ : shortParticipleRoot
+ ? {
+ short: accentPastPart(
concatPsString(
- shortImperfectiveRoot.p === "وړ" ? ensureShortWurShwaShift(shortImperfectiveRoot) : shortImperfectiveRoot,
- presentParticipleSuffix,
- ),
+ ensureShortWurShwaShift(shortParticipleRoot),
+ eyEndingUnaccented
+ )
+ ),
+ long: accentPastPart(concatPsString(infinitive, eyEndingUnaccented)),
+ }
+ : accentPastPart(concatPsString(infinitive, eyEndingUnaccented));
+
+ // TODO: make this into a rule?
+ const shortImperfectiveRoot =
+ entry.p === "وتل" ? { p: "وتل", f: "watl" } : removeEndingL(infinitive);
+ const accentPresPart = (pp: T.PsString): T.PsString =>
+ accentOnNFromEnd(pp, 1);
+ const present =
+ complement && spaceInForm(infinitive)
+ ? makeSepStativePart(complement, "present")
+ : shortParticipleRoot &&
+ (!psStringEquals(shortParticipleRoot, shortImperfectiveRoot) ||
+ entry.p === "وتل")
+ ? {
+ short: accentPresPart(
+ concatPsString(shortParticipleRoot, presentParticipleSuffix)
+ ),
+ long: accentPresPart(
+ concatPsString(shortImperfectiveRoot, presentParticipleSuffix)
+ ),
+ }
+ : "short" in stem.imperfective &&
+ entry.shortIntrans &&
+ entry.p !== "اوسېدل"
+ ? {
+ short: accentPresPart(
+ concatPsString(stem.imperfective.short, presentParticipleSuffix)
+ ),
+ long: accentPresPart(
+ concatPsString(shortImperfectiveRoot, presentParticipleSuffix)
+ ),
+ }
+ : accentPresPart(
+ concatPsString(
+ shortImperfectiveRoot.p === "وړ"
+ ? ensureShortWurShwaShift(shortImperfectiveRoot)
+ : shortImperfectiveRoot,
+ presentParticipleSuffix
+ )
);
- return {
- past,
- present,
- };
+ return {
+ past,
+ present,
+ };
}
/**
* Adds a perfective و - oo prefix to a verb
- *
+ *
* @param entry - the dictionary entry for the verb
*/
function addOoPrefix(
- s: T.SingleOrLengthOpts,
- entry: T.DictionaryEntryNoFVars,
-): { ps: T.SingleOrLengthOpts, pSplit: number, fSplit: number } {
- let pSplit = 0;
- let fSplit = 0;
- // A bit of side effects in this function... sorry!
- function attachOo(ps: T.PsString): T.PsString;
- function attachOo(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts;
- function attachOo(ps: T.SingleOrLengthOpts): T.SingleOrLengthOpts {
- if ("long" in ps) {
- return {
- short: attachOo(ps.short),
- long: attachOo(ps.long),
- };
- }
- if (entry.separationAtP && entry.separationAtF) {
- pSplit = entry.separationAtP;
- fSplit = entry.separationAtF;
- return ps;
- }
- if (entry.noOo) {
- return ps;
- }
- if (entry.sepOo) {
- pSplit = 2;
- fSplit = 3;
- return {
- p: `و ${ps.p}`,
- f: `oo\`${ps.f}`,
- };
- }
- const startsWithA = ps.p.charAt(0) === "ا" && ps.f.charAt(0) === "a";
- if (startsWithA) {
- pSplit = 2;
- fSplit = 3;
- return {
- p: `و${ps.p}`,
- f: `wa${ps.f}`,
- };
- }
- const startsWithAa = ["آ", "ا"].includes(ps.p.charAt(0)) && ps.f.slice(0, 2) === "aa";
- if (startsWithAa) {
- pSplit = 2;
- fSplit = 3;
- return {
- p: `وا${ps.p.substr(1)}`,
- f: `w${ps.f}`,
- };
- }
- const startsWithOo = ["óo", "oo"].includes(ps.f.slice(0, 2));
- if (startsWithOo) {
- pSplit = 1;
- fSplit = 2;
- return {
- p: `و${ps.p}`,
- f: `wU${ps.f}`,
- };
- }
- const startsWithEe = ["ée", "ee"].includes(ps.f.slice(0, 2)) && ps.p.slice(0, 2) === "ای";
- const startsWithE = ["e", "é"].includes(ps.f[0]) && ps.p.slice(0, 2) === "اې";
- if (startsWithEe || startsWithE) {
- pSplit = 2;
- fSplit = startsWithEe ? 3 : 2;
- return {
- p: `و${ps.p.slice(1)}`,
- f: `w${ps.f}`,
- };
- }
- const startsWithO = ["ó", "o"].includes(ps.f[0]) && ps.p.slice(0, 2) === "او";
- if (startsWithO) {
- pSplit = 1;
- fSplit = 2;
- return {
- p: `و${ps.p}`,
- f: `oo\`${ps.f}`,
- };
- }
- pSplit = 1;
- fSplit = 2;
- return {
- p: `و${ps.p}`,
- f: `oo${ps.f}`,
- };
+ s: T.SingleOrLengthOpts,
+ entry: T.DictionaryEntryNoFVars
+): { ps: T.SingleOrLengthOpts; pSplit: number; fSplit: number } {
+ let pSplit = 0;
+ let fSplit = 0;
+ // A bit of side effects in this function... sorry!
+ function attachOo(ps: T.PsString): T.PsString;
+ function attachOo(
+ ps: T.SingleOrLengthOpts
+ ): T.SingleOrLengthOpts;
+ function attachOo(
+ ps: T.SingleOrLengthOpts
+ ): T.SingleOrLengthOpts {
+ if ("long" in ps) {
+ return {
+ short: attachOo(ps.short),
+ long: attachOo(ps.long),
+ };
}
- const attachedOo = attachOo(s);
+ if (entry.separationAtP && entry.separationAtF) {
+ pSplit = entry.separationAtP;
+ fSplit = entry.separationAtF;
+ return ps;
+ }
+ if (entry.noOo) {
+ return ps;
+ }
+ if (entry.sepOo) {
+ pSplit = 2;
+ fSplit = 3;
+ return {
+ p: `و ${ps.p}`,
+ f: `oo\`${ps.f}`,
+ };
+ }
+ const startsWithA = ps.p.charAt(0) === "ا" && ps.f.charAt(0) === "a";
+ if (startsWithA) {
+ pSplit = 2;
+ fSplit = 3;
+ return {
+ p: `و${ps.p}`,
+ f: `wa${ps.f}`,
+ };
+ }
+ const startsWithAa =
+ ["آ", "ا"].includes(ps.p.charAt(0)) && ps.f.slice(0, 2) === "aa";
+ if (startsWithAa) {
+ pSplit = 2;
+ fSplit = 3;
+ return {
+ p: `وا${ps.p.substr(1)}`,
+ f: `w${ps.f}`,
+ };
+ }
+ const startsWithOo = ["óo", "oo"].includes(ps.f.slice(0, 2));
+ if (startsWithOo) {
+ pSplit = 1;
+ fSplit = 2;
+ return {
+ p: `و${ps.p}`,
+ f: `wU${ps.f}`,
+ };
+ }
+ const startsWithEe =
+ ["ée", "ee"].includes(ps.f.slice(0, 2)) && ps.p.slice(0, 2) === "ای";
+ const startsWithE =
+ ["e", "é"].includes(ps.f[0]) && ps.p.slice(0, 2) === "اې";
+ if (startsWithEe || startsWithE) {
+ pSplit = 2;
+ fSplit = startsWithEe ? 3 : 2;
+ return {
+ p: `و${ps.p.slice(1)}`,
+ f: `w${ps.f}`,
+ };
+ }
+ const startsWithO =
+ ["ó", "o"].includes(ps.f[0]) && ps.p.slice(0, 2) === "او";
+ if (startsWithO) {
+ pSplit = 1;
+ fSplit = 2;
+ return {
+ p: `و${ps.p}`,
+ f: `oo\`${ps.f}`,
+ };
+ }
+ pSplit = 1;
+ fSplit = 2;
return {
- ps: accentOnFront(attachedOo),
- pSplit: entry.separationAtP ? entry.separationAtP : pSplit,
- fSplit: entry.separationAtF ? entry.separationAtF : fSplit,
+ p: `و${ps.p}`,
+ f: `oo${ps.f}`,
};
+ }
+ const attachedOo = attachOo(s);
+ return {
+ ps: accentOnFront(attachedOo),
+ pSplit: entry.separationAtP ? entry.separationAtP : pSplit,
+ fSplit: entry.separationAtF ? entry.separationAtF : fSplit,
+ };
}
-function ensureUnisexInf(complement: T.DictionaryEntryNoFVars): T.UnisexInflections {
- const inf = inflectWord(complement);
- if (inf !== false && !!inf.inflections && isUnisexSet(inf.inflections)) {
- return inf.inflections as T.UnisexInflections;
- }
- const word = makePsString(complement.p, complement.f);
- return {
- masc: [
- [word],
- [word],
- [word],
- ],
- fem: [
- [word],
- [word],
- [word],
- ],
- };
+function ensureUnisexInf(
+ complement: T.DictionaryEntryNoFVars
+): T.UnisexInflections {
+ const inf = inflectWord(complement);
+ if (inf !== false && !!inf.inflections && isUnisexSet(inf.inflections)) {
+ return inf.inflections as T.UnisexInflections;
+ }
+ const word = makePsString(complement.p, complement.f);
+ return {
+ masc: [[word], [word], [word]],
+ fem: [[word], [word], [word]],
+ };
}
function getDynamicAuxVerb(entry: T.DictionaryEntryNoFVars): {
- entry: T.DictionaryEntryNoFVars,
- complement?: T.DictionaryEntryNoFVars,
+ entry: T.DictionaryEntryNoFVars;
+ complement?: T.DictionaryEntryNoFVars;
} {
- const auxWord = entry.p.trim().split(" ").slice(-1)[0];
- const auxWordResult = dynamicAuxVerbs.find((a) => a.entry.p === auxWord);
- /* istanbul ignore next */
- if (!auxWordResult) {
- throw new Error("unknown auxilary verb for dynamic compound");
- }
- return {
- entry: removeFVarients(auxWordResult.entry),
- ...("complement" in auxWordResult) ? {
- complement: auxWordResult.complement ? removeFVarients(auxWordResult.complement) : undefined,
- } : {},
- };
+ const auxWord = entry.p.trim().split(" ").slice(-1)[0];
+ const auxWordResult = dynamicAuxVerbs.find((a) => a.entry.p === auxWord);
+ /* istanbul ignore next */
+ if (!auxWordResult) {
+ throw new Error("unknown auxilary verb for dynamic compound");
+ }
+ return {
+ entry: removeFVarients(auxWordResult.entry),
+ ...("complement" in auxWordResult
+ ? {
+ complement: auxWordResult.complement
+ ? removeFVarients(auxWordResult.complement)
+ : undefined,
+ }
+ : {}),
+ };
}
function getComplementPerson(
- complement: T.DictionaryEntryNoFVars,
- usesSeperatePluralForm?: boolean,
+ complement: T.DictionaryEntryNoFVars,
+ usesSeperatePluralForm?: boolean
): T.Person {
- const number = (
- (complement.c && complement.c.includes("pl.")) || usesSeperatePluralForm
- ) ? "plural" : "singular";
- const gender = (complement.c && complement.c.includes("n. m.")) ? "masc" : "fem";
- return getPersonNumber(gender, number);
+ const number =
+ (complement.c && complement.c.includes("pl.")) || usesSeperatePluralForm
+ ? "plural"
+ : "singular";
+ const gender =
+ complement.c && complement.c.includes("n. m.") ? "masc" : "fem";
+ return getPersonNumber(gender, number);
}
-function makeDynamicPerfectiveSplit(comp: T.PsString, auxSplit: T.SplitInfo): T.SplitInfo {
- if ("mascSing" in auxSplit) {
- return {
- mascSing: makeDynamicPerfectiveSplit(comp, auxSplit.mascSing) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- mascPlur: makeDynamicPerfectiveSplit(comp, auxSplit.mascPlur) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- femSing: makeDynamicPerfectiveSplit(comp, auxSplit.femSing) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- femPlur: makeDynamicPerfectiveSplit(comp, auxSplit.femPlur) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- };
- }
- if ("long" in auxSplit) {
- return {
- long: makeDynamicPerfectiveSplit(comp, auxSplit.long) as [T.PsString, T.PsString],
- short: makeDynamicPerfectiveSplit(comp, auxSplit.short) as [T.PsString, T.PsString],
- ...auxSplit.mini ? {
- mini: makeDynamicPerfectiveSplit(comp, auxSplit.mini) as [T.PsString, T.PsString],
- } : {},
- };
- }
- return [
- concatPsString(comp, " ", auxSplit[0]),
- auxSplit[1],
- ];
-}
-
-export function getAbilityRootsAndStems(info: T.NonComboVerbInfo): T.AbilityRootsAndStems {
- const isIntransitiveStativeCompound =
- (info.type === "stative compound" && info.transitivity === "intransitive")
- || isTlulVerb(info.entry);
- const roots = getAbilityRoots(info.root, isIntransitiveStativeCompound);
- return addAbilityHelperRootsAndStems(roots, isIntransitiveStativeCompound);
-}
-
-function addAbilityHelperRootsAndStems(roots: T.VerbRootSet, isIntransitiveStativeCompound: boolean): T.AbilityRootsAndStems {
- function addAbilityHelperToRoot(
- r: T.OptionalPersonInflections>,
- helper: T.PsString,
- ): T.OptionalPersonInflections> {
- if ("mascSing" in r) {
- return {
- mascSing: addAbilityHelperToRoot(r.mascSing, helper) as T.LengthOptions,
- mascPlur: addAbilityHelperToRoot(r.mascPlur, helper) as T.LengthOptions,
- femSing: addAbilityHelperToRoot(r.femSing, helper) as T.LengthOptions,
- femPlur: addAbilityHelperToRoot(r.femPlur, helper) as T.LengthOptions,
- }
- }
- return {
- long: concatPsString(r.long, " ", helper),
- short: concatPsString(r.short, " ", helper),
- };
- }
- const stemHelper = getLong(noPersInfs(kedulStat.info.stem.perfective));
- const rootHelper = noPersInfs(kedulStat.info.root.perfective).long;
+function makeDynamicPerfectiveSplit(
+ comp: T.PsString,
+ auxSplit: T.SplitInfo
+): T.SplitInfo {
+ if ("mascSing" in auxSplit) {
return {
- stem: {
- perfective: addAbilityHelperToRoot(roots.perfective, stemHelper),
- imperfective: addAbilityHelperToRoot(roots.imperfective, stemHelper),
- ...roots.perfectiveSplit ? {
- perfectiveSplit: addAbilityHelperToPerfectiveSplit(roots.perfectiveSplit, stemHelper),
- } : {},
- },
- root: {
- perfective: addAbilityHelperToRoot(roots.perfective, rootHelper),
- imperfective: addAbilityHelperToRoot(roots.imperfective, rootHelper),
- ...roots.perfectiveSplit ? {
- perfectiveSplit: addAbilityHelperToPerfectiveSplit(roots.perfectiveSplit, rootHelper),
- } : {},
- },
+ mascSing: makeDynamicPerfectiveSplit(
+ comp,
+ auxSplit.mascSing
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ mascPlur: makeDynamicPerfectiveSplit(
+ comp,
+ auxSplit.mascPlur
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ femSing: makeDynamicPerfectiveSplit(
+ comp,
+ auxSplit.femSing
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ femPlur: makeDynamicPerfectiveSplit(
+ comp,
+ auxSplit.femPlur
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
};
+ }
+ if ("long" in auxSplit) {
+ return {
+ long: makeDynamicPerfectiveSplit(comp, auxSplit.long) as [
+ T.PsString,
+ T.PsString
+ ],
+ short: makeDynamicPerfectiveSplit(comp, auxSplit.short) as [
+ T.PsString,
+ T.PsString
+ ],
+ ...(auxSplit.mini
+ ? {
+ mini: makeDynamicPerfectiveSplit(comp, auxSplit.mini) as [
+ T.PsString,
+ T.PsString
+ ],
+ }
+ : {}),
+ };
+ }
+ return [concatPsString(comp, " ", auxSplit[0]), auxSplit[1]];
}
-function addAbilityHelperToPerfectiveSplit(s: T.SplitInfo, helper: T.PsString): T.SplitInfo {
- if ("mascSing" in s) {
- return {
- mascSing: addAbilityHelperToPerfectiveSplit(s.mascSing, helper) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- mascPlur: addAbilityHelperToPerfectiveSplit(s.mascPlur, helper) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- femSing: addAbilityHelperToPerfectiveSplit(s.femSing, helper) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- femPlur: addAbilityHelperToPerfectiveSplit(s.femPlur, helper) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
- };
+export function getAbilityRootsAndStems(
+ info: T.NonComboVerbInfo
+): T.AbilityRootsAndStems {
+ const isIntransitiveStativeCompound =
+ (info.type === "stative compound" &&
+ info.transitivity === "intransitive") ||
+ isTlulVerb(info.entry);
+ const roots = getAbilityRoots(info.root, isIntransitiveStativeCompound);
+ return addAbilityHelperRootsAndStems(roots, isIntransitiveStativeCompound);
+}
+
+function addAbilityHelperRootsAndStems(
+ roots: T.VerbRootSet,
+ isIntransitiveStativeCompound: boolean
+): T.AbilityRootsAndStems {
+ function addAbilityHelperToRoot(
+ r: T.OptionalPersonInflections>,
+ helper: T.PsString
+ ): T.OptionalPersonInflections> {
+ if ("mascSing" in r) {
+ return {
+ mascSing: addAbilityHelperToRoot(
+ r.mascSing,
+ helper
+ ) as T.LengthOptions,
+ mascPlur: addAbilityHelperToRoot(
+ r.mascPlur,
+ helper
+ ) as T.LengthOptions,
+ femSing: addAbilityHelperToRoot(
+ r.femSing,
+ helper
+ ) as T.LengthOptions,
+ femPlur: addAbilityHelperToRoot(
+ r.femPlur,
+ helper
+ ) as T.LengthOptions,
+ };
}
return {
- long: [
- getLong(s)[0],
- concatPsString(getLong(s)[1], " ", helper),
- ],
- short: [
- getShort(s)[0],
- concatPsString(getShort(s)[1], " ", helper),
- ],
+ long: concatPsString(r.long, " ", helper),
+ short: concatPsString(r.short, " ", helper),
};
+ }
+ const stemHelper = getLong(noPersInfs(kedulStat.info.stem.perfective));
+ const rootHelper = noPersInfs(kedulStat.info.root.perfective).long;
+ return {
+ stem: {
+ perfective: addAbilityHelperToRoot(roots.perfective, stemHelper),
+ imperfective: addAbilityHelperToRoot(roots.imperfective, stemHelper),
+ ...(roots.perfectiveSplit
+ ? {
+ perfectiveSplit: addAbilityHelperToPerfectiveSplit(
+ roots.perfectiveSplit,
+ stemHelper
+ ),
+ }
+ : {}),
+ },
+ root: {
+ perfective: addAbilityHelperToRoot(roots.perfective, rootHelper),
+ imperfective: addAbilityHelperToRoot(roots.imperfective, rootHelper),
+ ...(roots.perfectiveSplit
+ ? {
+ perfectiveSplit: addAbilityHelperToPerfectiveSplit(
+ roots.perfectiveSplit,
+ rootHelper
+ ),
+ }
+ : {}),
+ },
+ };
}
-export function getPassiveRootsAndStems(info: T.NonComboVerbInfo, withTails?: boolean): T.PassiveRootsAndStems | undefined {
- if (info.transitivity === "intransitive") return undefined;
+function addAbilityHelperToPerfectiveSplit(
+ s: T.SplitInfo,
+ helper: T.PsString
+): T.SplitInfo {
+ if ("mascSing" in s) {
return {
- stem: getPassiveStem(info.root, info.root.perfectiveSplit, withTails),
- root: getPassiveRoot(info.root, info.root.perfectiveSplit, withTails),
- participle: {
- past: getPassivePastParticiple(info.root.imperfective, withTails),
- },
+ mascSing: addAbilityHelperToPerfectiveSplit(
+ s.mascSing,
+ helper
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ mascPlur: addAbilityHelperToPerfectiveSplit(
+ s.mascPlur,
+ helper
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ femSing: addAbilityHelperToPerfectiveSplit(
+ s.femSing,
+ helper
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
+ femPlur: addAbilityHelperToPerfectiveSplit(
+ s.femPlur,
+ helper
+ ) as T.SingleOrLengthOpts<[T.PsString, T.PsString]>,
};
+ }
+ return {
+ long: [getLong(s)[0], concatPsString(getLong(s)[1], " ", helper)],
+ short: [getShort(s)[0], concatPsString(getShort(s)[1], " ", helper)],
+ };
+}
+
+export function getPassiveRootsAndStems(
+ info: T.NonComboVerbInfo,
+ withTails?: boolean
+): T.PassiveRootsAndStems | undefined {
+ if (info.transitivity === "intransitive") return undefined;
+ return {
+ stem: getPassiveStem(info.root, info.root.perfectiveSplit, withTails),
+ root: getPassiveRoot(info.root, info.root.perfectiveSplit, withTails),
+ participle: {
+ past: getPassivePastParticiple(info.root.imperfective, withTails),
+ },
+ };
}
const passiveRootTail: T.PsString = { p: "ی", f: "ey" };
-function getPassiveStem(root: T.VerbRootSet, splitInfo: T.SplitInfo | undefined, withTails?: boolean): T.VerbStemSet {
- const perfectiveRoot = withTails ? concatPsString(root.perfective, passiveRootTail) : root.perfective;
- const imperfectiveRoot = withTails ? concatPsString(root.imperfective, passiveRootTail) : root.imperfective;
- return {
- perfective: getPassiveStemAspect(perfectiveRoot, "perfective"),
- imperfective: getPassiveStemAspect(imperfectiveRoot, "imperfective"),
- ...splitInfo ? {
- perfectiveSplit: getPassiveStemPerfectiveSplit(perfectiveRoot, splitInfo),
- } : {},
- };
-}
-
-function getPassiveStemPerfectiveSplit(stem: T.OptionalPersonInflections>, splitInfo: T.SplitInfo): T.SplitInfo {
- const si = "long" in splitInfo ? splitInfo.long : splitInfo;
- if ("mascSing" in si) {
- if (!("mascSing" in stem)) throw new Error("persInflections doesn't match perfective split");
- return {
- "mascSing": getPassiveStemPerfectiveSplit(stem.mascSing, si.mascSing) as [T.PsString, T.PsString],
- "mascPlur": getPassiveStemPerfectiveSplit(stem.mascPlur, si.mascPlur) as [T.PsString, T.PsString],
- "femSing": getPassiveStemPerfectiveSplit(stem.femSing, si.femSing) as [T.PsString, T.PsString],
- "femPlur": getPassiveStemPerfectiveSplit(stem.femPlur, si.femPlur) as [T.PsString, T.PsString],
+function getPassiveStem(
+ root: T.VerbRootSet,
+ splitInfo: T.SplitInfo | undefined,
+ withTails?: boolean
+): T.VerbStemSet {
+ const perfectiveRoot = withTails
+ ? concatPsString(root.perfective, passiveRootTail)
+ : root.perfective;
+ const imperfectiveRoot = withTails
+ ? concatPsString(root.imperfective, passiveRootTail)
+ : root.imperfective;
+ return {
+ perfective: getPassiveStemAspect(perfectiveRoot, "perfective"),
+ imperfective: getPassiveStemAspect(imperfectiveRoot, "imperfective"),
+ ...(splitInfo
+ ? {
+ perfectiveSplit: getPassiveStemPerfectiveSplit(
+ perfectiveRoot,
+ splitInfo
+ ),
}
- }
- return [
- si[0],
- // @ts-ignore
- concatPsString(si[1], " ", stativeAux.intransitive.info.stem.perfective),
- ];
+ : {}),
+ };
}
-function getPassiveRootPerfectiveSplit(root: T.OptionalPersonInflections>, splitInfo: T.SplitInfo): T.SplitInfo {
- const si = "long" in splitInfo ? splitInfo.long : splitInfo;
- if ("mascSing" in si) {
- if (!("mascSing" in root)) throw new Error("persInflections doesn't match perfective split");
- return {
- "mascSing": getPassiveRootPerfectiveSplit(root.mascSing, si.mascSing) as [T.PsString, T.PsString],
- "mascPlur": getPassiveRootPerfectiveSplit(root.mascPlur, si.mascPlur) as [T.PsString, T.PsString],
- "femSing": getPassiveRootPerfectiveSplit(root.femSing, si.femSing) as [T.PsString, T.PsString],
- "femPlur": getPassiveRootPerfectiveSplit(root.femPlur, si.femPlur) as [T.PsString, T.PsString],
- };
- }
+function getPassiveStemPerfectiveSplit(
+ stem: T.OptionalPersonInflections>,
+ splitInfo: T.SplitInfo
+): T.SplitInfo {
+ const si = "long" in splitInfo ? splitInfo.long : splitInfo;
+ if ("mascSing" in si) {
+ if (!("mascSing" in stem))
+ throw new Error("persInflections doesn't match perfective split");
return {
- short: [
- si[0],
- // @ts-ignore
- concatPsString(si[1], " ", stativeAux.intransitive.info.root.perfective.short),
- ],
- long: [
- si[0],
- // @ts-ignore
- concatPsString(si[1], " ", stativeAux.intransitive.info.root.perfective.long),
- ],
+ mascSing: getPassiveStemPerfectiveSplit(stem.mascSing, si.mascSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ mascPlur: getPassiveStemPerfectiveSplit(stem.mascPlur, si.mascPlur) as [
+ T.PsString,
+ T.PsString
+ ],
+ femSing: getPassiveStemPerfectiveSplit(stem.femSing, si.femSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ femPlur: getPassiveStemPerfectiveSplit(stem.femPlur, si.femPlur) as [
+ T.PsString,
+ T.PsString
+ ],
};
+ }
+ return [
+ si[0],
+ // @ts-ignore
+ concatPsString(si[1], " ", stativeAux.intransitive.info.stem.perfective),
+ ];
+}
+
+function getPassiveRootPerfectiveSplit(
+ root: T.OptionalPersonInflections>,
+ splitInfo: T.SplitInfo
+): T.SplitInfo {
+ const si = "long" in splitInfo ? splitInfo.long : splitInfo;
+ if ("mascSing" in si) {
+ if (!("mascSing" in root))
+ throw new Error("persInflections doesn't match perfective split");
+ return {
+ mascSing: getPassiveRootPerfectiveSplit(root.mascSing, si.mascSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ mascPlur: getPassiveRootPerfectiveSplit(root.mascPlur, si.mascPlur) as [
+ T.PsString,
+ T.PsString
+ ],
+ femSing: getPassiveRootPerfectiveSplit(root.femSing, si.femSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ femPlur: getPassiveRootPerfectiveSplit(root.femPlur, si.femPlur) as [
+ T.PsString,
+ T.PsString
+ ],
+ };
+ }
+ return {
+ short: [
+ si[0],
+ concatPsString(
+ si[1],
+ " ",
+ // @ts-ignore
+ stativeAux.intransitive.info.root.perfective.short
+ ),
+ ],
+ long: [
+ si[0],
+ concatPsString(
+ si[1],
+ " ",
+ // @ts-ignore
+ stativeAux.intransitive.info.root.perfective.long
+ ),
+ ],
+ };
}
const abilityTail = { p: "ی", f: "ey" };
const abilityTailAccented = { p: "ی", f: "éy" };
-function getAbilityRoots(root: T.VerbRootSet, isIntransitiveStativeCompound: boolean): T.VerbRootSet {
- function getAspectAbilityRoot(root: T.VerbRootSet[T.Aspect], aspect: T.Aspect): T.OptionalPersonInflections> {
- if ("mascSing" in root) {
- return {
- mascSing: getAspectAbilityRoot(root.mascSing, aspect) as T.LengthOptions,
- mascPlur: getAspectAbilityRoot(root.mascPlur, aspect) as T.LengthOptions,
- femSing: getAspectAbilityRoot(root.femSing, aspect) as T.LengthOptions,
- femPlur: getAspectAbilityRoot(root.femPlur, aspect) as T.LengthOptions,
- };
- }
- return {
- long: concatPsString(root.long, abilityTail) as T.PsString,
- short: concatPsString(root.short, aspect === "imperfective" ? abilityTailAccented : abilityTail) as T.PsString,
- }
- }
- function getAbilityRootPerfectiveSplit(s: T.SplitInfo): T.SplitInfo {
- if ("mascSing" in s) {
- return {
- mascSing: getAbilityRootPerfectiveSplit(s.mascSing) as [T.PsString, T.PsString],
- mascPlur: getAbilityRootPerfectiveSplit(s.mascPlur) as [T.PsString, T.PsString],
- femSing: getAbilityRootPerfectiveSplit(s.femSing) as [T.PsString, T.PsString],
- femPlur: getAbilityRootPerfectiveSplit(s.femPlur) as [T.PsString, T.PsString],
- };
- }
- return {
- long: [getLong(s)[0], concatPsString(getLong(s)[1], abilityTail)],
- short: [getShort(s)[0], concatPsString(getShort(s)[1], abilityTail)],
- }
- }
- return {
- perfective: getAspectAbilityRoot(
- !isIntransitiveStativeCompound ? root.perfective : root.imperfective,
- !isIntransitiveStativeCompound ? "perfective" : "imperfective",
- ),
- imperfective: getAspectAbilityRoot(root.imperfective, "imperfective"),
- ...(root.perfectiveSplit && !isIntransitiveStativeCompound) ? {
- perfectiveSplit: getAbilityRootPerfectiveSplit(root.perfectiveSplit),
- } : {},
- };
-}
-
-function getPassiveRoot(root: T.VerbRootSet, splitInfo: T.SplitInfo | undefined, withTails?: boolean): T.VerbRootSet {
- const perfectiveRoot = withTails ? concatPsString(root.perfective, passiveRootTail) : root.perfective;
- const imperfectiveRoot = withTails ? concatPsString(root.imperfective, passiveRootTail) : root.imperfective;
- return {
- perfective: getPassiveRootAspect(perfectiveRoot, "perfective"),
- imperfective: getPassiveRootAspect(imperfectiveRoot, "imperfective"),
- ...splitInfo ? {
- perfectiveSplit: getPassiveRootPerfectiveSplit(perfectiveRoot, splitInfo),
- } : {},
- };
-}
-
-function getPassivePastParticiple(root: T.OptionalPersonInflections>, withTails?: boolean): T.OptionalPersonInflections> {
+function getAbilityRoots(
+ root: T.VerbRootSet,
+ isIntransitiveStativeCompound: boolean
+): T.VerbRootSet {
+ function getAspectAbilityRoot(
+ root: T.VerbRootSet[T.Aspect],
+ aspect: T.Aspect
+ ): T.OptionalPersonInflections> {
if ("mascSing" in root) {
- return {
- "mascSing": getPassivePastParticiple(root.mascSing) as T.LengthOptions,
- "mascPlur": getPassivePastParticiple(root.mascPlur) as T.LengthOptions,
- "femSing": getPassivePastParticiple(root.femPlur) as T.LengthOptions,
- "femPlur": getPassivePastParticiple(root.femPlur) as T.LengthOptions,
- };
+ return {
+ mascSing: getAspectAbilityRoot(
+ root.mascSing,
+ aspect
+ ) as T.LengthOptions,
+ mascPlur: getAspectAbilityRoot(
+ root.mascPlur,
+ aspect
+ ) as T.LengthOptions,
+ femSing: getAspectAbilityRoot(
+ root.femSing,
+ aspect
+ ) as T.LengthOptions,
+ femPlur: getAspectAbilityRoot(
+ root.femPlur,
+ aspect
+ ) as T.LengthOptions,
+ };
}
- const r = withTails ? concatPsString(root, passiveRootTail) : root;
+ return {
+ long: concatPsString(root.long, abilityTail) as T.PsString,
+ short: concatPsString(
+ root.short,
+ aspect === "imperfective" ? abilityTailAccented : abilityTail
+ ) as T.PsString,
+ };
+ }
+ function getAbilityRootPerfectiveSplit(s: T.SplitInfo): T.SplitInfo {
+ if ("mascSing" in s) {
+ return {
+ mascSing: getAbilityRootPerfectiveSplit(s.mascSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ mascPlur: getAbilityRootPerfectiveSplit(s.mascPlur) as [
+ T.PsString,
+ T.PsString
+ ],
+ femSing: getAbilityRootPerfectiveSplit(s.femSing) as [
+ T.PsString,
+ T.PsString
+ ],
+ femPlur: getAbilityRootPerfectiveSplit(s.femPlur) as [
+ T.PsString,
+ T.PsString
+ ],
+ };
+ }
+ return {
+ long: [getLong(s)[0], concatPsString(getLong(s)[1], abilityTail)],
+ short: [getShort(s)[0], concatPsString(getShort(s)[1], abilityTail)],
+ };
+ }
+ return {
+ perfective: getAspectAbilityRoot(
+ !isIntransitiveStativeCompound ? root.perfective : root.imperfective,
+ !isIntransitiveStativeCompound ? "perfective" : "imperfective"
+ ),
+ imperfective: getAspectAbilityRoot(root.imperfective, "imperfective"),
+ ...(root.perfectiveSplit && !isIntransitiveStativeCompound
+ ? {
+ perfectiveSplit: getAbilityRootPerfectiveSplit(root.perfectiveSplit),
+ }
+ : {}),
+ };
+}
+
+function getPassiveRoot(
+ root: T.VerbRootSet,
+ splitInfo: T.SplitInfo | undefined,
+ withTails?: boolean
+): T.VerbRootSet {
+ const perfectiveRoot = withTails
+ ? concatPsString(root.perfective, passiveRootTail)
+ : root.perfective;
+ const imperfectiveRoot = withTails
+ ? concatPsString(root.imperfective, passiveRootTail)
+ : root.imperfective;
+ return {
+ perfective: getPassiveRootAspect(perfectiveRoot, "perfective"),
+ imperfective: getPassiveRootAspect(imperfectiveRoot, "imperfective"),
+ ...(splitInfo
+ ? {
+ perfectiveSplit: getPassiveRootPerfectiveSplit(
+ perfectiveRoot,
+ splitInfo
+ ),
+ }
+ : {}),
+ };
+}
+
+function getPassivePastParticiple(
+ root: T.OptionalPersonInflections>,
+ withTails?: boolean
+): T.OptionalPersonInflections> {
+ if ("mascSing" in root) {
+ return {
+ mascSing: getPassivePastParticiple(
+ root.mascSing
+ ) as T.LengthOptions,
+ mascPlur: getPassivePastParticiple(
+ root.mascPlur
+ ) as T.LengthOptions,
+ femSing: getPassivePastParticiple(
+ root.femPlur
+ ) as T.LengthOptions,
+ femPlur: getPassivePastParticiple(
+ root.femPlur
+ ) as T.LengthOptions,
+ };
+ }
+ const r = withTails ? concatPsString(root, passiveRootTail) : root;
+ // @ts-ignore
+ return concatPsString(
+ removeAccents(getLong(r)),
+ " ",
+ stativeAux.intransitive.info.participle.past
+ ) as T.PsString;
+}
+
+function getPassiveStemAspect(
+ root: T.FullForm,
+ aspect: T.Aspect
+): T.FullForm {
+ if ("mascSing" in root) {
+ return {
+ mascSing: getPassiveStemAspect(root.mascSing, aspect) as T.PsString,
+ mascPlur: getPassiveStemAspect(root.mascPlur, aspect) as T.PsString,
+ femSing: getPassiveStemAspect(root.femPlur, aspect) as T.PsString,
+ femPlur: getPassiveStemAspect(root.femPlur, aspect) as T.PsString,
+ };
+ }
+ return concatPsString(
+ aspect === "imperfective" ? removeAccents(getLong(root)) : getLong(root),
+ " ",
+ stativeAux.intransitive.info.stem[aspect]
+ );
+}
+
+function getPassiveRootAspect(
+ root: T.OptionalPersonInflections>,
+ aspect: T.Aspect
+): T.OptionalPersonInflections> {
+ if ("mascSing" in root) {
+ return {
+ mascSing: getPassiveRootAspect(
+ root.mascSing,
+ aspect
+ ) as T.LengthOptions,
+ mascPlur: getPassiveRootAspect(
+ root.mascPlur,
+ aspect
+ ) as T.LengthOptions,
+ femPlur: getPassiveRootAspect(
+ root.femPlur,
+ aspect
+ ) as T.LengthOptions,
+ femSing: getPassiveRootAspect(
+ root.femPlur,
+ aspect
+ ) as T.LengthOptions,
+ };
+ }
+ const rootR =
+ aspect === "imperfective" ? removeAccents(root.long) : root.long;
+ return {
+ long: concatPsString(
+ rootR,
+ " ",
+ // @ts-ignore
+ stativeAux.intransitive.info.root[aspect].long
+ ),
// @ts-ignore
- return concatPsString(removeAccents(getLong(r)), " ", stativeAux.intransitive.info.participle.past) as T.PsString;
+ short: concatPsString(
+ rootR,
+ " ",
+ // @ts-ignore
+ stativeAux.intransitive.info.root[aspect].short
+ ),
+ };
}
-
-function getPassiveStemAspect(root: T.FullForm, aspect: T.Aspect): T.FullForm {
- if ("mascSing" in root) {
- return {
- "mascSing": getPassiveStemAspect(root.mascSing, aspect) as T.PsString,
- "mascPlur": getPassiveStemAspect(root.mascPlur, aspect) as T.PsString,
- "femSing": getPassiveStemAspect(root.femPlur, aspect) as T.PsString,
- "femPlur": getPassiveStemAspect(root.femPlur, aspect) as T.PsString,
- };
- }
- return concatPsString(
- aspect === "imperfective" ? removeAccents(getLong(root)) : getLong(root),
- " ",
- stativeAux.intransitive.info.stem[aspect],
- );
-}
-
-function getPassiveRootAspect(root: T.OptionalPersonInflections>, aspect: T.Aspect): T.OptionalPersonInflections> {
- if ("mascSing" in root) {
- return {
- "mascSing": getPassiveRootAspect(root.mascSing, aspect) as T.LengthOptions,
- "mascPlur": getPassiveRootAspect(root.mascPlur, aspect) as T.LengthOptions,
- "femPlur": getPassiveRootAspect(root.femPlur, aspect) as T.LengthOptions,
- "femSing": getPassiveRootAspect(root.femPlur, aspect) as T.LengthOptions,
- };
- }
- const rootR = aspect === "imperfective" ? removeAccents(root.long) : root.long
- return {
- long: concatPsString(
- rootR,
- " ",
- // @ts-ignore
- stativeAux.intransitive.info.root[aspect].long,
- ),
- // @ts-ignore
- short: concatPsString(
- rootR,
- " ",
- // @ts-ignore
- stativeAux.intransitive.info.root[aspect].short,
- ),
- }
-}
\ No newline at end of file
diff --git a/src/types.ts b/src/types.ts
index 2fbe948..7c0cd3e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -12,446 +12,503 @@
export type PsStringField = "p" | "f";
export type PsString = {
- [k in PsStringField]: string;
+ [k in PsStringField]: string;
} & {
- e?: string;
+ e?: string;
+};
+export type PsJSX = {
+ p: JSX.Element;
+ f: JSX.Element;
+ e?: JSX.Element | string;
};
-export type PsJSX = { p: JSX.Element, f: JSX.Element, e?: JSX.Element | string };
export type PsWord = PsString & {
- hyphen?: HyphenPsContent[],
+ hyphen?: HyphenPsContent[];
};
-export type HyphenPsContent = {
- type: "unwritten",
- f: string,
-} & Omit | ({
- type: "written",
-} & PsString);
+export type HyphenPsContent =
+ | ({
+ type: "unwritten";
+ f: string;
+ } & Omit)
+ | ({
+ type: "written";
+ } & PsString);
export type DictionaryInfo = {
- title: string;
- license: string;
- release: number;
- numberOfEntries: number;
- url: string;
- infoUrl: string;
-}
+ title: string;
+ license: string;
+ release: number;
+ numberOfEntries: number;
+ url: string;
+ infoUrl: string;
+};
export type Dictionary = {
- info: DictionaryInfo;
- entries: DictionaryEntry[];
-}
+ info: DictionaryInfo;
+ entries: DictionaryEntry[];
+};
export type AllWordsWithInflections = {
- info: DictionaryInfo,
- words: PsString[],
+ info: DictionaryInfo;
+ words: PsString[];
};
// TODO: MAKE THIS A RECORD TYPE
-// Record && Record &&
+// Record && Record &&
// Partial> && Partial>
export type DictionaryEntry = {
- // BASE REQUIRED INFO
- /** timestamp - used for word id */
- ts: number;
- /** Pashto alphabetical index */
- i: number;
- /**
- * commonality rank
- * 0 - wrong
- * 1 - historical/not in use
- * 2 - rarely used
- * 3 - used but there are more common alternatives
- * 4 - common
- */
- r?: number;
- /** entry in Pashto */
- p: string;
- /** entry in Phonetics */
- f: string;
- /** entry in simplified phonetics */
- g: string;
- /** entry in English */
- e: string;
+ // BASE REQUIRED INFO
+ /** timestamp - used for word id */
+ ts: number;
+ /** Pashto alphabetical index */
+ i: number;
+ /**
+ * commonality rank
+ * 0 - wrong
+ * 1 - historical/not in use
+ * 2 - rarely used
+ * 3 - used but there are more common alternatives
+ * 4 - common
+ */
+ r?: number;
+ /** entry in Pashto */
+ p: string;
+ /** entry in Phonetics */
+ f: string;
+ /** entry in simplified phonetics */
+ g: string;
+ /** entry in English */
+ e: string;
- // PART OF SPEECH AND LINK INFO
- /** part of speech info */
- c?: string;
- /** link - timestamp of related word */
- l?: number;
+ // PART OF SPEECH AND LINK INFO
+ /** part of speech info */
+ c?: string;
+ /** link - timestamp of related word */
+ l?: number;
- // INFLECTION INFO
- /** first masculine irregular inflection in Pashto */
- infap?: string;
- /** first masculine irregular inflection in Phonetics */
- infaf?: string;
- /** base for second masculine / feminine irregular inflection in Pashto */
- infbp?: string;
- /** base for second masculine / feminine irregular inflection in Phonetics */
- infbf?: string;
- /** entry does not inflect? */
- noInf?: boolean;
+ // INFLECTION INFO
+ /** first masculine irregular inflection in Pashto */
+ infap?: string;
+ /** first masculine irregular inflection in Phonetics */
+ infaf?: string;
+ /** base for second masculine / feminine irregular inflection in Pashto */
+ infbp?: string;
+ /** base for second masculine / feminine irregular inflection in Phonetics */
+ infbf?: string;
+ /** entry does not inflect? */
+ noInf?: boolean;
- // PLURAL INFO
- /** Arabic plural in Pashto */
- app?: string;
- /** Arabic plural in Phonetics */
- apf?: string;
- /** Pashto irregular plural in Pashto */
- ppp?: string;
- /** Pashto irregular plural in phonetics */
- ppf?: string;
+ // PLURAL INFO
+ /** Arabic plural in Pashto */
+ app?: string;
+ /** Arabic plural in Phonetics */
+ apf?: string;
+ /** Pashto irregular plural in Pashto */
+ ppp?: string;
+ /** Pashto irregular plural in phonetics */
+ ppf?: string;
- // VERB INFO
- /** imperfective (present) stem in Pashto */
- psp?: string;
- /** imperfective (present) stem in Phonetics */
- psf?: string;
- /** perfective (subjunctive) stem in Pashto */
- ssp?: string;
- /** perfective (subjunctive) stem in Phonetics */
- ssf?: string;
- /** perfective root in Pashto */
- prp?: string;
- /** perfective root in Phonetics */
- prf?: string;
- /** past participle in Pashto */
- pprtp?: string;
- /** past participle in Phonetics */
- pprtf?: string;
- /** The idiosyncratic third person singular masc. short past in Pashto */
- tppp?: string;
- /** The idiosyncratic third person singular masc. short past in Phonetics */
- tppf?: string;
- /** intransitive short version is available like ګرځېږي and ګرځي */
- shortIntrans?: boolean;
- /** does not take a و - oo perfective verb prefix? */
- noOo?: boolean;
- /** takes a seperate و - oo perfective verb prefix? */
- sepOo?: boolean;
- /** Pashto separation point for seperable verbs */
- separationAtP?: number;
- /** Phonetics separation point for seperable verbs */
- separationAtF?: number;
+ // VERB INFO
+ /** imperfective (present) stem in Pashto */
+ psp?: string;
+ /** imperfective (present) stem in Phonetics */
+ psf?: string;
+ /** perfective (subjunctive) stem in Pashto */
+ ssp?: string;
+ /** perfective (subjunctive) stem in Phonetics */
+ ssf?: string;
+ /** perfective root in Pashto */
+ prp?: string;
+ /** perfective root in Phonetics */
+ prf?: string;
+ /** past participle in Pashto */
+ pprtp?: string;
+ /** past participle in Phonetics */
+ pprtf?: string;
+ /** The idiosyncratic third person singular masc. short past in Pashto */
+ tppp?: string;
+ /** The idiosyncratic third person singular masc. short past in Phonetics */
+ tppf?: string;
+ /** intransitive short version is available like ګرځېږي and ګرځي */
+ shortIntrans?: boolean;
+ /** does not take a و - oo perfective verb prefix? */
+ noOo?: boolean;
+ /** takes a seperate و - oo perfective verb prefix? */
+ sepOo?: boolean;
+ /** Pashto separation point for seperable verbs */
+ separationAtP?: number;
+ /** Phonetics separation point for seperable verbs */
+ separationAtF?: number;
- // PHONETICS - PASHTO - DIACRITICS INFO
- /** Is an exception to the rules of diacritics for Pashto/Phonetics */
- diacExcept?: boolean;
+ // PHONETICS - PASHTO - DIACRITICS INFO
+ /** Is an exception to the rules of diacritics for Pashto/Phonetics */
+ diacExcept?: boolean;
- /** the English conjugations of a verb comma seperated set of 5 ie. "see,sees,seeing,saw,seen" or single word ie. "walk" if regular - or the english singular version of a noun */
- ec?: string;
- /** the English partical of a English phrasal verb - or the english irregular plural of a noun */
- ep?: string;
-}
+ /** the English conjugations of a verb comma seperated set of 5 ie. "see,sees,seeing,saw,seen" or single word ie. "walk" if regular - or the english singular version of a noun */
+ ec?: string;
+ /** the English partical of a English phrasal verb - or the english irregular plural of a noun */
+ ep?: string;
+};
-export type DictionaryEntryNoFVars = DictionaryEntry & { __brand: "name for a dictionary entry with all the phonetics variations removed" };
-export type VerbDictionaryEntryNoFVars = VerbDictionaryEntry & { __brand2: "name for a verb dictionary entry with all the phonetics variations removed" };
+export type DictionaryEntryNoFVars = DictionaryEntry & {
+ __brand: "name for a dictionary entry with all the phonetics variations removed";
+};
+export type VerbDictionaryEntryNoFVars = VerbDictionaryEntry & {
+ __brand2: "name for a verb dictionary entry with all the phonetics variations removed";
+};
export type VerbEntryNoFVars = {
- entry: VerbDictionaryEntryNoFVars,
- complement?: DictionaryEntryNoFVars,
-} & { __brand: "name for a verb entry with all the phonetics variations removed" };
-export type PsStringNoFVars = PsString & { __brand: "name for a ps string with all the phonetics variations removed" };
-export type FStringNoFVars = string & { __brand: "name for a phonetics string with all the phonetics variations removed" };
-
+ entry: VerbDictionaryEntryNoFVars;
+ complement?: DictionaryEntryNoFVars;
+} & {
+ __brand: "name for a verb entry with all the phonetics variations removed";
+};
+export type PsStringNoFVars = PsString & {
+ __brand: "name for a ps string with all the phonetics variations removed";
+};
+export type FStringNoFVars = string & {
+ __brand: "name for a phonetics string with all the phonetics variations removed";
+};
export const dictionaryEntryTextFields = [
- "p",
- "f",
- "e",
- "c",
- "infap",
- "infaf",
- "infbp",
- "infbf",
- "app",
- "apf",
- "ppp",
- "ppf",
- "psp",
- "psf",
- "ssp",
- "ssf",
- "prp",
- "prf",
- "pprtp",
- "pprtf",
- "tppp",
- "tppf",
- "ec",
- "ep",
+ "p",
+ "f",
+ "e",
+ "c",
+ "infap",
+ "infaf",
+ "infbp",
+ "infbf",
+ "app",
+ "apf",
+ "ppp",
+ "ppf",
+ "psp",
+ "psf",
+ "ssp",
+ "ssf",
+ "prp",
+ "prf",
+ "pprtp",
+ "pprtf",
+ "tppp",
+ "tppf",
+ "ec",
+ "ep",
] as const;
-export type DictionaryEntryTextField = typeof dictionaryEntryTextFields[number];
+export type DictionaryEntryTextField =
+ (typeof dictionaryEntryTextFields)[number];
export const dictionaryEntryBooleanFields = [
- "noInf", "shortIntrans", "noOo", "sepOo", "diacExcept",
+ "noInf",
+ "shortIntrans",
+ "noOo",
+ "sepOo",
+ "diacExcept",
] as const;
export const dictionaryEntryNumberFields = [
- "ts", "r", "i", "l", "separationAtP", "separationAtF",
+ "ts",
+ "r",
+ "i",
+ "l",
+ "separationAtP",
+ "separationAtF",
] as const;
-export type DictionaryEntryBooleanField = typeof dictionaryEntryBooleanFields[number];
-export type DictionaryEntryNumberField = typeof dictionaryEntryNumberFields[number];
-export type DictionaryEntryField = DictionaryEntryTextField | DictionaryEntryBooleanField | DictionaryEntryNumberField;
+export type DictionaryEntryBooleanField =
+ (typeof dictionaryEntryBooleanFields)[number];
+export type DictionaryEntryNumberField =
+ (typeof dictionaryEntryNumberFields)[number];
+export type DictionaryEntryField =
+ | DictionaryEntryTextField
+ | DictionaryEntryBooleanField
+ | DictionaryEntryNumberField;
-// TODO: make
+// TODO: make
export type DictionaryEntryError = {
- errors: string[],
- p: string,
- f: string,
- e: string,
- ts: number,
- erroneousFields: DictionaryEntryField[],
-}
+ errors: string[];
+ p: string;
+ f: string;
+ e: string;
+ ts: number;
+ erroneousFields: DictionaryEntryField[];
+};
export type Spelling = "Afghan" | "Pakistani ی" | "Pakistani ي";
export type TextOptions = {
- pTextSize: "normal" | "larger" | "largest";
- phonetics: "lingdocs" | "ipa" | "alalc" | "none";
- dialect: "standard" | "peshawer" | "southern";
- spelling: Spelling;
- diacritics: boolean;
-}
+ pTextSize: "normal" | "larger" | "largest";
+ phonetics: "lingdocs" | "ipa" | "alalc" | "none";
+ dialect: "standard" | "peshawer" | "southern";
+ spelling: Spelling;
+ diacritics: boolean;
+};
export enum Person {
- FirstSingMale = 0,
- FirstSingFemale,
- SecondSingMale,
- SecondSingFemale,
- ThirdSingMale,
- ThirdSingFemale,
- FirstPlurMale,
- FirstPlurFemale,
- SecondPlurMale,
- SecondPlurFemale,
- ThirdPlurMale,
- ThirdPlurFemale,
+ FirstSingMale = 0,
+ FirstSingFemale,
+ SecondSingMale,
+ SecondSingFemale,
+ ThirdSingMale,
+ ThirdSingFemale,
+ FirstPlurMale,
+ FirstPlurFemale,
+ SecondPlurMale,
+ SecondPlurFemale,
+ ThirdPlurMale,
+ ThirdPlurFemale,
}
// INPUT
// all information to be passed to conjugating functions
export type VerbInfoBase = {
- entry: VerbEntry,
- transitivity: Transitivity;
- yulEnding: boolean | null;
- stem: VerbStemSet;
- root: VerbRootSet;
- participle: ParticipleSet;
- idiosyncraticThirdMascSing?: ShortThirdPersFormSet;
-}
+ entry: VerbEntry;
+ transitivity: Transitivity;
+ yulEnding: boolean | null;
+ stem: VerbStemSet;
+ root: VerbRootSet;
+ participle: ParticipleSet;
+ idiosyncraticThirdMascSing?: ShortThirdPersFormSet;
+};
export type PassiveRootsAndStems = {
- stem: VerbStemSet,
- root: VerbRootSet,
- participle: {
- past: FullForm,
- },
-}
+ stem: VerbStemSet;
+ root: VerbRootSet;
+ participle: {
+ past: FullForm;
+ };
+};
export type AbilityRootsAndStems = Omit;
export type SimpleVerbInfo = VerbInfoBase & {
- type: "simple";
-}
+ type: "simple";
+};
export type StativeCompoundVerbInfo = VerbInfoBase & {
- type: "stative compound"
- complement: UnisexInflections;
-}
+ type: "stative compound";
+ complement: UnisexInflections;
+};
export type GenerativeStativeCompoundVerbInfo = VerbInfoBase & {
- type: "generative stative compound"
- objComplement: ObjComplement,
- singularForm?: GenerativeStativeCompoundVerbInfo,
- // TODO: Could add intransitive form 🤪
-}
+ type: "generative stative compound";
+ objComplement: ObjComplement;
+ singularForm?: GenerativeStativeCompoundVerbInfo;
+ // TODO: Could add intransitive form 🤪
+};
export type DynamicCompoundVerbInfo = VerbInfoBase & {
- type: "dynamic compound";
- objComplement: ObjComplement;
- auxVerb: DictionaryEntry;
- auxVerbComplement?: DictionaryEntry;
- singularForm?: DynamicCompoundVerbInfo;
- intransitiveForm?: DynamicCompoundVerbInfo;
-}
+ type: "dynamic compound";
+ objComplement: ObjComplement;
+ auxVerb: DictionaryEntry;
+ auxVerbComplement?: DictionaryEntry;
+ singularForm?: DynamicCompoundVerbInfo;
+ intransitiveForm?: DynamicCompoundVerbInfo;
+};
export type ObjComplement = {
- entry: DictionaryEntry;
- plural?: PsString;
- person: Person;
-}
+ entry: DictionaryEntry;
+ plural?: PsString;
+ person: Person;
+};
-export type NonComboVerbInfo = SimpleVerbInfo |
- StativeCompoundVerbInfo | DynamicCompoundVerbInfo | GenerativeStativeCompoundVerbInfo;
+export type NonComboVerbInfo =
+ | SimpleVerbInfo
+ | StativeCompoundVerbInfo
+ | DynamicCompoundVerbInfo
+ | GenerativeStativeCompoundVerbInfo;
-export type VerbInfo = NonComboVerbInfo | {
- type: "transitive or grammatically transitive simple";
- transitive: SimpleVerbInfo;
- grammaticallyTransitive: SimpleVerbInfo;
-} | {
- type: "dynamic or stative compound";
- transitivity: Transitivity;
- stative: StativeCompoundVerbInfo;
- dynamic: DynamicCompoundVerbInfo;
-} | {
- type: "dynamic or generative stative compound";
- transitivity: Transitivity;
- stative: GenerativeStativeCompoundVerbInfo;
- dynamic: DynamicCompoundVerbInfo;
-}
+export type VerbInfo =
+ | NonComboVerbInfo
+ | {
+ type: "transitive or grammatically transitive simple";
+ transitive: SimpleVerbInfo;
+ grammaticallyTransitive: SimpleVerbInfo;
+ }
+ | {
+ type: "dynamic or stative compound";
+ transitivity: Transitivity;
+ stative: StativeCompoundVerbInfo;
+ dynamic: DynamicCompoundVerbInfo;
+ }
+ | {
+ type: "dynamic or generative stative compound";
+ transitivity: Transitivity;
+ stative: GenerativeStativeCompoundVerbInfo;
+ dynamic: DynamicCompoundVerbInfo;
+ };
-export type Transitivity = "transitive" | "intransitive" | "grammatically transitive";
+export type Transitivity =
+ | "transitive"
+ | "intransitive"
+ | "grammatically transitive";
export type SplitInfo = FullForm<[PsString, PsString]>;
export type VerbStemSet = {
- perfective: FullForm;
- imperfective: FullForm;
- perfectiveSplit?: SplitInfo;
-}
+ perfective: FullForm;
+ imperfective: FullForm;
+ perfectiveSplit?: SplitInfo;
+};
export type VerbRootSet = {
- perfective: OptionalPersonInflections>;
- imperfective: OptionalPersonInflections>;
- perfectiveSplit?: SplitInfo;
-}
+ perfective: OptionalPersonInflections>;
+ imperfective: OptionalPersonInflections>;
+ perfectiveSplit?: SplitInfo;
+};
export type ParticipleSet = {
- present: FullForm,
- past: FullForm,
-}
+ present: FullForm;
+ past: FullForm;
+};
export type ShortThirdPersFormSet = {
- [K in Aspect]: PsString;
-}
+ [K in Aspect]: PsString;
+};
export type Aspect = "perfective" | "imperfective";
export type Length = "short" | "long" | "mini";
export type LengthOptions = {
- long: T;
- short: T;
- mini?: T;
-}
+ long: T;
+ short: T;
+ mini?: T;
+};
-export type PersonInflectionsField = "mascSing" | "mascPlur" | "femSing" | "femPlur";
-export type OptionalPersonInflections = {
- [K in PersonInflectionsField]: T;
-} | T;
+export type PersonInflectionsField =
+ | "mascSing"
+ | "mascPlur"
+ | "femSing"
+ | "femPlur";
+export type PersonInflections = {
+ [K in PersonInflectionsField]: T;
+};
+export type OptionalPersonInflections = PersonInflections | T;
export type SingleOrLengthOpts = T | LengthOptions;
export type VerbConjugation = {
- info: NonComboVerbInfo,
- // INFINITIVE = info.root.imperfective.long
- imperfective: AspectContent; // --╖ ASPECT = "imperfective"
- perfective: AspectContent; // --╜ ASPECT = "perfective"
- hypothetical: VerbForm; // INFINITIVE - ul + aay
- participle: ParticipleContent;
- perfect: PerfectContent; // PPART = PAST PARTICIPLE (plus spectial short forms)
- passive?: PassiveContent; // only on transitive verbs
- singularForm?: VerbConjugation;
-}
-
-export type VerbOutput = VerbConjugation | {
- info: VerbInfo,
- stative: VerbConjugation,
- dynamic: VerbConjugation,
-} | {
- info: VerbInfo,
- transitive: VerbConjugation,
- grammaticallyTransitive: VerbConjugation,
+ info: NonComboVerbInfo;
+ // INFINITIVE = info.root.imperfective.long
+ imperfective: AspectContent; // --╖ ASPECT = "imperfective"
+ perfective: AspectContent; // --╜ ASPECT = "perfective"
+ hypothetical: VerbForm; // INFINITIVE - ul + aay
+ participle: ParticipleContent;
+ perfect: PerfectContent; // PPART = PAST PARTICIPLE (plus spectial short forms)
+ passive?: PassiveContent; // only on transitive verbs
+ singularForm?: VerbConjugation;
};
+export type VerbOutput =
+ | VerbConjugation
+ | {
+ info: VerbInfo;
+ stative: VerbConjugation;
+ dynamic: VerbConjugation;
+ }
+ | {
+ info: VerbInfo;
+ transitive: VerbConjugation;
+ grammaticallyTransitive: VerbConjugation;
+ };
+
export type PassiveContent = {
- imperfective: AspectContentPassive // --╖ ASPECT = "imperfective"
- perfective: AspectContentPassive // --╜ ASPECT = "perfective"
- perfect: PerfectContent; // PPART INFINITIVE + kedulStat perfect.pastParticiple
- // TODO: ADD PARTICIPLE
-}
+ imperfective: AspectContentPassive; // --╖ ASPECT = "imperfective"
+ perfective: AspectContentPassive; // --╜ ASPECT = "perfective"
+ perfect: PerfectContent; // PPART INFINITIVE + kedulStat perfect.pastParticiple
+ // TODO: ADD PARTICIPLE
+};
// ASPECT -> AspectContent
export type AspectContent = {
- // STEM = info.stem[ASPECT]
- // ROOT = info.root[ASPECT]
- nonImperative: VerbForm; // STEM + pres ending
- future: VerbForm; // به + this.nonImperative
- imperative: ImperativeForm; // STEM + imperative ending
- past: VerbForm; // ROOT + past ending
- habitualPast: VerbForm; // ba + past
- modal: ModalContent;
-}
+ // STEM = info.stem[ASPECT]
+ // ROOT = info.root[ASPECT]
+ nonImperative: VerbForm; // STEM + pres ending
+ future: VerbForm; // به + this.nonImperative
+ imperative: ImperativeForm; // STEM + imperative ending
+ past: VerbForm; // ROOT + past ending
+ habitualPast: VerbForm; // ba + past
+ modal: ModalContent;
+};
// ASPECT -> AspectContentPssive
export type AspectContentPassive = Omit & {
- imperative: undefined,
+ imperative: undefined;
};
export type ModalContent = {
- nonImperative: VerbForm; // ROOT + ey + kedulStat.perfective.nonImperative
- future: VerbForm; // به + this.nonImperative
- past: VerbForm; // ROOT + ey + kedulStat.perfective.past
- habitualPast: VerbForm; // ba + past
- hypotheticalPast: VerbForm; // ROOT + ey + shw + ey
-}
+ nonImperative: VerbForm; // ROOT + ey + kedulStat.perfective.nonImperative
+ future: VerbForm; // به + this.nonImperative
+ past: VerbForm; // ROOT + ey + kedulStat.perfective.past
+ habitualPast: VerbForm; // ba + past
+ hypotheticalPast: VerbForm; // ROOT + ey + shw + ey
+};
-export type ParticipleForm = SingleOrLengthOpts | SingleOrLengthOpts