negatives
This commit is contained in:
parent
56b92a912c
commit
fc3431199c
|
@ -17,6 +17,7 @@ const working = [
|
||||||
"noun phrases (except participles)",
|
"noun phrases (except participles)",
|
||||||
"mini-pronouns for shrunken servants",
|
"mini-pronouns for shrunken servants",
|
||||||
"grammar error correction",
|
"grammar error correction",
|
||||||
|
"negatives",
|
||||||
];
|
];
|
||||||
|
|
||||||
const todo = [
|
const todo = [
|
||||||
|
@ -42,6 +43,7 @@ const examples = [
|
||||||
"د غټې ماشومې زاړه پلار ولیدم",
|
"د غټې ماشومې زاړه پلار ولیدم",
|
||||||
"ستا پخواني ملګري مې ولیدل",
|
"ستا پخواني ملګري مې ولیدل",
|
||||||
"ما ډوډۍ خوړله",
|
"ما ډوډۍ خوړله",
|
||||||
|
"وامې نه خیست",
|
||||||
];
|
];
|
||||||
|
|
||||||
function ParserDemo({ opts }: { opts: T.TextOptions }) {
|
function ParserDemo({ opts }: { opts: T.TextOptions }) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { fmapParseResult } from "../fp-ps";
|
import { fmapParseResult } from "../fp-ps";
|
||||||
import { parseKidsSection } from "./parse-kids-section";
|
import { parseKidsSection } from "./parse-kids-section";
|
||||||
|
import { parseNeg } from "./parse-negative";
|
||||||
import { parseNP } from "./parse-np";
|
import { parseNP } from "./parse-np";
|
||||||
import { parsePH } from "./parse-ph";
|
import { parsePH } from "./parse-ph";
|
||||||
import { parseVerb } from "./parse-verb";
|
import { parseVerb } from "./parse-verb";
|
||||||
|
@ -31,8 +32,9 @@ export function parseBlocks(
|
||||||
([ph, v]) => (ph ? [ph, v] : [v]),
|
([ph, v]) => (ph ? [ph, v] : [v]),
|
||||||
parseVerb(tokens, verbLookup)
|
parseVerb(tokens, verbLookup)
|
||||||
);
|
);
|
||||||
|
const neg = fmapParseResult((x) => [x], parseNeg(tokens));
|
||||||
const kidsR = parseKidsSection(tokens, []);
|
const kidsR = parseKidsSection(tokens, []);
|
||||||
const allResults = [...np, ...ph, ...vb, ...kidsR] as T.ParseResult<
|
const allResults = [...np, ...ph, ...neg, ...vb, ...kidsR] as T.ParseResult<
|
||||||
T.ParsedBlock[] | { kids: T.ParsedKid[] }
|
T.ParsedBlock[] | { kids: T.ParsedKid[] }
|
||||||
>[];
|
>[];
|
||||||
// TODO: is this necessary?
|
// TODO: is this necessary?
|
||||||
|
@ -46,6 +48,7 @@ export function parseBlocks(
|
||||||
// ];
|
// ];
|
||||||
// }
|
// }
|
||||||
return bindParseResult(allResults, (tokens, r) => {
|
return bindParseResult(allResults, (tokens, r) => {
|
||||||
|
const errors: T.ParseError[] = [];
|
||||||
if ("kids" in r) {
|
if ("kids" in r) {
|
||||||
return {
|
return {
|
||||||
next: parseBlocks(tokens, lookup, verbLookup, blocks, [
|
next: parseBlocks(tokens, lookup, verbLookup, blocks, [
|
||||||
|
@ -65,7 +68,18 @@ export function parseBlocks(
|
||||||
if (!phMatches(prevPh, vb)) {
|
if (!phMatches(prevPh, vb)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return parseBlocks(tokens, lookup, verbLookup, [...blocks, ...r], kids);
|
// don't allow two negatives
|
||||||
|
if (
|
||||||
|
"type" in r[0] &&
|
||||||
|
r[0].type === "negative" &&
|
||||||
|
blocks.some((b) => "type" in b && b.type === "negative")
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
next: parseBlocks(tokens, lookup, verbLookup, [...blocks, ...r], kids),
|
||||||
|
errors,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as T from "../../../types";
|
||||||
|
import { returnParseResult } from "./utils";
|
||||||
|
|
||||||
|
export function parseNeg(
|
||||||
|
tokens: Readonly<T.Token[]>
|
||||||
|
): T.ParseResult<T.NegativeBlock>[] {
|
||||||
|
if (tokens.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const [{ s }, ...rest] = tokens;
|
||||||
|
if (s === "نه") {
|
||||||
|
return returnParseResult(rest, {
|
||||||
|
type: "negative",
|
||||||
|
imperative: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (s === "مه") {
|
||||||
|
return returnParseResult(rest, {
|
||||||
|
type: "negative",
|
||||||
|
imperative: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
|
@ -36,6 +36,8 @@ import { isFirstOrSecondPersPronoun } from "../phrase-building/render-vp";
|
||||||
|
|
||||||
// TODO: transitivity options
|
// TODO: transitivity options
|
||||||
|
|
||||||
|
// TODO: the و is really making it slow down... why?
|
||||||
|
|
||||||
export function parseVP(
|
export function parseVP(
|
||||||
tokens: Readonly<T.Token[]>,
|
tokens: Readonly<T.Token[]>,
|
||||||
lookup: (s: Partial<T.DictionaryEntry>) => T.DictionaryEntry[],
|
lookup: (s: Partial<T.DictionaryEntry>) => T.DictionaryEntry[],
|
||||||
|
@ -46,16 +48,30 @@ export function parseVP(
|
||||||
}
|
}
|
||||||
const blocks = parseBlocks(tokens, lookup, verbLookup, [], []);
|
const blocks = parseBlocks(tokens, lookup, verbLookup, [], []);
|
||||||
return bindParseResult(blocks, (tokens, { blocks, kids }) => {
|
return bindParseResult(blocks, (tokens, { blocks, kids }) => {
|
||||||
const ph = blocks.find((x) => "type" in x && x.type === "PH") as
|
const phIndex = blocks.findIndex((x) => "type" in x && x.type === "PH");
|
||||||
| T.ParsedPH
|
const vbeIndex = blocks.findIndex((x) => "type" in x && x.type === "VB");
|
||||||
| undefined;
|
|
||||||
const verb = blocks.find((x) => "type" in x && x.type === "VB") as
|
|
||||||
| T.ParsedVBE
|
|
||||||
| undefined;
|
|
||||||
const ba = !!kids.find((k) => k === "ba");
|
const ba = !!kids.find((k) => k === "ba");
|
||||||
|
const negIndex = blocks.findIndex(
|
||||||
|
(x) => "type" in x && x.type === "negative" && !x.imperative
|
||||||
|
);
|
||||||
|
const ph = phIndex !== -1 ? (blocks[phIndex] as T.ParsedPH) : undefined;
|
||||||
|
const verb =
|
||||||
|
vbeIndex !== -1 ? (blocks[vbeIndex] as T.ParsedVBE) : undefined;
|
||||||
|
const negative = negIndex !== -1;
|
||||||
if (!verb || verb.type !== "VB" || verb.info.type !== "verb") {
|
if (!verb || verb.type !== "VB" || verb.info.type !== "verb") {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
!negativeInPlace({
|
||||||
|
neg: negIndex,
|
||||||
|
v: vbeIndex,
|
||||||
|
phIndex: phIndex,
|
||||||
|
ph,
|
||||||
|
kids: !!kids.length,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
if (verb.info.aspect === "perfective") {
|
if (verb.info.aspect === "perfective") {
|
||||||
// TODO: check that the perfective head is in the right place and actually matches
|
// TODO: check that the perfective head is in the right place and actually matches
|
||||||
if (!ph) {
|
if (!ph) {
|
||||||
|
@ -77,7 +93,7 @@ export function parseVP(
|
||||||
: "transitive",
|
: "transitive",
|
||||||
canChangeTransitivity: false,
|
canChangeTransitivity: false,
|
||||||
canChangeStatDyn: false,
|
canChangeStatDyn: false,
|
||||||
negative: false,
|
negative,
|
||||||
tense,
|
tense,
|
||||||
canChangeVoice: true,
|
canChangeVoice: true,
|
||||||
isCompound: false,
|
isCompound: false,
|
||||||
|
@ -509,3 +525,31 @@ function getTenseFromRootsStems(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function negativeInPlace({
|
||||||
|
neg,
|
||||||
|
v,
|
||||||
|
phIndex,
|
||||||
|
ph,
|
||||||
|
kids,
|
||||||
|
}: {
|
||||||
|
neg: number;
|
||||||
|
v: number;
|
||||||
|
phIndex: number;
|
||||||
|
ph: T.ParsedPH | undefined;
|
||||||
|
kids: boolean;
|
||||||
|
}): boolean {
|
||||||
|
if (neg === -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ph) {
|
||||||
|
if (!kids && !["و", "وا"].includes(ph.s) && neg === phIndex - 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return neg === phIndex + 1;
|
||||||
|
}
|
||||||
|
if (neg < v - 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -1176,6 +1176,8 @@ export type EntryLookupPortal<X extends VerbEntry | DictionaryEntry> = {
|
||||||
|
|
||||||
export type EquativeBlock = { type: "equative"; equative: EquativeRendered };
|
export type EquativeBlock = { type: "equative"; equative: EquativeRendered };
|
||||||
|
|
||||||
|
export type NegativeBlock = { type: "negative"; imperative: boolean };
|
||||||
|
|
||||||
export type Block = {
|
export type Block = {
|
||||||
key: number;
|
key: number;
|
||||||
block:
|
block:
|
||||||
|
@ -1185,14 +1187,14 @@ export type Block = {
|
||||||
| Rendered<PredicateSelectionComplete>
|
| Rendered<PredicateSelectionComplete>
|
||||||
| Rendered<ComplementSelection>
|
| Rendered<ComplementSelection>
|
||||||
| Rendered<UnselectedComplementSelection>
|
| Rendered<UnselectedComplementSelection>
|
||||||
| { type: "negative"; imperative: boolean }
|
| NegativeBlock
|
||||||
| EquativeBlock
|
| EquativeBlock
|
||||||
| VB
|
| VB
|
||||||
| VBE
|
| VBE
|
||||||
| VHead;
|
| VHead;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ParsedBlock = ParsedNP | ParsedPH | ParsedVBE;
|
export type ParsedBlock = ParsedNP | ParsedPH | ParsedVBE | NegativeBlock;
|
||||||
|
|
||||||
export type ParsedNP = {
|
export type ParsedNP = {
|
||||||
inflected: boolean;
|
inflected: boolean;
|
||||||
|
|
Loading…
Reference in New Issue