refactor np and add negative in equative clause
This commit is contained in:
parent
1d9ff2b9e1
commit
440a9decb7
|
@ -10,18 +10,13 @@ import {
|
||||||
ExplorerState,
|
ExplorerState,
|
||||||
ExplorerReducerAction,
|
ExplorerReducerAction,
|
||||||
} from "./explorer-types";
|
} from "./explorer-types";
|
||||||
// import {
|
|
||||||
// makeBlockWPronouns,
|
|
||||||
// } from "./explorer-helpers";
|
|
||||||
import {
|
import {
|
||||||
equativeMachine,
|
equativeMachine,
|
||||||
assembleEquativeOutput,
|
assembleEquativeOutput,
|
||||||
} from "../../lib/equative-machine";
|
} from "../../lib/equative-machine";
|
||||||
import {
|
import {
|
||||||
isPluralNounEntry,
|
|
||||||
isUnisexNounEntry,
|
isUnisexNounEntry,
|
||||||
isAdjectiveEntry,
|
isAdjectiveEntry,
|
||||||
isSingularEntry,
|
|
||||||
isVerbEntry,
|
isVerbEntry,
|
||||||
isLocativeAdverbEntry,
|
isLocativeAdverbEntry,
|
||||||
isNounEntry,
|
isNounEntry,
|
||||||
|
@ -47,6 +42,7 @@ function SingleItemDisplay({ state }: { state: ExplorerState }) {
|
||||||
subject,
|
subject,
|
||||||
predicate,
|
predicate,
|
||||||
tense: state.tense,
|
tense: state.tense,
|
||||||
|
negative: state.negative,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return <div>
|
return <div>
|
||||||
|
@ -72,56 +68,27 @@ function makeNounPhrase(entry: NounEntry | UnisexNounEntry | VerbEntry, state: E
|
||||||
entry,
|
entry,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const isUnisex = isUnisexNounEntry(entry);
|
|
||||||
if (isUnisex && isSingularEntry(entry)) {
|
|
||||||
return {
|
return {
|
||||||
type: "unisex noun",
|
type: "noun",
|
||||||
number: state[entity].info.number,
|
number: state[entity].info.number,
|
||||||
gender: state[entity].info.gender,
|
gender: state[entity].info.gender,
|
||||||
entry,
|
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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({
|
if (!length && "long" in assembleEquativeOutput(equativeMachine({
|
||||||
subject: { type: "pronoun", pronounType: "near", person: 0 },
|
subject: { type: "pronoun", pronounType: "near", person: 0 },
|
||||||
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
|
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
|
||||||
? { type: "compliment", entry: e }
|
? { type: "compliment", entry: e }
|
||||||
: { type: "unisex noun", gender: "masc", number: "singular", entry: e },
|
: { type: "noun", gender: "masc", number: "singular", entry: e },
|
||||||
tense,
|
tense,
|
||||||
|
negative,
|
||||||
}))) {
|
}))) {
|
||||||
return {
|
return {
|
||||||
short: makeBlockWPronouns(e, tense, "short") as T.VerbBlock,
|
short: makeBlockWPronouns(e, tense, negative, "short") as T.VerbBlock,
|
||||||
long: makeBlockWPronouns(e, tense, "long") as T.VerbBlock,
|
long: makeBlockWPronouns(e, tense, negative, "long") as T.VerbBlock,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const makeP = (p: T.Person): T.ArrayOneOrMore<T.PsString> => {
|
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 },
|
subject: { type: "pronoun", pronounType: "far", person: p },
|
||||||
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
|
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
|
||||||
? { type: "compliment", entry: 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,
|
tense,
|
||||||
|
negative,
|
||||||
}));
|
}));
|
||||||
if ("long" in b) {
|
if ("long" in b) {
|
||||||
if (!length) throw new Error("bad length processing");
|
if (!length) throw new Error("bad length processing");
|
||||||
|
@ -151,7 +119,7 @@ export function makeBlockWPronouns(e: AdjectiveEntry | UnisexNounEntry | Locativ
|
||||||
function PronounBlockDisplay({ state }: { state: ExplorerState }) {
|
function PronounBlockDisplay({ state }: { state: ExplorerState }) {
|
||||||
const pred = state.predicate[state.predicate.type];
|
const pred = state.predicate[state.predicate.type];
|
||||||
if (!isVerbEntry(pred) && (isAdjectiveEntry(pred) || isLocativeAdverbEntry(pred) || (isNounEntry(pred) && isUnisexNounEntry(pred)))) {
|
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
|
return <VerbTable
|
||||||
textOptions={opts}
|
textOptions={opts}
|
||||||
block={chooseLength(block, state.length)}
|
block={chooseLength(block, state.length)}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import EquativeDisplay from "./EquativeDisplay";
|
||||||
const defaultState: ExplorerState = {
|
const defaultState: ExplorerState = {
|
||||||
tense: "present",
|
tense: "present",
|
||||||
length: "short",
|
length: "short",
|
||||||
|
negative: false,
|
||||||
predicate: {
|
predicate: {
|
||||||
type: "adjective",
|
type: "adjective",
|
||||||
adjective: defaultAdjective,
|
adjective: defaultAdjective,
|
||||||
|
|
|
@ -94,6 +94,12 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
|
||||||
// },
|
// },
|
||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
|
if (action.type === "setNegative") {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
negative: action.payload,
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
length: action.payload,
|
length: action.payload,
|
||||||
|
|
|
@ -209,5 +209,16 @@ export function TenseSelector({ state, dispatch }: {
|
||||||
placeholder={options.find(o => o.value === state.tense)?.label}
|
placeholder={options.find(o => o.value === state.tense)?.label}
|
||||||
{...zIndexProps}
|
{...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>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ export type ExplorerState = {
|
||||||
length: "short" | "long",
|
length: "short" | "long",
|
||||||
subject: SubjectEntityInfo,
|
subject: SubjectEntityInfo,
|
||||||
predicate: PredicateEntityInfo,
|
predicate: PredicateEntityInfo,
|
||||||
|
negative: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SubjectEntityInfo = EntitiyInfo & { type: SubjectType };
|
export type SubjectEntityInfo = EntitiyInfo & { type: SubjectType };
|
||||||
|
@ -46,4 +47,6 @@ export type ExplorerReducerAction = {
|
||||||
type: "setTense", payload: EquativeTense,
|
type: "setTense", payload: EquativeTense,
|
||||||
} | {
|
} | {
|
||||||
type: "setLength", payload: "short" | "long",
|
type: "setLength", payload: "short" | "long",
|
||||||
|
} | {
|
||||||
|
type: "setNegative", payload: boolean,
|
||||||
};
|
};
|
|
@ -4,6 +4,7 @@ import {
|
||||||
getVerbBlockPosFromPerson,
|
getVerbBlockPosFromPerson,
|
||||||
getPersonFromVerbForm,
|
getPersonFromVerbForm,
|
||||||
concatPsString,
|
concatPsString,
|
||||||
|
removeAccents,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import {
|
import {
|
||||||
personFromNP,
|
personFromNP,
|
||||||
|
@ -12,6 +13,7 @@ import {
|
||||||
import {
|
import {
|
||||||
evaluateCompliment,
|
evaluateCompliment,
|
||||||
} from "./compliment-tools";
|
} from "./compliment-tools";
|
||||||
|
import { isPluralNounEntry } from "./type-predicates";
|
||||||
|
|
||||||
// Equative Rules
|
// Equative Rules
|
||||||
// - An equative equates a SUBJECT: Noun Phrase and a PREDICATE: Noun Phrase | Compliment
|
// - 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))
|
? evaluateCompliment(e.predicate, personFromNP(e.subject))
|
||||||
: evaluateNP(e.predicate);
|
: evaluateNP(e.predicate);
|
||||||
const equative = makeEquative(e);
|
const equative = makeEquative(e);
|
||||||
|
const negative = !!e?.negative;
|
||||||
return {
|
return {
|
||||||
ba,
|
ba,
|
||||||
subject,
|
subject,
|
||||||
predicate,
|
predicate,
|
||||||
equative,
|
equative,
|
||||||
|
negative,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +51,19 @@ export function assembleEquativeOutput(o: EquativeClauseOutput): T.SingleOrLengt
|
||||||
const equatives = o.equative.ps;
|
const equatives = o.equative.ps;
|
||||||
const predicates = o.predicate.ps;
|
const predicates = o.predicate.ps;
|
||||||
const ba = o.ba ? { p: " به", f: " ba" } : "";
|
const ba = o.ba ? { p: " به", f: " ba" } : "";
|
||||||
|
const neg = o.negative ? { p: "نه ", f: "nú " } : "";
|
||||||
const ps = o.subject.ps.flatMap(subj => (
|
const ps = o.subject.ps.flatMap(subj => (
|
||||||
predicates.flatMap(pred => (
|
predicates.flatMap(pred => (
|
||||||
equatives.map(eq => (
|
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"
|
? "past"
|
||||||
: e.tense;
|
: e.tense;
|
||||||
const subjP = personFromNP(e.subject);
|
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
|
? T.Person.ThirdSingMale
|
||||||
: subjP
|
: subjP
|
||||||
const pashtoPerson = (e.subject.type === "pronoun")
|
const pashtoPerson = (e.subject.type === "pronoun")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isMascNounEntry } from "./type-predicates";
|
import { isMascNounEntry, isPluralNounEntry, isUnisexNounEntry } from "./type-predicates";
|
||||||
import {
|
import {
|
||||||
Types as T,
|
Types as T,
|
||||||
getEnglishWord,
|
getEnglishWord,
|
||||||
|
@ -18,14 +18,8 @@ export function personFromNP(np: NounPhrase): T.Person {
|
||||||
if (np.type === "pronoun") {
|
if (np.type === "pronoun") {
|
||||||
return np.person;
|
return np.person;
|
||||||
}
|
}
|
||||||
const gender: T.Gender = "gender" in np
|
const gender = nounGender(np);
|
||||||
? np.gender
|
const number = nounNumber(np);
|
||||||
: isMascNounEntry(np.entry)
|
|
||||||
? "masc"
|
|
||||||
: "fem";
|
|
||||||
const number: NounNumber = np.type === "plural noun"
|
|
||||||
? "plural"
|
|
||||||
: np.number;
|
|
||||||
return number === "plural"
|
return number === "plural"
|
||||||
? (gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
|
? (gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
|
||||||
: (gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
: (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);
|
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 } {
|
function evaluatePronoun(p: Pronoun): { ps: T.PsString[], e: string } {
|
||||||
// TODO: Will need to handle inflecting and inflecting english pronouns etc.
|
// TODO: Will need to handle inflecting and inflecting english pronouns etc.
|
||||||
const [row, col] = getVerbBlockPosFromPerson(p.person);
|
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 } {
|
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 english = getEnglishFromNoun(n.entry, number);
|
||||||
const pashto = ((): T.PsString[] => {
|
const pashto = ((): T.PsString[] => {
|
||||||
const infs = inflectWord(n.entry);
|
const infs = inflectWord(n.entry);
|
||||||
const gender: T.Gender = "gender" in n ? n.gender :
|
const gender = nounGender(n);
|
||||||
(isMascNounEntry(n.entry) ? "masc" : "fem");
|
|
||||||
const ps = number === "singular"
|
const ps = number === "singular"
|
||||||
? getInf(infs, "inflections", gender, false)
|
? getInf(infs, "inflections", gender, false)
|
||||||
: [
|
: [
|
||||||
|
|
|
@ -5,6 +5,7 @@ type EquativeClause = {
|
||||||
subject: NounPhrase,
|
subject: NounPhrase,
|
||||||
predicate: NounPhrase | Compliment,
|
predicate: NounPhrase | Compliment,
|
||||||
tense: EquativeTense,
|
tense: EquativeTense,
|
||||||
|
negative?: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type EquativeClauseOutput = {
|
type EquativeClauseOutput = {
|
||||||
|
@ -17,6 +18,7 @@ type EquativeClauseOutput = {
|
||||||
e: string,
|
e: string,
|
||||||
},
|
},
|
||||||
ba: boolean,
|
ba: boolean,
|
||||||
|
negative: boolean,
|
||||||
equative: {
|
equative: {
|
||||||
ps: import("@lingdocs/pashto-inflector").Types.SentenceForm,
|
ps: import("@lingdocs/pashto-inflector").Types.SentenceForm,
|
||||||
e: string[],
|
e: string[],
|
||||||
|
@ -25,23 +27,12 @@ type EquativeClauseOutput = {
|
||||||
|
|
||||||
type NounPhrase = Pronoun | Noun | Participle;
|
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 Noun = {
|
||||||
type: "unisex noun",
|
type: "noun",
|
||||||
number: NounNumber,
|
entry: NounEntry,
|
||||||
gender: import("@lingdocs/pashto-inflector").Types.Gender,
|
number?: NounNumber,
|
||||||
entry: UnisexNounEntry,
|
gender?: import("@lingdocs/pashto-inflector").Types.Gender,
|
||||||
possesor?: Noun,
|
|
||||||
adjectives?: AdjectiveEntry[],
|
|
||||||
} | {
|
|
||||||
type: "plural noun",
|
|
||||||
entry: PluralNounEntry<MascNounEntry | FemNounEntry>,
|
|
||||||
possesor?: Noun,
|
|
||||||
adjectives?: AdjectiveEntry[],
|
|
||||||
} | {
|
|
||||||
type: "singular noun",
|
|
||||||
number: NounNumber,
|
|
||||||
entry: SingularEntry<MascNounEntry | FemNounEntry>,
|
|
||||||
possesor?: Noun,
|
possesor?: Noun,
|
||||||
adjectives?: AdjectiveEntry[],
|
adjectives?: AdjectiveEntry[],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue