diff --git a/src/components/equative-explorer/EquativeDisplay.tsx b/src/components/equative-explorer/EquativeDisplay.tsx index b5383dc..7b546b2 100644 --- a/src/components/equative-explorer/EquativeDisplay.tsx +++ b/src/components/equative-explorer/EquativeDisplay.tsx @@ -10,18 +10,13 @@ import { ExplorerState, ExplorerReducerAction, } from "./explorer-types"; -// import { -// makeBlockWPronouns, -// } from "./explorer-helpers"; import { equativeMachine, assembleEquativeOutput, } from "../../lib/equative-machine"; import { - isPluralNounEntry, isUnisexNounEntry, isAdjectiveEntry, - isSingularEntry, isVerbEntry, isLocativeAdverbEntry, isNounEntry, @@ -47,6 +42,7 @@ function SingleItemDisplay({ state }: { state: ExplorerState }) { subject, predicate, tense: state.tense, + negative: state.negative, }) ); return
@@ -72,56 +68,27 @@ function makeNounPhrase(entry: NounEntry | UnisexNounEntry | VerbEntry, state: E entry, }; } - const isUnisex = isUnisexNounEntry(entry); - if (isUnisex && isSingularEntry(entry)) { - return { - type: "unisex noun", - number: state[entity].info.number, - gender: state[entity].info.gender, - entry, - }; - } - if (isUnisex && isPluralNounEntry(entry)) { - return { - type: "unisex noun", - number: state[entity].info.number, - gender: state[entity].info.gender, - entry, - }; - } - if (isUnisex) { - throw new Error("improper unisex noun"); - } - if (isPluralNounEntry(entry)) { - const e = entry as PluralNounEntry; - return { - type: "plural noun", - entry: e, - }; - } - if (isSingularEntry(entry)) { - const e = entry as SingularEntry; - return { - type: "singular noun", - entry: e, - number: state[entity].info.number, - }; - } - throw new Error("unable to make subject input from entry"); + return { + type: "noun", + number: state[entity].info.number, + gender: state[entity].info.gender, + entry, + }; } -export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | LocativeAdverbEntry, tense: EquativeTense, length?: "short" | "long"): T.SingleOrLengthOpts { +export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | LocativeAdverbEntry, tense: EquativeTense, negative: boolean, length?: "short" | "long"): T.SingleOrLengthOpts { // if the output's gonna have long / short forms (if it's past or wouldBe) then recursive call to make the long and short versions if (!length && "long" in assembleEquativeOutput(equativeMachine({ subject: { type: "pronoun", pronounType: "near", person: 0 }, predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e)) ? { type: "compliment", entry: e } - : { type: "unisex noun", gender: "masc", number: "singular", entry: e }, + : { type: "noun", gender: "masc", number: "singular", entry: e }, tense, + negative, }))) { return { - short: makeBlockWPronouns(e, tense, "short") as T.VerbBlock, - long: makeBlockWPronouns(e, tense, "long") as T.VerbBlock, + short: makeBlockWPronouns(e, tense, negative, "short") as T.VerbBlock, + long: makeBlockWPronouns(e, tense, negative, "long") as T.VerbBlock, }; } const makeP = (p: T.Person): T.ArrayOneOrMore => { @@ -129,8 +96,9 @@ export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | Locativ subject: { type: "pronoun", pronounType: "far", person: p }, predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e)) ? { type: "compliment", entry: e } - : { type: "unisex noun", gender: personGender(p), number: personIsPlural(p) ? "plural" : "singular", entry: e }, + : { type: "noun", gender: personGender(p), number: personIsPlural(p) ? "plural" : "singular", entry: e }, tense, + negative, })); if ("long" in b) { if (!length) throw new Error("bad length processing"); @@ -151,7 +119,7 @@ export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | Locativ function PronounBlockDisplay({ state }: { state: ExplorerState }) { const pred = state.predicate[state.predicate.type]; if (!isVerbEntry(pred) && (isAdjectiveEntry(pred) || isLocativeAdverbEntry(pred) || (isNounEntry(pred) && isUnisexNounEntry(pred)))) { - const block = makeBlockWPronouns(pred, state.tense); + const block = makeBlockWPronouns(pred, state.tense, state.negative); return o.value === state.tense)?.label} {...zIndexProps} /> +
+ dispatch({ type: "setNegative", payload: p === "neg" })} + /> +
} diff --git a/src/components/equative-explorer/explorer-types.ts b/src/components/equative-explorer/explorer-types.ts index 0714190..23053eb 100644 --- a/src/components/equative-explorer/explorer-types.ts +++ b/src/components/equative-explorer/explorer-types.ts @@ -10,6 +10,7 @@ export type ExplorerState = { length: "short" | "long", subject: SubjectEntityInfo, predicate: PredicateEntityInfo, + negative: boolean, }; export type SubjectEntityInfo = EntitiyInfo & { type: SubjectType }; @@ -46,4 +47,6 @@ export type ExplorerReducerAction = { type: "setTense", payload: EquativeTense, } | { type: "setLength", payload: "short" | "long", +} | { + type: "setNegative", payload: boolean, }; \ No newline at end of file diff --git a/src/lib/equative-machine.ts b/src/lib/equative-machine.ts index 039afd1..071e2ca 100644 --- a/src/lib/equative-machine.ts +++ b/src/lib/equative-machine.ts @@ -4,6 +4,7 @@ import { getVerbBlockPosFromPerson, getPersonFromVerbForm, concatPsString, + removeAccents, } from "@lingdocs/pashto-inflector"; import { personFromNP, @@ -12,6 +13,7 @@ import { import { evaluateCompliment, } from "./compliment-tools"; +import { isPluralNounEntry } from "./type-predicates"; // Equative Rules // - An equative equates a SUBJECT: Noun Phrase and a PREDICATE: Noun Phrase | Compliment @@ -27,11 +29,13 @@ export function equativeMachine(e: EquativeClause): EquativeClauseOutput { ? evaluateCompliment(e.predicate, personFromNP(e.subject)) : evaluateNP(e.predicate); const equative = makeEquative(e); + const negative = !!e?.negative; return { ba, subject, predicate, equative, + negative, }; } @@ -47,10 +51,19 @@ export function assembleEquativeOutput(o: EquativeClauseOutput): T.SingleOrLengt const equatives = o.equative.ps; const predicates = o.predicate.ps; const ba = o.ba ? { p: " به", f: " ba" } : ""; + const neg = o.negative ? { p: "نه ", f: "nú " } : ""; const ps = o.subject.ps.flatMap(subj => ( predicates.flatMap(pred => ( equatives.map(eq => ( - concatPsString(subj, ba, " ", pred, " ", eq)) + concatPsString( + subj, + ba, + " ", + pred, + " ", + neg, + o.negative ? removeAccents(eq) : eq, + )) ) )) )); @@ -71,7 +84,7 @@ function makeEquative(e: EquativeClause) { ? "past" : e.tense; const subjP = personFromNP(e.subject); - const englishPerson = (e.subject.type === "plural noun" || e.subject.type === "participle") + const englishPerson = (e.subject.type === "participle" || (e.subject.type === "noun" && isPluralNounEntry(e.subject.entry))) ? T.Person.ThirdSingMale : subjP const pashtoPerson = (e.subject.type === "pronoun") diff --git a/src/lib/np-tools.test.ts b/src/lib/np-tools.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/np-tools.ts b/src/lib/np-tools.ts index a9e3462..9d75e1a 100644 --- a/src/lib/np-tools.ts +++ b/src/lib/np-tools.ts @@ -1,4 +1,4 @@ -import { isMascNounEntry } from "./type-predicates"; +import { isMascNounEntry, isPluralNounEntry, isUnisexNounEntry } from "./type-predicates"; import { Types as T, getEnglishWord, @@ -18,14 +18,8 @@ export function personFromNP(np: NounPhrase): T.Person { if (np.type === "pronoun") { return np.person; } - const gender: T.Gender = "gender" in np - ? np.gender - : isMascNounEntry(np.entry) - ? "masc" - : "fem"; - const number: NounNumber = np.type === "plural noun" - ? "plural" - : np.number; + const gender = nounGender(np); + const number = nounNumber(np); return number === "plural" ? (gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale) : (gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale); @@ -41,6 +35,30 @@ export function evaluateNP(np: NounPhrase): { ps: T.PsString[], e: string } { return evaluateNoun(np); } +function nounGender(n: Noun): T.Gender { + const nGender = isUnisexNounEntry(n.entry) + ? "unisex" + : isMascNounEntry(n.entry) + ? "masc" + : "fem"; + return (nGender === "unisex" && n.gender) + ? n.gender + : (nGender === "unisex") + ? "masc" + : nGender; +} + +function nounNumber(n: Noun): NounNumber { + const nNumber = isPluralNounEntry(n.entry) + ? "plural" + : "singular"; + return nNumber === "plural" + ? "plural" + : n.number + ? n.number + : nNumber; +} + function evaluatePronoun(p: Pronoun): { ps: T.PsString[], e: string } { // TODO: Will need to handle inflecting and inflecting english pronouns etc. const [row, col] = getVerbBlockPosFromPerson(p.person); @@ -51,12 +69,11 @@ function evaluatePronoun(p: Pronoun): { ps: T.PsString[], e: string } { } function evaluateNoun(n: Noun): { ps: T.PsString[], e: string } { - const number: NounNumber = "number" in n ? n.number : "plural"; + const number = nounNumber(n); const english = getEnglishFromNoun(n.entry, number); const pashto = ((): T.PsString[] => { const infs = inflectWord(n.entry); - const gender: T.Gender = "gender" in n ? n.gender : - (isMascNounEntry(n.entry) ? "masc" : "fem"); + const gender = nounGender(n); const ps = number === "singular" ? getInf(infs, "inflections", gender, false) : [ diff --git a/src/types/gramm-types.d.ts b/src/types/gramm-types.d.ts index f04d1c6..ec4c62c 100644 --- a/src/types/gramm-types.d.ts +++ b/src/types/gramm-types.d.ts @@ -5,6 +5,7 @@ type EquativeClause = { subject: NounPhrase, predicate: NounPhrase | Compliment, tense: EquativeTense, + negative?: boolean, }; type EquativeClauseOutput = { @@ -17,6 +18,7 @@ type EquativeClauseOutput = { e: string, }, ba: boolean, + negative: boolean, equative: { ps: import("@lingdocs/pashto-inflector").Types.SentenceForm, e: string[], @@ -25,23 +27,12 @@ type EquativeClauseOutput = { type NounPhrase = Pronoun | Noun | Participle; -// TODO: better, simpler type here +// The gender and number can be added, if it conflicts with the noun it will be ignored type Noun = { - type: "unisex noun", - number: NounNumber, - gender: import("@lingdocs/pashto-inflector").Types.Gender, - entry: UnisexNounEntry, - possesor?: Noun, - adjectives?: AdjectiveEntry[], -} | { - type: "plural noun", - entry: PluralNounEntry, - possesor?: Noun, - adjectives?: AdjectiveEntry[], -} | { - type: "singular noun", - number: NounNumber, - entry: SingularEntry, + type: "noun", + entry: NounEntry, + number?: NounNumber, + gender?: import("@lingdocs/pashto-inflector").Types.Gender, possesor?: Noun, adjectives?: AdjectiveEntry[], };