better format with NP and AP selections etc
This commit is contained in:
parent
bb0e2daf0d
commit
4e5075ca19
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/pashto-inflector",
|
"name": "@lingdocs/pashto-inflector",
|
||||||
"version": "2.7.3",
|
"version": "2.8.0",
|
||||||
"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",
|
||||||
|
|
|
@ -16,11 +16,11 @@ function APPicker(props: {
|
||||||
onRemove: () => void,
|
onRemove: () => void,
|
||||||
}) {
|
}) {
|
||||||
const [type, setType] = useState<APType | undefined>(props.AP
|
const [type, setType] = useState<APType | undefined>(props.AP
|
||||||
? props.AP.type
|
? props.AP.selection.type
|
||||||
: undefined);
|
: undefined);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setType(props.AP
|
setType(props.AP
|
||||||
? props.AP.type
|
? props.AP.selection.type
|
||||||
: undefined);
|
: undefined);
|
||||||
}, [props.AP]);
|
}, [props.AP]);
|
||||||
function handleClear() {
|
function handleClear() {
|
||||||
|
@ -73,15 +73,15 @@ function APPicker(props: {
|
||||||
{type === "adverb" ?
|
{type === "adverb" ?
|
||||||
<AdverbPicker
|
<AdverbPicker
|
||||||
entryFeeder={props.entryFeeder.adverbs}
|
entryFeeder={props.entryFeeder.adverbs}
|
||||||
adjective={props.AP?.type === "adverb" ? props.AP : undefined}
|
adjective={props.AP?.selection.type === "adverb" ? props.AP.selection : undefined}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={props.onChange}
|
onChange={(a) => props.onChange(a ? { type: "AP", selection: a } : undefined)}
|
||||||
/>
|
/>
|
||||||
: type === "sandwich" ?
|
: type === "sandwich" ?
|
||||||
<SandwichPicker
|
<SandwichPicker
|
||||||
onChange={props.onChange}
|
onChange={(a) => props.onChange(a ? { type: "AP", selection: a } : undefined)}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
sandwich={props.AP?.type === "sandwich" ? props.AP : undefined}
|
sandwich={props.AP?.selection.type === "sandwich" ? props.AP.selection : undefined}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
phraseIsComplete={props.phraseIsComplete}
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
onExit={handleSandwichExit}
|
onExit={handleSandwichExit}
|
||||||
|
|
|
@ -49,10 +49,10 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
|
||||||
{result.e && <div className="text-muted mt-3">
|
{result.e && <div className="text-muted mt-3">
|
||||||
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
||||||
</div>}
|
</div>}
|
||||||
{EP.predicate.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4">
|
{EP.predicate.selection.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4">
|
||||||
<p>⚠️ NOTE: This means that the subject {renderedSubject.e ? `(${renderedSubject.e})` : ""} is <strong>the action/idea</strong> of
|
<p>⚠️ NOTE: This means that the subject {renderedSubject.selection.e ? `(${renderedSubject.selection.e})` : ""} is <strong>the action/idea</strong> of
|
||||||
{` `}
|
{` `}
|
||||||
"{rendered.predicate.e ? rendered.predicate.e : "the particple"}".</p>
|
"{rendered.predicate.selection.e ? rendered.predicate.selection.e : "the particple"}".</p>
|
||||||
<p>It <strong>does not</strong> mean that the subject is doing the action, which is what the transaltion sounds like in English.</p>
|
<p>It <strong>does not</strong> mean that the subject is doing the action, which is what the transaltion sounds like in English.</p>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -38,7 +38,7 @@ function EPExplorer(props: {
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder: T.EntryFeeder,
|
||||||
}) {
|
}) {
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
|
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
|
||||||
const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState4", flashMessage);
|
const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState5", flashMessage);
|
||||||
const [alert, setAlert] = useState<string | undefined>(undefined);
|
const [alert, setAlert] = useState<string | undefined>(undefined);
|
||||||
const [showClipped, setShowClipped] = useState<string>("");
|
const [showClipped, setShowClipped] = useState<string>("");
|
||||||
const parent = useRef<HTMLDivElement>(null);
|
const parent = useRef<HTMLDivElement>(null);
|
||||||
|
@ -57,7 +57,7 @@ function EPExplorer(props: {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
const subject = getSubjectSelection(eps.blocks).selection;
|
const subject = getSubjectSelection(eps.blocks).selection;
|
||||||
const king = subject?.type === "pronoun"
|
const king = subject?.selection.type === "pronoun"
|
||||||
? "subject"
|
? "subject"
|
||||||
: eps.predicate.type === "Complement"
|
: eps.predicate.type === "Complement"
|
||||||
? "subject"
|
? "subject"
|
||||||
|
|
|
@ -65,15 +65,15 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc
|
||||||
blocks: adjustSubjectSelection(eps.blocks, subject),
|
blocks: adjustSubjectSelection(eps.blocks, subject),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (subject.type === "pronoun" && eps.predicate.type === "NP" && eps.predicate.NP?.type === "noun" && isUnisexNounEntry(eps.predicate.NP.entry)) {
|
if (subject.selection.type === "pronoun" && eps.predicate.type === "NP" && eps.predicate.NP?.selection.type === "noun" && isUnisexNounEntry(eps.predicate.NP.selection.entry)) {
|
||||||
const predicate = eps.predicate.NP;
|
const predicate = eps.predicate.NP.selection;
|
||||||
const adjusted = {
|
const adjusted = {
|
||||||
...predicate,
|
...predicate,
|
||||||
...predicate.numberCanChange ? {
|
...predicate.numberCanChange ? {
|
||||||
number: personNumber(subject.person),
|
number: personNumber(subject.selection.person),
|
||||||
} : {},
|
} : {},
|
||||||
...predicate.genderCanChange ? {
|
...predicate.genderCanChange ? {
|
||||||
gender: personGender(subject.person),
|
gender: personGender(subject.selection.person),
|
||||||
} : {},
|
} : {},
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -81,7 +81,10 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc
|
||||||
blocks: adjustSubjectSelection(eps.blocks, subject),
|
blocks: adjustSubjectSelection(eps.blocks, subject),
|
||||||
predicate: {
|
predicate: {
|
||||||
...eps.predicate,
|
...eps.predicate,
|
||||||
NP: adjusted,
|
NP: {
|
||||||
|
type: "NP",
|
||||||
|
selection: adjusted,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -103,15 +106,18 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const subject = getSubjectSelection(eps.blocks).selection;
|
const subject = getSubjectSelection(eps.blocks).selection;
|
||||||
if (subject?.type === "pronoun" && selection.type === "noun" && isUnisexNounEntry(selection.entry)) {
|
if (subject?.selection.type === "pronoun" && selection.selection.type === "noun" && isUnisexNounEntry(selection.selection.entry)) {
|
||||||
const { gender, number } = selection;
|
const { gender, number } = selection.selection;
|
||||||
const pronoun = subject.person;
|
const pronoun = subject.selection.person;
|
||||||
const newPronoun = movePersonNumber(movePersonGender(pronoun, gender), number);
|
const newPronoun = movePersonNumber(movePersonGender(pronoun, gender), number);
|
||||||
return {
|
return {
|
||||||
...eps,
|
...eps,
|
||||||
blocks: adjustSubjectSelection(eps.blocks, {
|
blocks: adjustSubjectSelection(eps.blocks, {
|
||||||
...subject,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...subject.selection,
|
||||||
person: newPronoun,
|
person: newPronoun,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
predicate: {
|
predicate: {
|
||||||
...eps.predicate,
|
...eps.predicate,
|
||||||
|
|
|
@ -15,11 +15,11 @@ function EqCompPicker(props: {
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder: T.EntryFeeder,
|
||||||
}) {
|
}) {
|
||||||
const [compType, setCompType] = useState<T.EqCompType | undefined>(props.comp
|
const [compType, setCompType] = useState<T.EqCompType | undefined>(props.comp
|
||||||
? props.comp.type
|
? props.comp.selection.type
|
||||||
: undefined);
|
: undefined);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCompType(props.comp
|
setCompType(props.comp
|
||||||
? props.comp.type
|
? props.comp.selection.type
|
||||||
: undefined);
|
: undefined);
|
||||||
}, [props.comp]);
|
}, [props.comp]);
|
||||||
function handleClear() {
|
function handleClear() {
|
||||||
|
@ -68,23 +68,23 @@ function EqCompPicker(props: {
|
||||||
{compType === "adjective" ?
|
{compType === "adjective" ?
|
||||||
<AdjectivePicker
|
<AdjectivePicker
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
adjective={props.comp?.type === "adjective" ? props.comp : undefined}
|
adjective={props.comp?.selection.type === "adjective" ? props.comp.selection : undefined}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={props.onChange}
|
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||||
phraseIsComplete={props.phraseIsComplete}
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
/>
|
/>
|
||||||
: compType === "loc. adv."
|
: compType === "loc. adv."
|
||||||
? <LocativeAdverbPicker
|
? <LocativeAdverbPicker
|
||||||
entryFeeder={props.entryFeeder.locativeAdverbs}
|
entryFeeder={props.entryFeeder.locativeAdverbs}
|
||||||
adjective={props.comp?.type === "loc. adv." ? props.comp : undefined}
|
adjective={props.comp?.selection.type === "loc. adv." ? props.comp.selection : undefined}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={props.onChange}
|
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||||
/>
|
/>
|
||||||
: compType === "sandwich"
|
: compType === "sandwich"
|
||||||
? <SandwichPicker
|
? <SandwichPicker
|
||||||
onChange={props.onChange}
|
onChange={(a) => props.onChange(a ? { type: "EQComp", selection: a } : undefined)}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
sandwich={props.comp?.type === "sandwich" ? props.comp : undefined}
|
sandwich={props.comp?.selection.type === "sandwich" ? props.comp.selection : undefined}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
onExit={handleSandwichExit}
|
onExit={handleSandwichExit}
|
||||||
// TODO: get phraseIsComplete working here
|
// TODO: get phraseIsComplete working here
|
||||||
|
|
|
@ -25,19 +25,19 @@ function NPPicker(props: {
|
||||||
phraseIsComplete: boolean,
|
phraseIsComplete: boolean,
|
||||||
isShrunk?: boolean,
|
isShrunk?: boolean,
|
||||||
}) {
|
}) {
|
||||||
if (props.is2ndPersonPicker && ((props.np?.type !== "pronoun") || !isSecondPerson(props.np.person))) {
|
if (props.is2ndPersonPicker && ((props.np?.selection.type !== "pronoun") || !isSecondPerson(props.np.selection.person))) {
|
||||||
throw new Error("can't use 2ndPerson NPPicker without a pronoun");
|
throw new Error("can't use 2ndPerson NPPicker without a pronoun");
|
||||||
}
|
}
|
||||||
const [addingPoss, setAddingPoss] = useState<boolean>(false);
|
const [addingPoss, setAddingPoss] = useState<boolean>(false);
|
||||||
const [npType, setNpType] = useState<T.NPType | undefined>(props.np ? props.np.type : undefined);
|
const [npType, setNpType] = useState<T.NPType | undefined>(props.np ? props.np.selection.type : undefined);
|
||||||
const onChange = (np: T.NPSelection | undefined) => {
|
const onChange = (np: T.NPSelection | undefined) => {
|
||||||
props.onChange(ensureSingleShrink(props.np, np))
|
props.onChange(ensureSingleShrink(props.np, np))
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNpType(props.np ? props.np.type : undefined);
|
setNpType(props.np ? props.np.selection.type : undefined);
|
||||||
}, [props.np]);
|
}, [props.np]);
|
||||||
function handleClear() {
|
function handleClear() {
|
||||||
if (props.np && props.np.type === "noun" && props.np.dynamicComplement) return;
|
if (props.np && props.np.selection.type === "noun" && props.np.selection.dynamicComplement) return;
|
||||||
setNpType(undefined);
|
setNpType(undefined);
|
||||||
onChange(undefined);
|
onChange(undefined);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ function NPPicker(props: {
|
||||||
distance: "far",
|
distance: "far",
|
||||||
};
|
};
|
||||||
setNpType(ntp);
|
setNpType(ntp);
|
||||||
onChange(pronoun);
|
onChange({ type: "NP", selection: pronoun });
|
||||||
} else {
|
} else {
|
||||||
if (props.np) {
|
if (props.np) {
|
||||||
onChange(undefined);
|
onChange(undefined);
|
||||||
|
@ -60,39 +60,48 @@ function NPPicker(props: {
|
||||||
}
|
}
|
||||||
// TODO: REMOVE
|
// TODO: REMOVE
|
||||||
function handlePossesiveChange(p: T.NPSelection | undefined) {
|
function handlePossesiveChange(p: T.NPSelection | undefined) {
|
||||||
if (!props.np || props.np.type === "pronoun") return;
|
if (!props.np || props.np.selection.type === "pronoun") return;
|
||||||
if (!p) {
|
if (!p) {
|
||||||
onChange({
|
onChange({
|
||||||
...props.np,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...props.np.selection,
|
||||||
possesor: undefined,
|
possesor: undefined,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isNewPosesser = checkForNewPossesor(p, props.np.possesor);
|
const isNewPosesser = checkForNewPossesor(p, props.np.selection.possesor);
|
||||||
const possesor: T.PossesorSelection = {
|
const possesor: T.PossesorSelection = {
|
||||||
np: p,
|
np: p,
|
||||||
shrunken: (!isNewPosesser && props.np.possesor) ? props.np.possesor.shrunken : false,
|
shrunken: (!isNewPosesser && props.np.selection.possesor) ? props.np.selection.possesor.shrunken : false,
|
||||||
};
|
};
|
||||||
onChange({
|
onChange({
|
||||||
...props.np,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...props.np.selection,
|
||||||
possesor,
|
possesor,
|
||||||
});
|
|
||||||
}
|
|
||||||
function handleToggleShrunken() {
|
|
||||||
if (!props.np || props.np.type === "pronoun" || !props.np.possesor || !props.phraseIsComplete) return;
|
|
||||||
onChange({
|
|
||||||
...props.np,
|
|
||||||
possesor: {
|
|
||||||
...props.np.possesor,
|
|
||||||
shrunken: !props.np.possesor.shrunken,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const isDynamicComplement = props.np && props.np.type === "noun" && props.np.dynamicComplement;
|
function handleToggleShrunken() {
|
||||||
|
if (!props.np || props.np.selection.type === "pronoun" || !props.np.selection.possesor || !props.phraseIsComplete) return;
|
||||||
|
onChange({
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...props.np.selection,
|
||||||
|
possesor: {
|
||||||
|
...props.np.selection.possesor,
|
||||||
|
shrunken: !props.np.selection.possesor.shrunken,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const isDynamicComplement = props.np && props.np.selection.type === "noun" && props.np.selection.dynamicComplement;
|
||||||
const clearButton = (!props.cantClear && !props.is2ndPersonPicker && !isDynamicComplement)
|
const clearButton = (!props.cantClear && !props.is2ndPersonPicker && !isDynamicComplement)
|
||||||
? <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>
|
? <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>
|
||||||
: <div></div>;
|
: <div></div>;
|
||||||
const possesiveLabel = props.np?.type === "participle" ? "Subj/Obj" : "Possesor";
|
const possesiveLabel = props.np?.selection.type === "participle" ? "Subj/Obj" : "Possesor";
|
||||||
return <>
|
return <>
|
||||||
<div className="d-flex flex-row justify-content-between">
|
<div className="d-flex flex-row justify-content-between">
|
||||||
<div></div>
|
<div></div>
|
||||||
|
@ -121,15 +130,15 @@ function NPPicker(props: {
|
||||||
</button>
|
</button>
|
||||||
</div>)}
|
</div>)}
|
||||||
</div>}
|
</div>}
|
||||||
{(props.np && props.np.type !== "pronoun" && (props.np.possesor || addingPoss)) && <div className="mb-3" style={{
|
{(props.np && props.np.selection.type !== "pronoun" && (props.np.selection.possesor || addingPoss)) && <div className="mb-3" style={{
|
||||||
paddingLeft: "0.65rem",
|
paddingLeft: "0.65rem",
|
||||||
borderLeft: "2px solid grey",
|
borderLeft: "2px solid grey",
|
||||||
background: (props.np.possesor?.shrunken && !props.isShrunk) ? shrunkenBackground : "inherit",
|
background: (props.np.selection.possesor?.shrunken && !props.isShrunk) ? shrunkenBackground : "inherit",
|
||||||
}}>
|
}}>
|
||||||
<div className="d-flex flex-row text-muted mb-2">
|
<div className="d-flex flex-row text-muted mb-2">
|
||||||
<div>{possesiveLabel}:</div>
|
<div>{possesiveLabel}:</div>
|
||||||
{(props.np.possesor && !props.isShrunk && props.phraseIsComplete) && <div className="clickable ml-3 mr-2" onClick={handleToggleShrunken}>
|
{(props.np.selection.possesor && !props.isShrunk && props.phraseIsComplete) && <div className="clickable ml-3 mr-2" onClick={handleToggleShrunken}>
|
||||||
{!props.np.possesor.shrunken ? "🪄" : "👶"}
|
{!props.np.selection.possesor.shrunken ? "🪄" : "👶"}
|
||||||
</div>}
|
</div>}
|
||||||
<div className="clickable ml-2" onClick={() => {
|
<div className="clickable ml-2" onClick={() => {
|
||||||
setAddingPoss(false);
|
setAddingPoss(false);
|
||||||
|
@ -143,7 +152,7 @@ function NPPicker(props: {
|
||||||
onChange={handlePossesiveChange}
|
onChange={handlePossesiveChange}
|
||||||
counterPart={undefined}
|
counterPart={undefined}
|
||||||
cantClear
|
cantClear
|
||||||
np={props.np.possesor ? props.np.possesor.np : undefined}
|
np={props.np.selection.possesor ? props.np.selection.possesor.np : undefined}
|
||||||
role="possesor"
|
role="possesor"
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
|
@ -152,11 +161,11 @@ function NPPicker(props: {
|
||||||
{(npType === "noun" || npType === "participle") && props.np && !addingPoss && <div>
|
{(npType === "noun" || npType === "participle") && props.np && !addingPoss && <div>
|
||||||
<span className="clickable text-muted" onClick={() => setAddingPoss(true)}>+ {possesiveLabel}</span>
|
<span className="clickable text-muted" onClick={() => setAddingPoss(true)}>+ {possesiveLabel}</span>
|
||||||
</div>}
|
</div>}
|
||||||
{(npType === "pronoun" && props.np?.type === "pronoun")
|
{(npType === "pronoun" && props.np?.selection.type === "pronoun")
|
||||||
? <PronounPicker
|
? <PronounPicker
|
||||||
role={props.role}
|
role={props.role}
|
||||||
pronoun={props.np}
|
pronoun={props.np.selection}
|
||||||
onChange={onChange}
|
onChange={(p) => onChange({ type: "NP", selection: p })}
|
||||||
is2ndPersonPicker={props.is2ndPersonPicker}
|
is2ndPersonPicker={props.is2ndPersonPicker}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
|
@ -164,15 +173,15 @@ function NPPicker(props: {
|
||||||
? <NounPicker
|
? <NounPicker
|
||||||
phraseIsComplete={props.phraseIsComplete}
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
noun={(props.np && props.np.type === "noun") ? props.np : undefined}
|
noun={(props.np && props.np.selection.type === "noun") ? props.np.selection : undefined}
|
||||||
onChange={onChange}
|
onChange={(s) => onChange(s ? { type: "NP", selection: s } : undefined)}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
: npType === "participle"
|
: npType === "participle"
|
||||||
? <ParticiplePicker
|
? <ParticiplePicker
|
||||||
entryFeeder={props.entryFeeder.verbs}
|
entryFeeder={props.entryFeeder.verbs}
|
||||||
participle={(props.np && props.np.type === "participle") ? props.np : undefined}
|
participle={(props.np && props.np.selection.type === "participle") ? props.np.selection : undefined}
|
||||||
onChange={onChange}
|
onChange={(s) => onChange(s ? { type: "NP", selection: s } : undefined)}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
: null
|
: null
|
||||||
|
@ -184,44 +193,53 @@ function NPPicker(props: {
|
||||||
function ensureSingleShrink(old: T.NPSelection | undefined, s: T.NPSelection | undefined): T.NPSelection | undefined {
|
function ensureSingleShrink(old: T.NPSelection | undefined, s: T.NPSelection | undefined): T.NPSelection | undefined {
|
||||||
if (!s) return s;
|
if (!s) return s;
|
||||||
function countShrinks(np: T.NPSelection): number {
|
function countShrinks(np: T.NPSelection): number {
|
||||||
if (np.type === "pronoun") return 0;
|
if (np.selection.type === "pronoun") return 0;
|
||||||
if (!np.possesor) return 0;
|
if (!np.selection.possesor) return 0;
|
||||||
return (np.possesor.shrunken ? 1 : 0) + countShrinks(np.possesor.np);
|
return (np.selection.possesor.shrunken ? 1 : 0) + countShrinks(np.selection.possesor.np);
|
||||||
}
|
}
|
||||||
function keepNewShrink(old: T.NPSelection, n: T.NPSelection): T.NPSelection {
|
function keepNewShrink(old: T.NPSelection, n: T.NPSelection): T.NPSelection {
|
||||||
if (n.type === "pronoun") return n;
|
if (n.selection.type === "pronoun") return n;
|
||||||
if (old.type === "pronoun" || !n.possesor || !old.possesor) return n;
|
if (old.selection.type === "pronoun" || !n.selection.possesor || !old.selection.possesor) return n;
|
||||||
if (n.possesor.shrunken && !old.possesor.shrunken) {
|
if (n.selection.possesor.shrunken && !old.selection.possesor.shrunken) {
|
||||||
return {
|
return {
|
||||||
...n,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...n.selection,
|
||||||
possesor: {
|
possesor: {
|
||||||
...n.possesor,
|
...n.selection.possesor,
|
||||||
np: removeShrinks(n.possesor.np),
|
np: removeShrinks(n.selection.possesor.np),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...n,
|
type: "NP",
|
||||||
|
selection:{
|
||||||
|
...n.selection,
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: keepNewShrink(old.possesor.np, n.possesor.np),
|
np: keepNewShrink(old.selection.possesor.np, n.selection.possesor.np),
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
function removeShrinks(n: T.NPSelection): T.NPSelection {
|
function removeShrinks(n: T.NPSelection): T.NPSelection {
|
||||||
if (n.type === "pronoun") return n;
|
if (n.selection.type === "pronoun") return n;
|
||||||
if (!n.possesor) return n;
|
if (!n.selection.possesor) return n;
|
||||||
return {
|
return {
|
||||||
...n,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...n.selection,
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: removeShrinks(n.possesor.np),
|
np: removeShrinks(n.selection.possesor.np),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!old) return s;
|
if (!old) return s;
|
||||||
if (s.type === "pronoun") return s;
|
if (s.selection.type === "pronoun") return s;
|
||||||
if (!s.possesor) return s;
|
if (!s.selection.possesor) return s;
|
||||||
const numOfShrinks = countShrinks(s);
|
const numOfShrinks = countShrinks(s);
|
||||||
if (numOfShrinks < 2) return s;
|
if (numOfShrinks < 2) return s;
|
||||||
return keepNewShrink(old, s);
|
return keepNewShrink(old, s);
|
||||||
|
@ -234,12 +252,12 @@ function checkForNewPossesor(n: T.NPSelection | undefined, old: T.PossesorSelect
|
||||||
if (n.type !== old.np.type) {
|
if (n.type !== old.np.type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (n.type === "pronoun") return false;
|
if (n.selection.type === "pronoun") return false;
|
||||||
if (n.type === "noun" && old.np.type === "noun") {
|
if (n.selection.type === "noun" && old.np.selection.type === "noun") {
|
||||||
return n.entry.ts !== old.np.entry.ts;
|
return n.selection.entry.ts !== old.np.selection.entry.ts;
|
||||||
}
|
}
|
||||||
if (n.type === "participle" && old.np.type === "participle") {
|
if (n.selection.type === "participle" && old.np.selection.type === "participle") {
|
||||||
return n.verb.entry.ts !== old.np.verb.entry.ts;
|
return n.selection.verb.entry.ts !== old.np.selection.verb.entry.ts;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ function VPExplorer(props: {
|
||||||
props.loaded
|
props.loaded
|
||||||
? props.loaded
|
? props.loaded
|
||||||
: savedVps => makeVPSelectionState(props.verb, savedVps),
|
: savedVps => makeVPSelectionState(props.verb, savedVps),
|
||||||
"vpsState12",
|
"vpsState14",
|
||||||
flashMessage,
|
flashMessage,
|
||||||
);
|
);
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
||||||
|
@ -217,7 +217,7 @@ function VPExplorer(props: {
|
||||||
<i className="fas fa-chevron-right" />
|
<i className="fas fa-chevron-right" />
|
||||||
</div> : <div/>}
|
</div> : <div/>}
|
||||||
</div>
|
</div>
|
||||||
{(!block || block.type === "adverb" || block.type === "sandwich")
|
{(!block || block.type === "AP")
|
||||||
? <APPicker
|
? <APPicker
|
||||||
phraseIsComplete={phraseIsComplete}
|
phraseIsComplete={phraseIsComplete}
|
||||||
heading="AP"
|
heading="AP"
|
||||||
|
|
|
@ -269,9 +269,9 @@ function QuizNPDisplay({ children, stage, opts }: {
|
||||||
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
||||||
: <div className="text-centered" style={{ fontSize: "large" }}>
|
: <div className="text-centered" style={{ fontSize: "large" }}>
|
||||||
{stage === "blanks" && <div>
|
{stage === "blanks" && <div>
|
||||||
<InlinePs opts={opts}>{children.ps[0]}</InlinePs>
|
<InlinePs opts={opts}>{children.selection.ps[0]}</InlinePs>
|
||||||
</div>}
|
</div>}
|
||||||
<div>{children.e}</div>
|
<div>{children.selection.e}</div>
|
||||||
</div>}
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
@ -377,11 +377,11 @@ function getOptionFromResult(r: {
|
||||||
function completeVPs(vps: T.VPSelectionState): T.VPSelectionComplete {
|
function completeVPs(vps: T.VPSelectionState): T.VPSelectionComplete {
|
||||||
const vpsSubj = getSubjectSelection(vps.blocks).selection;
|
const vpsSubj = getSubjectSelection(vps.blocks).selection;
|
||||||
const vpsObj = getObjectSelection(vps.blocks).selection;
|
const vpsObj = getObjectSelection(vps.blocks).selection;
|
||||||
const oldSubj = vpsSubj?.type === "pronoun"
|
const oldSubj = vpsSubj?.selection.type === "pronoun"
|
||||||
? vpsSubj.person
|
? vpsSubj.selection.person
|
||||||
: undefined;
|
: undefined;
|
||||||
const oldObj = (typeof vpsObj === "object" && vpsObj.type === "pronoun")
|
const oldObj = (typeof vpsObj === "object" && vpsObj.selection.type === "pronoun")
|
||||||
? vpsObj.person
|
? vpsObj.selection.person
|
||||||
: undefined;
|
: undefined;
|
||||||
const { subj, obj } = randomSubjObj(
|
const { subj, obj } = randomSubjObj(
|
||||||
oldSubj === undefined
|
oldSubj === undefined
|
||||||
|
@ -400,20 +400,26 @@ function completeVPs(vps: T.VPSelectionState): T.VPSelectionComplete {
|
||||||
...vps,
|
...vps,
|
||||||
blocks: adjustObjectSelection(
|
blocks: adjustObjectSelection(
|
||||||
adjustSubjectSelection(vps.blocks, {
|
adjustSubjectSelection(vps.blocks, {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: subj,
|
person: subj,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
(
|
(
|
||||||
(typeof vpsObj === "object" && !(vpsObj.type === "noun" && vpsObj.dynamicComplement))
|
(typeof vpsObj === "object" && !(vpsObj.selection.type === "noun" && vpsObj.selection.dynamicComplement))
|
||||||
||
|
||
|
||||||
vpsObj === undefined
|
vpsObj === undefined
|
||||||
)
|
)
|
||||||
? {
|
? {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: obj,
|
person: obj,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
: vpsObj,
|
: vpsObj,
|
||||||
),
|
),
|
||||||
verb,
|
verb,
|
||||||
|
@ -426,30 +432,40 @@ function getRandomVPSelection(mix: MixType = "both") {
|
||||||
const subject = getSubjectSelection(VPS.blocks).selection;
|
const subject = getSubjectSelection(VPS.blocks).selection;
|
||||||
const object = getObjectSelection(VPS.blocks).selection;
|
const object = getObjectSelection(VPS.blocks).selection;
|
||||||
const verb = VPS.verb;
|
const verb = VPS.verb;
|
||||||
const oldSubj = (subject.type === "pronoun")
|
const oldSubj = (subject.selection.type === "pronoun")
|
||||||
? subject.person
|
? subject.selection.person
|
||||||
: undefined;
|
: undefined;
|
||||||
const oldObj = (typeof object === "object" && object.type === "pronoun")
|
const oldObj = (typeof object === "object" && object.selection.type === "pronoun")
|
||||||
? object.person
|
? object.selection.person
|
||||||
: undefined;
|
: undefined;
|
||||||
const { subj, obj } = randomSubjObj(
|
const { subj, obj } = randomSubjObj(
|
||||||
oldSubj !== undefined ? { subj: oldSubj, obj: oldObj } : undefined
|
oldSubj !== undefined ? { subj: oldSubj, obj: oldObj } : undefined
|
||||||
);
|
);
|
||||||
const randSubj: T.PronounSelection = subject?.type === "pronoun" ? {
|
const randSubj: T.NPSelection = {
|
||||||
...subject,
|
type: "NP",
|
||||||
|
selection: (
|
||||||
|
subject?.selection.type === "pronoun" ? {
|
||||||
|
...subject.selection,
|
||||||
person: subj,
|
person: subj,
|
||||||
} : {
|
} : {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: subj,
|
person: subj,
|
||||||
|
}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
const randObj: T.PronounSelection = typeof object === "object" && object.type === "pronoun" ? {
|
const randObj: T.NPSelection = {
|
||||||
...object,
|
type: "NP",
|
||||||
|
selection: (
|
||||||
|
typeof object === "object" && object.selection.type === "pronoun" ? {
|
||||||
|
...object.selection,
|
||||||
person: obj,
|
person: obj,
|
||||||
} : {
|
} : {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: obj,
|
person: obj,
|
||||||
|
}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
// ensure that the verb selection is complete
|
// ensure that the verb selection is complete
|
||||||
if (mix === "tenses") {
|
if (mix === "tenses") {
|
||||||
|
@ -466,7 +482,7 @@ function getRandomVPSelection(mix: MixType = "both") {
|
||||||
blocks: possibleShuffleArray(adjustObjectSelection(
|
blocks: possibleShuffleArray(adjustObjectSelection(
|
||||||
adjustSubjectSelection(VPS.blocks, randSubj),
|
adjustSubjectSelection(VPS.blocks, randSubj),
|
||||||
(
|
(
|
||||||
(typeof object === "object" && !(object.type === "noun" && object.dynamicComplement))
|
(typeof object === "object" && !(object.selection.type === "noun" && object.selection.dynamicComplement))
|
||||||
||
|
||
|
||||||
object === undefined
|
object === undefined
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function makeVPSelectionState(
|
||||||
const info = getVerbInfo(verb.entry, verb.complement);
|
const info = getVerbInfo(verb.entry, verb.complement);
|
||||||
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
||||||
? makeNounSelection(info.objComplement.entry as T.NounEntry, undefined, true)
|
? makeNounSelection(info.objComplement.entry as T.NounEntry, undefined, true)
|
||||||
: (os?.blocks ? getSubjectSelection(os.blocks) : undefined);
|
: (os?.blocks ? getSubjectSelection(os.blocks).selection : undefined);
|
||||||
function getTransObjFromos() {
|
function getTransObjFromos() {
|
||||||
const osObj = os ? getObjectSelection(os.blocks).selection : undefined;
|
const osObj = os ? getObjectSelection(os.blocks).selection : undefined;
|
||||||
if (
|
if (
|
||||||
|
@ -20,7 +20,7 @@ export function makeVPSelectionState(
|
||||||
osObj === "none" ||
|
osObj === "none" ||
|
||||||
typeof osObj === "number" ||
|
typeof osObj === "number" ||
|
||||||
os.verb.isCompound === "dynamic" ||
|
os.verb.isCompound === "dynamic" ||
|
||||||
(osObj?.type === "noun" && osObj.dynamicComplement)
|
(osObj?.selection.type === "noun" && osObj.selection.dynamicComplement)
|
||||||
) return undefined;
|
) return undefined;
|
||||||
return osObj;
|
return osObj;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ export function changeStatDyn(v: T.VPSelectionState, s: "dynamic" | "stative"):
|
||||||
blocks: adjustObjectSelection(
|
blocks: adjustObjectSelection(
|
||||||
v.blocks,
|
v.blocks,
|
||||||
s === "dynamic"
|
s === "dynamic"
|
||||||
? makeNounSelection(info.dynamic.objComplement.entry as T.NounEntry, undefined, true)
|
? { type: "NP", selection: makeNounSelection(info.dynamic.objComplement.entry as T.NounEntry, undefined, true) }
|
||||||
: undefined,
|
: undefined,
|
||||||
),
|
),
|
||||||
verb: {
|
verb: {
|
||||||
|
|
|
@ -285,8 +285,8 @@ export function vpsReducer(vps: T.VPSelectionState, action: VpsReducerAction, se
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasPronounConflict(subject: T.NPSelection | undefined, object: undefined | T.VerbObject): boolean {
|
function hasPronounConflict(subject: T.NPSelection | undefined, object: undefined | T.VerbObject): boolean {
|
||||||
const subjPronoun = (subject && subject.type === "pronoun") ? subject : undefined;
|
const subjPronoun = (subject && subject.selection.type === "pronoun") ? subject.selection : undefined;
|
||||||
const objPronoun = (object && typeof object === "object" && object.type === "pronoun") ? object : undefined;
|
const objPronoun = (object && typeof object === "object" && object.selection.type === "pronoun") ? object.selection : undefined;
|
||||||
if (!subjPronoun || !objPronoun) return false;
|
if (!subjPronoun || !objPronoun) return false;
|
||||||
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
||||||
}
|
}
|
|
@ -11,13 +11,13 @@ export function randomPerson(a?: { prev?: T.Person, counterPart?: T.VerbObject |
|
||||||
if (!a) {
|
if (!a) {
|
||||||
return getRandPers();
|
return getRandPers();
|
||||||
}
|
}
|
||||||
if (a.counterPart !== undefined && typeof a.counterPart === "object" && a.counterPart.type === "pronoun") {
|
if (a.counterPart !== undefined && typeof a.counterPart === "object" && a.counterPart.selection.type === "pronoun") {
|
||||||
// with counterpart pronoun
|
// with counterpart pronoun
|
||||||
let newP = 0;
|
let newP = 0;
|
||||||
do {
|
do {
|
||||||
newP = getRandPers();
|
newP = getRandPers();
|
||||||
} while (
|
} while (
|
||||||
isInvalidSubjObjCombo(a.counterPart.person, newP)
|
isInvalidSubjObjCombo(a.counterPart.selection.person, newP)
|
||||||
||
|
||
|
||||||
(newP === a.prev)
|
(newP === a.prev)
|
||||||
);
|
);
|
||||||
|
|
|
@ -56,23 +56,59 @@ export function makeAPBlock(): { key: number, block: undefined } {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeSubjectSelection(selection: T.SubjectSelection | T.NPSelection | undefined): T.SubjectSelection {
|
export function makeSubjectSelection(selection: T.SubjectSelection | T.NPSelection | T.NPSelection["selection"] | undefined): T.SubjectSelection {
|
||||||
if (selection?.type === "subjectSelection") {
|
if (!selection) {
|
||||||
|
return {
|
||||||
|
type: "subjectSelection",
|
||||||
|
selection: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (selection.type === "subjectSelection") {
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
if (selection.type === "NP") {
|
||||||
return {
|
return {
|
||||||
type: "subjectSelection",
|
type: "subjectSelection",
|
||||||
selection,
|
selection,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
|
type: "subjectSelection",
|
||||||
|
selection: {
|
||||||
|
type: "NP",
|
||||||
|
selection,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function makeObjectSelection(selection: T.ObjectSelection | T.ObjectNP | T.NPSelection | undefined): T.ObjectSelection {
|
export function makeObjectSelection(selection: T.ObjectSelection | T.ObjectNP | T.NPSelection | T.NPSelection["selection"] | undefined): T.ObjectSelection {
|
||||||
if (selection && typeof selection === "object" && selection.type === "objectSelection") {
|
if (!selection) {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection: undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof selection !== "object") {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (selection.type === "objectSelection") {
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
if (selection.type === "NP") {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection,
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
type: "objectSelection",
|
type: "objectSelection",
|
||||||
selection: selection,
|
selection: {
|
||||||
|
type: "NP",
|
||||||
|
selection,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ export function getVPSegmentsAndKids(VP: T.VPRendered, form?: T.FormVersion): {
|
||||||
if (typeof block.selection !== "object") return accum;
|
if (typeof block.selection !== "object") return accum;
|
||||||
return [
|
return [
|
||||||
...accum,
|
...accum,
|
||||||
makeSegment(getPashtoFromRendered(block.selection, subject.person)),
|
makeSegment(getPashtoFromRendered(block.selection, subject.selection.person)),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
|
@ -478,8 +478,8 @@ export function findPossesivesToShrinkInVP(VP: T.VPRendered, f: {
|
||||||
}): T.Rendered<T.NPSelection>[] {
|
}): T.Rendered<T.NPSelection>[] {
|
||||||
return VP.blocks.reduce((found, block) => {
|
return VP.blocks.reduce((found, block) => {
|
||||||
if (block.type === "subjectSelection") {
|
if (block.type === "subjectSelection") {
|
||||||
if (block.selection.role === "king" && f.removedKing) return found;
|
if (block.selection.selection.role === "king" && f.removedKing) return found;
|
||||||
if (block.selection.role === "servant" && f.shrunkServant) return found;
|
if (block.selection.selection.role === "servant" && f.shrunkServant) return found;
|
||||||
return [
|
return [
|
||||||
...findPossesivesInNP(block.selection),
|
...findPossesivesInNP(block.selection),
|
||||||
...found,
|
...found,
|
||||||
|
@ -487,19 +487,19 @@ export function findPossesivesToShrinkInVP(VP: T.VPRendered, f: {
|
||||||
}
|
}
|
||||||
if (block.type === "objectSelection") {
|
if (block.type === "objectSelection") {
|
||||||
if (typeof block.selection !== "object") return found;
|
if (typeof block.selection !== "object") return found;
|
||||||
if (block.selection.role === "king" && f.removedKing) return found;
|
if (block.selection.selection.role === "king" && f.removedKing) return found;
|
||||||
if (block.selection.role === "servant" && f.shrunkServant) return found;
|
if (block.selection.selection.role === "servant" && f.shrunkServant) return found;
|
||||||
return [
|
return [
|
||||||
...findPossesivesInNP(block.selection),
|
...findPossesivesInNP(block.selection),
|
||||||
...found,
|
...found,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (block.type === "sandwich") {
|
if (block.selection.type === "sandwich") {
|
||||||
if (block.inside.type === "pronoun") {
|
if (block.selection.inside.selection.type === "pronoun") {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
...findPossesivesInNP(block.inside),
|
...findPossesivesInNP(block.selection.inside),
|
||||||
...found,
|
...found,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -510,18 +510,18 @@ export function findPossesivesToShrinkInVP(VP: T.VPRendered, f: {
|
||||||
function findPossesivesInNP(NP: T.Rendered<T.NPSelection> | T.ObjectNP | undefined): T.Rendered<T.NPSelection>[] {
|
function findPossesivesInNP(NP: T.Rendered<T.NPSelection> | T.ObjectNP | undefined): T.Rendered<T.NPSelection>[] {
|
||||||
if (NP === undefined) return [];
|
if (NP === undefined) return [];
|
||||||
if (typeof NP !== "object") return [];
|
if (typeof NP !== "object") return [];
|
||||||
if (!NP.possesor) return [];
|
if (!NP.selection.possesor) return [];
|
||||||
if (NP.adjectives) {
|
if (NP.selection.adjectives) {
|
||||||
const { adjectives, ...rest } = NP;
|
const { adjectives, ...rest } = NP.selection;
|
||||||
return [
|
return [
|
||||||
...findPossesivesInAdjectives(adjectives),
|
...findPossesivesInAdjectives(adjectives),
|
||||||
...findPossesivesInNP(rest),
|
...findPossesivesInNP({ type: "NP", selection: rest }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (NP.possesor.shrunken) {
|
if (NP.selection.possesor.shrunken) {
|
||||||
return [NP.possesor.np];
|
return [NP.selection.possesor.np];
|
||||||
}
|
}
|
||||||
return findPossesivesInNP(NP.possesor.np);
|
return findPossesivesInNP(NP.selection.possesor.np);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPossesivesInAdjectives(a: T.Rendered<T.AdjectiveSelection>[]): T.Rendered<T.NPSelection>[] {
|
function findPossesivesInAdjectives(a: T.Rendered<T.AdjectiveSelection>[]): T.Rendered<T.NPSelection>[] {
|
||||||
|
@ -551,8 +551,8 @@ export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
||||||
...found,
|
...found,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (block.type === "sandwich") {
|
if (block.selection.type === "sandwich") {
|
||||||
const found: FoundNP[] = findPossesivesInNP(block.inside).map(np => ({ np, from: "AP" }));
|
const found: FoundNP[] = findPossesivesInNP(block.selection.inside).map(np => ({ np, from: "AP" }));
|
||||||
return [
|
return [
|
||||||
...accum,
|
...accum,
|
||||||
...found,
|
...found,
|
||||||
|
@ -560,15 +560,15 @@ export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
||||||
}
|
}
|
||||||
return accum;
|
return accum;
|
||||||
}, [] as FoundNP[]);
|
}, [] as FoundNP[]);
|
||||||
const inPredicate: FoundNP[] = ((EP.predicate.type === "loc. adv.")
|
const inPredicate: FoundNP[] = ((EP.predicate.selection.type === "loc. adv.")
|
||||||
? []
|
? []
|
||||||
: (EP.predicate.type === "adjective")
|
: (EP.predicate.selection.type === "adjective")
|
||||||
? findPossesivesInAdjective(EP.predicate)
|
? findPossesivesInAdjective(EP.predicate.selection)
|
||||||
: EP.predicate.type === "sandwich"
|
: EP.predicate.selection.type === "sandwich"
|
||||||
? findPossesivesInNP(EP.predicate.inside)
|
? findPossesivesInNP(EP.predicate.selection.inside)
|
||||||
: EP.predicate.type === "pronoun"
|
: EP.predicate.selection.type === "pronoun"
|
||||||
? []
|
? []
|
||||||
: findPossesivesInNP(EP.predicate)).map(np => ({ np, from: "predicate" }));
|
: findPossesivesInNP({ type: "NP", selection: EP.predicate.selection })).map(np => ({ np, from: "predicate" }));
|
||||||
return [
|
return [
|
||||||
...inBlocks,
|
...inBlocks,
|
||||||
...inPredicate,
|
...inPredicate,
|
||||||
|
@ -587,11 +587,11 @@ export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
||||||
|
|
||||||
export function shrinkNP(np: T.Rendered<T.NPSelection>): Segment {
|
export function shrinkNP(np: T.Rendered<T.NPSelection>): Segment {
|
||||||
function getFirstSecThird(): 1 | 2 | 3 {
|
function getFirstSecThird(): 1 | 2 | 3 {
|
||||||
if ([0, 1, 6, 7].includes(np.person)) return 1;
|
if ([0, 1, 6, 7].includes(np.selection.person)) return 1;
|
||||||
if ([2, 3, 8, 9].includes(np.person)) return 2;
|
if ([2, 3, 8, 9].includes(np.selection.person)) return 2;
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
const [row, col] = getVerbBlockPosFromPerson(np.person);
|
const [row, col] = getVerbBlockPosFromPerson(np.selection.person);
|
||||||
return makeSegment(pronouns.mini[row][col], ["isKid", getFirstSecThird()]);
|
return makeSegment(pronouns.mini[row][col], ["isKid", getFirstSecThird()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,15 @@ 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(np: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): T.PsString[] {
|
function getBaseAndAdjectives({ selection }: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): T.PsString[] {
|
||||||
if (np.type === "sandwich") {
|
if (selection.type === "sandwich") {
|
||||||
return getSandwichPsBaseAndAdjectives(np);
|
return getSandwichPsBaseAndAdjectives(selection);
|
||||||
}
|
}
|
||||||
const adjs = "adjectives" in np && np.adjectives;
|
const adjs = "adjectives" in selection && selection.adjectives;
|
||||||
if (!adjs) {
|
if (!adjs) {
|
||||||
return np.ps;
|
return selection.ps;
|
||||||
}
|
}
|
||||||
return np.ps.map(p => (
|
return selection.ps.map(p => (
|
||||||
concatPsString(
|
concatPsString(
|
||||||
adjs.reduce((accum, curr) => (
|
adjs.reduce((accum, curr) => (
|
||||||
// TODO: with variations of adjs?
|
// TODO: with variations of adjs?
|
||||||
|
@ -27,10 +27,10 @@ function getBaseAndAdjectives(np: T.Rendered<T.NPSelection | T.EqCompSelection |
|
||||||
|
|
||||||
function getSandwichPsBaseAndAdjectives(s: T.Rendered<T.SandwichSelection<T.Sandwich>>): T.PsString[] {
|
function getSandwichPsBaseAndAdjectives(s: T.Rendered<T.SandwichSelection<T.Sandwich>>): T.PsString[] {
|
||||||
const insideBase = getBaseAndAdjectives(s.inside);
|
const insideBase = getBaseAndAdjectives(s.inside);
|
||||||
const willContractWithPronoun = s.before && s.before.p === "د" && s.inside.type === "pronoun"
|
const willContractWithPronoun = s.before && s.before.p === "د" && s.inside.selection.type === "pronoun"
|
||||||
&& (isFirstPerson(s.inside.person) || isSecondPerson(s.inside.person))
|
&& (isFirstPerson(s.inside.selection.person) || isSecondPerson(s.inside.selection.person))
|
||||||
const contracted = (willContractWithPronoun && s.inside.type === "pronoun")
|
const contracted = (willContractWithPronoun && s.inside.selection.type === "pronoun")
|
||||||
? contractPronoun(s.inside)
|
? contractPronoun(s.inside.selection)
|
||||||
: undefined
|
: undefined
|
||||||
return insideBase.map((inside) => (
|
return insideBase.map((inside) => (
|
||||||
concatPsString(
|
concatPsString(
|
||||||
|
@ -52,54 +52,63 @@ function contractPronoun(n: T.Rendered<T.PronounSelection>): T.PsString | undefi
|
||||||
}
|
}
|
||||||
|
|
||||||
function trimOffShrunkenPossesive(p: T.Rendered<T.NPSelection>): T.Rendered<T.NPSelection> {
|
function trimOffShrunkenPossesive(p: T.Rendered<T.NPSelection>): T.Rendered<T.NPSelection> {
|
||||||
if (!("possesor" in p)) {
|
if (!("possesor" in p.selection)) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
if (!p.possesor) {
|
if (!p.selection.possesor) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
if (p.possesor.shrunken) {
|
if (p.selection.possesor.shrunken) {
|
||||||
return {
|
return {
|
||||||
...p,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...p.selection,
|
||||||
possesor: undefined,
|
possesor: undefined,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...p,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...p.selection,
|
||||||
possesor: {
|
possesor: {
|
||||||
...p.possesor,
|
...p.selection.possesor,
|
||||||
np: trimOffShrunkenPossesive(p.possesor.np),
|
np: trimOffShrunkenPossesive(p.selection.possesor.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.EqCompSelection> | T.Rendered<T.APSelection>, subjectsPerson: false | T.Person): T.PsString[] {
|
||||||
const base = getBaseAndAdjectives(b);
|
const base = getBaseAndAdjectives(b);
|
||||||
if (b.type === "loc. adv." || b.type === "adverb") {
|
if (b.selection.type === "loc. adv." || b.selection.type === "adverb") {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
if (b.type === "adjective") {
|
if (b.selection.type === "adjective") {
|
||||||
if (!b.sandwich) {
|
if (!b.selection.sandwich) {
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
const sandwichPs = getPashtoFromRendered(b.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 => (
|
||||||
concatPsString(s, " ", p)
|
concatPsString(s, " ", p)
|
||||||
))
|
))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
const trimmed = b.type === "sandwich" ? {
|
const trimmed = b.selection.type === "sandwich" ? {
|
||||||
...b,
|
type: b.type,
|
||||||
inside: trimOffShrunkenPossesive(b.inside),
|
selection: {
|
||||||
} : trimOffShrunkenPossesive(b);
|
...b.selection,
|
||||||
if (trimmed.type === "sandwich") {
|
inside: trimOffShrunkenPossesive(b.selection.inside),
|
||||||
return trimmed.inside.possesor
|
},
|
||||||
? addPossesor(trimmed.inside.possesor.np, base, subjectsPerson)
|
} : trimOffShrunkenPossesive({ type: "NP", selection: b.selection });
|
||||||
|
if (trimmed.selection.type === "sandwich") {
|
||||||
|
return trimmed.selection.inside.selection.possesor
|
||||||
|
? addPossesor(trimmed.selection.inside.selection.possesor.np, base, subjectsPerson)
|
||||||
: base;
|
: base;
|
||||||
}
|
}
|
||||||
if (trimmed.possesor) {
|
if (trimmed.selection.possesor) {
|
||||||
return addPossesor(trimmed.possesor.np, base, subjectsPerson);
|
return addPossesor(trimmed.selection.possesor.np, base, subjectsPerson);
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
@ -114,19 +123,19 @@ function addPossesor(owner: T.Rendered<T.NPSelection>, existing: T.PsString[], s
|
||||||
}
|
}
|
||||||
const wPossesor = existing.flatMap(ps => (
|
const wPossesor = existing.flatMap(ps => (
|
||||||
getBaseAndAdjectives(owner).map(v => (
|
getBaseAndAdjectives(owner).map(v => (
|
||||||
(owner.type === "pronoun" && subjectsPerson !== false && willBeReflexive(subjectsPerson, owner.person))
|
(owner.selection.type === "pronoun" && subjectsPerson !== false && willBeReflexive(subjectsPerson, owner.selection.person))
|
||||||
? concatPsString({ p: "خپل", f: "khpul" }, " ", ps)
|
? concatPsString({ p: "خپل", f: "khpul" }, " ", ps)
|
||||||
: (owner.type === "pronoun" && isFirstPerson(owner.person))
|
: (owner.selection.type === "pronoun" && isFirstPerson(owner.selection.person))
|
||||||
? concatPsString({ p: "ز", f: "z" }, v, " ", ps)
|
? concatPsString({ p: "ز", f: "z" }, v, " ", ps)
|
||||||
: (owner.type === "pronoun" && isSecondPerson(owner.person))
|
: (owner.selection.type === "pronoun" && isSecondPerson(owner.selection.person))
|
||||||
? concatPsString({ p: "س", f: "s" }, v, " ", ps)
|
? concatPsString({ p: "س", f: "s" }, v, " ", ps)
|
||||||
: concatPsString({ p: "د", f: "du" }, " ", v, " ", ps)
|
: concatPsString({ p: "د", f: "du" }, " ", v, " ", ps)
|
||||||
))
|
))
|
||||||
));
|
));
|
||||||
if (!owner.possesor) {
|
if (!owner.selection.possesor) {
|
||||||
return wPossesor;
|
return wPossesor;
|
||||||
}
|
}
|
||||||
return addPossesor(owner.possesor.np, wPossesor, subjectsPerson);
|
return addPossesor(owner.selection.possesor.np, wPossesor, subjectsPerson);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addArticlesAndAdjs(np: T.Rendered<T.NounSelection>): string | undefined {
|
function addArticlesAndAdjs(np: T.Rendered<T.NounSelection>): string | undefined {
|
||||||
|
@ -156,10 +165,10 @@ function addPossesors(possesor: T.Rendered<T.NPSelection> | undefined, base: str
|
||||||
}
|
}
|
||||||
if (!base) return undefined;
|
if (!base) return undefined;
|
||||||
if (!possesor) return base;
|
if (!possesor) return base;
|
||||||
if (possesor.type === "pronoun") {
|
if (possesor.selection.type === "pronoun") {
|
||||||
return type === "noun"
|
return type === "noun"
|
||||||
? `${pronounPossEng(possesor.person)} ${removeArticles(base)}`
|
? `${pronounPossEng(possesor.selection.person)} ${removeArticles(base)}`
|
||||||
: `(${pronounPossEng(possesor.person)}) ${removeArticles(base)} (${possesor.e})`
|
: `(${pronounPossEng(possesor.selection.person)}) ${removeArticles(base)} (${possesor.selection.e})`
|
||||||
}
|
}
|
||||||
const possesorE = getEnglishFromRendered(possesor);
|
const possesorE = getEnglishFromRendered(possesor);
|
||||||
if (!possesorE) return undefined;
|
if (!possesorE) return undefined;
|
||||||
|
@ -191,23 +200,23 @@ function pronounPossEng(p: T.Person): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnglishFromRendered(r: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): string | undefined {
|
export function getEnglishFromRendered(r: T.Rendered<T.NPSelection | T.EqCompSelection | T.APSelection>): string | undefined {
|
||||||
if (r.type === "sandwich") {
|
if (r.selection.type === "sandwich") {
|
||||||
return getEnglishFromRenderedSandwich(r);
|
return getEnglishFromRenderedSandwich(r.selection);
|
||||||
}
|
}
|
||||||
if (!r.e) return undefined;
|
if (!r.selection.e) return undefined;
|
||||||
if (r.type === "loc. adv." || r.type === "adverb") {
|
if (r.selection.type === "loc. adv." || r.selection.type === "adverb") {
|
||||||
return r.e;
|
return r.selection.e;
|
||||||
}
|
}
|
||||||
if (r.type === "adjective") {
|
if (r.selection.type === "adjective") {
|
||||||
return getEnglishFromRenderedAdjective(r);
|
return getEnglishFromRenderedAdjective(r.selection);
|
||||||
}
|
}
|
||||||
if (r.type === "pronoun") {
|
if (r.selection.type === "pronoun") {
|
||||||
return r.e;
|
return r.selection.e;
|
||||||
}
|
}
|
||||||
if (r.type === "participle") {
|
if (r.selection.type === "participle") {
|
||||||
return addPossesors(r.possesor?.np, r.e, r.type);
|
return addPossesors(r.selection.possesor?.np, r.selection.e, r.selection.type);
|
||||||
}
|
}
|
||||||
return addPossesors(r.possesor?.np, addArticlesAndAdjs(r), r.type);
|
return addPossesors(r.selection.possesor?.np, addArticlesAndAdjs(r.selection), r.selection.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnglishFromRenderedSandwich(r: T.Rendered<T.SandwichSelection<T.Sandwich>>): string | undefined {
|
function getEnglishFromRenderedSandwich(r: T.Rendered<T.SandwichSelection<T.Sandwich>>): string | undefined {
|
||||||
|
|
|
@ -2,11 +2,15 @@ import * as T from "../../types";
|
||||||
import { renderAdverbSelection } from "./render-ep";
|
import { renderAdverbSelection } from "./render-ep";
|
||||||
import { renderSandwich } from "./render-sandwich";
|
import { renderSandwich } from "./render-sandwich";
|
||||||
|
|
||||||
export function renderAPSelection(ap: T.APSelection): T.Rendered<T.APSelection> {
|
export function renderAPSelection({ selection }: T.APSelection): T.Rendered<T.APSelection> {
|
||||||
if (ap.type === "sandwich") {
|
if (selection.type === "sandwich") {
|
||||||
return renderSandwich(ap);
|
return {
|
||||||
|
type: "AP",
|
||||||
|
selection: renderSandwich(selection),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// if (ap.type === "adverb") {
|
return {
|
||||||
return renderAdverbSelection(ap);
|
type: "AP",
|
||||||
// }
|
selection: renderAdverbSelection(selection),
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ import { EPSBlocksAreComplete, getSubjectSelection } from "./blocks-utils";
|
||||||
|
|
||||||
export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
||||||
const subject = getSubjectSelection(EP.blocks).selection;
|
const subject = getSubjectSelection(EP.blocks).selection;
|
||||||
const king = (subject.type === "pronoun")
|
const king = (subject.selection.type === "pronoun")
|
||||||
? "subject"
|
? "subject"
|
||||||
: EP.predicate.type === "NP"
|
: EP.predicate.type === "NP"
|
||||||
? "predicate"
|
? "predicate"
|
||||||
|
@ -27,8 +27,8 @@ export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
||||||
? getPersonFromNP(EP.predicate.selection)
|
? getPersonFromNP(EP.predicate.selection)
|
||||||
: getPersonFromNP(subject);
|
: getPersonFromNP(subject);
|
||||||
const kingIsParticiple = king === "subject"
|
const kingIsParticiple = king === "subject"
|
||||||
? (subject.type === "participle")
|
? (subject.selection.type === "participle")
|
||||||
: (EP.predicate.type === "NP" && EP.predicate.selection.type === "participle");
|
: (EP.predicate.type === "NP" && EP.predicate.selection.selection.type === "participle");
|
||||||
return {
|
return {
|
||||||
type: "EPRendered",
|
type: "EPRendered",
|
||||||
king: EP.predicate.type === "Complement" ? "subject" : "predicate",
|
king: EP.predicate.type === "Complement" ? "subject" : "predicate",
|
||||||
|
@ -60,11 +60,19 @@ export function getEquativeForm(tense: T.EquativeTense): { hasBa: boolean, form:
|
||||||
|
|
||||||
function renderEPSBlocks(blocks: T.EPSBlockComplete[], king: "subject" | "predicate"): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>)[] {
|
function renderEPSBlocks(blocks: T.EPSBlockComplete[], king: "subject" | "predicate"): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>)[] {
|
||||||
return blocks.map(({ block }): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>) => {
|
return blocks.map(({ block }): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>) => {
|
||||||
if (block.type === "adverb") {
|
if (block.type === "AP") {
|
||||||
return renderAdverbSelection(block);
|
if (block.selection.type === "adverb") {
|
||||||
|
return {
|
||||||
|
type: "AP",
|
||||||
|
selection: renderAdverbSelection(block.selection),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (block.type === "sandwich") {
|
// if (block.selection.type === "sandwich") {
|
||||||
return renderSandwich(block);
|
return {
|
||||||
|
type: "AP",
|
||||||
|
selection: renderSandwich(block.selection),
|
||||||
|
};
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "subjectSelection",
|
type: "subjectSelection",
|
||||||
|
@ -98,26 +106,35 @@ export function renderAdverbSelection(a: T.AdverbSelection): T.Rendered<T.Adverb
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEqCompSelection(s: T.EqCompSelection, person: T.Person): T.Rendered<T.EqCompSelection> {
|
function renderEqCompSelection(s: T.EqCompSelection, person: T.Person): T.Rendered<T.EqCompSelection> {
|
||||||
if (s.type === "sandwich") {
|
if (s.selection.type === "sandwich") {
|
||||||
return renderSandwich(s);
|
return {
|
||||||
|
type: "EQComp",
|
||||||
|
selection: renderSandwich(s.selection),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
const e = getEnglishWord(s.entry);
|
const e = getEnglishWord(s.selection.entry);
|
||||||
if (!e || typeof e !== "string") {
|
if (!e || typeof e !== "string") {
|
||||||
throw new Error("error getting english for compliment");
|
throw new Error("error getting english for compliment");
|
||||||
}
|
}
|
||||||
if (isLocativeAdverbEntry(s.entry)) {
|
if (isLocativeAdverbEntry(s.selection.entry)) {
|
||||||
return {
|
return {
|
||||||
|
type: "EQComp",
|
||||||
|
selection: {
|
||||||
type: "loc. adv.",
|
type: "loc. adv.",
|
||||||
entry: s.entry,
|
entry: s.selection.entry,
|
||||||
ps: [psStringFromEntry(s.entry)],
|
ps: [psStringFromEntry(s.selection.entry)],
|
||||||
e,
|
e,
|
||||||
inflected: false,
|
inflected: false,
|
||||||
person,
|
person,
|
||||||
role: "none",
|
role: "none",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (s.type === "adjective") {
|
if (s.selection.type === "adjective") {
|
||||||
return renderAdjectiveSelection(s, person, false, "none")
|
return {
|
||||||
|
type: "EQComp",
|
||||||
|
selection: renderAdjectiveSelection(s.selection, person, false, "none"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
throw new Error("invalid EqCompSelection");
|
throw new Error("invalid EqCompSelection");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,23 @@ export function renderNPSelection(NP: T.NPSelection | T.ObjectNP, inflected: boo
|
||||||
}
|
}
|
||||||
return NP;
|
return NP;
|
||||||
}
|
}
|
||||||
if (NP.type === "noun") {
|
if (NP.selection.type === "noun") {
|
||||||
return renderNounSelection(NP, inflected, soRole);
|
return {
|
||||||
|
type: "NP",
|
||||||
|
selection: renderNounSelection(NP.selection, inflected, soRole),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (NP.type === "pronoun") {
|
if (NP.selection.type === "pronoun") {
|
||||||
return renderPronounSelection(NP, inflected, inflectEnglish, soRole);
|
return {
|
||||||
|
type: "NP",
|
||||||
|
selection: renderPronounSelection(NP.selection, inflected, inflectEnglish, soRole),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (NP.type === "participle") {
|
if (NP.selection.type === "participle") {
|
||||||
return renderParticipleSelection(NP, inflected, soRole)
|
return {
|
||||||
|
type: "NP",
|
||||||
|
selection: renderParticipleSelection(NP.selection, inflected, soRole),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
throw new Error("unknown NP type");
|
throw new Error("unknown NP type");
|
||||||
};
|
};
|
||||||
|
@ -91,10 +100,10 @@ function renderParticipleSelection(p: T.ParticipleSelection, inflected: boolean,
|
||||||
|
|
||||||
function renderPossesor(possesor: T.PossesorSelection | undefined, possesorRole: "servant" | "king" | "none" | "subj/obj"): T.RenderedPossesorSelection | undefined {
|
function renderPossesor(possesor: T.PossesorSelection | undefined, possesorRole: "servant" | "king" | "none" | "subj/obj"): T.RenderedPossesorSelection | undefined {
|
||||||
if (!possesor) return undefined;
|
if (!possesor) return undefined;
|
||||||
const isSingUnisexAnim5PatternNoun = (possesor.np.type === "noun"
|
const isSingUnisexAnim5PatternNoun = (possesor.np.selection.type === "noun"
|
||||||
&& possesor.np.number === "singular"
|
&& possesor.np.selection.number === "singular"
|
||||||
&& isAnimNounEntry(possesor.np.entry)
|
&& isAnimNounEntry(possesor.np.selection.entry)
|
||||||
&& isPattern5Entry(possesor.np.entry)
|
&& isPattern5Entry(possesor.np.selection.entry)
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
shrunken: possesor.shrunken,
|
shrunken: possesor.shrunken,
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { isPattern1Entry, isPattern5Entry, isAnimNounEntry } from "../type-predi
|
||||||
import { renderNPSelection } from "./render-np";
|
import { renderNPSelection } from "./render-np";
|
||||||
|
|
||||||
export function renderSandwich(s: T.SandwichSelection<T.Sandwich>): T.Rendered<T.SandwichSelection<T.Sandwich>> {
|
export function renderSandwich(s: T.SandwichSelection<T.Sandwich>): T.Rendered<T.SandwichSelection<T.Sandwich>> {
|
||||||
const inflectInside = (isLocationSandwich(s) && s.inside.type === "noun" && isPattern1Entry(s.inside.entry) && s.inside.number === "singular")
|
const inflectInside = (isLocationSandwich(s) && s.inside.selection.type === "noun" && isPattern1Entry(s.inside.selection.entry) && s.inside.selection.number === "singular")
|
||||||
? false
|
? false
|
||||||
: (s.inside.type === "noun" && isPattern5Entry(s.inside.entry) && isAnimNounEntry(s.inside.entry))
|
: (s.inside.selection.type === "noun" && isPattern5Entry(s.inside.selection.entry) && isAnimNounEntry(s.inside.selection.entry))
|
||||||
? false
|
? false
|
||||||
: true;
|
: true;
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -261,8 +261,8 @@ export function getKingAndServant(isPast: boolean, isTransitive: boolean):
|
||||||
|
|
||||||
function isFirstOrSecondPersPronoun(o: "none" | T.NPSelection | T.Person.ThirdPlurMale): boolean {
|
function isFirstOrSecondPersPronoun(o: "none" | T.NPSelection | T.Person.ThirdPlurMale): boolean {
|
||||||
if (typeof o !== "object") return false;
|
if (typeof o !== "object") return false;
|
||||||
if (o.type !== "pronoun") return false;
|
if (o.selection.type !== "pronoun") return false;
|
||||||
return [0,1,2,3,6,7,8,9].includes(o.person);
|
return [0,1,2,3,6,7,8,9].includes(o.selection.person);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPerfective(t: T.Tense): boolean {
|
function isPerfective(t: T.Tense): boolean {
|
||||||
|
@ -283,11 +283,11 @@ function isPerfective(t: T.Tense): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMascSingAnimatePattern4(np: T.NPSelection): boolean {
|
function isMascSingAnimatePattern4(np: T.NPSelection): boolean {
|
||||||
if (np.type !== "noun") {
|
if (np.selection.type !== "noun") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isPattern4Entry(np.entry)
|
return isPattern4Entry(np.selection.entry)
|
||||||
&& np.entry.c.includes("anim.")
|
&& np.selection.entry.c.includes("anim.")
|
||||||
&& (np.number === "singular")
|
&& (np.selection.number === "singular")
|
||||||
&& (np.gender === "masc");
|
&& (np.selection.gender === "masc");
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,15 +125,15 @@ export function getPersonFromNP(np: T.NPSelection | T.ObjectNP): T.Person | unde
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (typeof np === "number") return np;
|
if (typeof np === "number") return np;
|
||||||
if (np.type === "participle") {
|
if (np.selection.type === "participle") {
|
||||||
return T.Person.ThirdPlurMale;
|
return T.Person.ThirdPlurMale;
|
||||||
}
|
}
|
||||||
if (np.type === "pronoun") {
|
if (np.selection.type === "pronoun") {
|
||||||
return np.person;
|
return np.selection.person;
|
||||||
}
|
}
|
||||||
return np.number === "plural"
|
return np.selection.number === "plural"
|
||||||
? (np.gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
|
? (np.selection.gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
|
||||||
: (np.gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
: (np.selection.gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeBa(ps: T.PsString): T.PsString {
|
export function removeBa(ps: T.PsString): T.PsString {
|
||||||
|
@ -258,14 +258,17 @@ export function isThirdPerson(p: T.Person): boolean {
|
||||||
export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelectionState): T.VPSelectionState {
|
export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelectionState): T.VPSelectionState {
|
||||||
const subject = getSubjectSelection(vps.blocks).selection;
|
const subject = getSubjectSelection(vps.blocks).selection;
|
||||||
const object = getObjectSelection(vps.blocks).selection;
|
const object = getObjectSelection(vps.blocks).selection;
|
||||||
const subjIs2ndPerson = (subject?.type === "pronoun") && isSecondPerson(subject.person);
|
const subjIs2ndPerson = (subject?.selection.type === "pronoun") && isSecondPerson(subject.selection.person);
|
||||||
const objIs2ndPerson = (typeof object === "object")
|
const objIs2ndPerson = (typeof object === "object")
|
||||||
&& (object.type === "pronoun")
|
&& (object.selection.type === "pronoun")
|
||||||
&& isSecondPerson(object.person);
|
&& isSecondPerson(object.selection.person);
|
||||||
const default2ndPersSubject: T.PronounSelection = {
|
const default2ndPersSubject: T.NPSelection = {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: T.Person.SecondSingMale,
|
person: T.Person.SecondSingMale,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
function getNon2ndPersPronoun() {
|
function getNon2ndPersPronoun() {
|
||||||
let newObjPerson: T.Person;
|
let newObjPerson: T.Person;
|
||||||
|
@ -278,22 +281,25 @@ export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelectionState):
|
||||||
return vps;
|
return vps;
|
||||||
}
|
}
|
||||||
if (subjIs2ndPerson && objIs2ndPerson) {
|
if (subjIs2ndPerson && objIs2ndPerson) {
|
||||||
if (typeof object !== "object" || object.type !== "pronoun") {
|
if (typeof object !== "object" || object.selection.type !== "pronoun") {
|
||||||
return vps;
|
return vps;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...vps,
|
...vps,
|
||||||
blocks: adjustObjectSelection(vps.blocks, {
|
blocks: adjustObjectSelection(vps.blocks, {
|
||||||
...object,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...object.selection,
|
||||||
person: getNon2ndPersPronoun(),
|
person: getNon2ndPersPronoun(),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!subjIs2ndPerson && objIs2ndPerson) {
|
if (!subjIs2ndPerson && objIs2ndPerson) {
|
||||||
if (typeof object !== "object" || object.type !== "pronoun") {
|
if (typeof object !== "object" || object.selection.type !== "pronoun") {
|
||||||
return {
|
return {
|
||||||
...vps,
|
...vps,
|
||||||
blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject),
|
blocks: adjustSubjectSelection(vps.blocks, default2ndPersSubject)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -301,9 +307,12 @@ export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelectionState):
|
||||||
blocks: adjustObjectSelection(
|
blocks: adjustObjectSelection(
|
||||||
adjustSubjectSelection(vps.blocks, default2ndPersSubject),
|
adjustSubjectSelection(vps.blocks, default2ndPersSubject),
|
||||||
{
|
{
|
||||||
...object,
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
...object.selection,
|
||||||
person: getNon2ndPersPronoun(),
|
person: getNon2ndPersPronoun(),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
46
src/types.ts
46
src/types.ts
|
@ -610,9 +610,15 @@ export type VerbObject =
|
||||||
// or intransitive "none"
|
// or intransitive "none"
|
||||||
ObjectNP;
|
ObjectNP;
|
||||||
|
|
||||||
export type NPSelection = NounSelection | PronounSelection | ParticipleSelection;
|
export type NPSelection = {
|
||||||
|
type: "NP",
|
||||||
|
selection: NounSelection | PronounSelection | ParticipleSelection,
|
||||||
|
};
|
||||||
|
|
||||||
export type APSelection = AdverbSelection | SandwichSelection<Sandwich>;
|
export type APSelection = {
|
||||||
|
type: "AP",
|
||||||
|
selection: AdverbSelection | SandwichSelection<Sandwich>,
|
||||||
|
};
|
||||||
|
|
||||||
export type NPType = "noun" | "pronoun" | "participle";
|
export type NPType = "noun" | "pronoun" | "participle";
|
||||||
|
|
||||||
|
@ -679,7 +685,35 @@ export type RenderedPossesorSelection = {
|
||||||
shrunken: boolean,
|
shrunken: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Rendered<T extends NPSelection | EqCompSelection | AdjectiveSelection | SandwichSelection<Sandwich> | APSelection | SubjectSelectionComplete | ObjectSelectionComplete> = T extends SandwichSelection<Sandwich>
|
export type Rendered<
|
||||||
|
T extends
|
||||||
|
| NPSelection
|
||||||
|
| NPSelection["selection"]
|
||||||
|
| APSelection
|
||||||
|
| APSelection["selection"]
|
||||||
|
| EqCompSelection
|
||||||
|
| EqCompSelection["selection"]
|
||||||
|
| SubjectSelectionComplete
|
||||||
|
| ObjectSelectionComplete
|
||||||
|
| AdjectiveSelection
|
||||||
|
| SandwichSelection<Sandwich>
|
||||||
|
> =
|
||||||
|
T extends NPSelection
|
||||||
|
? {
|
||||||
|
type: "NP",
|
||||||
|
selection: Rendered<NPSelection["selection"]>
|
||||||
|
}
|
||||||
|
: T extends APSelection
|
||||||
|
? {
|
||||||
|
type: "AP",
|
||||||
|
selection: Rendered<APSelection["selection"]>
|
||||||
|
}
|
||||||
|
: T extends EqCompSelection
|
||||||
|
? {
|
||||||
|
type: "EQComp",
|
||||||
|
selection: Rendered<EqCompSelection["selection"]>
|
||||||
|
}
|
||||||
|
: T extends SandwichSelection<Sandwich>
|
||||||
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
||||||
inside: Rendered<NPSelection>,
|
inside: Rendered<NPSelection>,
|
||||||
}
|
}
|
||||||
|
@ -727,7 +761,6 @@ export type Rendered<T extends NPSelection | EqCompSelection | AdjectiveSelectio
|
||||||
np: Rendered<NPSelection>,
|
np: Rendered<NPSelection>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// TODO: recursive changing this down into the possesor etc.
|
|
||||||
|
|
||||||
export type EPSelectionState = {
|
export type EPSelectionState = {
|
||||||
blocks: EPSBlock[],
|
blocks: EPSBlock[],
|
||||||
|
@ -772,7 +805,10 @@ export type EPSelectionComplete = Omit<EPSelectionState, "predicate" | "blocks">
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EqCompType = "adjective" | "loc. adv." | "sandwich"
|
export type EqCompType = "adjective" | "loc. adv." | "sandwich"
|
||||||
export type EqCompSelection = AdjectiveSelection | LocativeAdverbSelection | SandwichSelection<Sandwich>;
|
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,
|
||||||
|
|
Loading…
Reference in New Issue