refactor np and add negative in equative clause

This commit is contained in:
lingdocs 2021-11-01 15:57:12 -04:00
parent 1d9ff2b9e1
commit 440a9decb7
9 changed files with 87 additions and 77 deletions

View File

@ -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 <div>
@ -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<MascNounEntry | FemNounEntry>;
return {
type: "plural noun",
entry: e,
};
}
if (isSingularEntry(entry)) {
const e = entry as SingularEntry<MascNounEntry | FemNounEntry>;
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<T.VerbBlock> {
export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | LocativeAdverbEntry, tense: EquativeTense, negative: boolean, length?: "short" | "long"): T.SingleOrLengthOpts<T.VerbBlock> {
// 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<T.PsString> => {
@ -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 <VerbTable
textOptions={opts}
block={chooseLength(block, state.length)}

View File

@ -22,6 +22,7 @@ import EquativeDisplay from "./EquativeDisplay";
const defaultState: ExplorerState = {
tense: "present",
length: "short",
negative: false,
predicate: {
type: "adjective",
adjective: defaultAdjective,

View File

@ -94,6 +94,12 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
// },
// };
// }
if (action.type === "setNegative") {
return {
...state,
negative: action.payload,
};
}
return {
...state,
length: action.payload,

View File

@ -209,5 +209,16 @@ export function TenseSelector({ state, dispatch }: {
placeholder={options.find(o => o.value === state.tense)?.label}
{...zIndexProps}
/>
<div className="text-center mb-2">
<ButtonSelect
small
options={[
{ label: "Pos.", value: "pos" },
{ label: "Neg.", value: "neg" },
]}
value={state.negative ? "neg" : "pos"}
handleChange={(p) => dispatch({ type: "setNegative", payload: p === "neg" })}
/>
</div>
</div>
}

View File

@ -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,
};

View File

@ -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")

0
src/lib/np-tools.test.ts Normal file
View File

View File

@ -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)
: [

View File

@ -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<MascNounEntry | FemNounEntry>,
possesor?: Noun,
adjectives?: AdjectiveEntry[],
} | {
type: "singular noun",
number: NounNumber,
entry: SingularEntry<MascNounEntry | FemNounEntry>,
type: "noun",
entry: NounEntry,
number?: NounNumber,
gender?: import("@lingdocs/pashto-inflector").Types.Gender,
possesor?: Noun,
adjectives?: AdjectiveEntry[],
};