more refactoring, monad-ish? phrase segments in the phrase compiler

This commit is contained in:
lingdocs 2022-03-25 21:58:00 +05:00
parent e32f2cd6e7
commit c8c2132bbf
1 changed files with 65 additions and 56 deletions

View File

@ -18,12 +18,8 @@ type SegmentDescriptions = {
isBa?: boolean, isBa?: boolean,
} }
type SDT = keyof SegmentDescriptions;
type Segment = { ps: T.PsString[] } & SegmentDescriptions & {
adjust: (o: { ps?: T.PsString | T.PsString[], desc?: SDT[] }) => Segment,
};
// TODO: make it an option to include O S V order // TODO: make it an option to include O S V order
// TODO: tu ba laaR nu she hyphens all messed up
export function compileVP(VP: VPRendered, form: FormVersion): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] } { export function compileVP(VP: VPRendered, form: FormVersion): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] } {
const verb = VP.verb.ps; const verb = VP.verb.ps;
@ -59,10 +55,15 @@ function compilePs({ NPs, kids, verb: { head, rest }, negative }: CompilePsInput
}; };
} }
const verbWNegativeVersions = compileVerbWNegative(head, rest, negative); const verbWNegativeVersions = compileVerbWNegative(head, rest, negative);
// potential different versions of where the nu goes
return verbWNegativeVersions.flatMap((verbSegments) => ( return verbWNegativeVersions.flatMap((verbSegments) => (
// potential reordering of NPs
NPs.flatMap(NP => { NPs.flatMap(NP => {
// put in kids
const segments = putKidsInKidsSection([...NP, ...verbSegments], kids); const segments = putKidsInKidsSection([...NP, ...verbSegments], kids);
// space out the words properly
const withProperSpaces = addSpacesBetweenSegments(segments); const withProperSpaces = addSpacesBetweenSegments(segments);
// throw it all together into a PsString
return combineSegments(withProperSpaces); return combineSegments(withProperSpaces);
}) })
)); ));
@ -110,10 +111,10 @@ function getSegmentsAndKids(VP: VPRendered, form: FormVersion): { kids: Segment[
return { return {
kids: [ kids: [
...VP.verb.hasBa ...VP.verb.hasBa
? [makeSegment(grammarUnits.baParticle, ["isBa"])] : [], ? [makeSegment(grammarUnits.baParticle, ["isBa", "isKid"])] : [],
...toShrink ...toShrink
? [shrink(toShrink)] : [], ? [shrink(toShrink)] : [],
].map(k => ({...k, isKid: true })), ],
NPs: [ NPs: [
[ [
...showSubject ? [makeSegment(main.subject)] : [], ...showSubject ? [makeSegment(main.subject)] : [],
@ -132,7 +133,7 @@ function getSegmentsAndKids(VP: VPRendered, form: FormVersion): { kids: Segment[
function shrink(np: Rendered<NPSelection>): Segment { function shrink(np: Rendered<NPSelection>): Segment {
const [row, col] = getVerbBlockPosFromPerson(np.person); const [row, col] = getVerbBlockPosFromPerson(np.person);
return makeSegment(grammarUnits.pronouns.mini[row][col], ["isMiniPronoun"]); return makeSegment(grammarUnits.pronouns.mini[row][col], ["isKid", "isMiniPronoun"]);
} }
function putKidsInKidsSection(segments: Segment[], kids: Segment[]): Segment[] { function putKidsInKidsSection(segments: Segment[], kids: Segment[]): Segment[] {
@ -141,35 +142,12 @@ function putKidsInKidsSection(segments: Segment[], kids: Segment[]): Segment[] {
return [ return [
first, first,
...(first.isVerbHead && rest[0] && rest[0].isVerbRest) ...(first.isVerbHead && rest[0] && rest[0].isVerbRest)
? kids.map(k => ({ ...k, isKidBetweenHeadAndRest: true })) ? kids.map(k => k.adjust({ desc: ["isKidBetweenHeadAndRest"] }))
: kids, : kids,
...rest, ...rest,
]; ];
} }
function makeSegment(
ps: T.PsString | T.PsString[],
options?: (keyof SegmentDescriptions)[],
): Segment {
return {
ps: Array.isArray(ps) ? ps : [ps],
...options && options.reduce((all, curr) => ({
...all,
[curr]: true,
}), {}),
adjust: function(o: { ps?: T.PsString | T.PsString[], desc?: SDT[] }): Segment {
return {
...this,
...o.ps ? { ps: Array.isArray(o.ps) ? o.ps : [o.ps] } : {},
...o.desc && o.desc.reduce((all, curr) => ({
...all,
[curr]: true,
}), {}),
};
},
}
}
function compileVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], negative: boolean): Segment[][] { function compileVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], negative: boolean): Segment[][] {
const rest = makeSegment(restRaw.map(removeBa), ["isVerbRest"]); const rest = makeSegment(restRaw.map(removeBa), ["isVerbRest"]);
const headSegment: Segment | undefined = !head const headSegment: Segment | undefined = !head
@ -182,35 +160,81 @@ function compileVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
); );
if (!negative) { if (!negative) {
return [ return [
[ headSegment ? [headSegment, rest] : [rest],
...headSegment ? [headSegment] : [],
rest,
],
]; ];
} }
const nu: T.PsString = { p: "نه", f: "nú" }; const nu: T.PsString = { p: "نه", f: "nú" };
if (!headSegment) { if (!headSegment) {
return [[ return [[
makeSegment(nu, ["isNu"]), makeSegment(nu, ["isNu"]),
rest.adjust({ ps: rest.ps.map(p => removeAccents(p)) }), rest.adjust({ ps: removeAccents }),
]]; ]];
} }
return [ return [
[ [
...headSegment ? [headSegment.adjust({ ps: headSegment.ps.map(h =>removeAccents(h)) })] : [], ...headSegment ? [headSegment.adjust({ ps: removeAccents })] : [],
rest.adjust({ rest.adjust({
ps: rest.ps.map(r => concatPsString(nu, " ", removeAccents(r))), ps: r => concatPsString(nu, " ", removeAccents(r)),
desc: ["isNu"], desc: ["isNu"],
}), }),
], ],
...!headSegment.isOoOrWaaHead ? [[ ...!headSegment.isOoOrWaaHead ? [[
makeSegment(nu, ["isNu"]), makeSegment(nu, ["isNu"]),
headSegment.adjust({ ps: headSegment.ps.map(h =>removeAccents(h)) }), headSegment.adjust({ ps: removeAccents }),
rest.adjust({ ps: rest.ps.map(p => removeAccents(p)) }), rest.adjust({ ps: removeAccents }),
]] : [], ]] : [],
]; ];
} }
function compileEnglish(VP: VPRendered): string[] | undefined {
function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
return e.replace("$SUBJ", subject).replace("$OBJ", object || "");
}
const engSubj = VP.subject.e || undefined;
const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
// require all English parts for making the English phrase
return (VP.englishBase && engSubj && (engObj || typeof VP.object !== "object"))
? VP.englishBase.map(e => insertEWords(e, {
subject: engSubj,
object: engObj,
}))
: undefined;
}
type SDT = keyof SegmentDescriptions;
type Segment = { ps: T.PsString[] } & SegmentDescriptions & {
adjust: (o: { ps?: T.PsString | T.PsString[] | ((ps: T.PsString) => T.PsString), desc?: SDT[] }) => Segment,
};
function makeSegment(
ps: T.PsString | T.PsString[],
options?: (keyof SegmentDescriptions)[],
): Segment {
return {
ps: Array.isArray(ps) ? ps : [ps],
...options && options.reduce((all, curr) => ({
...all,
[curr]: true,
}), {}),
adjust: function(o: { ps?: T.PsString | T.PsString[] | ((ps: T.PsString) => T.PsString), desc?: SDT[] }): Segment {
return {
...this,
...o.ps ? {
ps: Array.isArray(o.ps)
? o.ps
: "p" in o.ps
? [o.ps]
: this.ps.map(o.ps)
} : {},
...o.desc && o.desc.reduce((all, curr) => ({
...all,
[curr]: true,
}), {}),
};
},
}
}
function combineSegments(loe: (Segment | " " | "" | T.PsString)[]): T.PsString[] { function combineSegments(loe: (Segment | " " | "" | T.PsString)[]): T.PsString[] {
const first = loe[0]; const first = loe[0];
const rest = loe.slice(1); const rest = loe.slice(1);
@ -227,18 +251,3 @@ function combineSegments(loe: (Segment | " " | "" | T.PsString)[]): T.PsString[]
) )
); );
} }
function compileEnglish(VP: VPRendered): string[] | undefined {
function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
return e.replace("$SUBJ", subject).replace("$OBJ", object || "");
}
const engSubj = VP.subject.e || undefined;
const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
// require all English parts for making the English phrase
return (VP.englishBase && engSubj && (engObj || typeof VP.object !== "object"))
? VP.englishBase.map(e => insertEWords(e, {
subject: engSubj,
object: engObj,
}))
: undefined;
}