custom type guards!
This commit is contained in:
parent
96be0e0a28
commit
7a8edbc4ce
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/pashto-inflector",
|
"name": "@lingdocs/pashto-inflector",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"author": "lingdocs.com",
|
"author": "lingdocs.com",
|
||||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||||
"homepage": "https://verbs.lingdocs.com",
|
"homepage": "https://verbs.lingdocs.com",
|
||||||
|
|
|
@ -52,7 +52,7 @@ function formHasVariations(form: T.VerbForm | T.ImperativeForm | T.ParticipleFor
|
||||||
if (!isVerbBlock(form)) {
|
if (!isVerbBlock(form)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !isAllOne(form as T.VerbBlock);
|
return !isAllOne(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pronouns = undefined | {
|
type Pronouns = undefined | {
|
||||||
|
|
|
@ -246,7 +246,7 @@ function getMatchingInflection(
|
||||||
return infs[persNum % 2 === 0 ? "masc" : "fem"][singPlur][0];
|
return infs[persNum % 2 === 0 ? "masc" : "fem"][singPlur][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVerbBlock(x: unknown) {
|
export function isVerbBlock(x: unknown): x is T.VerbBlock {
|
||||||
return (
|
return (
|
||||||
Array.isArray(x) &&
|
Array.isArray(x) &&
|
||||||
(x.length === 6) &&
|
(x.length === 6) &&
|
||||||
|
@ -254,7 +254,7 @@ export function isVerbBlock(x: unknown) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isImperativeBlock(x: unknown) {
|
export function isImperativeBlock(x: unknown): x is T.ImperativeBlock {
|
||||||
return (
|
return (
|
||||||
Array.isArray(x) &&
|
Array.isArray(x) &&
|
||||||
(x.length === 2) &&
|
(x.length === 2) &&
|
||||||
|
@ -262,7 +262,7 @@ export function isImperativeBlock(x: unknown) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isInflectionSet(x: any): boolean {
|
export function isInflectionSet(x: any): x is T.InflectionSet {
|
||||||
return (
|
return (
|
||||||
Array.isArray(x)
|
Array.isArray(x)
|
||||||
&& (x.length === 3)
|
&& (x.length === 3)
|
||||||
|
@ -346,8 +346,7 @@ export function addToForm(
|
||||||
const add = addingLengthChosen.map((e) => {
|
const add = addingLengthChosen.map((e) => {
|
||||||
if (e === " ") return e;
|
if (e === " ") return e;
|
||||||
if (isVerbBlock(e)) {
|
if (isVerbBlock(e)) {
|
||||||
const block = e as T.VerbBlock;
|
return e[persNum][singPlur][0];
|
||||||
return block[persNum][singPlur][0];
|
|
||||||
}
|
}
|
||||||
const f = e as T.UnisexInflections | T.PsString[] | T.OptionalPersonInflections<T.PsString>;
|
const f = e as T.UnisexInflections | T.PsString[] | T.OptionalPersonInflections<T.PsString>;
|
||||||
if (Array.isArray(f)) {
|
if (Array.isArray(f)) {
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import {
|
|
||||||
searchConjugation,
|
|
||||||
} from "./search-conjugation";
|
|
||||||
import {
|
|
||||||
conjugateVerb,
|
|
||||||
} from "./verb-conjugation";
|
|
||||||
|
|
||||||
test("combo verbs should be searchable", () => {
|
|
||||||
const conjugation = conjugateVerb(
|
|
||||||
{ i: 0, ts: 0, p: "قتل کول", f: "qatul kawul", e:"to kill", g: "qatil kawul", c: "v. dyn./stat. comp. trans.", l: 2 },
|
|
||||||
{ i: 1, ts: 2, p: "قتل", f: "qatul", e: "murder", g: "qatul", c: "n. m." },
|
|
||||||
);
|
|
||||||
// console.log(conjugation);
|
|
||||||
// @ts-ignore
|
|
||||||
const { grammaticallyTransitive, transitive } = conjugation;
|
|
||||||
// console.log(JSON.stringify(grammaticallyTransitive, null, " "));
|
|
||||||
// @ts-ignore
|
|
||||||
const result = searchConjugation(conjugation, "ولیدل");
|
|
||||||
expect(result).toBeTruthy();
|
|
||||||
});
|
|
|
@ -1,143 +0,0 @@
|
||||||
import * as T from "../types";
|
|
||||||
import {
|
|
||||||
isVerbBlock,
|
|
||||||
isImperativeBlock,
|
|
||||||
isInflectionSet,
|
|
||||||
} from "./p-text-helpers";
|
|
||||||
import { personFromVerbBlockPos } from "./misc-helpers";
|
|
||||||
|
|
||||||
const inflectionNames: InflectionName[] = ["plain", "1st", "2nd"];
|
|
||||||
|
|
||||||
type ObPile = { [key: string]: ObRec; }
|
|
||||||
type ObRec = any[] | { p: string } | ObPile;
|
|
||||||
|
|
||||||
type ConjSearchResults = {
|
|
||||||
form: string[],
|
|
||||||
position: InflectionName[] | T.Person[] | null,
|
|
||||||
}[];
|
|
||||||
|
|
||||||
type BlockResult = {
|
|
||||||
blockResult: true,
|
|
||||||
position: InflectionName[] | T.Person[] | null,
|
|
||||||
}
|
|
||||||
|
|
||||||
type InflectionName = "plain" | "1st" | "2nd";
|
|
||||||
|
|
||||||
export function searchConjugation(pile: ObPile, s: string): ConjSearchResults {
|
|
||||||
|
|
||||||
function searchObRecord(record: ObRec): null | BlockResult | ConjSearchResults {
|
|
||||||
// hit a bottom part a tree, see if what we're looking for is there
|
|
||||||
if (Array.isArray(record)) {
|
|
||||||
return searchBlock(record, s);
|
|
||||||
}
|
|
||||||
// TODO: This is only because of the grammatically transitive past participle!! Should change that to make it faster
|
|
||||||
if ("p" in record) {
|
|
||||||
// @ts-ignore
|
|
||||||
return searchSinglePs(record, s);
|
|
||||||
}
|
|
||||||
// look further down the tree recursively
|
|
||||||
return searchConjugation(record, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.entries(pile).reduce((res: ConjSearchResults, entry) => {
|
|
||||||
const [name, value] = entry;
|
|
||||||
if (name === "info") {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
const result = searchObRecord(value);
|
|
||||||
// Result: Hit the bottom and nothing found
|
|
||||||
if (result === null) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
// Result: Hit the bottom and found what we were looking for
|
|
||||||
// add in the path and position
|
|
||||||
if ("blockResult" in result) {
|
|
||||||
return [
|
|
||||||
...res,
|
|
||||||
{
|
|
||||||
form: [name],
|
|
||||||
position: result.position,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
// Result: Have to keep looking down recursively
|
|
||||||
// add in the current path to all the results
|
|
||||||
const rb: ConjSearchResults = [
|
|
||||||
...res,
|
|
||||||
...result.map((r) => ({
|
|
||||||
...r,
|
|
||||||
form: [name, ...r.form],
|
|
||||||
})),
|
|
||||||
]
|
|
||||||
return rb;
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchSinglePs(ps: T.PsString, s: string): null | BlockResult {
|
|
||||||
if (ps.p === s) {
|
|
||||||
return {
|
|
||||||
blockResult: true,
|
|
||||||
position: null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchBlock(block: any[], s: string): null | BlockResult {
|
|
||||||
if (isVerbBlock(block)) {
|
|
||||||
const verbBlock = block as T.VerbBlock;
|
|
||||||
const position = searchVerbBlock(verbBlock, s);
|
|
||||||
if (position.length) {
|
|
||||||
return {
|
|
||||||
blockResult: true,
|
|
||||||
position: position.map(pos => personFromVerbBlockPos(pos)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isImperativeBlock(block)) {
|
|
||||||
const ImperativeBlock = block as T.ImperativeBlock;
|
|
||||||
const position = searchVerbBlock(ImperativeBlock, s);
|
|
||||||
if (position.length) {
|
|
||||||
return {
|
|
||||||
blockResult: true,
|
|
||||||
position: position.map(pos => personFromVerbBlockPos([pos[0] + 2, pos[1]])),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isInflectionSet(block)) {
|
|
||||||
const inflectionSet = block as T.InflectionSet;
|
|
||||||
const position = searchInflectionSet(inflectionSet, s);
|
|
||||||
if (position.length) {
|
|
||||||
return {
|
|
||||||
blockResult: true,
|
|
||||||
position: position,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchVerbBlock(vb: T.VerbBlock | T.ImperativeBlock, s: string): [number, number][] {
|
|
||||||
function searchRow(row: T.PersonLine): (0 | 1)[] {
|
|
||||||
return row.reduce((all: (0 | 1)[], item, i: number): (0 | 1)[] => {
|
|
||||||
const c = item.some(ps => ps.p === s)
|
|
||||||
? [...all, i as 0 | 1]
|
|
||||||
: all
|
|
||||||
return c;
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
return vb.reduce((found: [number, number][], row, i): [number, number][] => {
|
|
||||||
const inRow = searchRow(row);
|
|
||||||
if (inRow.length === 0) return found;
|
|
||||||
return [...found, ...inRow.map((f): [number, number] => [i, f])];
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchInflectionSet(inf: T.InflectionSet, s: string): InflectionName[] {
|
|
||||||
return inf.reduce((found: InflectionName[], item, i): InflectionName[] => {
|
|
||||||
if (item.some((ps) => ps.p === s)) {
|
|
||||||
return [...found, inflectionNames[i]];
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}, []);
|
|
||||||
}
|
|
|
@ -25,7 +25,6 @@ import VerbFormDisplay from "./components/VerbFormDisplay";
|
||||||
import VerbTable from "./components/VerbTable";
|
import VerbTable from "./components/VerbTable";
|
||||||
import Examples from "./components/Examples";
|
import Examples from "./components/Examples";
|
||||||
import VerbInfo, { RootsAndStems } from "./components/verb-info/VerbInfo";
|
import VerbInfo, { RootsAndStems } from "./components/verb-info/VerbInfo";
|
||||||
import { searchConjugation } from "./lib/search-conjugation";
|
|
||||||
import {
|
import {
|
||||||
addToForm,
|
addToForm,
|
||||||
concatPsString,
|
concatPsString,
|
||||||
|
@ -96,7 +95,6 @@ export {
|
||||||
phoneticsToDiacritics,
|
phoneticsToDiacritics,
|
||||||
addDiacritics,
|
addDiacritics,
|
||||||
translatePhonetics,
|
translatePhonetics,
|
||||||
searchConjugation,
|
|
||||||
getEnglishPersonInfo,
|
getEnglishPersonInfo,
|
||||||
getPersonFromVerbForm,
|
getPersonFromVerbForm,
|
||||||
getPersonNumber,
|
getPersonNumber,
|
||||||
|
|
Loading…
Reference in New Issue