1356 lines
33 KiB
TypeScript
1356 lines
33 KiB
TypeScript
/**
|
|
* Copyright (c) 2021 lingdocs.com
|
|
*
|
|
* This source code is licensed under the GPL3 license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*/
|
|
|
|
// type prettify<t> = {
|
|
// [k in keyof t]: t[k];
|
|
// } & {};
|
|
|
|
export type PsStringField = "p" | "f";
|
|
export type PsString = {
|
|
[k in PsStringField]: string;
|
|
} & {
|
|
e?: string;
|
|
};
|
|
export type PsJSX = {
|
|
p: JSX.Element;
|
|
f: JSX.Element;
|
|
e?: JSX.Element | string;
|
|
};
|
|
|
|
export type PsWord = PsString & {
|
|
hyphen?: HyphenPsContent[];
|
|
};
|
|
|
|
export type HyphenPsContent =
|
|
| ({
|
|
type: "unwritten";
|
|
f: string;
|
|
} & Omit<PsString, "p">)
|
|
| ({
|
|
type: "written";
|
|
} & PsString);
|
|
|
|
export type DictionaryInfo = {
|
|
title: string;
|
|
license: string;
|
|
release: number;
|
|
numberOfEntries: number;
|
|
url: string;
|
|
infoUrl: string;
|
|
};
|
|
|
|
export type Dictionary = {
|
|
info: DictionaryInfo;
|
|
entries: DictionaryEntry[];
|
|
};
|
|
|
|
export type AllWordsWithInflections = {
|
|
info: DictionaryInfo;
|
|
words: PsString[];
|
|
};
|
|
|
|
// TODO: MAKE THIS A RECORD TYPE
|
|
// Record<RequiredNumberFields, number> && Record<RequiredStringFields, string> &&
|
|
// Partial<Record<StringFields, string>> && Partial<Record<NumberFields, number>>
|
|
export type DictionaryEntry = {
|
|
// BASE REQUIRED INFO
|
|
/** timestamp - used for word id */
|
|
ts: number;
|
|
/** Pashto alphabetical index */
|
|
i: number;
|
|
/**
|
|
* commonality rank
|
|
* 0 - wrong
|
|
* 1 - historical/not in use
|
|
* 2 - rarely used
|
|
* 3 - used but there are more common alternatives
|
|
* 4 - common
|
|
*/
|
|
r?: number;
|
|
/** entry in Pashto */
|
|
p: string;
|
|
/** entry in Phonetics */
|
|
f: string;
|
|
/** entry in simplified phonetics */
|
|
g: string;
|
|
/** entry in English */
|
|
e: string;
|
|
|
|
// PART OF SPEECH AND LINK INFO
|
|
/** part of speech info */
|
|
c?: string;
|
|
/** link - timestamp of related word */
|
|
l?: number;
|
|
|
|
// INFLECTION INFO
|
|
/** first masculine irregular inflection in Pashto */
|
|
infap?: string;
|
|
/** first masculine irregular inflection in Phonetics */
|
|
infaf?: string;
|
|
/** base for second masculine / feminine irregular inflection in Pashto */
|
|
infbp?: string;
|
|
/** base for second masculine / feminine irregular inflection in Phonetics */
|
|
infbf?: string;
|
|
/** entry does not inflect? */
|
|
noInf?: boolean;
|
|
|
|
// PLURAL INFO
|
|
/** Arabic plural in Pashto */
|
|
app?: string;
|
|
/** Arabic plural in Phonetics */
|
|
apf?: string;
|
|
/** Pashto irregular plural in Pashto */
|
|
ppp?: string;
|
|
/** Pashto irregular plural in phonetics */
|
|
ppf?: string;
|
|
|
|
// VERB INFO
|
|
/** imperfective (present) stem in Pashto */
|
|
psp?: string;
|
|
/** imperfective (present) stem in Phonetics */
|
|
psf?: string;
|
|
/** perfective (subjunctive) stem in Pashto */
|
|
ssp?: string;
|
|
/** perfective (subjunctive) stem in Phonetics */
|
|
ssf?: string;
|
|
/** perfective root in Pashto */
|
|
prp?: string;
|
|
/** perfective root in Phonetics */
|
|
prf?: string;
|
|
/** past participle in Pashto */
|
|
pprtp?: string;
|
|
/** past participle in Phonetics */
|
|
pprtf?: string;
|
|
/** The idiosyncratic third person singular masc. short past in Pashto */
|
|
tppp?: string;
|
|
/** The idiosyncratic third person singular masc. short past in Phonetics */
|
|
tppf?: string;
|
|
/** intransitive short version is available like ګرځېږي and ګرځي */
|
|
shortIntrans?: boolean;
|
|
/** does not take a و - oo perfective verb prefix? */
|
|
noOo?: boolean;
|
|
/** takes a seperate و - oo perfective verb prefix? */
|
|
sepOo?: boolean;
|
|
/** Pashto separation point for seperable verbs */
|
|
separationAtP?: number;
|
|
/** Phonetics separation point for seperable verbs */
|
|
separationAtF?: number;
|
|
|
|
// PHONETICS - PASHTO - DIACRITICS INFO
|
|
/** Is an exception to the rules of diacritics for Pashto/Phonetics */
|
|
diacExcept?: boolean;
|
|
|
|
/** the English conjugations of a verb comma seperated set of 5 ie. "see,sees,seeing,saw,seen" or single word ie. "walk" if regular - or the english singular version of a noun */
|
|
ec?: string;
|
|
/** the English partical of a English phrasal verb - or the english irregular plural of a noun */
|
|
ep?: string;
|
|
};
|
|
|
|
export type DictionaryEntryNoFVars = DictionaryEntry & {
|
|
__brand: "name for a dictionary entry with all the phonetics variations removed";
|
|
};
|
|
export type VerbDictionaryEntryNoFVars = VerbDictionaryEntry & {
|
|
__brand2: "name for a verb dictionary entry with all the phonetics variations removed";
|
|
};
|
|
export type VerbEntryNoFVars = {
|
|
entry: VerbDictionaryEntryNoFVars;
|
|
complement?: DictionaryEntryNoFVars;
|
|
} & {
|
|
__brand: "name for a verb entry with all the phonetics variations removed";
|
|
};
|
|
export type PsStringNoFVars = PsString & {
|
|
__brand: "name for a ps string with all the phonetics variations removed";
|
|
};
|
|
export type FStringNoFVars = string & {
|
|
__brand: "name for a phonetics string with all the phonetics variations removed";
|
|
};
|
|
|
|
export const dictionaryEntryTextFields = [
|
|
"p",
|
|
"f",
|
|
"e",
|
|
"c",
|
|
"infap",
|
|
"infaf",
|
|
"infbp",
|
|
"infbf",
|
|
"app",
|
|
"apf",
|
|
"ppp",
|
|
"ppf",
|
|
"psp",
|
|
"psf",
|
|
"ssp",
|
|
"ssf",
|
|
"prp",
|
|
"prf",
|
|
"pprtp",
|
|
"pprtf",
|
|
"tppp",
|
|
"tppf",
|
|
"ec",
|
|
"ep",
|
|
] as const;
|
|
export type DictionaryEntryTextField =
|
|
(typeof dictionaryEntryTextFields)[number];
|
|
export const dictionaryEntryBooleanFields = [
|
|
"noInf",
|
|
"shortIntrans",
|
|
"noOo",
|
|
"sepOo",
|
|
"diacExcept",
|
|
] as const;
|
|
export const dictionaryEntryNumberFields = [
|
|
"ts",
|
|
"r",
|
|
"i",
|
|
"l",
|
|
"separationAtP",
|
|
"separationAtF",
|
|
] as const;
|
|
export type DictionaryEntryBooleanField =
|
|
(typeof dictionaryEntryBooleanFields)[number];
|
|
export type DictionaryEntryNumberField =
|
|
(typeof dictionaryEntryNumberFields)[number];
|
|
export type DictionaryEntryField =
|
|
| DictionaryEntryTextField
|
|
| DictionaryEntryBooleanField
|
|
| DictionaryEntryNumberField;
|
|
|
|
// TODO: make
|
|
|
|
export type DictionaryEntryError = {
|
|
errors: string[];
|
|
p: string;
|
|
f: string;
|
|
e: string;
|
|
ts: number;
|
|
erroneousFields: DictionaryEntryField[];
|
|
};
|
|
|
|
export type Spelling = "Afghan" | "Pakistani ی" | "Pakistani ي";
|
|
|
|
export type TextOptions = {
|
|
pTextSize: "normal" | "larger" | "largest";
|
|
phonetics: "lingdocs" | "ipa" | "alalc" | "none";
|
|
dialect: "standard" | "peshawer" | "southern";
|
|
spelling: Spelling;
|
|
diacritics: boolean;
|
|
};
|
|
|
|
export enum Person {
|
|
FirstSingMale = 0,
|
|
FirstSingFemale,
|
|
SecondSingMale,
|
|
SecondSingFemale,
|
|
ThirdSingMale,
|
|
ThirdSingFemale,
|
|
FirstPlurMale,
|
|
FirstPlurFemale,
|
|
SecondPlurMale,
|
|
SecondPlurFemale,
|
|
ThirdPlurMale,
|
|
ThirdPlurFemale,
|
|
}
|
|
|
|
// INPUT
|
|
// all information to be passed to conjugating functions
|
|
export type VerbInfoBase = {
|
|
entry: VerbEntry;
|
|
transitivity: Transitivity;
|
|
yulEnding: boolean | null;
|
|
stem: VerbStemSet;
|
|
root: VerbRootSet;
|
|
participle: ParticipleSet;
|
|
idiosyncraticThirdMascSing?: ShortThirdPersFormSet;
|
|
};
|
|
|
|
export type PassiveRootsAndStems = {
|
|
stem: VerbStemSet;
|
|
root: VerbRootSet;
|
|
participle: {
|
|
past: FullForm<PsString>;
|
|
};
|
|
};
|
|
|
|
export type AbilityRootsAndStems = Omit<PassiveRootsAndStems, "participle">;
|
|
|
|
export type SimpleVerbInfo = VerbInfoBase & {
|
|
type: "simple";
|
|
};
|
|
|
|
export type StativeCompoundVerbInfo = VerbInfoBase & {
|
|
type: "stative compound";
|
|
complement: UnisexInflections;
|
|
};
|
|
|
|
export type GenerativeStativeCompoundVerbInfo = VerbInfoBase & {
|
|
type: "generative stative compound";
|
|
objComplement: ObjComplement;
|
|
singularForm?: GenerativeStativeCompoundVerbInfo;
|
|
// TODO: Could add intransitive form 🤪
|
|
};
|
|
|
|
export type DynamicCompoundVerbInfo = VerbInfoBase & {
|
|
type: "dynamic compound";
|
|
objComplement: ObjComplement;
|
|
auxVerb: DictionaryEntry;
|
|
auxVerbComplement?: DictionaryEntry;
|
|
singularForm?: DynamicCompoundVerbInfo;
|
|
intransitiveForm?: DynamicCompoundVerbInfo;
|
|
};
|
|
|
|
export type ObjComplement = {
|
|
entry: DictionaryEntry;
|
|
plural?: PsString;
|
|
person: Person;
|
|
};
|
|
|
|
export type NonComboVerbInfo =
|
|
| SimpleVerbInfo
|
|
| StativeCompoundVerbInfo
|
|
| DynamicCompoundVerbInfo
|
|
| GenerativeStativeCompoundVerbInfo;
|
|
|
|
export type VerbInfo =
|
|
| NonComboVerbInfo
|
|
| {
|
|
type: "transitive or grammatically transitive simple";
|
|
transitive: SimpleVerbInfo;
|
|
grammaticallyTransitive: SimpleVerbInfo;
|
|
}
|
|
| {
|
|
type: "dynamic or stative compound";
|
|
transitivity: Transitivity;
|
|
stative: StativeCompoundVerbInfo;
|
|
dynamic: DynamicCompoundVerbInfo;
|
|
}
|
|
| {
|
|
type: "dynamic or generative stative compound";
|
|
transitivity: Transitivity;
|
|
stative: GenerativeStativeCompoundVerbInfo;
|
|
dynamic: DynamicCompoundVerbInfo;
|
|
};
|
|
|
|
export type Transitivity =
|
|
| "transitive"
|
|
| "intransitive"
|
|
| "grammatically transitive";
|
|
|
|
export type SplitInfo = FullForm<[PsString, PsString]>;
|
|
|
|
export type VerbStemSet = {
|
|
perfective: FullForm<PsString>;
|
|
imperfective: FullForm<PsString>;
|
|
perfectiveSplit?: SplitInfo;
|
|
};
|
|
|
|
export type VerbRootSet = {
|
|
perfective: OptionalPersonInflections<LengthOptions<PsString>>;
|
|
imperfective: OptionalPersonInflections<LengthOptions<PsString>>;
|
|
perfectiveSplit?: SplitInfo;
|
|
};
|
|
|
|
export type ParticipleSet = {
|
|
present: FullForm<PsString>;
|
|
past: FullForm<PsString>;
|
|
};
|
|
|
|
export type ShortThirdPersFormSet = {
|
|
[K in Aspect]: PsString;
|
|
};
|
|
|
|
export type Aspect = "perfective" | "imperfective";
|
|
|
|
export type Length = "short" | "long" | "mini";
|
|
|
|
export type LengthOptions<T> = {
|
|
long: T;
|
|
short: T;
|
|
mini?: T;
|
|
};
|
|
|
|
export type PersonInflectionsField =
|
|
| "mascSing"
|
|
| "mascPlur"
|
|
| "femSing"
|
|
| "femPlur";
|
|
export type PersonInflections<T> = {
|
|
[K in PersonInflectionsField]: T;
|
|
};
|
|
export type OptionalPersonInflections<T> = PersonInflections<T> | T;
|
|
|
|
export type SingleOrLengthOpts<T> = T | LengthOptions<T>;
|
|
|
|
export type VerbConjugation = {
|
|
info: NonComboVerbInfo;
|
|
// INFINITIVE = info.root.imperfective.long
|
|
imperfective: AspectContent; // --╖ ASPECT = "imperfective"
|
|
perfective: AspectContent; // --╜ ASPECT = "perfective"
|
|
hypothetical: VerbForm; // INFINITIVE - ul + aay
|
|
participle: ParticipleContent;
|
|
perfect: PerfectContent; // PPART = PAST PARTICIPLE (plus spectial short forms)
|
|
passive?: PassiveContent; // only on transitive verbs
|
|
singularForm?: VerbConjugation;
|
|
};
|
|
|
|
export type VerbOutput =
|
|
| VerbConjugation
|
|
| {
|
|
info: VerbInfo;
|
|
stative: VerbConjugation;
|
|
dynamic: VerbConjugation;
|
|
}
|
|
| {
|
|
info: VerbInfo;
|
|
transitive: VerbConjugation;
|
|
grammaticallyTransitive: VerbConjugation;
|
|
};
|
|
|
|
export type PassiveContent = {
|
|
imperfective: AspectContentPassive; // --╖ ASPECT = "imperfective"
|
|
perfective: AspectContentPassive; // --╜ ASPECT = "perfective"
|
|
perfect: PerfectContent; // PPART INFINITIVE + kedulStat perfect.pastParticiple
|
|
// TODO: ADD PARTICIPLE
|
|
};
|
|
|
|
// ASPECT -> AspectContent
|
|
export type AspectContent = {
|
|
// STEM = info.stem[ASPECT]
|
|
// ROOT = info.root[ASPECT]
|
|
nonImperative: VerbForm; // STEM + pres ending
|
|
future: VerbForm; // به + this.nonImperative
|
|
imperative: ImperativeForm; // STEM + imperative ending
|
|
past: VerbForm; // ROOT + past ending
|
|
habitualPast: VerbForm; // ba + past
|
|
modal: ModalContent;
|
|
};
|
|
|
|
// ASPECT -> AspectContentPssive
|
|
export type AspectContentPassive = Omit<AspectContent, "imperative"> & {
|
|
imperative: undefined;
|
|
};
|
|
|
|
export type ModalContent = {
|
|
nonImperative: VerbForm; // ROOT + ey + kedulStat.perfective.nonImperative
|
|
future: VerbForm; // به + this.nonImperative
|
|
past: VerbForm; // ROOT + ey + kedulStat.perfective.past
|
|
habitualPast: VerbForm; // ba + past
|
|
hypotheticalPast: VerbForm; // ROOT + ey + shw + ey
|
|
};
|
|
|
|
export type ParticipleForm =
|
|
| SingleOrLengthOpts<UnisexInflections>
|
|
| SingleOrLengthOpts<PsString>;
|
|
|
|
export type ParticipleContent = {
|
|
past: SingleOrLengthOpts<UnisexInflections> | SingleOrLengthOpts<PsString>;
|
|
// TODO: Should this ever have an object matrix??
|
|
present: SingleOrLengthOpts<UnisexInflections>;
|
|
};
|
|
|
|
// PPART -> PerfectContent
|
|
export type PerfectContent = {
|
|
halfPerfect: VerbForm; // PPART
|
|
past: VerbForm; // PPART + equative.past
|
|
present: VerbForm; // PPART + equative.prest
|
|
habitual: VerbForm; // PPART + equative.habit
|
|
subjunctive: VerbForm; // PPART + equative.subj
|
|
future: VerbForm; // ba + PPART + equative.subj
|
|
wouldBe: VerbForm; // ba + PPART + equative.past
|
|
pastSubjunctive: VerbForm; // PPART + waay
|
|
wouldHaveBeen: VerbForm; // PPART + ba + waay
|
|
};
|
|
|
|
// Plain, 1st, and 2nd Inflection
|
|
export type InflectionSet = ArrayFixed<ArrayOneOrMore<PsString>, 3>;
|
|
|
|
// Plural and Second Inflection
|
|
export type PluralInflectionSet = ArrayFixed<ArrayOneOrMore<PsString>, 2>;
|
|
|
|
export type Gender = "masc" | "fem";
|
|
|
|
export type UnisexSet<T> = Record<Gender, T>;
|
|
export type GenderedSet<T> =
|
|
| UnisexSet<T>
|
|
| Omit<UnisexSet<T>, "fem">
|
|
| Omit<UnisexSet<T>, "masc">;
|
|
export type UnisexInflections = UnisexSet<InflectionSet>;
|
|
|
|
export type Inflections = GenderedSet<InflectionSet>;
|
|
|
|
export type PluralInflections = GenderedSet<PluralInflectionSet>;
|
|
|
|
export type InflectorOutput =
|
|
| {
|
|
arabicPlural: PluralInflections;
|
|
plural?: PluralInflections;
|
|
bundledPlural?: PluralInflections;
|
|
inflections?: Inflections;
|
|
}
|
|
| {
|
|
plural: PluralInflections;
|
|
arabicPlural?: PluralInflections;
|
|
bundledPlural?: PluralInflections;
|
|
inflections?: Inflections;
|
|
}
|
|
| {
|
|
inflections: Inflections;
|
|
}
|
|
| false;
|
|
|
|
export type PersonLine = [
|
|
/** singular form of person */
|
|
ArrayOneOrMore<PsString>,
|
|
/** plural form of person */
|
|
ArrayOneOrMore<PsString>
|
|
];
|
|
|
|
/**
|
|
* The basic form of a verb conjugation
|
|
* Each line representing one person (singular and plural)
|
|
* 1st Person Male, 1st Person Female, 2nd Person Male etc...
|
|
*/
|
|
export type VerbBlock = [
|
|
PersonLine, // 1st Person Male
|
|
PersonLine, // 1st Person Female
|
|
PersonLine, // 2nd Person Male
|
|
PersonLine, // 2nd Person Female
|
|
PersonLine, // 3rd Person Male
|
|
PersonLine // 3rd Person Female
|
|
];
|
|
|
|
export type EnglishBlock = [
|
|
[string, string],
|
|
[string, string],
|
|
[string, string],
|
|
[string, string],
|
|
[string, string],
|
|
[string, string]
|
|
];
|
|
|
|
export type ImperativeBlock = [
|
|
PersonLine, // 2nd Person Male
|
|
PersonLine // 2nd Person Female
|
|
];
|
|
|
|
export type FullForm<T> = OptionalPersonInflections<SingleOrLengthOpts<T>>;
|
|
export type VerbForm = FullForm<VerbBlock>;
|
|
export type ImperativeForm = FullForm<ImperativeBlock>;
|
|
export type SentenceForm = SingleOrLengthOpts<ArrayOneOrMore<PsString>>;
|
|
|
|
export interface ArrayFixed<T, L extends number> extends Array<T> {
|
|
0: T;
|
|
length: L;
|
|
}
|
|
|
|
export type Wrapper<T> = T & { __brand: "wrapped" };
|
|
|
|
export type ArrayOneOrMore<T> = {
|
|
0: T;
|
|
} & T[];
|
|
|
|
export type RootsOrStemsToHighlight = (
|
|
| "imperfective root"
|
|
| "perfective root"
|
|
| "imperfective stem"
|
|
| "perfective stem"
|
|
| "past participle"
|
|
)[];
|
|
|
|
/* i.e. ec: ["take", "takes", "taking", "took", "taken"], ep: out */
|
|
export type EnglishVerbConjugationEc = [string, string, string, string, string];
|
|
export type EnglishVerbConjugation = {
|
|
ec: EnglishVerbConjugationEc;
|
|
ep: string | undefined;
|
|
};
|
|
|
|
export type DisplayFormItem =
|
|
| DisplayForm
|
|
| DisplayFormSubgroup
|
|
| DisplayFormForSentence;
|
|
export type EnglishBuilder = (
|
|
subject: Person,
|
|
ec: EnglishVerbConjugationEc,
|
|
neg: boolean
|
|
) => string[];
|
|
|
|
export type DisplayForm = {
|
|
label: string;
|
|
aspect?: Aspect;
|
|
form: VerbForm | ImperativeForm | ParticipleForm | SentenceForm;
|
|
advanced?: boolean;
|
|
englishBuilder?: EnglishBuilder;
|
|
formula: React.ReactNode;
|
|
explanation: React.ReactNode;
|
|
sentence?: boolean;
|
|
passive?: boolean;
|
|
past?: boolean;
|
|
reorderWithNegative?: boolean;
|
|
};
|
|
|
|
export type DisplayFormForSentence = Omit<DisplayForm, "form"> & {
|
|
form: VerbForm;
|
|
secondPronounNeeded?: boolean;
|
|
};
|
|
|
|
// {
|
|
// label: string,
|
|
// aspect?: Aspect,
|
|
// form: VerbForm,
|
|
// advanced?: boolean,
|
|
// englishBuilder?: EnglishBuilder,
|
|
// formula: React.ReactNode,
|
|
// secondPronounNeeded?: boolean,
|
|
// explanation: React.ReactNode,
|
|
// sentence?: boolean,
|
|
// passive?: boolean,
|
|
// past?: boolean,
|
|
// reorderWithNegative?: boolean,
|
|
// }
|
|
|
|
export type DisplayFormSubgroup = {
|
|
label: string;
|
|
subgroup: string;
|
|
advanced?: boolean;
|
|
content: DisplayFormItem[];
|
|
};
|
|
|
|
export type AayTail = "ey" | "aay";
|
|
|
|
export type NounEntry = DictionaryEntry & { c: string } & {
|
|
__brand: "a noun entry";
|
|
};
|
|
export type MascNounEntry = NounEntry & { __brand2: "a masc noun entry" };
|
|
export type FemNounEntry = NounEntry & { __brand2: "a fem noun entry" };
|
|
export type AnimNounEntry = NounEntry & { __brand3: "a anim noun entry" };
|
|
export type UnisexNounEntry = MascNounEntry & {
|
|
__brand3: "a unisex noun entry";
|
|
};
|
|
export type UnisexAnimNounEntry = UnisexNounEntry & {
|
|
__brand4: "an anim unisex noun entry";
|
|
};
|
|
export type AdverbEntry = DictionaryEntry & { c: string } & {
|
|
__brand: "an adverb entry";
|
|
};
|
|
export type LocativeAdverbEntry = AdverbEntry & {
|
|
__brand2: "a locative adverb entry";
|
|
};
|
|
export type AdjectiveEntry = DictionaryEntry & { c: string } & {
|
|
__brand: "an adjective entry";
|
|
};
|
|
export type VerbDictionaryEntry = DictionaryEntry & { c: string } & {
|
|
__brand: "a verb entry";
|
|
};
|
|
export type VerbEntry = {
|
|
entry: VerbDictionaryEntry;
|
|
// TODO: the compliment could also be typed? Maybe?
|
|
complement?: DictionaryEntry;
|
|
};
|
|
|
|
/** A dictionary entry that will include the complement / verb entry structure if it's a verb */
|
|
export type FullEntry = VerbEntry | DictionaryEntry;
|
|
|
|
export enum InflectionPattern {
|
|
None = 0,
|
|
Basic = 1,
|
|
UnstressedAy = 2,
|
|
StressedAy = 3,
|
|
Pashtun = 4,
|
|
Squish = 5,
|
|
FemInanEe = 6,
|
|
}
|
|
|
|
export type SingularEntry<T extends NounEntry> = T & {
|
|
__brand7: "a singular noun - as opposed to an always plural noun";
|
|
};
|
|
export type PluralNounEntry<T extends NounEntry> = T & {
|
|
__brand7: "a noun that is always plural";
|
|
};
|
|
|
|
export type Pattern1Entry<T> = T & { __brand3: "basic inflection pattern" };
|
|
export type Pattern2Entry<T> = T & {
|
|
__brand3: "ending in unstressed ی pattern";
|
|
};
|
|
export type Pattern3Entry<T> = T & { __brand3: "ending in stressed ی pattern" };
|
|
export type Pattern4Entry<T> = T & { __brand3: "Pashtoon pattern" };
|
|
export type Pattern5Entry<T> = T & { __brand3: "short squish pattern" };
|
|
export type Pattern6FemEntry<T extends FemNounEntry> = T & {
|
|
__brand3: "non anim. ending in ي";
|
|
};
|
|
export type NonInflecting<T> = T & { __brand3: "non-inflecting" };
|
|
|
|
export type Entry = NounEntry | AdjectiveEntry | AdverbEntry | VerbEntry;
|
|
// TODO: make this Rendered<VPSelectionComplete> with recursive Rendered<>
|
|
export type VPRendered = {
|
|
type: "VPRendered";
|
|
king: "subject" | "object";
|
|
servant: "subject" | "object" | undefined;
|
|
isPast: boolean;
|
|
isTransitive: boolean;
|
|
isCompound: "stative" | "dynamic" | "generative stative" | false;
|
|
blocks: Block[][];
|
|
kids: Kid[];
|
|
englishBase?: string[];
|
|
form: FormVersion;
|
|
whatsAdjustable: "both" | "king" | "servant";
|
|
};
|
|
|
|
export type VerbTense =
|
|
| "presentVerb"
|
|
| "subjunctiveVerb"
|
|
| "perfectiveFuture"
|
|
| "imperfectiveFuture"
|
|
| "perfectivePast"
|
|
| "imperfectivePast"
|
|
| "habitualPerfectivePast"
|
|
| "habitualImperfectivePast";
|
|
export type NounNumber = "singular" | "plural";
|
|
|
|
export type EquativeTense =
|
|
| "present"
|
|
| "subjunctive"
|
|
| "habitual"
|
|
| "past"
|
|
| "future"
|
|
| "wouldBe"
|
|
| "pastSubjunctive"
|
|
| "wouldHaveBeen";
|
|
export type EquativeTenseWithoutBa =
|
|
| "present"
|
|
| "subjunctive"
|
|
| "habitual"
|
|
| "past"
|
|
| "pastSubjunctive";
|
|
export type PerfectTense = `${EquativeTense}Perfect`;
|
|
export type AbilityTense = `${VerbTense}Modal`;
|
|
export type ImperativeTense = `${Aspect}Imperative`;
|
|
export type Tense =
|
|
| EquativeTense
|
|
| VerbTense
|
|
| PerfectTense
|
|
| AbilityTense
|
|
| ImperativeTense;
|
|
|
|
export type SubjectSelection = {
|
|
type: "subjectSelection";
|
|
selection: NPSelection | undefined;
|
|
};
|
|
|
|
export type ObjectSelection = {
|
|
type: "objectSelection";
|
|
selection: NPSelection | ObjectNP | undefined;
|
|
};
|
|
|
|
export type SubjectSelectionComplete = {
|
|
type: "subjectSelection";
|
|
selection: NPSelection;
|
|
};
|
|
|
|
export type PredicateSelectionComplete = {
|
|
type: "predicateSelection";
|
|
selection: ComplementSelection | NPSelection;
|
|
};
|
|
|
|
export type ObjectSelectionComplete = {
|
|
type: "objectSelection";
|
|
selection: NPSelection | ObjectNP;
|
|
};
|
|
|
|
export type VPSelectionState = {
|
|
blocks: VPSBlock[];
|
|
verb: VerbSelection;
|
|
externalComplement:
|
|
| undefined
|
|
| UnselectedComplementSelection
|
|
| ComplementSelection;
|
|
form: FormVersion;
|
|
};
|
|
|
|
export type VPSelectionComplete = {
|
|
blocks: VPSBlockComplete[];
|
|
verb: VerbSelectionComplete;
|
|
externalComplement: VPSelectionState["externalComplement"];
|
|
form: FormVersion;
|
|
};
|
|
|
|
export type VerbFormName =
|
|
| VerbTense
|
|
| PerfectTense
|
|
| AbilityTense
|
|
| ImperativeTense;
|
|
|
|
export type VerbSelectionComplete = Omit<
|
|
VerbSelection,
|
|
"verbTense" | "perfectTense" | "imperativeTense" | "tenseCategory"
|
|
> & {
|
|
tense: VerbFormName;
|
|
};
|
|
|
|
export type Voice = "active" | "passive";
|
|
|
|
export type NewVerbSelection = {
|
|
type: "verb";
|
|
verb: VerbEntryNoFVars;
|
|
dynAuxVerb?: VerbEntryNoFVars;
|
|
voice: Voice;
|
|
canChangeVoice: boolean;
|
|
negative: boolean;
|
|
tense: VerbTense | PerfectTense | AbilityTense | ImperativeTense;
|
|
transitivity: Transitivity;
|
|
canChangeTransGenTrans: boolean;
|
|
compound: "stative" | "dynamic" | false;
|
|
canChangeStatDyn: boolean;
|
|
canBeGenStat: boolean;
|
|
variableRs: boolean;
|
|
};
|
|
|
|
export type VerbSelection = {
|
|
type: "verb";
|
|
verb: VerbEntry;
|
|
dynAuxVerb?: VerbEntry;
|
|
transitivity: Transitivity;
|
|
canChangeTransitivity: boolean;
|
|
canChangeStatDyn: boolean;
|
|
isCompound: "stative" | "dynamic" | "generative stative" | false;
|
|
voice: Voice;
|
|
canChangeVoice: boolean;
|
|
negative: boolean;
|
|
verbTense: VerbTense;
|
|
perfectTense: PerfectTense;
|
|
imperativeTense: ImperativeTense;
|
|
tenseCategory: "basic" | "modal" | "perfect" | "imperative";
|
|
};
|
|
|
|
export type VerbRendered = Omit<VerbSelectionComplete, "object"> & {
|
|
ps: {
|
|
head: PsString | undefined;
|
|
rest: SingleOrLengthOpts<PsString[]>;
|
|
};
|
|
hasBa: boolean;
|
|
person: Person;
|
|
};
|
|
|
|
export type VerbObject =
|
|
// transitive verb - object not selected yet
|
|
| undefined
|
|
// transitive verb - obect selected
|
|
| NPSelection
|
|
// grammatically transitive verb with unspoken 3rd pers masc plur entity
|
|
// or intransitive "none"
|
|
| ObjectNP;
|
|
|
|
export type NPSelection = {
|
|
type: "NP";
|
|
selection: NounSelection | PronounSelection | ParticipleSelection;
|
|
};
|
|
|
|
export type APSelection = {
|
|
type: "AP";
|
|
selection: AdverbSelection | SandwichSelection<Sandwich>;
|
|
};
|
|
|
|
export type NPType = "noun" | "pronoun" | "participle";
|
|
|
|
export type ObjectNP = "none" | Person.ThirdPlurMale;
|
|
|
|
export type PossesorSelection = {
|
|
shrunken: boolean;
|
|
np: NPSelection;
|
|
};
|
|
|
|
// TODO require/import Person and PsString
|
|
export type NounSelection = {
|
|
type: "noun";
|
|
entry: NounEntry;
|
|
gender: Gender;
|
|
genderCanChange: boolean;
|
|
number: NounNumber;
|
|
numberCanChange: boolean;
|
|
dynamicComplement?: boolean;
|
|
genStativeComplement?: boolean;
|
|
adjectives: AdjectiveSelection[];
|
|
possesor: undefined | PossesorSelection;
|
|
demonstrative: undefined | DemonstrativeSelection;
|
|
};
|
|
|
|
export type DemonstrativeSelection = {
|
|
type: "demonstrative";
|
|
demonstrative: "daa" | "hagha" | "dagha";
|
|
hideNoun: boolean;
|
|
};
|
|
|
|
export type AdverbSelection = {
|
|
type: "adverb";
|
|
entry: AdverbEntry;
|
|
};
|
|
|
|
export type AdjectiveSelection = {
|
|
type: "adjective";
|
|
entry: AdjectiveEntry;
|
|
sandwich: SandwichSelection<Sandwich> | undefined;
|
|
};
|
|
|
|
export type LocativeAdverbSelection = {
|
|
type: "loc. adv.";
|
|
entry: LocativeAdverbEntry;
|
|
};
|
|
|
|
// take an argument for subject/object in rendering English
|
|
export type PronounSelection = {
|
|
type: "pronoun";
|
|
person: Person;
|
|
distance: "near" | "far";
|
|
};
|
|
|
|
export type ParticipleSelection = {
|
|
type: "participle";
|
|
verb: VerbEntry;
|
|
possesor: undefined | PossesorSelection;
|
|
};
|
|
|
|
// not object
|
|
// type Primitive = string | Function | number | boolean | Symbol | undefined | null;
|
|
// If T has key K ("user"), replace it
|
|
export type ReplaceKey<T, K extends string, R> = T extends Record<K, unknown>
|
|
? Omit<T, K> & Record<K, R>
|
|
: T;
|
|
|
|
export type FormVersion = { removeKing: boolean; shrinkServant: boolean };
|
|
|
|
// TODO: rendered should would for rendering T.PossesorSelection etc
|
|
// look recursively down on something
|
|
export type RenderedPossesorSelection = {
|
|
np: Rendered<NPSelection>;
|
|
shrunken: boolean;
|
|
};
|
|
|
|
export type UnselectedComplementSelection = {
|
|
type: "complement";
|
|
selection: { type: "unselected" };
|
|
};
|
|
|
|
export type Rendered<
|
|
T extends
|
|
| NPSelection
|
|
| NPSelection["selection"]
|
|
| APSelection
|
|
| APSelection["selection"]
|
|
| SubjectSelectionComplete
|
|
| ObjectSelectionComplete
|
|
| PredicateSelectionComplete
|
|
| AdjectiveSelection
|
|
| SandwichSelection<Sandwich>
|
|
| ComplementSelection
|
|
| DemonstrativeSelection
|
|
| ComplementSelection["selection"]
|
|
| UnselectedComplementSelection
|
|
| undefined
|
|
> = T extends NPSelection
|
|
? {
|
|
type: "NP";
|
|
selection: Rendered<NPSelection["selection"]>;
|
|
}
|
|
: T extends APSelection
|
|
? {
|
|
type: "AP";
|
|
selection: Rendered<APSelection["selection"]>;
|
|
}
|
|
: T extends ComplementSelection
|
|
? {
|
|
type: "complement";
|
|
selection: Rendered<ComplementSelection["selection"]>;
|
|
}
|
|
: T extends UnselectedComplementSelection
|
|
? {
|
|
type: "complement";
|
|
selection: {
|
|
type: "unselected";
|
|
ps: PsString[];
|
|
e: string;
|
|
};
|
|
}
|
|
: T extends SandwichSelection<Sandwich>
|
|
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
|
inside: Rendered<NPSelection>;
|
|
}
|
|
: T extends AdverbSelection
|
|
? {
|
|
type: "adverb";
|
|
entry: AdverbEntry;
|
|
person: Person;
|
|
ps: PsString[];
|
|
e?: string;
|
|
}
|
|
: T extends AdjectiveSelection
|
|
? {
|
|
type: "adjective";
|
|
entry: AdjectiveEntry;
|
|
ps: PsString[];
|
|
e?: string;
|
|
sandwich: Rendered<SandwichSelection<Sandwich>> | undefined;
|
|
inflected: boolean;
|
|
person: Person;
|
|
}
|
|
: T extends DemonstrativeSelection
|
|
? {
|
|
type: "demonstrative";
|
|
demonstrative: DemonstrativeSelection["demonstrative"];
|
|
hideNoun: boolean;
|
|
ps: PsString;
|
|
}
|
|
: T extends ComplementSelection
|
|
? {
|
|
type: "complement";
|
|
selection: Rendered<ComplementSelection["selection"]>;
|
|
}
|
|
: T extends SubjectSelectionComplete
|
|
? {
|
|
type: "subjectSelection";
|
|
selection: Rendered<NPSelection>;
|
|
}
|
|
: T extends ObjectSelectionComplete
|
|
? {
|
|
type: "objectSelection";
|
|
selection: Rendered<NPSelection> | Person.ThirdPlurMale | "none";
|
|
}
|
|
: T extends PredicateSelectionComplete
|
|
? {
|
|
type: "predicateSelection";
|
|
selection: Rendered<ComplementSelection> | Rendered<NPSelection>;
|
|
}
|
|
: T extends undefined
|
|
? {
|
|
type: "undefined";
|
|
ps: PsString;
|
|
}
|
|
: // TODO: this will be a problem (removing the change gender etc)
|
|
// if we want to make the sentence diagram interactive
|
|
ReplaceKey<
|
|
Omit<
|
|
T,
|
|
| "changeGender"
|
|
| "changeNumber"
|
|
| "changeDistance"
|
|
| "adjectives"
|
|
| "possesor"
|
|
>,
|
|
"e",
|
|
string
|
|
> & {
|
|
ps: SingleOrLengthOpts<PsString[]>;
|
|
e?: string;
|
|
inflected: boolean;
|
|
person: Person;
|
|
role: "king" | "servant" | "none";
|
|
// TODO: better recursive thing
|
|
adjectives?: Rendered<AdjectiveSelection>[];
|
|
possesor?: {
|
|
shrunken: boolean;
|
|
np: Rendered<NPSelection>;
|
|
};
|
|
demonstrative?: Rendered<DemonstrativeSelection>;
|
|
};
|
|
|
|
export type EPSelectionState = {
|
|
blocks: EPSBlock[];
|
|
predicate: {
|
|
type: "NP" | "Complement";
|
|
NP: NPSelection | undefined;
|
|
Complement: ComplementSelection | undefined;
|
|
};
|
|
equative: EquativeSelection;
|
|
omitSubject: boolean;
|
|
};
|
|
|
|
export type EPSBlock = {
|
|
key: number;
|
|
block: SubjectSelection | APSelection | undefined;
|
|
};
|
|
export type EPSBlockComplete = {
|
|
key: number;
|
|
block: SubjectSelectionComplete | APSelection;
|
|
};
|
|
|
|
export type VPSBlock = {
|
|
key: number;
|
|
// TODO: confusing use of APSelection / should be like APSelection s APSelection complete like the others
|
|
block:
|
|
| SubjectSelection
|
|
| ObjectSelection
|
|
| (APSelection | undefined)
|
|
| ComplementSelection;
|
|
};
|
|
export type VPSBlockComplete = {
|
|
key: number;
|
|
block:
|
|
| SubjectSelectionComplete
|
|
| ObjectSelectionComplete
|
|
| APSelection
|
|
| ComplementSelection;
|
|
};
|
|
|
|
export type EPSelectionComplete = Omit<
|
|
EPSelectionState,
|
|
"predicate" | "blocks"
|
|
> & {
|
|
blocks: EPSBlockComplete[];
|
|
predicate: PredicateSelectionComplete;
|
|
omitSubject: boolean;
|
|
};
|
|
|
|
export type ComplementType =
|
|
| "adjective"
|
|
| "loc. adv."
|
|
| "sandwich"
|
|
| "comp. noun";
|
|
|
|
export type SandwichSelection<S extends Sandwich> = S & {
|
|
inside: NPSelection;
|
|
};
|
|
|
|
export type ComplementSelection = {
|
|
type: "complement";
|
|
selection:
|
|
| AdjectiveSelection
|
|
| LocativeAdverbSelection
|
|
| SandwichSelection<Sandwich>
|
|
| NounSelection;
|
|
};
|
|
|
|
export type Sandwich = {
|
|
type: "sandwich";
|
|
before: PsString | undefined;
|
|
after: PsString | undefined;
|
|
e: string;
|
|
};
|
|
|
|
export type EquativeSelection = {
|
|
tense: EquativeTense;
|
|
negative: boolean;
|
|
};
|
|
|
|
export type EquativeRendered = EquativeSelection & {
|
|
ps: SingleOrLengthOpts<PsString[]>;
|
|
person: Person;
|
|
hasBa: boolean;
|
|
};
|
|
|
|
export type EPRendered = {
|
|
type: "EPRendered";
|
|
blocks: Block[][];
|
|
kids: Kid[];
|
|
englishBase?: string[];
|
|
omitSubject: boolean;
|
|
};
|
|
|
|
export type EntryFeeder =
|
|
| {
|
|
nouns: EntryLookupPortal<NounEntry>;
|
|
verbs: EntryLookupPortal<VerbEntry>;
|
|
adjectives: EntryLookupPortal<AdjectiveEntry>;
|
|
locativeAdverbs: EntryLookupPortal<LocativeAdverbEntry>;
|
|
adverbs: EntryLookupPortal<AdverbEntry>;
|
|
}
|
|
| {
|
|
nouns: NounEntry[];
|
|
verbs: VerbEntry[];
|
|
adjectives: AdjectiveEntry[];
|
|
locativeAdverbs: LocativeAdverbEntry[];
|
|
adverbs: AdverbEntry[];
|
|
};
|
|
|
|
export type EntryFeederSingleType<X extends VerbEntry | DictionaryEntry> =
|
|
| X[]
|
|
| EntryLookupPortal<X>;
|
|
|
|
export type EntryLookupPortal<X extends VerbEntry | DictionaryEntry> = {
|
|
search: (s: string) => X[];
|
|
getByTs: (ts: number) => X | undefined;
|
|
};
|
|
|
|
export type EquativeBlock = { type: "equative"; equative: EquativeRendered };
|
|
|
|
export type NegativeBlock = { type: "negative"; imperative: boolean };
|
|
|
|
export type Block = {
|
|
key: number;
|
|
block:
|
|
| Rendered<SubjectSelectionComplete>
|
|
| Rendered<ObjectSelectionComplete>
|
|
| Rendered<APSelection>
|
|
| Rendered<PredicateSelectionComplete>
|
|
| Rendered<ComplementSelection>
|
|
| Rendered<UnselectedComplementSelection>
|
|
| NegativeBlock
|
|
| EquativeBlock
|
|
| VB
|
|
| VBE
|
|
| VHead;
|
|
};
|
|
|
|
export type ParsedBlock =
|
|
| ParsedNP
|
|
| ParsedPH
|
|
| ParsedVBE
|
|
| ParsedVBP
|
|
| APSelection
|
|
| NegativeBlock;
|
|
|
|
export type ParsedKidsSection = {
|
|
type: "kids";
|
|
kids: ParsedKid[];
|
|
};
|
|
|
|
export type ParsedNP = {
|
|
type: "NP";
|
|
inflected: boolean;
|
|
selection: NPSelection;
|
|
};
|
|
export type ParsedPH = {
|
|
type: "PH";
|
|
s: string;
|
|
};
|
|
export type ParsedVBE = Omit<VBE, "ps">;
|
|
export type ParsedVBP = Omit<VBP, "ps">;
|
|
|
|
export type Kid = {
|
|
key: number;
|
|
kid: { type: "ba" } | MiniPronoun;
|
|
};
|
|
|
|
export type ParsedMiniPronoun = "me" | "de" | "ye" | "mU";
|
|
|
|
export type ParsedKid = "ba" | ParsedMiniPronoun;
|
|
|
|
export type MiniPronoun = {
|
|
type: "mini-pronoun";
|
|
person: Person;
|
|
ps: PsString;
|
|
source: "servant" | "possesive";
|
|
np: NPSelection;
|
|
};
|
|
|
|
export type RenderVerbOutput = {
|
|
hasBa: boolean;
|
|
vbs: VerbRenderedOutput;
|
|
};
|
|
export type VerbRenderedOutput = [[VHead] | [], [VBP, VBE] | [VBE]];
|
|
export type RootsStemsOutput = [[VHead] | [], [VBP, VB] | [VB]]; // or perfect / equative
|
|
|
|
export type VB = VBBasic | Welded;
|
|
/** A VB block that has had a person verb ending attached */
|
|
export type VBE = VB & {
|
|
person: Person;
|
|
info:
|
|
| {
|
|
type: "equative";
|
|
tense: EquativeTenseWithoutBa;
|
|
}
|
|
| {
|
|
type: "verb";
|
|
aspect: Aspect;
|
|
base: "stem" | "root";
|
|
verb: VerbEntry;
|
|
abilityAux?: boolean;
|
|
};
|
|
};
|
|
|
|
/** A VB block used for ability verbs or perfect (past participle)
|
|
* get optionally swapped in order with the VBE when used with negative
|
|
*/
|
|
export type VBP = VB & (VBPartInfo | VBAbilityInfo);
|
|
|
|
export type VBPartInfo = {
|
|
info: {
|
|
type: "ppart";
|
|
genNum: GenderNumber;
|
|
verb: VerbEntry;
|
|
};
|
|
};
|
|
|
|
export type VBAbilityInfo = {
|
|
info: {
|
|
type: "ability";
|
|
verb: VerbEntry;
|
|
aspect: Aspect;
|
|
};
|
|
};
|
|
|
|
// in VB OR VBE - add root / stem and entry for parsing info
|
|
// but how would that work with perfect and ability verbs ...
|
|
|
|
export type VBNoLenghts<V extends VB> = V extends VBBasic
|
|
? Omit<VBBasic, "ps"> & { ps: PsString[] }
|
|
: Omit<Welded, "right"> & { right: VBNoLenghts<Exclude<VB, Welded>> };
|
|
|
|
export type VBBasic = {
|
|
type: "VB";
|
|
ps: SingleOrLengthOpts<PsString[]>;
|
|
};
|
|
|
|
export type GenderNumber = {
|
|
gender: Gender;
|
|
number: NounNumber;
|
|
};
|
|
|
|
export type Welded = {
|
|
type: "welded";
|
|
left: NComp | VBBasic | Welded;
|
|
right: VBBasic | (VBBasic & (VBPartInfo | VBAbilityInfo));
|
|
};
|
|
|
|
export type VHead = PH | NComp;
|
|
|
|
/** perfective head block */
|
|
export type PH = {
|
|
type: "PH";
|
|
ps: PsString;
|
|
};
|
|
|
|
export type NComp = {
|
|
type: "NComp";
|
|
comp: Comp;
|
|
};
|
|
|
|
// element can be one of
|
|
// - adjective
|
|
// - locative adv
|
|
// - sandwich (TODO)
|
|
// - noun
|
|
export type Comp = AdjComp | OtherComp;
|
|
|
|
export type AdjComp = {
|
|
type: "AdjComp";
|
|
ps: PsString;
|
|
number: NounNumber;
|
|
gender: Gender;
|
|
};
|
|
|
|
export type OtherComp = {
|
|
type: "Comp";
|
|
ps: PsString;
|
|
};
|
|
|
|
export type Token = {
|
|
i: number;
|
|
s: string;
|
|
};
|
|
|
|
export type ParseError = {
|
|
message: string;
|
|
token?: Token;
|
|
};
|
|
|
|
/** a tuple containing the [left over tokens, parse result, errors associated with the result] */
|
|
export type ParseResult<P> = {
|
|
tokens: Readonly<Token[]>;
|
|
body: P;
|
|
errors: ParseError[];
|
|
};
|