added event emitter for VPExplorer for monitoring events
This commit is contained in:
parent
b5e33b1db9
commit
23f3dcd2c5
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "pashto-inflector",
|
"name": "pashto-inflector",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pashto-inflector",
|
"name": "pashto-inflector",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "pashto-inflector",
|
"name": "pashto-inflector",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"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",
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/ps-react",
|
"name": "@lingdocs/ps-react",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@lingdocs/ps-react",
|
"name": "@lingdocs/ps-react",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/auto-animate": "^1.0.0-beta.3",
|
"@formkit/auto-animate": "^1.0.0-beta.3",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/ps-react",
|
"name": "@lingdocs/ps-react",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"description": "Pashto inflector library module with React components",
|
"description": "Pashto inflector library module with React components",
|
||||||
"main": "dist/components/library.js",
|
"main": "dist/components/library.js",
|
||||||
"module": "dist/components/library.js",
|
"module": "dist/components/library.js",
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 71 KiB |
|
@ -10,7 +10,10 @@ import { completeVPSelection } from "../../../lib/src/phrase-building/vp-tools";
|
||||||
import VPExplorerQuiz from "./VPExplorerQuiz";
|
import VPExplorerQuiz from "./VPExplorerQuiz";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import LZString from "lz-string";
|
import LZString from "lz-string";
|
||||||
import { vpsReducer } from "../../../lib/src/phrase-building/vps-reducer";
|
import {
|
||||||
|
VpsReducerAction,
|
||||||
|
vpsReducer,
|
||||||
|
} from "../../../lib/src/phrase-building/vps-reducer";
|
||||||
import { getObjectSelection } from "../../../lib/src/phrase-building/blocks-utils";
|
import { getObjectSelection } from "../../../lib/src/phrase-building/blocks-utils";
|
||||||
import VPPicker from "./VPPicker";
|
import VPPicker from "./VPPicker";
|
||||||
import AllTensesDisplay from "./AllTensesDisplay";
|
import AllTensesDisplay from "./AllTensesDisplay";
|
||||||
|
@ -34,6 +37,7 @@ function VPExplorer(props: {
|
||||||
handleLinkClick: ((ts: number) => void) | "none";
|
handleLinkClick: ((ts: number) => void) | "none";
|
||||||
entryFeeder: T.EntryFeeder;
|
entryFeeder: T.EntryFeeder;
|
||||||
onlyPhrases?: boolean;
|
onlyPhrases?: boolean;
|
||||||
|
eventEmitter?: (e: string) => void;
|
||||||
}) {
|
}) {
|
||||||
const [vps, adjustVps] = useStickyReducer(
|
const [vps, adjustVps] = useStickyReducer(
|
||||||
vpsReducer,
|
vpsReducer,
|
||||||
|
@ -85,7 +89,7 @@ function VPExplorer(props: {
|
||||||
const VPSFromUrl = getVPSFromUrl();
|
const VPSFromUrl = getVPSFromUrl();
|
||||||
if (VPSFromUrl) {
|
if (VPSFromUrl) {
|
||||||
setMode("phrases");
|
setMode("phrases");
|
||||||
adjustVps({
|
eventWrapper(adjustVps)({
|
||||||
type: "load vps",
|
type: "load vps",
|
||||||
payload: VPSFromUrl,
|
payload: VPSFromUrl,
|
||||||
});
|
});
|
||||||
|
@ -93,7 +97,15 @@ function VPExplorer(props: {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, []);
|
}, []);
|
||||||
function handleSubjObjSwap() {
|
function handleSubjObjSwap() {
|
||||||
adjustVps({ type: "swap subj/obj" });
|
eventWrapper(adjustVps)({ type: "swap subj/obj" });
|
||||||
|
}
|
||||||
|
function eventWrapper(f: (a: VpsReducerAction) => void) {
|
||||||
|
return function (action: VpsReducerAction) {
|
||||||
|
if (props.eventEmitter) {
|
||||||
|
props.eventEmitter(`VP exlorer ${props.verb.entry.p}`);
|
||||||
|
}
|
||||||
|
return f(action);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
function quizLock<T>(f: T) {
|
function quizLock<T>(f: T) {
|
||||||
if (mode === "quiz") {
|
if (mode === "quiz") {
|
||||||
|
@ -105,7 +117,7 @@ function VPExplorer(props: {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
function handleSetForm(form: T.FormVersion) {
|
function handleSetForm(form: T.FormVersion) {
|
||||||
adjustVps({
|
eventWrapper(adjustVps)({
|
||||||
type: "set form",
|
type: "set form",
|
||||||
payload: form,
|
payload: form,
|
||||||
});
|
});
|
||||||
|
@ -134,7 +146,7 @@ function VPExplorer(props: {
|
||||||
<div className="mt-3" style={{ maxWidth: "950px" }}>
|
<div className="mt-3" style={{ maxWidth: "950px" }}>
|
||||||
<VerbPicker
|
<VerbPicker
|
||||||
vps={vps}
|
vps={vps}
|
||||||
onChange={quizLock(adjustVps)}
|
onChange={quizLock(eventWrapper(adjustVps))}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
handleLinkClick={props.handleLinkClick}
|
handleLinkClick={props.handleLinkClick}
|
||||||
/>
|
/>
|
||||||
|
@ -190,13 +202,19 @@ function VPExplorer(props: {
|
||||||
<VPPicker
|
<VPPicker
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
onChange={(payload) => adjustVps({ type: "load vps", payload })}
|
onChange={(payload) =>
|
||||||
|
eventWrapper(adjustVps)({ type: "load vps", payload })
|
||||||
|
}
|
||||||
vps={vps}
|
vps={vps}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{mode !== "phrases" && (
|
{mode !== "phrases" && (
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<TensePicker vps={vps} onChange={adjustVps} mode={mode} />
|
<TensePicker
|
||||||
|
vps={vps}
|
||||||
|
onChange={eventWrapper(adjustVps)}
|
||||||
|
mode={mode}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{mode === "phrases" && (
|
{mode === "phrases" && (
|
||||||
|
@ -207,7 +225,7 @@ function VPExplorer(props: {
|
||||||
object={object}
|
object={object}
|
||||||
VS={vps.verb}
|
VS={vps.verb}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={adjustVps}
|
onChange={eventWrapper(adjustVps)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{mode === "quiz" && <VPExplorerQuiz opts={props.opts} vps={vps} />}
|
{mode === "quiz" && <VPExplorerQuiz opts={props.opts} vps={vps} />}
|
||||||
|
|
|
@ -5,12 +5,8 @@ import Phonetics from "../components/src/Phonetics";
|
||||||
import { getVerbInfo } from "../lib/src/verb-info";
|
import { getVerbInfo } from "../lib/src/verb-info";
|
||||||
import verbs from "../verbs";
|
import verbs from "../verbs";
|
||||||
import { useStickyState } from "../components/library";
|
import { useStickyState } from "../components/library";
|
||||||
import {
|
import { clamp } from "../lib/src/p-text-helpers";
|
||||||
clamp
|
import { randomNumber } from "../lib/src/misc-helpers";
|
||||||
} from "../lib/src/p-text-helpers";
|
|
||||||
import {
|
|
||||||
randomNumber,
|
|
||||||
} from "../lib/src/misc-helpers";
|
|
||||||
import { entryFeeder } from "./entryFeeder";
|
import { entryFeeder } from "./entryFeeder";
|
||||||
|
|
||||||
const transitivities: T.Transitivity[] = [
|
const transitivities: T.Transitivity[] = [
|
||||||
|
@ -19,10 +15,12 @@ const transitivities: T.Transitivity[] = [
|
||||||
"grammatically transitive",
|
"grammatically transitive",
|
||||||
];
|
];
|
||||||
|
|
||||||
const allVerbs = verbs.map((v: { entry: T.DictionaryEntry, complement?: T.DictionaryEntry }) => ({
|
const allVerbs = verbs.map(
|
||||||
|
(v: { entry: T.DictionaryEntry; complement?: T.DictionaryEntry }) => ({
|
||||||
verb: v,
|
verb: v,
|
||||||
info: getVerbInfo(v.entry, v.complement),
|
info: getVerbInfo(v.entry, v.complement),
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
|
|
||||||
type VerbType = "simple" | "stative compound" | "dynamic compound";
|
type VerbType = "simple" | "stative compound" | "dynamic compound";
|
||||||
const verbTypes: VerbType[] = [
|
const verbTypes: VerbType[] = [
|
||||||
|
@ -31,12 +29,14 @@ const verbTypes: VerbType[] = [
|
||||||
"dynamic compound",
|
"dynamic compound",
|
||||||
];
|
];
|
||||||
|
|
||||||
function VPBuilderDemo({ opts }: {
|
function VPBuilderDemo({ opts }: { opts: T.TextOptions }) {
|
||||||
opts: T.TextOptions,
|
|
||||||
}) {
|
|
||||||
const [verbTs, setVerbTs] = useStickyState<number>(0, "verbTs1");
|
const [verbTs, setVerbTs] = useStickyState<number>(0, "verbTs1");
|
||||||
const [verbTypeShowing, setVerbTypeShowing] = useStickyState<VerbType>("simple", "vTypeShowing");
|
const [verbTypeShowing, setVerbTypeShowing] = useStickyState<VerbType>(
|
||||||
const [transitivityShowing, setTransitivityShowing] = useStickyState<T.Transitivity>("intransitive", "transitivityShowing1");
|
"simple",
|
||||||
|
"vTypeShowing"
|
||||||
|
);
|
||||||
|
const [transitivityShowing, setTransitivityShowing] =
|
||||||
|
useStickyState<T.Transitivity>("intransitive", "transitivityShowing1");
|
||||||
// const onlyGrammTrans = (arr: Transitivity[]) => (
|
// const onlyGrammTrans = (arr: Transitivity[]) => (
|
||||||
// arr.length === 1 && arr[0] === "grammatically transitive"
|
// arr.length === 1 && arr[0] === "grammatically transitive"
|
||||||
// );
|
// );
|
||||||
|
@ -47,46 +47,56 @@ function VPBuilderDemo({ opts }: {
|
||||||
// }
|
// }
|
||||||
const handleVerbIndexChange = (e: any) => {
|
const handleVerbIndexChange = (e: any) => {
|
||||||
setVerbTs(parseInt(e.target.value));
|
setVerbTs(parseInt(e.target.value));
|
||||||
}
|
};
|
||||||
const handleTypeSelection = (e: any) => {
|
const handleTypeSelection = (e: any) => {
|
||||||
const type = e.target.value as VerbType;
|
const type = e.target.value as VerbType;
|
||||||
if (type === "dynamic compound") {
|
if (type === "dynamic compound") {
|
||||||
setTransitivityShowing("transitive");
|
setTransitivityShowing("transitive");
|
||||||
}
|
}
|
||||||
if (type === "stative compound" && transitivityShowing === "grammatically transitive") {
|
if (
|
||||||
|
type === "stative compound" &&
|
||||||
|
transitivityShowing === "grammatically transitive"
|
||||||
|
) {
|
||||||
setTransitivityShowing("transitive");
|
setTransitivityShowing("transitive");
|
||||||
}
|
}
|
||||||
setVerbTypeShowing(type);
|
setVerbTypeShowing(type);
|
||||||
}
|
};
|
||||||
const handleTransitivitySelection = (e: any) => {
|
const handleTransitivitySelection = (e: any) => {
|
||||||
const transitivity = e.target.value as T.Transitivity;
|
const transitivity = e.target.value as T.Transitivity;
|
||||||
if (transitivity === "grammatically transitive") {
|
if (transitivity === "grammatically transitive") {
|
||||||
setVerbTypeShowing("simple");
|
setVerbTypeShowing("simple");
|
||||||
}
|
}
|
||||||
if (transitivity === "intransitive" && verbTypeShowing === "dynamic compound") {
|
if (
|
||||||
|
transitivity === "intransitive" &&
|
||||||
|
verbTypeShowing === "dynamic compound"
|
||||||
|
) {
|
||||||
setTransitivityShowing("transitive");
|
setTransitivityShowing("transitive");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setTransitivityShowing(e.target.value as T.Transitivity);
|
setTransitivityShowing(e.target.value as T.Transitivity);
|
||||||
}
|
};
|
||||||
const verbsAvailable = allVerbs.filter((verb) => (
|
const verbsAvailable = allVerbs
|
||||||
(
|
.filter(
|
||||||
(verb.info.type === "transitive or grammatically transitive simple" && verbTypeShowing === "simple") && (transitivityShowing === "transitive" || transitivityShowing === "grammatically transitive")
|
(verb) =>
|
||||||
) ||
|
(verb.info.type === "transitive or grammatically transitive simple" &&
|
||||||
((
|
verbTypeShowing === "simple" &&
|
||||||
verbTypeShowing === verb.info.type ||
|
(transitivityShowing === "transitive" ||
|
||||||
(verbTypeShowing === "stative compound" && verb.info.type === "dynamic or stative compound") ||
|
transitivityShowing === "grammatically transitive")) ||
|
||||||
(verbTypeShowing === "dynamic compound" && verb.info.type === "dynamic or stative compound") ||
|
((verbTypeShowing === verb.info.type ||
|
||||||
(verbTypeShowing === "dynamic compound" && verb.info.type === "dynamic or generative stative compound") ||
|
(verbTypeShowing === "stative compound" &&
|
||||||
(verbTypeShowing === "stative compound" && verb.info.type === "dynamic or generative stative compound")
|
verb.info.type === "dynamic or stative compound") ||
|
||||||
|
(verbTypeShowing === "dynamic compound" &&
|
||||||
|
verb.info.type === "dynamic or stative compound") ||
|
||||||
|
(verbTypeShowing === "dynamic compound" &&
|
||||||
|
verb.info.type === "dynamic or generative stative compound") ||
|
||||||
|
(verbTypeShowing === "stative compound" &&
|
||||||
|
verb.info.type === "dynamic or generative stative compound")) &&
|
||||||
|
transitivityShowing === verb.info.transitivity)
|
||||||
)
|
)
|
||||||
&& (
|
.sort((a, b) => a.verb.entry.p.localeCompare(b.verb.entry.p, "ps"));
|
||||||
transitivityShowing === verb.info.transitivity
|
|
||||||
))
|
|
||||||
)).sort((a, b) => a.verb.entry.p.localeCompare(b.verb.entry.p, "ps"));
|
|
||||||
|
|
||||||
const v = (() => {
|
const v = (() => {
|
||||||
const vFound = verbsAvailable.find(v => v.verb.entry.ts === verbTs);
|
const vFound = verbsAvailable.find((v) => v.verb.entry.ts === verbTs);
|
||||||
if (vFound) return vFound;
|
if (vFound) return vFound;
|
||||||
if (verbsAvailable.length === 0) return undefined;
|
if (verbsAvailable.length === 0) return undefined;
|
||||||
const vTopOfList = verbsAvailable[0];
|
const vTopOfList = verbsAvailable[0];
|
||||||
|
@ -98,34 +108,46 @@ function VPBuilderDemo({ opts }: {
|
||||||
let newIndex: number;
|
let newIndex: number;
|
||||||
do {
|
do {
|
||||||
newIndex = randomNumber(0, verbsAvailable.length);
|
newIndex = randomNumber(0, verbsAvailable.length);
|
||||||
} while(verbsAvailable[newIndex].verb.entry.ts === verbTs);
|
} while (verbsAvailable[newIndex].verb.entry.ts === verbTs);
|
||||||
setVerbTs(verbsAvailable[newIndex].verb.entry.ts);
|
setVerbTs(verbsAvailable[newIndex].verb.entry.ts);
|
||||||
};
|
};
|
||||||
const makeVerbLabel = (entry: T.DictionaryEntry): string => (
|
const makeVerbLabel = (entry: T.DictionaryEntry): string =>
|
||||||
`${entry.p} - ${clamp(entry.e, 20)}`
|
`${entry.p} - ${clamp(entry.e, 20)}`;
|
||||||
);
|
|
||||||
// const rs = v ? getAllRs(v.verb as T.VerbEntry) : undefined
|
// const rs = v ? getAllRs(v.verb as T.VerbEntry) : undefined
|
||||||
return <div className="mt-4">
|
return (
|
||||||
<div className="d-block mx-auto card" style={{ maxWidth: "700px", background: "var(--closer)"}}>
|
<div className="mt-4">
|
||||||
|
<div
|
||||||
|
className="d-block mx-auto card"
|
||||||
|
style={{ maxWidth: "700px", background: "var(--closer)" }}
|
||||||
|
>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
{v ?
|
{v ? (
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-1">Select a verb:</div>
|
<div className="mb-1">Select a verb:</div>
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
<select className="custom-select" value={verbTs} onChange={handleVerbIndexChange}>
|
<select
|
||||||
{verbsAvailable.length
|
className="custom-select"
|
||||||
? verbsAvailable.map((v, i) => (
|
value={verbTs}
|
||||||
|
onChange={handleVerbIndexChange}
|
||||||
|
>
|
||||||
|
{verbsAvailable.length ? (
|
||||||
|
verbsAvailable.map((v, i) => (
|
||||||
<option value={v.verb.entry.ts} key={i} dir="ltr">
|
<option value={v.verb.entry.ts} key={i} dir="ltr">
|
||||||
{"\u200E"}{makeVerbLabel(v.verb.entry)}
|
{"\u200E"}
|
||||||
|
{makeVerbLabel(v.verb.entry)}
|
||||||
</option>
|
</option>
|
||||||
))
|
))
|
||||||
: <option>Select a verb type</option>
|
) : (
|
||||||
}
|
<option>Select a verb type</option>
|
||||||
|
)}
|
||||||
</select>
|
</select>
|
||||||
<div className="input-group-append">
|
<div className="input-group-append">
|
||||||
<button className="btn btn-secondary" onClick={pickRandomVerb}>
|
<button
|
||||||
|
className="btn btn-secondary"
|
||||||
|
onClick={pickRandomVerb}
|
||||||
|
>
|
||||||
<i className="fas fa-random" />
|
<i className="fas fa-random" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,10 +165,11 @@ function VPBuilderDemo({ opts }: {
|
||||||
<div className="ml-3">{v.verb.entry.e}</div>
|
<div className="ml-3">{v.verb.entry.e}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
: <div className="alert alert-warning mb-4" role="alert">
|
) : (
|
||||||
|
<div className="alert alert-warning mb-4" role="alert">
|
||||||
No such verbs available...
|
No such verbs available...
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<h6>Verb type:</h6>
|
<h6>Verb type:</h6>
|
||||||
|
@ -161,9 +184,7 @@ function VPBuilderDemo({ opts }: {
|
||||||
value={type}
|
value={type}
|
||||||
onChange={() => null}
|
onChange={() => null}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label">
|
<label className="form-check-label">{type}</label>
|
||||||
{type}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -179,9 +200,7 @@ function VPBuilderDemo({ opts }: {
|
||||||
onChange={() => null}
|
onChange={() => null}
|
||||||
value={transitivity}
|
value={transitivity}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label">
|
<label className="form-check-label">{transitivity}</label>
|
||||||
{transitivity}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -189,15 +208,18 @@ function VPBuilderDemo({ opts }: {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{v?.verb.entry && <div style={{ paddingBottom: "20px" }}>
|
{v?.verb.entry && (
|
||||||
|
<div style={{ paddingBottom: "20px" }}>
|
||||||
<PhraseBuilder
|
<PhraseBuilder
|
||||||
handleLinkClick="none"
|
handleLinkClick="none"
|
||||||
verb={v.verb as T.VerbEntry}
|
verb={v.verb as T.VerbEntry}
|
||||||
entryFeeder={entryFeeder}
|
entryFeeder={entryFeeder}
|
||||||
opts={opts}
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>
|
||||||
</div>;
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VPBuilderDemo;
|
export default VPBuilderDemo;
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/inflect",
|
"name": "@lingdocs/inflect",
|
||||||
"version": "7.0.9",
|
"version": "7.0.11",
|
||||||
"description": "Pashto inflector library",
|
"description": "Pashto inflector library",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/lib/library.d.ts",
|
"types": "dist/lib/library.d.ts",
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { parseEquative } from "./parse-equative";
|
||||||
import { parseKidsSection } from "./parse-kids-section";
|
import { parseKidsSection } from "./parse-kids-section";
|
||||||
import { parseNeg } from "./parse-negative";
|
import { parseNeg } from "./parse-negative";
|
||||||
import { parseNPAP } from "./parse-npap";
|
import { parseNPAP } from "./parse-npap";
|
||||||
import { parsePastPart } from "./parse-past-part";
|
import { parseVBP } from "./parse-vbp";
|
||||||
import { parsePH } from "./parse-ph";
|
import { parsePH } from "./parse-ph";
|
||||||
import { parseVerb } from "./parse-verb";
|
import { parseVBE } from "./parse-vbe";
|
||||||
import {
|
import {
|
||||||
bindParseResult,
|
bindParseResult,
|
||||||
returnParseResult,
|
returnParseResult,
|
||||||
|
@ -14,6 +14,7 @@ import {
|
||||||
isParsedVBP,
|
isParsedVBP,
|
||||||
startsVerbSection,
|
startsVerbSection,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
|
import { isKedulStatEntry } from "./parse-verb-helpers";
|
||||||
|
|
||||||
export function parseBlocks(
|
export function parseBlocks(
|
||||||
tokens: Readonly<T.Token[]>,
|
tokens: Readonly<T.Token[]>,
|
||||||
|
@ -32,14 +33,15 @@ export function parseBlocks(
|
||||||
(b): b is T.ParsedPH => b.type === "PH"
|
(b): b is T.ParsedPH => b.type === "PH"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TOOD: rather parse VBP / VBE
|
||||||
const allBlocks: T.ParseResult<T.ParsedBlock | T.ParsedKidsSection>[] = [
|
const allBlocks: T.ParseResult<T.ParsedBlock | T.ParsedKidsSection>[] = [
|
||||||
...(!inVerbSection ? parseNPAP(tokens, lookup) : []),
|
...(!inVerbSection ? parseNPAP(tokens, lookup) : []),
|
||||||
// ensure at most one of each PH, VBE, VBP
|
// ensure at most one of each PH, VBE, VBP
|
||||||
...(prevPh ? [] : parsePH(tokens)),
|
...(prevPh ? [] : parsePH(tokens)),
|
||||||
...(blocks.some(isParsedVBE)
|
...(blocks.some(isParsedVBE)
|
||||||
? []
|
? []
|
||||||
: [...parseVerb(tokens, lookup), ...parseEquative(tokens)]),
|
: [...parseVBE(tokens, lookup), ...parseEquative(tokens)]),
|
||||||
...(blocks.some(isParsedVBP) ? [] : parsePastPart(tokens, lookup)),
|
...(blocks.some(isParsedVBP) ? [] : parseVBP(tokens, lookup)),
|
||||||
...(blocks.some((b) => b.type === "negative") ? [] : parseNeg(tokens)),
|
...(blocks.some((b) => b.type === "negative") ? [] : parseNeg(tokens)),
|
||||||
...parseKidsSection(tokens, []),
|
...parseKidsSection(tokens, []),
|
||||||
];
|
];
|
||||||
|
@ -82,12 +84,24 @@ function phMatches(
|
||||||
if (!ph) {
|
if (!ph) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vb) {
|
if (!vb) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vb.info.type !== "verb") {
|
if (vb.info.type !== "verb") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (["را", "در", "ور"].includes(ph?.s)) {
|
||||||
|
if (
|
||||||
|
isKedulStatEntry(vb.info.verb.entry) &&
|
||||||
|
vb.info.base === "stem" &&
|
||||||
|
vb.info.aspect === "perfective"
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: handle را غل etc! ? or is
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const verbPh = getPhFromVerb(vb.info.verb, vb.info.base);
|
const verbPh = getPhFromVerb(vb.info.verb, vb.info.base);
|
||||||
return verbPh === ph.s;
|
return verbPh === ph.s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
/* eslint-disable jest/valid-title */
|
||||||
|
import * as T from "../../../types";
|
||||||
|
import { parseKedul } from "./parse-kedul";
|
||||||
|
import { kedulDyn, kedulStat } from "./irreg-verbs";
|
||||||
|
import { tokenizer } from "./tokenizer";
|
||||||
|
import { getPeople, removeKeys } from "./utils";
|
||||||
|
|
||||||
|
const tests: {
|
||||||
|
label: string;
|
||||||
|
cases: {
|
||||||
|
input: string;
|
||||||
|
output: T.ParsedVBE[];
|
||||||
|
}[];
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
label: "keG-",
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
input: "کېږې",
|
||||||
|
output: getPeople(2, "sing").flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "ked-",
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
input: "کېدم",
|
||||||
|
output: getPeople(1, "sing").flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "کېدل",
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person: T.Person.ThirdPlurMale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person: T.Person.ThirdPlurMale,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "کېدلل",
|
||||||
|
output: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "sh-",
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
input: "شې",
|
||||||
|
output: getPeople(2, "sing").flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "shw-",
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
input: "شوم",
|
||||||
|
output: getPeople(1, "sing").flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "شول",
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person: T.Person.ThirdPlurMale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person: T.Person.ThirdPlurMale,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "شولل",
|
||||||
|
output: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "sho",
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
input: "شو",
|
||||||
|
output: [
|
||||||
|
...[
|
||||||
|
T.Person.ThirdSingMale,
|
||||||
|
T.Person.FirstPlurMale,
|
||||||
|
T.Person.FirstPlurFemale,
|
||||||
|
].flatMap((person) =>
|
||||||
|
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
...[T.Person.FirstPlurMale, T.Person.FirstPlurFemale].flatMap(
|
||||||
|
(person) =>
|
||||||
|
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
tests.forEach(({ label, cases }) => {
|
||||||
|
test(label, () => {
|
||||||
|
cases.forEach(({ input, output }) => {
|
||||||
|
const tokens = tokenizer(input);
|
||||||
|
const vbe = parseKedul(tokens);
|
||||||
|
expect(vbe.every((v) => v.errors.length === 0)).toBe(true);
|
||||||
|
expect(removeKeys(vbe.map((v) => v.body))).toIncludeSameMembers(
|
||||||
|
removeKeys(output)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,154 @@
|
||||||
|
import * as T from "../../../types";
|
||||||
|
import { getVerbEnding } from "./parse-verb-helpers";
|
||||||
|
import { kedulDyn, kedulStat } from "./irreg-verbs";
|
||||||
|
import { returnParseResults } from "./utils";
|
||||||
|
|
||||||
|
export function parseKedul(
|
||||||
|
tokens: Readonly<T.Token[]>
|
||||||
|
): T.ParseResult<T.ParsedVBE>[] {
|
||||||
|
const [first, ...rest] = tokens;
|
||||||
|
const start = first.s.slice(0, -1);
|
||||||
|
const ending = first.s.at(-1) || "";
|
||||||
|
const people = getVerbEnding(ending);
|
||||||
|
if (first.s === "شو") {
|
||||||
|
return returnParseResults<T.ParsedVBE>(rest, [
|
||||||
|
...[
|
||||||
|
T.Person.ThirdSingMale,
|
||||||
|
T.Person.FirstPlurMale,
|
||||||
|
T.Person.FirstPlurFemale,
|
||||||
|
].flatMap((person) =>
|
||||||
|
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
...[T.Person.FirstPlurMale, T.Person.FirstPlurFemale].flatMap((person) =>
|
||||||
|
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (start === "کېږ") {
|
||||||
|
return returnParseResults<T.ParsedVBE>(
|
||||||
|
rest,
|
||||||
|
people.stem.flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (start === "کېد" || (start === "کېدل" && ending !== "ل")) {
|
||||||
|
return returnParseResults<T.ParsedVBE>(
|
||||||
|
rest,
|
||||||
|
people.root.flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "imperfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (start === "ش") {
|
||||||
|
return returnParseResults<T.ParsedVBE>(
|
||||||
|
rest,
|
||||||
|
people.stem.flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "stem",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (start === "شو" || (start === "شول" && ending !== "ل")) {
|
||||||
|
return returnParseResults<T.ParsedVBE>(
|
||||||
|
rest,
|
||||||
|
people.root.flatMap<T.ParsedVBE>((person) => [
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulStat,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "VB",
|
||||||
|
info: {
|
||||||
|
aspect: "perfective",
|
||||||
|
base: "root",
|
||||||
|
type: "verb",
|
||||||
|
verb: kedulDyn,
|
||||||
|
},
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import {
|
||||||
raatlul,
|
raatlul,
|
||||||
} from "./irreg-verbs";
|
} from "./irreg-verbs";
|
||||||
import { lookup, wordQuery } from "./lookup";
|
import { lookup, wordQuery } from "./lookup";
|
||||||
import { parseVerb } from "./parse-verb";
|
import { parseVBE } from "./parse-vbe";
|
||||||
import { tokenizer } from "./tokenizer";
|
import { tokenizer } from "./tokenizer";
|
||||||
import { getPeople, removeKeys } from "./utils";
|
import { getPeople, removeKeys } from "./utils";
|
||||||
|
|
||||||
|
@ -935,9 +935,6 @@ const tests: {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// TODO: It would probably be more effecient just to return the kedul verb options
|
|
||||||
// and then when we put things together with the perfective head parsed they could
|
|
||||||
// become raatlul etc...
|
|
||||||
{
|
{
|
||||||
input: "شي",
|
input: "شي",
|
||||||
output: [
|
output: [
|
||||||
|
@ -965,42 +962,6 @@ const tests: {
|
||||||
},
|
},
|
||||||
verb: kedulStat,
|
verb: kedulStat,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
stem: {
|
|
||||||
persons: [
|
|
||||||
T.Person.ThirdSingMale,
|
|
||||||
T.Person.ThirdSingFemale,
|
|
||||||
T.Person.ThirdPlurMale,
|
|
||||||
T.Person.ThirdPlurFemale,
|
|
||||||
],
|
|
||||||
aspects: ["perfective"],
|
|
||||||
},
|
|
||||||
verb: raatlul,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
stem: {
|
|
||||||
persons: [
|
|
||||||
T.Person.ThirdSingMale,
|
|
||||||
T.Person.ThirdSingFemale,
|
|
||||||
T.Person.ThirdPlurMale,
|
|
||||||
T.Person.ThirdPlurFemale,
|
|
||||||
],
|
|
||||||
aspects: ["perfective"],
|
|
||||||
},
|
|
||||||
verb: dartlul,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
stem: {
|
|
||||||
persons: [
|
|
||||||
T.Person.ThirdSingMale,
|
|
||||||
T.Person.ThirdSingFemale,
|
|
||||||
T.Person.ThirdPlurMale,
|
|
||||||
T.Person.ThirdPlurFemale,
|
|
||||||
],
|
|
||||||
aspects: ["perfective"],
|
|
||||||
},
|
|
||||||
verb: wartlul,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1011,7 +972,7 @@ tests.forEach(({ label, cases }) => {
|
||||||
test(label, () => {
|
test(label, () => {
|
||||||
cases.forEach(({ input, output }) => {
|
cases.forEach(({ input, output }) => {
|
||||||
const tokens = tokenizer(input);
|
const tokens = tokenizer(input);
|
||||||
const vbs = parseVerb(tokens, lookup).map((r) => r.body);
|
const vbs = parseVBE(tokens, lookup).map((r) => r.body);
|
||||||
const madeVbsS = output.reduce<T.ParsedVBE[]>((acc, o) => {
|
const madeVbsS = output.reduce<T.ParsedVBE[]>((acc, o) => {
|
||||||
return [
|
return [
|
||||||
...acc,
|
...acc,
|
|
@ -1,26 +1,22 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { removeFVarientsFromVerb } from "../accent-and-ps-utils";
|
import { removeFVarientsFromVerb } from "../accent-and-ps-utils";
|
||||||
import { isInVarients, lastVowelNotA } from "../p-text-helpers";
|
import { isInVarients, lastVowelNotA } from "../p-text-helpers";
|
||||||
import {
|
import { dartlul, raatlul, tlul, wartlul } from "./irreg-verbs";
|
||||||
dartlul,
|
|
||||||
kedulDyn,
|
|
||||||
kedulStat,
|
|
||||||
raatlul,
|
|
||||||
tlul,
|
|
||||||
wartlul,
|
|
||||||
} from "./irreg-verbs";
|
|
||||||
import { LookupFunction } from "./lookup";
|
import { LookupFunction } from "./lookup";
|
||||||
import { shortVerbEndConsonant } from "./misc";
|
import { shortVerbEndConsonant } from "./misc";
|
||||||
|
import { parseKedul } from "./parse-kedul";
|
||||||
|
import { getVerbEnding } from "./parse-verb-helpers";
|
||||||
|
|
||||||
// TODO: کول verbs!
|
// TODO: کول verbs!
|
||||||
// check that aawu stuff is working
|
// check that aawu stuff is working
|
||||||
// check oo`azmooy -
|
// check oo`azmooy -
|
||||||
// check څاته
|
// check څاته
|
||||||
// laaRa shum etc
|
// laaRa shum etc
|
||||||
|
// TODO: proper use of perfective with sh
|
||||||
|
// TODO: use of raa, dar, war with sh
|
||||||
// TODO: هغه لاړ
|
// TODO: هغه لاړ
|
||||||
|
|
||||||
export function parseVerb(
|
export function parseVBE(
|
||||||
tokens: Readonly<T.Token[]>,
|
tokens: Readonly<T.Token[]>,
|
||||||
lookup: LookupFunction
|
lookup: LookupFunction
|
||||||
): T.ParseResult<T.ParsedVBE>[] {
|
): T.ParseResult<T.ParsedVBE>[] {
|
||||||
|
@ -36,6 +32,7 @@ export function parseVerb(
|
||||||
errors: [],
|
errors: [],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
const kedulStat = parseKedul(tokens);
|
||||||
const ending = first.s.at(-1) || "";
|
const ending = first.s.at(-1) || "";
|
||||||
const people = getVerbEnding(ending);
|
const people = getVerbEnding(ending);
|
||||||
const imperativePeople = getImperativeVerbEnding(ending);
|
const imperativePeople = getImperativeVerbEnding(ending);
|
||||||
|
@ -46,11 +43,14 @@ export function parseVerb(
|
||||||
// console.log({ verbs: JSON.stringify(verbs) });
|
// console.log({ verbs: JSON.stringify(verbs) });
|
||||||
// }
|
// }
|
||||||
// Then find out which ones match exactly and how
|
// Then find out which ones match exactly and how
|
||||||
return matchVerbs(first.s, verbs, people, imperativePeople).map((body) => ({
|
return [
|
||||||
|
...kedulStat,
|
||||||
|
...matchVerbs(first.s, verbs, people, imperativePeople).map((body) => ({
|
||||||
tokens: rest,
|
tokens: rest,
|
||||||
body,
|
body,
|
||||||
errors: [],
|
errors: [],
|
||||||
}));
|
})),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchVerbs(
|
function matchVerbs(
|
||||||
|
@ -65,6 +65,9 @@ function matchVerbs(
|
||||||
const w: T.ParsedVBE[] = [];
|
const w: T.ParsedVBE[] = [];
|
||||||
const lEnding = s.endsWith("ل");
|
const lEnding = s.endsWith("ل");
|
||||||
const base = s.endsWith("ل") ? s : s.slice(0, -1);
|
const base = s.endsWith("ل") ? s : s.slice(0, -1);
|
||||||
|
if (["کېږ", "کېد", "ش", "شو", "شول"].includes(base)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const matchShortOrLong = (b: string, x: string) => {
|
const matchShortOrLong = (b: string, x: string) => {
|
||||||
return b === x || (!lEnding && b === x.slice(0, -1));
|
return b === x || (!lEnding && b === x.slice(0, -1));
|
||||||
};
|
};
|
||||||
|
@ -317,61 +320,6 @@ function getImperativeVerbEnding(e: string): T.Person[] {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVerbEnding(e: string): {
|
|
||||||
stem: T.Person[];
|
|
||||||
root: T.Person[];
|
|
||||||
} {
|
|
||||||
if (e === "م") {
|
|
||||||
return {
|
|
||||||
root: [T.Person.FirstSingMale, T.Person.FirstSingFemale],
|
|
||||||
stem: [T.Person.FirstSingMale, T.Person.FirstSingFemale],
|
|
||||||
};
|
|
||||||
} else if (e === "ې") {
|
|
||||||
return {
|
|
||||||
root: [
|
|
||||||
T.Person.SecondSingMale,
|
|
||||||
T.Person.SecondSingFemale,
|
|
||||||
T.Person.ThirdPlurFemale,
|
|
||||||
],
|
|
||||||
stem: [T.Person.SecondSingMale, T.Person.SecondSingFemale],
|
|
||||||
};
|
|
||||||
} else if (e === "ي") {
|
|
||||||
return {
|
|
||||||
stem: [
|
|
||||||
T.Person.ThirdSingMale,
|
|
||||||
T.Person.ThirdSingFemale,
|
|
||||||
T.Person.ThirdPlurMale,
|
|
||||||
T.Person.ThirdPlurFemale,
|
|
||||||
],
|
|
||||||
root: [],
|
|
||||||
};
|
|
||||||
} else if (e === "و") {
|
|
||||||
return {
|
|
||||||
root: [T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
|
|
||||||
stem: [T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
|
|
||||||
};
|
|
||||||
} else if (e === "ئ") {
|
|
||||||
return {
|
|
||||||
root: [T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
|
||||||
stem: [T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
|
||||||
};
|
|
||||||
} else if (e === "ه") {
|
|
||||||
return {
|
|
||||||
root: [T.Person.ThirdSingFemale],
|
|
||||||
stem: [],
|
|
||||||
};
|
|
||||||
} else if (e === "ل") {
|
|
||||||
return {
|
|
||||||
root: [T.Person.ThirdPlurMale],
|
|
||||||
stem: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
root: [],
|
|
||||||
stem: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: could handle all sh- verbs for efficiencies sake
|
// TODO: could handle all sh- verbs for efficiencies sake
|
||||||
function parseIrregularVerb(s: string): T.ParsedVBE[] {
|
function parseIrregularVerb(s: string): T.ParsedVBE[] {
|
||||||
if (["ته", "راته", "ورته", "درته"].includes(s)) {
|
if (["ته", "راته", "ورته", "درته"].includes(s)) {
|
||||||
|
@ -394,38 +342,6 @@ function parseIrregularVerb(s: string): T.ParsedVBE[] {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (s === "شو") {
|
|
||||||
return [
|
|
||||||
...[
|
|
||||||
T.Person.ThirdSingMale,
|
|
||||||
T.Person.FirstPlurMale,
|
|
||||||
T.Person.FirstPlurFemale,
|
|
||||||
].flatMap((person) =>
|
|
||||||
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
|
||||||
type: "VB",
|
|
||||||
info: {
|
|
||||||
aspect: "perfective",
|
|
||||||
base: "root",
|
|
||||||
type: "verb",
|
|
||||||
verb,
|
|
||||||
},
|
|
||||||
person,
|
|
||||||
}))
|
|
||||||
),
|
|
||||||
...[T.Person.FirstPlurMale, T.Person.FirstPlurFemale].flatMap((person) =>
|
|
||||||
[kedulStat, kedulDyn].map<T.ParsedVBE>((verb) => ({
|
|
||||||
type: "VB",
|
|
||||||
info: {
|
|
||||||
aspect: "perfective",
|
|
||||||
base: "stem",
|
|
||||||
type: "verb",
|
|
||||||
verb,
|
|
||||||
},
|
|
||||||
person,
|
|
||||||
}))
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { lookup, wordQuery } from "./lookup";
|
import { lookup, wordQuery } from "./lookup";
|
||||||
import { tokenizer } from "./tokenizer";
|
import { tokenizer } from "./tokenizer";
|
||||||
import { parsePastPart } from "./parse-past-part";
|
import { parseVBP } from "./parse-vbp";
|
||||||
import { kawulDyn, kawulStat, kedulDyn, kedulStat } from "./irreg-verbs";
|
import { kawulDyn, kawulStat, kedulDyn, kedulStat } from "./irreg-verbs";
|
||||||
|
|
||||||
const leedul = wordQuery("لیدل", "verb");
|
const leedul = wordQuery("لیدل", "verb");
|
||||||
|
@ -178,7 +178,7 @@ describe("parsing past participles", () => {
|
||||||
test(label, () => {
|
test(label, () => {
|
||||||
cases.forEach(({ input, output }) => {
|
cases.forEach(({ input, output }) => {
|
||||||
const tokens = tokenizer(input);
|
const tokens = tokenizer(input);
|
||||||
const res = parsePastPart(tokens, lookup).map(({ body }) => body);
|
const res = parseVBP(tokens, lookup).map(({ body }) => body);
|
||||||
expect(res).toEqual(output);
|
expect(res).toEqual(output);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -2,13 +2,23 @@ import * as T from "../../../types";
|
||||||
import { LookupFunction } from "./lookup";
|
import { LookupFunction } from "./lookup";
|
||||||
import { returnParseResult } from "./utils";
|
import { returnParseResult } from "./utils";
|
||||||
|
|
||||||
export function parsePastPart(
|
export function parseVBP(
|
||||||
tokens: Readonly<T.Token[]>,
|
tokens: Readonly<T.Token[]>,
|
||||||
lookup: LookupFunction
|
lookup: LookupFunction
|
||||||
): T.ParseResult<T.ParsedVBP>[] {
|
): T.ParseResult<T.ParsedVBP>[] {
|
||||||
if (tokens.length === 0) {
|
if (tokens.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
return [
|
||||||
|
...parsePastPart(tokens, lookup),
|
||||||
|
// ...parseAbility(tokens),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePastPart(
|
||||||
|
tokens: Readonly<T.Token[]>,
|
||||||
|
lookup: LookupFunction
|
||||||
|
): T.ParseResult<T.ParsedVBP>[] {
|
||||||
const [{ s }, ...rest] = tokens;
|
const [{ s }, ...rest] = tokens;
|
||||||
const ending: "ی" | "ي" | "ې" = s.at(-1) as "ی" | "ي" | "ې";
|
const ending: "ی" | "ي" | "ې" = s.at(-1) as "ی" | "ي" | "ې";
|
||||||
if (!ending || !["ی", "ي", "ې"].includes(ending)) {
|
if (!ending || !["ی", "ي", "ې"].includes(ending)) {
|
||||||
|
@ -32,6 +42,34 @@ export function parsePastPart(
|
||||||
.flatMap((m) => returnParseResult(rest, m));
|
.flatMap((m) => returnParseResult(rest, m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function parseAbility(
|
||||||
|
// tokens: Readonly<T.Token[]>,
|
||||||
|
// lookup: LookupFunction
|
||||||
|
// ): T.ParseResult<T.ParsedVBP>[] {
|
||||||
|
// // TODO: keday
|
||||||
|
// if (tokens.length === 0) {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
// const [{ s }, ...rest] = tokens;
|
||||||
|
// const start = s.endsWith("ای")
|
||||||
|
// ? s.slice(0, -2)
|
||||||
|
// : s.endsWith("ی")
|
||||||
|
// ? s.slice(0, 1)
|
||||||
|
// : "";
|
||||||
|
// if (!start) return [];
|
||||||
|
// const matches = lookup(start, "ability");
|
||||||
|
// return matches
|
||||||
|
// .map<T.ParsedVBP>((verb) => ({
|
||||||
|
// type: "VB",
|
||||||
|
// info: {
|
||||||
|
// type: "ability",
|
||||||
|
// verb,
|
||||||
|
// aspect: "perfective", // TODO GET ASPECT!!
|
||||||
|
// },
|
||||||
|
// }))
|
||||||
|
// .flatMap((m) => returnParseResult(rest, m));
|
||||||
|
// }
|
||||||
|
|
||||||
function endingGenderNum(ending: "ی" | "ي" | "ې"): T.GenderNumber[] {
|
function endingGenderNum(ending: "ی" | "ي" | "ې"): T.GenderNumber[] {
|
||||||
if (ending === "ی") {
|
if (ending === "ی") {
|
||||||
return [
|
return [
|
|
@ -0,0 +1,60 @@
|
||||||
|
import * as T from "../../../types";
|
||||||
|
|
||||||
|
export function isKedulStatEntry(v: T.VerbDictionaryEntry): boolean {
|
||||||
|
return v.p === "کېدل" && v.e === "to become _____";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getVerbEnding(e: string): {
|
||||||
|
stem: T.Person[];
|
||||||
|
root: T.Person[];
|
||||||
|
} {
|
||||||
|
if (e === "م") {
|
||||||
|
return {
|
||||||
|
root: [T.Person.FirstSingMale, T.Person.FirstSingFemale],
|
||||||
|
stem: [T.Person.FirstSingMale, T.Person.FirstSingFemale],
|
||||||
|
};
|
||||||
|
} else if (e === "ې") {
|
||||||
|
return {
|
||||||
|
root: [
|
||||||
|
T.Person.SecondSingMale,
|
||||||
|
T.Person.SecondSingFemale,
|
||||||
|
T.Person.ThirdPlurFemale,
|
||||||
|
],
|
||||||
|
stem: [T.Person.SecondSingMale, T.Person.SecondSingFemale],
|
||||||
|
};
|
||||||
|
} else if (e === "ي") {
|
||||||
|
return {
|
||||||
|
stem: [
|
||||||
|
T.Person.ThirdSingMale,
|
||||||
|
T.Person.ThirdSingFemale,
|
||||||
|
T.Person.ThirdPlurMale,
|
||||||
|
T.Person.ThirdPlurFemale,
|
||||||
|
],
|
||||||
|
root: [],
|
||||||
|
};
|
||||||
|
} else if (e === "و") {
|
||||||
|
return {
|
||||||
|
root: [T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
|
||||||
|
stem: [T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
|
||||||
|
};
|
||||||
|
} else if (e === "ئ") {
|
||||||
|
return {
|
||||||
|
root: [T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
||||||
|
stem: [T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
||||||
|
};
|
||||||
|
} else if (e === "ه") {
|
||||||
|
return {
|
||||||
|
root: [T.Person.ThirdSingFemale],
|
||||||
|
stem: [],
|
||||||
|
};
|
||||||
|
} else if (e === "ل") {
|
||||||
|
return {
|
||||||
|
root: [T.Person.ThirdPlurMale],
|
||||||
|
stem: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
root: [],
|
||||||
|
stem: [],
|
||||||
|
};
|
||||||
|
}
|
|
@ -104,6 +104,7 @@ function getTenses(
|
||||||
}
|
}
|
||||||
if (verb.info.type === "verb") {
|
if (verb.info.type === "verb") {
|
||||||
if (verb.info.aspect === "perfective") {
|
if (verb.info.aspect === "perfective") {
|
||||||
|
// TODO: handle kedul sh perfective
|
||||||
if (!ph) {
|
if (!ph) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,18 @@ export function bindParseResult<C, D>(
|
||||||
return cleanOutResults(nextPossibilities);
|
return cleanOutResults(nextPossibilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function returnParseResults<D>(
|
||||||
|
tokens: Readonly<T.Token[]>,
|
||||||
|
body: D[],
|
||||||
|
errors?: T.ParseError[]
|
||||||
|
): T.ParseResult<D>[] {
|
||||||
|
return body.map<T.ParseResult<D>>((b) => ({
|
||||||
|
tokens,
|
||||||
|
body: b,
|
||||||
|
errors: errors || [],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
export function returnParseResultS<D>(
|
export function returnParseResultS<D>(
|
||||||
tokens: Readonly<T.Token[]>,
|
tokens: Readonly<T.Token[]>,
|
||||||
body: D,
|
body: D,
|
||||||
|
|
|
@ -34,6 +34,8 @@ type BlankoutOptions = {
|
||||||
predicate?: boolean;
|
predicate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Should there be a way to get length options on compiled VP ?
|
||||||
|
|
||||||
// function compilePs({ blocks, kids, verb: { head, rest }, VP }: CompilePsInput): T.SingleOrLengthOpts<T.PsString[]> {
|
// function compilePs({ blocks, kids, verb: { head, rest }, VP }: CompilePsInput): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
// if ("long" in rest) {
|
// if ("long" in rest) {
|
||||||
// return {
|
// return {
|
||||||
|
@ -87,13 +89,13 @@ export function compileVP(
|
||||||
export function compileVP(
|
export function compileVP(
|
||||||
VP: T.VPRendered,
|
VP: T.VPRendered,
|
||||||
form: T.FormVersion,
|
form: T.FormVersion,
|
||||||
combineLengths: true,
|
combineLengths: boolean,
|
||||||
blankOut?: BlankoutOptions
|
blankOut?: BlankoutOptions
|
||||||
): { ps: T.PsString[]; e?: string[] };
|
): { ps: T.PsString[]; e?: string[] };
|
||||||
export function compileVP(
|
export function compileVP(
|
||||||
VP: T.VPRendered,
|
VP: T.VPRendered,
|
||||||
form: T.FormVersion,
|
form: T.FormVersion,
|
||||||
combineLengths?: true,
|
combineLengths?: boolean,
|
||||||
blankOut?: BlankoutOptions
|
blankOut?: BlankoutOptions
|
||||||
): { ps: T.SingleOrLengthOpts<T.PsString[]>; e?: string[] } {
|
): { ps: T.SingleOrLengthOpts<T.PsString[]>; e?: string[] } {
|
||||||
// const verb = getVerbFromBlocks(VP.blocks).block;
|
// const verb = getVerbFromBlocks(VP.blocks).block;
|
||||||
|
|
|
@ -868,6 +868,14 @@ export type PossesorSelection = {
|
||||||
np: NPSelection;
|
np: NPSelection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Noun = {
|
||||||
|
entry: NounEntry;
|
||||||
|
gender: Gender;
|
||||||
|
number: "sing" | "plur";
|
||||||
|
adjectives: AdjectiveSelection[];
|
||||||
|
possesor: undefined | Noun;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO require/import Person and PsString
|
// TODO require/import Person and PsString
|
||||||
export type NounSelection = {
|
export type NounSelection = {
|
||||||
type: "noun";
|
type: "noun";
|
||||||
|
|
Loading…
Reference in New Issue