diff --git a/package.json b/package.json index 77c1fe8..f43917f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lingdocs/pashto-inflector", - "version": "3.7.9", + "version": "3.8.0", "author": "lingdocs.com", "description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations", "homepage": "https://verbs.lingdocs.com", diff --git a/src/lib/phrase-building/render-adj.ts b/src/lib/phrase-building/render-adj.ts index 162ae31..ef79c69 100644 --- a/src/lib/phrase-building/render-adj.ts +++ b/src/lib/phrase-building/render-adj.ts @@ -10,6 +10,7 @@ import { personIsPlural, } from "../../lib/misc-helpers"; import { renderSandwich } from "./render-sandwich"; +import { isPattern1Entry } from "../type-predicates"; function chooseInflection(inflections: T.UnisexSet, pers: T.Person, inflected?: boolean): T.ArrayOneOrMore { const gender = personGender(pers); @@ -29,14 +30,20 @@ export function inflectAdjective(a: T.AdjectiveSelection, person: T.Person, infl return chooseInflection(infs.inflections, person, inflected); } -export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Person, inflected: boolean): T.Rendered { +export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Person, inflected: boolean, isLocationSingSandwich?: boolean): T.Rendered { const eWord = getEnglishWord(a.entry); const e = !eWord ? undefined : typeof eWord === "string" ? eWord : (eWord.singular || undefined); - const ps = inflectAdjective(a, person, inflected); + const ps = inflectAdjective( + a, + person, + isLocationSingSandwich && isPattern1Entry(a.entry) + ? false + : inflected, + ); return { type: "adjective", entry: a.entry, diff --git a/src/lib/phrase-building/render-ep.ts b/src/lib/phrase-building/render-ep.ts index 38beb43..6b9ffac 100644 --- a/src/lib/phrase-building/render-ep.ts +++ b/src/lib/phrase-building/render-ep.ts @@ -43,7 +43,7 @@ function getEPSBlocksAndKids(EP: T.EPSelectionComplete): { kids: T.Kid[], blocks makeBlock({ type: "predicateSelection", selection: EP.predicate.selection.type === "NP" - ? renderNPSelection(EP.predicate.selection, false, false, "subject", "king") + ? renderNPSelection(EP.predicate.selection, false, false, "subject", "king", false) // we won't have an unselected complement in the EP - TODO: make safer? : renderComplementSelection(EP.predicate.selection, commandingPerson) as T.Rendered, }), @@ -119,7 +119,7 @@ function renderEPSBlocks(blocks: T.EPSBlockComplete[]): T.Block[] { } return makeBlock({ type: "subjectSelection", - selection: renderNPSelection(block.selection, false, false, "subject", "none"), + selection: renderNPSelection(block.selection, false, false, "subject", "none", false), }); }); } diff --git a/src/lib/phrase-building/render-np.ts b/src/lib/phrase-building/render-np.ts index 1ac1774..768730b 100644 --- a/src/lib/phrase-building/render-np.ts +++ b/src/lib/phrase-building/render-np.ts @@ -14,11 +14,11 @@ import { } from "../../lib/np-tools"; import { getEnglishWord } from "../get-english-word"; import { renderAdjectiveSelection } from "./render-adj"; -import { isPattern5Entry, isAnimNounEntry } from "../type-predicates"; +import { isPattern5Entry, isAnimNounEntry, isPattern1Entry } from "../type-predicates"; -export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "subject", soRole: "servant" | "king" | "none"): T.Rendered; -export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "object", soRole: "servant" | "king" | "none"): T.Rendered; -export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "subject" | "object", soRole: "servant" | "king" | "none"): T.Rendered { +export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "subject", soRole: "servant" | "king" | "none", isLocationSandwich: boolean): T.Rendered; +export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "object", soRole: "servant" | "king" | "none", isLocationSandwich: boolean): T.Rendered; +export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflectEnglish: boolean, role: "subject" | "object", soRole: "servant" | "king" | "none", isLocationSandwich: boolean): T.Rendered { if (typeof NP !== "object") { if (role !== "object") { throw new Error("ObjectNP only allowed for objects"); @@ -28,7 +28,7 @@ export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflect if (NP.selection.type === "noun") { return { type: "NP", - selection: renderNounSelection(NP.selection, inflected, soRole), + selection: renderNounSelection(NP.selection, inflected, soRole, undefined, isLocationSandwich), }; } if (NP.selection.type === "pronoun") { @@ -46,12 +46,13 @@ export function renderNPSelection(NP: T.NPSelection, inflected: boolean, inflect throw new Error("unknown NP type"); }; -export function renderNounSelection(n: T.NounSelection, inflected: boolean, role: "servant" | "king" | "none", noArticles?: true | "noArticles"): T.Rendered { +export function renderNounSelection(n: T.NounSelection, inflected: boolean, role: "servant" | "king" | "none", noArticles?: true | "noArticles", isLocationSandwich?: boolean): T.Rendered { const english = getEnglishFromNoun(n.entry, n.number, noArticles); + const nounInflects = !(isLocationSandwich && isPattern1Entry(n.entry) && n.number === "singular") const pashto = ((): T.PsString[] => { const infs = inflectWord(n.entry); const ps = n.number === "singular" - ? getInf(infs, "inflections", n.gender, false, inflected) + ? getInf(infs, "inflections", n.gender, false, nounInflects) : (() => { const plural = getInf(infs, "plural", n.gender, true, inflected); return [ @@ -68,7 +69,7 @@ export function renderNounSelection(n: T.NounSelection, inflected: boolean, role const person = getPersonNumber(n.gender, n.number); return { ...n, - adjectives: n.adjectives.map(a => renderAdjectiveSelection(a, person, inflected)), + adjectives: n.adjectives.map(a => renderAdjectiveSelection(a, person, inflected, isLocationSandwich && n.number === "singular")), person, inflected, role, @@ -132,6 +133,7 @@ function renderPossesor(possesor: T.PossesorSelection | undefined, possesorRole: possesorRole === "subj/obj" ? true : false, "subject", possesorRole === "subj/obj" ? "none" : possesorRole, + false, ), }; } diff --git a/src/lib/phrase-building/render-sandwich.ts b/src/lib/phrase-building/render-sandwich.ts index 9e65b28..f6dab97 100644 --- a/src/lib/phrase-building/render-sandwich.ts +++ b/src/lib/phrase-building/render-sandwich.ts @@ -1,11 +1,9 @@ import * as T from "../../types"; -import { isPattern1Entry, isPattern5Entry, isAnimNounEntry } from "../type-predicates"; +import { isPattern5Entry, isAnimNounEntry } from "../type-predicates"; import { renderNPSelection } from "./render-np"; export function renderSandwich(s: T.SandwichSelection): T.Rendered> { - const inflectInside = (isLocationSandwich(s) && s.inside.selection.type === "noun" && isPattern1Entry(s.inside.selection.entry) && s.inside.selection.number === "singular") - ? false - : (s.inside.selection.type === "noun" && isPattern5Entry(s.inside.selection.entry) && isAnimNounEntry(s.inside.selection.entry)) + const inflectInside: boolean | "locationSandwich" = (s.inside.selection.type === "noun" && isPattern5Entry(s.inside.selection.entry) && isAnimNounEntry(s.inside.selection.entry)) ? false : true; return { @@ -16,11 +14,12 @@ export function renderSandwich(s: T.SandwichSelection): T.Rendered): boolean { - // TODO: more nuanced version of this? - return s.before?.p === "په" && s.after?.f === "کې"; + // TODO: more nuanced version of this? or just په ? + return (s.before?.p === "په") && (s.after?.p === "کې"); } \ No newline at end of file diff --git a/src/lib/phrase-building/render-vp.ts b/src/lib/phrase-building/render-vp.ts index 02a0072..55a2750 100644 --- a/src/lib/phrase-building/render-vp.ts +++ b/src/lib/phrase-building/render-vp.ts @@ -292,7 +292,7 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: { ...blocks, makeBlock({ type: "subjectSelection", - selection: renderNPSelection(block.selection, config.inflectSubject, false, "subject", config.king === "subject" ? "king" : "servant"), + selection: renderNPSelection(block.selection, config.inflectSubject, false, "subject", config.king === "subject" ? "king" : "servant", false), }), ]; } @@ -307,7 +307,7 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: { }), ]; } - const selection = renderNPSelection(object, config.inflectObject, true, "object", config.king === "object" ? "king" : "servant"); + const selection = renderNPSelection(object, config.inflectObject, true, "object", config.king === "object" ? "king" : "servant", false); return [ ...blocks, makeBlock({