/** * 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 = { // [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) | ({ 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 && Record && // Partial> && Partial> 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; }; }; export type AbilityRootsAndStems = Omit; 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; imperfective: FullForm; perfectiveSplit?: SplitInfo; }; export type VerbRootSet = { perfective: OptionalPersonInflections>; imperfective: OptionalPersonInflections>; perfectiveSplit?: SplitInfo; }; export type ParticipleSet = { present: FullForm; past: FullForm; }; export type ShortThirdPersFormSet = { [K in Aspect]: PsString; }; export type Aspect = "perfective" | "imperfective"; export type Length = "short" | "long" | "mini"; export type LengthOptions = { long: T; short: T; mini?: T; }; export type PersonInflectionsField = | "mascSing" | "mascPlur" | "femSing" | "femPlur"; export type PersonInflections = { [K in PersonInflectionsField]: T; }; export type OptionalPersonInflections = PersonInflections | T; export type SingleOrLengthOpts = T | LengthOptions; 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 & { 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 | SingleOrLengthOpts; export type ParticipleContent = { past: SingleOrLengthOpts | SingleOrLengthOpts; // TODO: Should this ever have an object matrix?? present: SingleOrLengthOpts; }; // 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, 3>; // Plural and Second Inflection export type PluralInflectionSet = ArrayFixed, 2>; export type Gender = "masc" | "fem"; export type UnisexSet = Record; export type GenderedSet = | UnisexSet | Omit, "fem"> | Omit, "masc">; export type UnisexInflections = UnisexSet; export type Inflections = GenderedSet; export type PluralInflections = GenderedSet; 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, /** plural form of person */ ArrayOneOrMore ]; /** * 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 = OptionalPersonInflections>; export type VerbForm = FullForm; export type ImperativeForm = FullForm; export type SentenceForm = SingleOrLengthOpts>; export interface ArrayFixed extends Array { 0: T; length: L; } export type Wrapper = T & { __brand: "wrapped" }; export type ArrayOneOrMore = { 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 & { 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 & { __brand7: "a singular noun - as opposed to an always plural noun"; }; export type PluralNounEntry = T & { __brand7: "a noun that is always plural"; }; export type Pattern1Entry = T & { __brand3: "basic inflection pattern" }; export type Pattern2Entry = T & { __brand3: "ending in unstressed ی pattern"; }; export type Pattern3Entry = T & { __brand3: "ending in stressed ی pattern" }; export type Pattern4Entry = T & { __brand3: "Pashtoon pattern" }; export type Pattern5Entry = T & { __brand3: "short squish pattern" }; export type Pattern6FemEntry = T & { __brand3: "non anim. ending in ي"; }; export type NonInflecting = T & { __brand3: "non-inflecting" }; export type Entry = NounEntry | AdjectiveEntry | AdverbEntry | VerbEntry; // TODO: make this Rendered 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" | "wouldBe" | "pastSubjunctive" | "wouldHaveBeen"; 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, "object" | "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 & { ps: { head: PsString | undefined; rest: SingleOrLengthOpts; }; 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; }; 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 | 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 extends Record ? Omit & Record : 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; 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 | ComplementSelection | DemonstrativeSelection | ComplementSelection["selection"] | UnselectedComplementSelection | undefined > = T extends NPSelection ? { type: "NP"; selection: Rendered; } : T extends APSelection ? { type: "AP"; selection: Rendered; } : T extends ComplementSelection ? { type: "complement"; selection: Rendered; } : T extends UnselectedComplementSelection ? { type: "complement"; selection: { type: "unselected"; ps: PsString[]; e: string; }; } : T extends SandwichSelection ? Omit, "inside"> & { inside: Rendered; } : 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> | undefined; inflected: boolean; person: Person; } : T extends DemonstrativeSelection ? { type: "demonstrative"; demonstrative: DemonstrativeSelection["demonstrative"]; hideNoun: boolean; ps: PsString; } : T extends ComplementSelection ? { type: "complement"; selection: Rendered; } : T extends SubjectSelectionComplete ? { type: "subjectSelection"; selection: Rendered; } : T extends ObjectSelectionComplete ? { type: "objectSelection"; selection: Rendered | Person.ThirdPlurMale | "none"; } : T extends PredicateSelectionComplete ? { type: "predicateSelection"; selection: Rendered | Rendered; } : T extends undefined ? { type: "undefined"; ps: PsString; } : ReplaceKey< Omit< T, | "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor" >, "e", string > & { ps: PsString[]; e?: string; inflected: boolean; person: Person; role: "king" | "servant" | "none"; // TODO: better recursive thing adjectives?: Rendered[]; possesor?: { shrunken: boolean; np: Rendered; }; demonstrative?: Rendered; }; 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 & { inside: NPSelection; }; export type ComplementSelection = { type: "complement"; selection: | AdjectiveSelection | LocativeAdverbSelection | SandwichSelection | 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; person: Person; hasBa: boolean; }; export type EPRendered = { type: "EPRendered"; blocks: Block[][]; kids: Kid[]; englishBase?: string[]; omitSubject: boolean; }; export type EntryFeeder = | { nouns: EntryLookupPortal; verbs: EntryLookupPortal; adjectives: EntryLookupPortal; locativeAdverbs: EntryLookupPortal; adverbs: EntryLookupPortal; } | { nouns: NounEntry[]; verbs: VerbEntry[]; adjectives: AdjectiveEntry[]; locativeAdverbs: LocativeAdverbEntry[]; adverbs: AdverbEntry[]; }; export type EntryFeederSingleType = | X[] | EntryLookupPortal; export type EntryLookupPortal = { 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 | Rendered | Rendered | Rendered | Rendered | Rendered | NegativeBlock | EquativeBlock | VB | VBE | VHead; }; export type ParsedBlock = ParsedNP | ParsedPH | ParsedVBE | 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; 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 VBBasic ? Omit & { ps: PsString[] } : Omit & { right: VBNoLenghts> }; export type VBBasic = { type: "VB"; ps: SingleOrLengthOpts; }; 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

= { tokens: Readonly; body: P; errors: ParseError[]; };