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,
}
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: tu ba laaR nu she hyphens all messed up
export function compileVP(VP: VPRendered, form: FormVersion): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] } {
const verb = VP.verb.ps;
@ -59,10 +55,15 @@ function compilePs({ NPs, kids, verb: { head, rest }, negative }: CompilePsInput
};
}
const verbWNegativeVersions = compileVerbWNegative(head, rest, negative);
// potential different versions of where the nu goes
return verbWNegativeVersions.flatMap((verbSegments) => (
// potential reordering of NPs
NPs.flatMap(NP => {
// put in kids
const segments = putKidsInKidsSection([...NP, ...verbSegments], kids);
// space out the words properly
const withProperSpaces = addSpacesBetweenSegments(segments);
// throw it all together into a PsString
return combineSegments(withProperSpaces);
})
));
@ -110,10 +111,10 @@ function getSegmentsAndKids(VP: VPRendered, form: FormVersion): { kids: Segment[
return {
kids: [
...VP.verb.hasBa
? [makeSegment(grammarUnits.baParticle, ["isBa"])] : [],
? [makeSegment(grammarUnits.baParticle, ["isBa", "isKid"])] : [],
...toShrink
? [shrink(toShrink)] : [],
].map(k => ({...k, isKid: true })),
],
NPs: [
[
...showSubject ? [makeSegment(main.subject)] : [],
@ -132,7 +133,7 @@ function getSegmentsAndKids(VP: VPRendered, form: FormVersion): { kids: Segment[
function shrink(np: Rendered<NPSelection>): Segment {
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[] {
@ -141,35 +142,12 @@ function putKidsInKidsSection(segments: Segment[], kids: Segment[]): Segment[] {
return [
first,
...(first.isVerbHead && rest[0] && rest[0].isVerbRest)
? kids.map(k => ({ ...k, isKidBetweenHeadAndRest: true }))
? kids.map(k => k.adjust({ desc: ["isKidBetweenHeadAndRest"] }))
: kids,
...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[][] {
const rest = makeSegment(restRaw.map(removeBa), ["isVerbRest"]);
const headSegment: Segment | undefined = !head
@ -182,35 +160,81 @@ function compileVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
);
if (!negative) {
return [
[
...headSegment ? [headSegment] : [],
rest,
],
headSegment ? [headSegment, rest] : [rest],
];
}
const nu: T.PsString = { p: "نه", f: "nú" };
if (!headSegment) {
return [[
makeSegment(nu, ["isNu"]),
rest.adjust({ ps: rest.ps.map(p => removeAccents(p)) }),
rest.adjust({ ps: removeAccents }),
]];
}
return [
[
...headSegment ? [headSegment.adjust({ ps: headSegment.ps.map(h =>removeAccents(h)) })] : [],
...headSegment ? [headSegment.adjust({ ps: removeAccents })] : [],
rest.adjust({
ps: rest.ps.map(r => concatPsString(nu, " ", removeAccents(r))),
ps: r => concatPsString(nu, " ", removeAccents(r)),
desc: ["isNu"],
}),
],
...!headSegment.isOoOrWaaHead ? [[
makeSegment(nu, ["isNu"]),
headSegment.adjust({ ps: headSegment.ps.map(h =>removeAccents(h)) }),
rest.adjust({ ps: rest.ps.map(p => removeAccents(p)) }),
headSegment.adjust({ ps: removeAccents }),
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[] {
const first = loe[0];
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;
}