Ability to use complements in the phrase builder with kawul/kedul stative! This is still a bit messy, and I should somehow get the "verbComplement" types deprecated
This commit is contained in:
parent
66fd580411
commit
c3170f65f5
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@lingdocs/pashto-inflector",
|
||||
"version": "3.3.1",
|
||||
"version": "3.3.2",
|
||||
"author": "lingdocs.com",
|
||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||
"homepage": "https://verbs.lingdocs.com",
|
||||
|
|
|
@ -1,32 +1,37 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import * as T from "../../../types";
|
||||
import AdjectivePicker from "../../np-picker/AdjectivePicker";
|
||||
import LocativeAdverbPicker from "./LocativeAdverbPicker";
|
||||
import SandwichPicker from "../../np-picker/SandwichPicker";
|
||||
const compTypes: T.EqCompType[] = ["adjective", "loc. adv.", "sandwich"];
|
||||
import * as T from "../types";
|
||||
import AdjectivePicker from "./np-picker/AdjectivePicker";
|
||||
import LocativeAdverbPicker from "./ep-explorer/eq-comp-picker/LocativeAdverbPicker";
|
||||
import SandwichPicker from "./np-picker/SandwichPicker";
|
||||
const compTypes: T.ComplementType[] = ["adjective", "loc. adv.", "sandwich", "comp. noun"];
|
||||
|
||||
function EqCompPicker(props: {
|
||||
function selectionTypeToCompType(s: Exclude<T.ComplementType, "comp. noun"> | "noun"): T.ComplementType {
|
||||
if (s === "noun") return "comp. noun";
|
||||
return s;
|
||||
}
|
||||
|
||||
function ComplementPicker(props: {
|
||||
phraseIsComplete: boolean,
|
||||
onChange: (comp: T.EqCompSelection | undefined) => void,
|
||||
comp: T.EqCompSelection | undefined,
|
||||
onChange: (comp: T.ComplementSelection | undefined) => void,
|
||||
comp: T.ComplementSelection | undefined,
|
||||
opts: T.TextOptions,
|
||||
cantClear?: boolean,
|
||||
heading?: JSX.Element | string,
|
||||
entryFeeder: T.EntryFeeder,
|
||||
}) {
|
||||
const [compType, setCompType] = useState<T.EqCompType | undefined>(props.comp
|
||||
? props.comp.selection.type
|
||||
const [compType, setCompType] = useState<T.ComplementType | undefined>(props.comp
|
||||
? selectionTypeToCompType(props.comp.selection.type)
|
||||
: undefined);
|
||||
useEffect(() => {
|
||||
setCompType(props.comp
|
||||
? props.comp.selection.type
|
||||
? selectionTypeToCompType(props.comp.selection.type)
|
||||
: undefined);
|
||||
}, [props.comp]);
|
||||
function handleClear() {
|
||||
setCompType(undefined);
|
||||
props.onChange(undefined);
|
||||
}
|
||||
function handleCompTypeChange(ctp: T.EqCompType) {
|
||||
function handleCompTypeChange(ctp: T.ComplementType) {
|
||||
props.onChange(undefined);
|
||||
setCompType(ctp);
|
||||
}
|
||||
|
@ -70,7 +75,7 @@ function EqCompPicker(props: {
|
|||
entryFeeder={props.entryFeeder}
|
||||
adjective={props.comp?.selection.type === "adjective" ? props.comp.selection : undefined}
|
||||
opts={props.opts}
|
||||
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||
onChange={(a) => props.onChange(a ? { type: "complement", selection: a } : undefined)}
|
||||
phraseIsComplete={props.phraseIsComplete}
|
||||
/>
|
||||
: compType === "loc. adv."
|
||||
|
@ -78,11 +83,11 @@ function EqCompPicker(props: {
|
|||
entryFeeder={props.entryFeeder.locativeAdverbs}
|
||||
adjective={props.comp?.selection.type === "loc. adv." ? props.comp.selection : undefined}
|
||||
opts={props.opts}
|
||||
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||
onChange={(a) => props.onChange(a ? { type: "complement", selection: a } : undefined)}
|
||||
/>
|
||||
: compType === "sandwich"
|
||||
? <SandwichPicker
|
||||
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||
onChange={(a) => props.onChange(a ? { type: "complement", selection: a } : undefined)}
|
||||
opts={props.opts}
|
||||
sandwich={props.comp?.selection.type === "sandwich" ? props.comp.selection : undefined}
|
||||
entryFeeder={props.entryFeeder}
|
||||
|
@ -90,9 +95,13 @@ function EqCompPicker(props: {
|
|||
// TODO: get phraseIsComplete working here
|
||||
phraseIsComplete={props.phraseIsComplete}
|
||||
/>
|
||||
: compType === "comp. noun"
|
||||
? <div style={{ maxWidth: "9rem" }}>
|
||||
Sorry, can't choose complement nouns yet 🚧
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default EqCompPicker;
|
||||
export default ComplementPicker;
|
|
@ -30,8 +30,8 @@ function Block({ opts, block, king, script }: {
|
|||
const english = getEnglishFromRendered(block.block.selection);
|
||||
return <div className="text-center">
|
||||
<div><strong>Predicate</strong></div>
|
||||
{block.block.selection.type === "EQComp"
|
||||
? <EqCompBlock opts={opts} comp={block.block.selection.selection} script={script} />
|
||||
{block.block.selection.type === "complement"
|
||||
? <ComplementBlock opts={opts} comp={block.block.selection.selection} script={script} />
|
||||
: <NPBlock opts={opts} english={english} script={script}>{block.block.selection}</NPBlock>}
|
||||
</div>
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ function Block({ opts, block, king, script }: {
|
|||
if (block.block.type === "modalVerbKedulPart") {
|
||||
return <ModalAuxBlock opts={opts} aux={block.block} script={script} />
|
||||
}
|
||||
if (block.block.type === "complement") {
|
||||
return <ComplementBlock opts={opts} comp={block.block.selection} script={script} />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -99,7 +102,12 @@ function VerbSBlock({ opts, v, script }: {
|
|||
return <div className="text-center">
|
||||
{"long" in v.ps && <div className="clickable small mb-1" onClick={changeLength}>{length}</div>}
|
||||
<Border>
|
||||
<>
|
||||
{v.type === "verb" && v.complement && <span className="mx-2">
|
||||
<ComplementBlock opts={opts} comp={v.complement.selection} script={script} inside />
|
||||
</span>}
|
||||
{getLength(v.ps, length)[0][script]}
|
||||
</>
|
||||
</Border>
|
||||
<div>{v.type === "perfectParticipleBlock" ? "Past Partic." : "Verb"}</div>
|
||||
<EnglishBelow>{((v.type === "perfectParticipleBlock" ? "Past Partic." : "Verb")
|
||||
|
@ -244,10 +252,11 @@ function ObjectBlock({ opts, obj, role, script }: {
|
|||
</div>;
|
||||
}
|
||||
|
||||
function EqCompBlock({ opts, comp, script }: {
|
||||
function ComplementBlock({ opts, comp, script, inside }: {
|
||||
script: "p" | "f",
|
||||
opts: T.TextOptions,
|
||||
comp: T.Rendered<T.EqCompSelection["selection"]>,
|
||||
comp: T.Rendered<T.ComplementSelection["selection"]> | T.Rendered<T.UnselectedComplementSelection>["selection"],
|
||||
inside?: boolean,
|
||||
}) {
|
||||
function AdjectiveBlock({ opts, adj }: {
|
||||
opts: T.TextOptions,
|
||||
|
@ -274,18 +283,31 @@ function EqCompBlock({ opts, comp, script }: {
|
|||
<EnglishBelow>{adv.e}</EnglishBelow>
|
||||
</div>;
|
||||
}
|
||||
|
||||
return <div className="text-center">
|
||||
<div>Comp.</div>
|
||||
{comp.type === "adjective"
|
||||
? <AdjectiveBlock opts={opts} adj={comp} />
|
||||
: comp.type === "loc. adv."
|
||||
? <LocAdvBlock opts={opts} adv={comp} />
|
||||
: <div>
|
||||
<Sandwich opts={opts} sandwich={comp} script={script} />
|
||||
<div>Sandwich</div>
|
||||
? <LocAdvBlock opts={opts} adv={comp} />
|
||||
: comp.type === "noun"
|
||||
? <Border>
|
||||
NOT DONE YET
|
||||
</Border>
|
||||
: comp.type === "unselected"
|
||||
? <div>
|
||||
<Border>
|
||||
____
|
||||
</Border>
|
||||
{!inside && <>
|
||||
<div> </div>
|
||||
<EnglishBelow>{comp.e}</EnglishBelow>
|
||||
</div>}
|
||||
</>}
|
||||
</div>
|
||||
: <div>
|
||||
<Sandwich opts={opts} sandwich={comp} script={script} />
|
||||
<div>Sandwich</div>
|
||||
<EnglishBelow>{comp.e}</EnglishBelow>
|
||||
</div>}
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as T from "../../types";
|
|||
import NPPicker from "../np-picker/NPPicker";
|
||||
import EquativePicker from "./EquativePicker";
|
||||
import ButtonSelect from "../ButtonSelect";
|
||||
import EqCompPicker from "./eq-comp-picker/EqCompPicker";
|
||||
import ComplementPicker from "../ComplementPicker";
|
||||
import epsReducer, { EpsReducerAction } from "./eps-reducer";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { completeEPSelection } from "../../lib/phrase-building/render-ep";
|
||||
|
@ -92,10 +92,10 @@ function EPPicker({ opts, eps, onChange, entryFeeder }: {
|
|||
role="subject"
|
||||
onChange={payload => adjustEps({ type: "set predicate NP", payload })}
|
||||
opts={opts}
|
||||
/> : <EqCompPicker
|
||||
/> : <ComplementPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
comp={eps.predicate.type === "Complement" ? eps.predicate.Complement : undefined}
|
||||
onChange={payload => adjustEps({ type: "set predicate comp", payload })}
|
||||
onChange={payload => adjustEps({ type: "set predicate complement", payload })}
|
||||
opts={opts}
|
||||
entryFeeder={entryFeeder}
|
||||
/>}
|
||||
|
|
|
@ -17,8 +17,8 @@ export type EpsReducerAction = {
|
|||
type: "set predicate NP",
|
||||
payload: T.NPSelection | undefined,
|
||||
} | {
|
||||
type: "set predicate comp",
|
||||
payload: T.EqCompSelection | undefined,
|
||||
type: "set predicate complement",
|
||||
payload: T.ComplementSelection | undefined,
|
||||
} | {
|
||||
type: "set omitSubject",
|
||||
payload: "true" | "false",
|
||||
|
@ -134,7 +134,7 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc
|
|||
};
|
||||
return selection ? ensureMiniPronounsOk(eps, n, sendAlert) : n;
|
||||
}
|
||||
if (action.type === "set predicate comp") {
|
||||
if (action.type === "set predicate complement") {
|
||||
return {
|
||||
...eps,
|
||||
predicate: {
|
||||
|
|
|
@ -486,6 +486,7 @@ function getRandomVPSelection(mix: MixType = "both") {
|
|||
)),
|
||||
verb: randomizeTense(verb, true),
|
||||
form: { removeKing: false, shrinkServant: false },
|
||||
externalComplement: undefined,
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
@ -501,6 +502,7 @@ function getRandomVPSelection(mix: MixType = "both") {
|
|||
)),
|
||||
verb: randomizeTense(verb, true),
|
||||
form: { removeKing: false, shrinkServant: false },
|
||||
externalComplement: undefined,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,7 +8,13 @@ import VPExplorerExplanationModal, { roleIcon } from "./VPExplorerExplanationMod
|
|||
import { vpsReducer, VpsReducerAction } from "./vps-reducer";
|
||||
import APPicker from "../ap-picker/APPicker";
|
||||
import autoAnimate from "@formkit/auto-animate";
|
||||
import { getObjectSelection, getSubjectSelection, includesShrunkenServant, isNoObject } from "../../lib/phrase-building/blocks-utils";
|
||||
import {
|
||||
getObjectSelection,
|
||||
getSubjectSelection,
|
||||
includesShrunkenServant,
|
||||
isNoObject,
|
||||
} from "../../lib/phrase-building/blocks-utils";
|
||||
import ComplementPicker from "../ComplementPicker";
|
||||
|
||||
function VPPicker({ opts, vps, onChange, entryFeeder }: {
|
||||
opts: T.TextOptions,
|
||||
|
@ -156,11 +162,6 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
|
|||
{!servantIsShrunk ? "🪄" : "👶"}
|
||||
</span>
|
||||
}
|
||||
{(rendered && rendered.whatsAdjustable !== "servant") &&
|
||||
<span onClick={() => adjustVps({ type: "toggle king remove" })} className="mx-2 clickable">
|
||||
{!VPS?.form.removeKing ? "🚫" : "🙈"}
|
||||
</span>
|
||||
}
|
||||
</div>}
|
||||
entryFeeder={entryFeeder}
|
||||
role="object"
|
||||
|
@ -175,6 +176,19 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
|
|||
: null}
|
||||
</div>;
|
||||
})}
|
||||
{vps.externalComplement && <div className="my-2 card block-card p-1 mr-1" key="complementPicker">
|
||||
<div className="h5 text-center">Complement</div>
|
||||
<ComplementPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
comp={vps.externalComplement.selection.type === "unselected"
|
||||
? undefined
|
||||
: vps.externalComplement as T.ComplementSelection // TODO: just typescript being dumb? - looks like it
|
||||
}
|
||||
onChange={payload => adjustVps({ type: "set externalComplement", payload })}
|
||||
opts={opts}
|
||||
entryFeeder={entryFeeder}
|
||||
/>
|
||||
</div>}
|
||||
<div className="my-2">
|
||||
<TensePicker
|
||||
vps={vps}
|
||||
|
|
|
@ -71,10 +71,23 @@ export function makeVPSelectionState(
|
|||
canChangeVoice: transitivity === "transitive",
|
||||
canChangeStatDyn: "stative" in info,
|
||||
},
|
||||
externalComplement: takesExternalComplement(verb)
|
||||
? { type: "complement", selection: { type: "unselected" }}
|
||||
: undefined,
|
||||
form: os ? os.form : { removeKing: false, shrinkServant: false },
|
||||
};
|
||||
}
|
||||
|
||||
function takesExternalComplement(v: T.VerbEntry): boolean {
|
||||
if (v.entry.p === "کول" && v.entry.e.includes("to make")) {
|
||||
return true;
|
||||
}
|
||||
if (v.entry.p === "کېدل" && v.entry.e.includes("to become")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function changeStatDyn(v: T.VPSelectionState, s: "dynamic" | "stative"): T.VPSelectionState {
|
||||
const info = getVerbInfo(v.verb.verb.entry, v.verb.verb.complement);
|
||||
if (!("stative" in info)) {
|
||||
|
|
|
@ -74,7 +74,10 @@ export type VpsReducerAction = {
|
|||
index: number,
|
||||
direction: "back" | "forward",
|
||||
},
|
||||
};
|
||||
} | {
|
||||
type: "set externalComplement",
|
||||
payload: T.ComplementSelection | undefined,
|
||||
}
|
||||
|
||||
export function vpsReducer(vps: T.VPSelectionState, action: VpsReducerAction, sendAlert?: (msg: string) => void): T.VPSelectionState {
|
||||
return ensureMiniPronounsOk(vps, doReduce());
|
||||
|
@ -291,6 +294,18 @@ export function vpsReducer(vps: T.VPSelectionState, action: VpsReducerAction, se
|
|||
blocks: shiftBlock(vps.blocks, index, direction),
|
||||
};
|
||||
}
|
||||
if (action.type === "set externalComplement") {
|
||||
const selection = action.payload;
|
||||
return {
|
||||
...vps,
|
||||
externalComplement: selection === undefined
|
||||
// TODO: this is a bit messy
|
||||
// when using the ComplementPicker with an EP - undefined means it hasn't been selected
|
||||
// when using the ComplementPicker with a VP - undefined means there can be no complement
|
||||
? { type: "complement", selection: { type: "unselected" }}
|
||||
: selection,
|
||||
}
|
||||
}
|
||||
throw new Error("unknown vpsReducer state");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,18 @@ export function getPredicateSelectionFromBlocks(blocks: T.Block[][]): T.Rendered
|
|||
|
||||
export function getAPsFromBlocks(blocks: T.Block[][]): T.Rendered<T.APSelection>[] {
|
||||
return blocks[0].filter(b => b.block.type === "AP").map(b => b.block) as T.Rendered<T.APSelection>[];
|
||||
}
|
||||
}
|
||||
|
||||
export function getComplementFromBlocks(blocks: T.Block[][]): T.Rendered<T.ComplementSelection> | T.Rendered<T.UnselectedComplementSelection> | undefined {
|
||||
const complement = blocks[0].find(b => b.block.type === "complement");
|
||||
if (!complement) {
|
||||
return undefined;
|
||||
}
|
||||
if (complement.block.type !== "complement") {
|
||||
throw new Error("error finding complement - other kind of block retrieved");
|
||||
}
|
||||
return complement.block;
|
||||
}
|
||||
|
||||
export function getObjectSelection(blocks: T.VPSBlockComplete[]): T.ObjectSelectionComplete;
|
||||
export function getObjectSelection(blocks: T.VPSBlock[]): T.ObjectSelection;
|
||||
|
@ -256,7 +267,11 @@ export function removeAP<B extends T.VPSBlock[] | T.EPSBlock[]>(blocks: B, index
|
|||
}
|
||||
|
||||
export function isNoObject(b: T.VPSBlock["block"] | T.EPSBlock["block"]): b is { type: "objectSelection", selection: "none" } {
|
||||
return !!(b && b.type === "objectSelection" && b.selection === "none");
|
||||
return !!(
|
||||
b
|
||||
&&
|
||||
(b.type === "objectSelection" && b.selection === "none")
|
||||
);
|
||||
}
|
||||
|
||||
export function specifyEquativeLength(blocksWVars: T.Block[][], length: "long" | "short"): T.Block[][] {
|
||||
|
|
|
@ -14,12 +14,12 @@ import { completeVPSelection } from "./vp-tools";
|
|||
import { renderVP } from "./render-vp";
|
||||
import {
|
||||
getAPsFromBlocks,
|
||||
getComplementFromBlocks,
|
||||
getObjectSelectionFromBlocks,
|
||||
getPredicateSelectionFromBlocks,
|
||||
getSubjectSelectionFromBlocks,
|
||||
getVerbFromBlocks,
|
||||
hasEquativeWithLengths,
|
||||
hasVerbWithLengths,
|
||||
specifyEquativeLength,
|
||||
specifyVerbLength,
|
||||
} from "./blocks-utils";
|
||||
|
@ -81,10 +81,14 @@ export function compileVP(VP: T.VPRendered, form: T.FormVersion, combineLengths?
|
|||
}
|
||||
|
||||
function compileVPPs(blocks: T.Block[][], kids: T.Kid[], form: T.FormVersion, king: "subject" | "object"): T.SingleOrLengthOpts<T.PsString[]> {
|
||||
if (hasVerbWithLengths(blocks)) {
|
||||
const verbBlock = getVerbFromBlocks(blocks);
|
||||
if ("long" in verbBlock.block.ps) {
|
||||
return {
|
||||
long: compileVPPs(specifyVerbLength(blocks, "long"), kids, form, king) as T.PsString[],
|
||||
short: compileVPPs(specifyVerbLength(blocks, "short"), kids, form, king) as T.PsString[],
|
||||
..."mini" in verbBlock.block.ps ? {
|
||||
mini: compileVPPs(specifyVerbLength(blocks, "mini"), kids, form, king) as T.PsString[],
|
||||
} : {},
|
||||
};
|
||||
}
|
||||
const subjectPerson = getSubjectSelectionFromBlocks(blocks)
|
||||
|
@ -94,6 +98,7 @@ function compileVPPs(blocks: T.Block[][], kids: T.Kid[], form: T.FormVersion, ki
|
|||
kids,
|
||||
false,
|
||||
);
|
||||
console.log({ blocksWKids });
|
||||
return removeDuplicates(combineIntoText(blocksWKids, subjectPerson, {}));
|
||||
}
|
||||
|
||||
|
@ -198,7 +203,7 @@ function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsSt
|
|||
return [piece.block.ps];
|
||||
}
|
||||
if (piece.block.type === "verbComplement") {
|
||||
return [{ p: "---", f: "---"}]; //getPashtoFromRendered(piece.block.complement);
|
||||
return [{ p: "____", f: "____"}]; //getPashtoFromRendered(piece.block.complement);
|
||||
}
|
||||
if (piece.block.type === "objectSelection") {
|
||||
if (typeof piece.block.selection !== "object") {
|
||||
|
@ -208,7 +213,11 @@ function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsSt
|
|||
}
|
||||
if (piece.block.type === "verb") {
|
||||
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
|
||||
return getLong(piece.block.block.ps);
|
||||
const verbPs = getLong(piece.block.block.ps);
|
||||
if (piece.block.block.complement) {
|
||||
return combineComplementWVerbPs(piece.block.block.complement, verbPs);
|
||||
}
|
||||
return verbPs;
|
||||
}
|
||||
if (piece.block.type === "perfectParticipleBlock") {
|
||||
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
|
||||
|
@ -226,6 +235,13 @@ function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsSt
|
|||
// just using the short one for now - it will only be short anyways
|
||||
return getShort(piece.block.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;
|
||||
}
|
||||
}
|
||||
if ("kid" in piece) {
|
||||
if (piece.kid.type === "ba") {
|
||||
|
@ -235,10 +251,18 @@ function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsSt
|
|||
return [piece.kid.ps];
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("unrecognized piece type");
|
||||
}
|
||||
|
||||
function combineComplementWVerbPs(comp: T.Rendered<T.ComplementSelection | T.UnselectedComplementSelection>, v: T.PsString[]): T.PsString[] {
|
||||
const compPs = comp.selection.type === "sandwich"
|
||||
? getPashtoFromRendered({ type: "AP", selection: comp.selection }, false)
|
||||
: comp.selection.ps;
|
||||
return compPs.flatMap((c) => (
|
||||
v.map((p) => concatPsString(c, " ", p))
|
||||
));
|
||||
}
|
||||
|
||||
function getEngAPs(blocks: T.Block[][]): string {
|
||||
return getAPsFromBlocks(blocks).reduce((accum, curr) => {
|
||||
const e = getEnglishFromRendered(curr);
|
||||
|
@ -247,6 +271,17 @@ function getEngAPs(blocks: T.Block[][]): string {
|
|||
}, "");
|
||||
}
|
||||
|
||||
function getEngComplement(blocks: T.Block[][]): string | undefined {
|
||||
const comp = getComplementFromBlocks(blocks);
|
||||
if (!comp) return undefined;
|
||||
if (comp.selection === undefined) {
|
||||
return "____";
|
||||
}
|
||||
if (comp.selection.type === "sandwich") {
|
||||
return getEnglishFromRendered({ type: "AP", selection: comp.selection });
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
|
@ -261,8 +296,13 @@ function putKidsInKidsSection(blocksWVars: T.Block[][], kids: T.Kid[], enforceKi
|
|||
}
|
||||
|
||||
function compileEnglishVP(VP: T.VPRendered): string[] | undefined {
|
||||
function insertEWords(e: string, { subject, object, APs }: { subject: string, object?: string, APs: string }): string {
|
||||
return e.replace("$SUBJ", subject).replace("$OBJ", object || "") + APs;
|
||||
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 || "")
|
||||
// TODO: check if this always works
|
||||
+ (complement ? ` ${complement}` : "")
|
||||
+ APs;
|
||||
}
|
||||
const engSubj = getSubjectSelectionFromBlocks(VP.blocks).selection;
|
||||
const obj = getObjectSelectionFromBlocks(VP.blocks).selection;
|
||||
|
@ -272,6 +312,7 @@ function compileEnglishVP(VP: T.VPRendered): string[] | undefined {
|
|||
? ""
|
||||
: 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, {
|
||||
|
@ -279,6 +320,7 @@ function compileEnglishVP(VP: T.VPRendered): string[] | undefined {
|
|||
subject: getEnglishFromRendered(engSubj) || "",
|
||||
object: engObj ? getEnglishFromRendered(engObj) : "",
|
||||
APs: engAPs,
|
||||
complement: engComplement,
|
||||
})).map(capitalizeFirstLetter)
|
||||
: undefined;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,6 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
|
|||
function isToBe(v: T.EnglishVerbConjugationEc): boolean {
|
||||
return (v[2] === "being");
|
||||
}
|
||||
const futureEngBuilder: T.EnglishBuilder = (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
`$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
|
||||
]);
|
||||
// TODO: Pull these out to a seperate entity and import it
|
||||
const basicBuilders: Record<
|
||||
T.VerbTense,
|
||||
|
@ -59,8 +56,13 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
|
|||
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(ec) ? "be" : ec[0]}`,
|
||||
`$SUBJ ${n ? " not" : ""} should ${isToBe(ec) ? "be" : ec[0]}`,
|
||||
]),
|
||||
imperfectiveFuture: futureEngBuilder,
|
||||
perfectiveFuture: futureEngBuilder,
|
||||
imperfectiveFuture: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
`$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
|
||||
`$SUBJ will${n ? " not" : ""} be ${isToBe(ec) ? "be" : ec[2]}`,
|
||||
]),
|
||||
perfectiveFuture: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
`$SUBJ will${n ? " not" : ""} ${isToBe(ec) ? "be" : ec[0]}`,
|
||||
]),
|
||||
imperfectivePast: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
// - subj pastEquative (N && "not") ec.2 obj
|
||||
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${ec[2]}`,
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
import * as T from "../../types";
|
||||
import { concatPsString } from "../p-text-helpers";
|
||||
|
||||
function getBaseAndAdjectives({ selection }: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): T.PsString[] {
|
||||
function getBaseAndAdjectives({ selection }: T.Rendered<T.NPSelection | T.ComplementSelection | T.APSelection>): T.PsString[] {
|
||||
if (selection.type === "sandwich") {
|
||||
return getSandwichPsBaseAndAdjectives(selection);
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ function trimOffShrunkenPossesive(p: T.Rendered<T.NPSelection>): T.Rendered<T.NP
|
|||
};
|
||||
}
|
||||
|
||||
export function getPashtoFromRendered(b: T.Rendered<T.NPSelection> | T.Rendered<T.EqCompSelection> | T.Rendered<T.APSelection>, subjectsPerson: false | T.Person): T.PsString[] {
|
||||
export function getPashtoFromRendered(b: T.Rendered<T.NPSelection> | T.Rendered<T.ComplementSelection> | T.Rendered<T.APSelection>, subjectsPerson: false | T.Person): T.PsString[] {
|
||||
const base = getBaseAndAdjectives(b);
|
||||
if (b.selection.type === "loc. adv." || b.selection.type === "adverb") {
|
||||
return base;
|
||||
|
@ -88,6 +88,7 @@ export function getPashtoFromRendered(b: T.Rendered<T.NPSelection> | T.Rendered<
|
|||
if (!b.selection.sandwich) {
|
||||
return base
|
||||
}
|
||||
// TODO: Kinda cheating
|
||||
const sandwichPs = getPashtoFromRendered({ type: "AP", selection: b.selection.sandwich }, false);
|
||||
return base.flatMap(p => (
|
||||
sandwichPs.flatMap(s => (
|
||||
|
@ -199,7 +200,10 @@ function pronounPossEng(p: T.Person): string {
|
|||
return "their";
|
||||
}
|
||||
|
||||
export function getEnglishFromRendered(r: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): string | undefined {
|
||||
export function getEnglishFromRendered(r: T.Rendered<T.NPSelection | T.ComplementSelection | T.APSelection | T.SandwichSelection<T.Sandwich>>): string | undefined {
|
||||
if (r.type === "sandwich") {
|
||||
return getEnglishFromRenderedSandwich(r);
|
||||
}
|
||||
if (r.selection.type === "sandwich") {
|
||||
return getEnglishFromRenderedSandwich(r.selection);
|
||||
}
|
||||
|
|
|
@ -18,30 +18,29 @@ function chooseInflection(inflections: T.UnisexSet<T.InflectionSet>, pers: T.Per
|
|||
return inflections[gender][infNumber];
|
||||
}
|
||||
|
||||
export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Person, inflected: boolean, role: "king" | "servant" | "none"): T.Rendered<T.AdjectiveSelection> {
|
||||
export function inflectAdjective(a: T.AdjectiveSelection, person: T.Person, inflected: boolean): T.ArrayOneOrMore<T.PsString> {
|
||||
const infs = inflectWord(a.entry);
|
||||
if (!infs) {
|
||||
return [psStringFromEntry(a.entry)];
|
||||
}
|
||||
if (!infs.inflections || !isUnisexSet(infs.inflections)) {
|
||||
throw new Error("error getting inflections for adjective, looks like a noun's inflections");
|
||||
}
|
||||
return chooseInflection(infs.inflections, person, inflected);
|
||||
}
|
||||
|
||||
export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Person, inflected: boolean): T.Rendered<T.AdjectiveSelection> {
|
||||
const eWord = getEnglishWord(a.entry);
|
||||
const e = !eWord
|
||||
? undefined
|
||||
: typeof eWord === "string"
|
||||
? eWord
|
||||
: (eWord.singular || undefined);
|
||||
if (!infs) return {
|
||||
type: "adjective",
|
||||
entry: a.entry,
|
||||
ps: [psStringFromEntry(a.entry)],
|
||||
e,
|
||||
inflected,
|
||||
sandwich: a.sandwich ? renderSandwich(a.sandwich) : undefined,
|
||||
person,
|
||||
}
|
||||
if (!infs.inflections || !isUnisexSet(infs.inflections)) {
|
||||
throw new Error("error getting inflections for adjective, looks like a noun's inflections");
|
||||
}
|
||||
const ps = inflectAdjective(a, person, inflected);
|
||||
return {
|
||||
type: "adjective",
|
||||
entry: a.entry,
|
||||
ps: chooseInflection(infs.inflections, person, inflected),
|
||||
ps,
|
||||
e,
|
||||
inflected,
|
||||
person,
|
||||
|
|
|
@ -32,7 +32,7 @@ export function findPossesivesToShrink(
|
|||
];
|
||||
}
|
||||
if (block.type === "predicateSelection") {
|
||||
if (block.selection.type === "EQComp") {
|
||||
if (block.selection.type === "complement") {
|
||||
if (block.selection.selection.type === "sandwich") {
|
||||
return [
|
||||
...kids,
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import * as T from "../../types";
|
||||
import { renderNounSelection } from "./render-np";
|
||||
import { getEnglishWord } from "../get-english-word";
|
||||
import { psStringFromEntry } from "../p-text-helpers";
|
||||
import { renderAdjectiveSelection } from "./render-adj";
|
||||
import { renderSandwich } from "./render-sandwich";
|
||||
|
||||
export function renderComplementSelection(s: T.ComplementSelection | T.UnselectedComplementSelection, person: T.Person): T.Rendered<T.ComplementSelection | T.UnselectedComplementSelection> {
|
||||
if (s.selection.type === "unselected") {
|
||||
return {
|
||||
type: "complement",
|
||||
selection: {
|
||||
type: "unselected",
|
||||
ps: [{ p: "____", f: "____" }],
|
||||
e: "____",
|
||||
},
|
||||
};
|
||||
}
|
||||
if (s.selection.type === "sandwich") {
|
||||
return {
|
||||
type: "complement",
|
||||
selection: renderSandwich(s.selection),
|
||||
};
|
||||
}
|
||||
const e = getEnglishWord(s.selection.entry);
|
||||
if (!e || typeof e !== "string") {
|
||||
throw new Error("error getting english for compliment");
|
||||
}
|
||||
if (s.selection.type === "loc. adv.") {
|
||||
return {
|
||||
type: "complement",
|
||||
selection: {
|
||||
type: "loc. adv.",
|
||||
entry: s.selection.entry,
|
||||
ps: [psStringFromEntry(s.selection.entry)],
|
||||
e,
|
||||
inflected: false,
|
||||
// TODO: don't use persons for these
|
||||
person,
|
||||
role: "none",
|
||||
},
|
||||
};
|
||||
}
|
||||
if (s.selection.type === "adjective") {
|
||||
return {
|
||||
type: "complement",
|
||||
selection: renderAdjectiveSelection(s.selection, person, false),
|
||||
};
|
||||
}
|
||||
// if (s.selection.type === "noun") {
|
||||
return {
|
||||
type: "complement",
|
||||
selection: renderNounSelection(s.selection, false, "none"),
|
||||
};
|
||||
}
|
|
@ -8,12 +8,11 @@ import { getPersonFromVerbForm } from "../../lib/misc-helpers";
|
|||
import { getVerbBlockPosFromPerson } from "../misc-helpers";
|
||||
import { getEnglishWord } from "../get-english-word";
|
||||
import { psStringFromEntry } from "../p-text-helpers";
|
||||
import { isLocativeAdverbEntry } from "../type-predicates";
|
||||
import { renderAdjectiveSelection } from "./render-adj";
|
||||
import { renderSandwich } from "./render-sandwich";
|
||||
import { EPSBlocksAreComplete, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
|
||||
import { removeAccentsWLength } from "../accent-helpers";
|
||||
import { findPossesivesToShrink, orderKids } from "./render-common";
|
||||
import { renderComplementSelection } from "./render-complement";
|
||||
|
||||
export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
||||
const { kids, blocks, englishEquativePerson } = getEPSBlocksAndKids(EP);
|
||||
|
@ -45,7 +44,8 @@ function getEPSBlocksAndKids(EP: T.EPSelectionComplete): { kids: T.Kid[], blocks
|
|||
type: "predicateSelection",
|
||||
selection: EP.predicate.selection.type === "NP"
|
||||
? renderNPSelection(EP.predicate.selection, false, false, "subject", "king")
|
||||
: renderEqCompSelection(EP.predicate.selection, commandingPerson),
|
||||
// we won't have an unselected complement in the EP - TODO: make safer?
|
||||
: renderComplementSelection(EP.predicate.selection, commandingPerson) as T.Rendered<T.ComplementSelection>,
|
||||
}),
|
||||
makeBlock(equative),
|
||||
], EP.equative.negative);
|
||||
|
@ -150,40 +150,6 @@ export function renderAdverbSelection(a: T.AdverbSelection): T.Rendered<T.Adverb
|
|||
};
|
||||
}
|
||||
|
||||
function renderEqCompSelection(s: T.EqCompSelection, person: T.Person): T.Rendered<T.EqCompSelection> {
|
||||
if (s.selection.type === "sandwich") {
|
||||
return {
|
||||
type: "EQComp",
|
||||
selection: renderSandwich(s.selection),
|
||||
};
|
||||
}
|
||||
const e = getEnglishWord(s.selection.entry);
|
||||
if (!e || typeof e !== "string") {
|
||||
throw new Error("error getting english for compliment");
|
||||
}
|
||||
if (isLocativeAdverbEntry(s.selection.entry)) {
|
||||
return {
|
||||
type: "EQComp",
|
||||
selection: {
|
||||
type: "loc. adv.",
|
||||
entry: s.selection.entry,
|
||||
ps: [psStringFromEntry(s.selection.entry)],
|
||||
e,
|
||||
inflected: false,
|
||||
person,
|
||||
role: "none",
|
||||
},
|
||||
};
|
||||
}
|
||||
if (s.selection.type === "adjective") {
|
||||
return {
|
||||
type: "EQComp",
|
||||
selection: renderAdjectiveSelection(s.selection, person, false, "none"),
|
||||
};
|
||||
}
|
||||
throw new Error("invalid EqCompSelection");
|
||||
}
|
||||
|
||||
const equativeBuilders: Record<T.EquativeTense, (p: T.Person, n: boolean) => string[]> = {
|
||||
present: (p, n) => {
|
||||
return [
|
||||
|
|
|
@ -46,7 +46,7 @@ export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflect
|
|||
throw new Error("unknown NP type");
|
||||
};
|
||||
|
||||
function renderNounSelection(n: T.NounSelection, inflected: boolean, role: "servant" | "king" | "none"): T.Rendered<T.NounSelection> {
|
||||
export function renderNounSelection(n: T.NounSelection, inflected: boolean, role: "servant" | "king" | "none"): T.Rendered<T.NounSelection> {
|
||||
const english = getEnglishFromNoun(n.entry, n.number);
|
||||
const pashto = ((): T.PsString[] => {
|
||||
const infs = inflectWord(n.entry);
|
||||
|
@ -64,7 +64,7 @@ function renderNounSelection(n: T.NounSelection, inflected: boolean, role: "serv
|
|||
const person = getPersonNumber(n.gender, n.number);
|
||||
return {
|
||||
...n,
|
||||
adjectives: n.adjectives.map(a => renderAdjectiveSelection(a, person, inflected, role)),
|
||||
adjectives: n.adjectives.map(a => renderAdjectiveSelection(a, person, inflected)),
|
||||
person,
|
||||
inflected,
|
||||
role,
|
||||
|
|
|
@ -29,6 +29,7 @@ import { renderNPSelection } from "./render-np";
|
|||
import { findPerfectiveHead, getObjectSelection, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
|
||||
import { renderAPSelection } from "./render-ap";
|
||||
import { findPossesivesToShrink, orderKids, getMiniPronounPs } from "./render-common";
|
||||
import { renderComplementSelection } from "./render-complement";
|
||||
|
||||
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
||||
|
||||
|
@ -42,6 +43,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
|||
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");
|
||||
|
@ -56,8 +58,9 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
|||
inflectSubject,
|
||||
inflectObject,
|
||||
king,
|
||||
complementPerson,
|
||||
});
|
||||
const { verbBlocks, hasBa } = renderVerbSelection(VP.verb, kingPerson, objectPerson);
|
||||
const { verbBlocks, hasBa } = renderVerbSelection(VP.verb, kingPerson, objectPerson, VP.externalComplement);
|
||||
const b: T.VPRendered = {
|
||||
type: "VPRendered",
|
||||
king,
|
||||
|
@ -332,6 +335,7 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
|
|||
inflectSubject: boolean,
|
||||
inflectObject: boolean,
|
||||
king: "subject" | "object",
|
||||
complementPerson: T.Person | undefined,
|
||||
}): T.Block[] {
|
||||
return blocks.reduce((blocks, { block }): T.Block[] => {
|
||||
if (block.type === "subjectSelection") {
|
||||
|
@ -363,9 +367,20 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
|
|||
}),
|
||||
];
|
||||
}
|
||||
if (block.type === "AP") {
|
||||
return [
|
||||
...blocks,
|
||||
makeBlock(renderAPSelection(block)),
|
||||
];
|
||||
}
|
||||
return [
|
||||
...blocks,
|
||||
makeBlock(renderAPSelection(block)),
|
||||
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[]);
|
||||
}
|
||||
|
@ -390,7 +405,7 @@ type VerbBlocks =
|
|||
| [T.PerfectParticipleBlock, T.PerfectEquativeBlock] // perfect verb
|
||||
| [T.ModalVerbBlock, T.ModalVerbKedulPart] // modal verb
|
||||
|
||||
function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, objectPerson: T.Person | undefined): {
|
||||
function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, complementPerson: T.Person | undefined, externalComplement: T.ComplementSelection | T.UnselectedComplementSelection | undefined): {
|
||||
verbBlocks: VerbBlocks
|
||||
hasBa: boolean,
|
||||
} {
|
||||
|
@ -404,7 +419,9 @@ function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, obje
|
|||
: "stative" in conjugations
|
||||
? conjugations.stative
|
||||
: conjugations;
|
||||
const { ps: { head, rest }, hasBa } = getPsVerbConjugation(conj, vs, person, objectPerson);
|
||||
const { ps: { head, rest }, hasBa } = getPsVerbConjugation(conj, vs, person, complementPerson);
|
||||
const perfective = isPerfective(vs.tense);
|
||||
const stativeHelper = isStativeHelper(vs.verb)
|
||||
const vrb: T.VerbRenderedBlock = {
|
||||
type: "verb",
|
||||
block: {
|
||||
|
@ -412,11 +429,14 @@ function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, obje
|
|||
ps: rest,
|
||||
person,
|
||||
hasBa,
|
||||
complement: (!perfective && stativeHelper && externalComplement)
|
||||
? renderComplementSelection(externalComplement, complementPerson || T.Person.FirstSingMale)
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
const verbBlocks = [
|
||||
...(head ? (
|
||||
vs.isCompound === "stative" ? [{
|
||||
(vs.isCompound === "stative" && !vrb.block.complement) ? [{
|
||||
type: "verbComplement",
|
||||
complement: head,
|
||||
} as T.VerbComplementBlock] : [{
|
||||
|
@ -424,6 +444,9 @@ function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, obje
|
|||
ps: head,
|
||||
} as T.PerfectiveHeadBlock]
|
||||
) : [] as [T.VerbComplementBlock] | [T.PerfectiveHeadBlock] | []),
|
||||
...(externalComplement && perfective && stativeHelper)
|
||||
? [renderComplementSelection(externalComplement, complementPerson || T.Person.FirstSingMale)]
|
||||
: [],
|
||||
...splitUpIfModal(vrb),
|
||||
] as VerbBlocks;
|
||||
const perfectStuff = isPerfectTense(vrb.block.tense) ? getPerfectStuff(rest, vrb) : undefined;
|
||||
|
@ -433,6 +456,12 @@ function renderVerbSelection(vs: T.VerbSelectionComplete, person: T.Person, obje
|
|||
};
|
||||
}
|
||||
|
||||
function isStativeHelper(v: T.VerbEntry): boolean {
|
||||
if (v.entry.p === "کول" && v.entry.e.includes("make")) return true;
|
||||
if (v.entry.p === "کېدل" && v.entry.e.includes("become")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function splitUpIfModal(v: T.VerbRenderedBlock): [T.VerbRenderedBlock] | [T.ModalVerbBlock, T.ModalVerbKedulPart] {
|
||||
if (!isModalTense(v.block.tense)) {
|
||||
return [v];
|
||||
|
@ -489,7 +518,7 @@ function getPsVerbConjugation(conj: T.VerbConjugation, vs: T.VerbSelectionComple
|
|||
if (perfective) {
|
||||
const past = isPastTense(vs.tense);
|
||||
const splitInfo = conj.info[(past || isModalTense(vs.tense)) ? "root" : "stem"].perfectiveSplit;
|
||||
if (!splitInfo) return { ps: { head: undefined, rest: verbForm }, hasBa };
|
||||
if (!splitInfo) return { ps: { head: undefined, rest: removeBaFromForm(verbForm) }, hasBa };
|
||||
// TODO: Either solve this in the inflector or here, it seems silly (or redundant)
|
||||
// to have a length option in the perfective split stem??
|
||||
const [splitHead] = getLong(getMatrixBlock(splitInfo, objectPerson, person));
|
||||
|
|
66
src/types.ts
66
src/types.ts
|
@ -554,7 +554,7 @@ export type SubjectSelectionComplete = {
|
|||
|
||||
export type PredicateSelectionComplete = {
|
||||
type: "predicateSelection",
|
||||
selection: EqCompSelection | NPSelection,
|
||||
selection: ComplementSelection | NPSelection,
|
||||
};
|
||||
|
||||
export type ObjectSelectionComplete = {
|
||||
|
@ -565,12 +565,14 @@ export type ObjectSelectionComplete = {
|
|||
export type VPSelectionState = {
|
||||
blocks: VPSBlock[]
|
||||
verb: VerbSelection,
|
||||
externalComplement: undefined | UnselectedComplementSelection | ComplementSelection,
|
||||
form: FormVersion,
|
||||
};
|
||||
|
||||
export type VPSelectionComplete = {
|
||||
blocks: VPSBlockComplete[]
|
||||
verb: VerbSelectionComplete,
|
||||
externalComplement: VPSelectionState["externalComplement"],
|
||||
form: FormVersion,
|
||||
};
|
||||
|
||||
|
@ -690,19 +692,23 @@ export type RenderedPossesorSelection = {
|
|||
shrunken: boolean,
|
||||
};
|
||||
|
||||
export type UnselectedComplementSelection = { type: "complement", selection: { type: "unselected" }};
|
||||
|
||||
export type Rendered<
|
||||
T extends
|
||||
| NPSelection
|
||||
| NPSelection["selection"]
|
||||
| APSelection
|
||||
| APSelection["selection"]
|
||||
| EqCompSelection
|
||||
| EqCompSelection["selection"]
|
||||
| SubjectSelectionComplete
|
||||
| ObjectSelectionComplete
|
||||
| PredicateSelectionComplete
|
||||
| AdjectiveSelection
|
||||
| SandwichSelection<Sandwich>
|
||||
| SandwichSelection<Sandwich>
|
||||
| ComplementSelection
|
||||
| ComplementSelection["selection"]
|
||||
| UnselectedComplementSelection
|
||||
| undefined
|
||||
> =
|
||||
T extends NPSelection
|
||||
? {
|
||||
|
@ -714,10 +720,19 @@ export type Rendered<
|
|||
type: "AP",
|
||||
selection: Rendered<APSelection["selection"]>
|
||||
}
|
||||
: T extends EqCompSelection
|
||||
: T extends ComplementSelection
|
||||
? {
|
||||
type: "EQComp",
|
||||
selection: Rendered<EqCompSelection["selection"]>
|
||||
type: "complement",
|
||||
selection: Rendered<ComplementSelection["selection"]>
|
||||
}
|
||||
: T extends UnselectedComplementSelection
|
||||
? {
|
||||
type: "complement",
|
||||
selection: {
|
||||
type: "unselected",
|
||||
ps: PsString[],
|
||||
e: string,
|
||||
},
|
||||
}
|
||||
: T extends SandwichSelection<Sandwich>
|
||||
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
||||
|
@ -740,6 +755,11 @@ export type Rendered<
|
|||
inflected: boolean,
|
||||
person: Person,
|
||||
}
|
||||
: T extends ComplementSelection
|
||||
? {
|
||||
type: "complement",
|
||||
selection: Rendered<ComplementSelection["selection"]>,
|
||||
}
|
||||
: T extends SubjectSelectionComplete
|
||||
? {
|
||||
type: "subjectSelection",
|
||||
|
@ -753,8 +773,13 @@ export type Rendered<
|
|||
: T extends PredicateSelectionComplete
|
||||
? {
|
||||
type: "predicateSelection",
|
||||
selection: Rendered<EqCompSelection> | Rendered<NPSelection>,
|
||||
} : ReplaceKey<
|
||||
selection: Rendered<ComplementSelection> | Rendered<NPSelection>,
|
||||
} : T extends undefined
|
||||
? {
|
||||
type: "undefined",
|
||||
ps: PsString,
|
||||
}
|
||||
: ReplaceKey<
|
||||
Omit<T, "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor">,
|
||||
"e",
|
||||
string
|
||||
|
@ -777,7 +802,7 @@ export type EPSelectionState = {
|
|||
predicate: {
|
||||
type: "NP" | "Complement",
|
||||
NP: NPSelection | undefined,
|
||||
Complement: EqCompSelection | undefined,
|
||||
Complement: ComplementSelection | undefined,
|
||||
},
|
||||
equative: EquativeSelection,
|
||||
omitSubject: boolean,
|
||||
|
@ -795,11 +820,11 @@ export type EPSBlockComplete = {
|
|||
export type VPSBlock = {
|
||||
key: number,
|
||||
// TODO: confusing use of APSelection / should be like APSelection s APSelection complete like the others
|
||||
block: SubjectSelection | ObjectSelection | (APSelection | undefined),
|
||||
block: SubjectSelection | ObjectSelection | (APSelection | undefined) | ComplementSelection,
|
||||
};
|
||||
export type VPSBlockComplete = {
|
||||
key: number,
|
||||
block: SubjectSelectionComplete | ObjectSelectionComplete | APSelection,
|
||||
block: SubjectSelectionComplete | ObjectSelectionComplete | APSelection | ComplementSelection,
|
||||
};
|
||||
|
||||
export type EPSelectionComplete = Omit<EPSelectionState, "predicate" | "blocks"> & {
|
||||
|
@ -808,16 +833,20 @@ export type EPSelectionComplete = Omit<EPSelectionState, "predicate" | "blocks">
|
|||
omitSubject: boolean,
|
||||
};
|
||||
|
||||
export type EqCompType = "adjective" | "loc. adv." | "sandwich"
|
||||
export type EqCompSelection = {
|
||||
type: "EQComp",
|
||||
selection: AdjectiveSelection | LocativeAdverbSelection | SandwichSelection<Sandwich>,
|
||||
};
|
||||
export type ComplementType = "adjective" | "loc. adv." | "sandwich" | "comp. noun";
|
||||
|
||||
export type SandwichSelection<S extends Sandwich> = S & {
|
||||
inside: NPSelection,
|
||||
};
|
||||
|
||||
export type ComplementSelection = {
|
||||
type: "complement",
|
||||
selection: AdjectiveSelection
|
||||
| LocativeAdverbSelection
|
||||
| SandwichSelection<Sandwich>
|
||||
| NounSelection,
|
||||
};
|
||||
|
||||
export type Sandwich = {
|
||||
type: "sandwich",
|
||||
before: PsString | undefined,
|
||||
|
@ -898,6 +927,7 @@ export type VerbRenderedBlock = {
|
|||
hasBa: boolean,
|
||||
ps: SingleOrLengthOpts<PsString[]>,
|
||||
person: Person,
|
||||
complement: undefined | Rendered<ComplementSelection> | Rendered<UnselectedComplementSelection>,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -907,6 +937,8 @@ export type Block = {
|
|||
| Rendered<ObjectSelectionComplete>
|
||||
| Rendered<APSelection>
|
||||
| Rendered<PredicateSelectionComplete>
|
||||
| Rendered<ComplementSelection>
|
||||
| Rendered<UnselectedComplementSelection>
|
||||
| PerfectParticipleBlock
|
||||
| PerfectEquativeBlock
|
||||
| ModalVerbBlock
|
||||
|
|
|
@ -46,4 +46,6 @@ module.exports = [
|
|||
1527815348, // تلل - to go
|
||||
1527815216, // راتلل - to come
|
||||
1527819674, // څملاستل - to lie down
|
||||
]
|
||||
1581086654898, // کېدل - to become
|
||||
1527812754, // کېدل - to happen
|
||||
];
|
||||
|
|
|
@ -87,4 +87,6 @@ module.exports = [
|
|||
1527815214, // راوړل - to bring
|
||||
1527819827, // راوستل - to bring
|
||||
1527812275, // لیدل - to see
|
||||
]
|
||||
1579015359582, // کول - to make
|
||||
1527812752, // کول - to do
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue