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