possesive mini pronouns
This commit is contained in:
parent
5f356fdb63
commit
db3bc8303b
|
@ -13,7 +13,7 @@ import { lookup, wordQuery } from "./lookup";
|
||||||
import { parseVP } from "./parse-vp";
|
import { parseVP } from "./parse-vp";
|
||||||
import { tokenizer } from "./tokenizer";
|
import { tokenizer } from "./tokenizer";
|
||||||
import { tlul } from "./irreg-verbs";
|
import { tlul } from "./irreg-verbs";
|
||||||
import { getPeople, removeKeys } from "./utils";
|
import { addShrunkenPossesor, getPeople, removeKeys } from "./utils";
|
||||||
|
|
||||||
const sarey = wordQuery("سړی", "noun");
|
const sarey = wordQuery("سړی", "noun");
|
||||||
const rasedul = wordQuery("رسېدل", "verb");
|
const rasedul = wordQuery("رسېدل", "verb");
|
||||||
|
@ -890,8 +890,9 @@ const tests: {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "سړی یې وویني",
|
input: "سړی یې ووهي",
|
||||||
output: getPeople(3, "both").map((person) => ({
|
output: [
|
||||||
|
...getPeople(3, "both").map<T.VPSelectionComplete>((person) => ({
|
||||||
blocks: [
|
blocks: [
|
||||||
{
|
{
|
||||||
key: 1,
|
key: 1,
|
||||||
|
@ -910,7 +911,7 @@ const tests: {
|
||||||
],
|
],
|
||||||
verb: {
|
verb: {
|
||||||
type: "verb",
|
type: "verb",
|
||||||
verb: leedul,
|
verb: wahul,
|
||||||
transitivity: "transitive",
|
transitivity: "transitive",
|
||||||
canChangeTransitivity: false,
|
canChangeTransitivity: false,
|
||||||
canChangeStatDyn: false,
|
canChangeStatDyn: false,
|
||||||
|
@ -926,11 +927,58 @@ const tests: {
|
||||||
shrinkServant: true,
|
shrinkServant: true,
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
...getPeople(3, "both").flatMap<T.VPSelectionComplete>((person) =>
|
||||||
|
getPeople(3, "both").map<T.VPSelectionComplete>((person2) => ({
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
key: 1,
|
||||||
|
block: makeSubjectSelectionComplete({
|
||||||
|
type: "NP",
|
||||||
|
selection: makePronounSelection(person),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 1,
|
||||||
|
block: makeObjectSelectionComplete(
|
||||||
|
addShrunkenPossesor(
|
||||||
|
{
|
||||||
|
type: "NP",
|
||||||
|
selection: makeNounSelection(sarey, undefined),
|
||||||
|
},
|
||||||
|
person2
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
verb: {
|
||||||
|
type: "verb",
|
||||||
|
verb: wahul,
|
||||||
|
transitivity: "transitive",
|
||||||
|
canChangeTransitivity: false,
|
||||||
|
canChangeStatDyn: false,
|
||||||
|
negative: false,
|
||||||
|
tense: "subjunctiveVerb",
|
||||||
|
canChangeVoice: true,
|
||||||
|
isCompound: false,
|
||||||
|
voice: "active",
|
||||||
|
},
|
||||||
|
externalComplement: undefined,
|
||||||
|
form: {
|
||||||
|
removeKing: true,
|
||||||
|
shrinkServant: false,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "سړی مو ویني",
|
input: "سړی مو ویني",
|
||||||
output: [...getPeople(1, "pl"), ...getPeople(2, "pl")].map(
|
output: [
|
||||||
(person) => ({
|
// the man sees you/us
|
||||||
|
...[
|
||||||
|
...getPeople(1, "pl"),
|
||||||
|
...getPeople(2, "pl"),
|
||||||
|
].map<T.VPSelectionComplete>((person) => ({
|
||||||
blocks: [
|
blocks: [
|
||||||
{
|
{
|
||||||
key: 1,
|
key: 1,
|
||||||
|
@ -964,13 +1012,98 @@ const tests: {
|
||||||
removeKing: false,
|
removeKing: false,
|
||||||
shrinkServant: true,
|
shrinkServant: true,
|
||||||
},
|
},
|
||||||
})
|
})),
|
||||||
|
// your/our man sees
|
||||||
|
...[
|
||||||
|
...getPeople(1, "pl"),
|
||||||
|
...getPeople(2, "pl"),
|
||||||
|
].map<T.VPSelectionComplete>((person) => ({
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
key: 1,
|
||||||
|
block: makeSubjectSelectionComplete(
|
||||||
|
addShrunkenPossesor(
|
||||||
|
{
|
||||||
|
type: "NP",
|
||||||
|
selection: makeNounSelection(sarey, undefined),
|
||||||
|
},
|
||||||
|
person
|
||||||
|
)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "سړي مې واهه",
|
key: 1,
|
||||||
output: [],
|
block: {
|
||||||
error: true,
|
type: "objectSelection",
|
||||||
|
selection: T.Person.ThirdPlurMale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
verb: {
|
||||||
|
type: "verb",
|
||||||
|
verb: leedul,
|
||||||
|
transitivity: "grammatically transitive",
|
||||||
|
canChangeTransitivity: false,
|
||||||
|
canChangeStatDyn: false,
|
||||||
|
negative: false,
|
||||||
|
tense: "presentVerb",
|
||||||
|
canChangeVoice: true,
|
||||||
|
isCompound: false,
|
||||||
|
voice: "active",
|
||||||
|
},
|
||||||
|
externalComplement: undefined,
|
||||||
|
form: {
|
||||||
|
removeKing: false,
|
||||||
|
shrinkServant: false,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
// they/he sees your/our man
|
||||||
|
...[
|
||||||
|
...getPeople(1, "pl"),
|
||||||
|
...getPeople(2, "pl"),
|
||||||
|
].flatMap<T.VPSelectionComplete>((possPers) =>
|
||||||
|
getPeople(3, "both").map<T.VPSelectionComplete>((subjPers) => ({
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
key: 1,
|
||||||
|
block: makeSubjectSelectionComplete({
|
||||||
|
type: "NP",
|
||||||
|
selection: makePronounSelection(subjPers),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 1,
|
||||||
|
block: makeObjectSelectionComplete(
|
||||||
|
addShrunkenPossesor(
|
||||||
|
{
|
||||||
|
type: "NP",
|
||||||
|
selection: makeNounSelection(sarey, undefined),
|
||||||
|
},
|
||||||
|
possPers
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
verb: {
|
||||||
|
type: "verb",
|
||||||
|
verb: leedul,
|
||||||
|
transitivity: "transitive",
|
||||||
|
canChangeTransitivity: false,
|
||||||
|
canChangeStatDyn: false,
|
||||||
|
negative: false,
|
||||||
|
tense: "presentVerb",
|
||||||
|
canChangeVoice: true,
|
||||||
|
isCompound: false,
|
||||||
|
voice: "active",
|
||||||
|
},
|
||||||
|
externalComplement: undefined,
|
||||||
|
form: {
|
||||||
|
removeKing: true,
|
||||||
|
shrinkServant: false,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import {
|
import {
|
||||||
|
addShrunkenPossesor,
|
||||||
bindParseResult,
|
bindParseResult,
|
||||||
|
canTakeShrunkenPossesor,
|
||||||
isNeg,
|
isNeg,
|
||||||
isNonOoPh,
|
isNonOoPh,
|
||||||
isPH,
|
isPH,
|
||||||
|
@ -27,6 +29,11 @@ import { isSecondPerson, personToGenNum } from "../misc-helpers";
|
||||||
import { equals, zip } from "rambda";
|
import { equals, zip } from "rambda";
|
||||||
import { isImperativeTense } from "../type-predicates";
|
import { isImperativeTense } from "../type-predicates";
|
||||||
// to hide equatives type-doubling issue
|
// to hide equatives type-doubling issue
|
||||||
|
// TODO: THESE SHOULD ERROR!!
|
||||||
|
// ماشومانې لاړل
|
||||||
|
// ماشومان لاړلې
|
||||||
|
|
||||||
|
// TODO: problem with 3rd pers seng verb endings اواز مې دې واورېده
|
||||||
|
|
||||||
// TODO: word query for kawul/kedul/stat/dyn
|
// TODO: word query for kawul/kedul/stat/dyn
|
||||||
|
|
||||||
|
@ -43,11 +50,15 @@ export function parseVP(
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const blocks = parseBlocks(tokens, lookup, [], []);
|
const blocks = parseBlocks(tokens, lookup, [], []);
|
||||||
return bindParseResult(blocks, (tokens, { blocks, kids }) => {
|
const blocksWPossPossibilities = createPossesivePossibilities(blocks);
|
||||||
|
return bindParseResult(
|
||||||
|
blocksWPossPossibilities,
|
||||||
|
(tokens, { blocks, kids }) => {
|
||||||
const ba = kids.some((k) => k === "ba");
|
const ba = kids.some((k) => k === "ba");
|
||||||
const miniPronouns = getMiniPronouns(kids);
|
const miniPronouns = getMiniPronouns(kids);
|
||||||
const npsAndAps = blocks.filter(
|
const npsAndAps = blocks.filter(
|
||||||
(x): x is T.ParsedNP | T.APSelection => x.type === "NP" || x.type === "AP"
|
(x): x is T.ParsedNP | T.APSelection =>
|
||||||
|
x.type === "NP" || x.type === "AP"
|
||||||
);
|
);
|
||||||
const verbSection = blocks.findIndex(startsVerbSection);
|
const verbSection = blocks.findIndex(startsVerbSection);
|
||||||
// TODO: would be nice if this could pass error messages about the
|
// TODO: would be nice if this could pass error messages about the
|
||||||
|
@ -57,7 +68,8 @@ export function parseVP(
|
||||||
}
|
}
|
||||||
const tenses = getTenses(blocks, ba);
|
const tenses = getTenses(blocks, ba);
|
||||||
// TODO get errors from the get tenses (perfect verbs not agreeing)
|
// TODO get errors from the get tenses (perfect verbs not agreeing)
|
||||||
return tenses.flatMap(({ tense, person, transitivities, negative, verb }) =>
|
return tenses.flatMap(
|
||||||
|
({ tense, person, transitivities, negative, verb }) =>
|
||||||
finishPossibleVPSs({
|
finishPossibleVPSs({
|
||||||
tense,
|
tense,
|
||||||
transitivities,
|
transitivities,
|
||||||
|
@ -69,7 +81,8 @@ export function parseVP(
|
||||||
person,
|
person,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTenses(
|
function getTenses(
|
||||||
|
@ -487,6 +500,9 @@ function finishTransitive({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (miniPronouns.length > 1) {
|
||||||
|
errors.push({ message: "unknown mini-pronoun" });
|
||||||
|
}
|
||||||
if (np.inflected) {
|
if (np.inflected) {
|
||||||
errors.push({
|
errors.push({
|
||||||
message: !isPast
|
message: !isPast
|
||||||
|
@ -553,6 +569,9 @@ function finishTransitive({
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
const miniPronErrors: T.ParseError[] = miniPronouns.length
|
||||||
|
? [{ message: "unknown mini-pronoun" }]
|
||||||
|
: [];
|
||||||
if (isPast) {
|
if (isPast) {
|
||||||
return (
|
return (
|
||||||
[
|
[
|
||||||
|
@ -598,7 +617,7 @@ function finishTransitive({
|
||||||
shrinkServant: false,
|
shrinkServant: false,
|
||||||
},
|
},
|
||||||
} as T.VPSelectionComplete,
|
} as T.VPSelectionComplete,
|
||||||
errors
|
[...miniPronErrors, ...errors]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -657,7 +676,7 @@ function finishTransitive({
|
||||||
shrinkServant: false,
|
shrinkServant: false,
|
||||||
},
|
},
|
||||||
} as T.VPSelectionComplete,
|
} as T.VPSelectionComplete,
|
||||||
errors
|
[...miniPronErrors, ...errors]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1033,3 +1052,137 @@ function mapOutnpsAndAps(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createPossesivePossibilities(
|
||||||
|
blocks: T.ParseResult<{
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
}>[]
|
||||||
|
): T.ParseResult<{
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
}>[] {
|
||||||
|
// Case 1: no mini pronouns
|
||||||
|
// Case 2: 1 mini pronoun
|
||||||
|
// - don't use any as possesive
|
||||||
|
// Case 3: 2 mini pronouns
|
||||||
|
// - don't use any as possesive
|
||||||
|
// - use first as possesive
|
||||||
|
// - use second as possesive
|
||||||
|
// - use both as possesive
|
||||||
|
function pullOutMiniPronoun(
|
||||||
|
body: {
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
},
|
||||||
|
pos: 0 | 1
|
||||||
|
): {
|
||||||
|
adjusted: {
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
};
|
||||||
|
miniPronoun: T.ParsedMiniPronoun;
|
||||||
|
} {
|
||||||
|
const miniPronoun = getMiniPronouns(body.kids)[pos];
|
||||||
|
if (!miniPronoun) {
|
||||||
|
throw new Error("tried to pull out non-existent mini-pronoun");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
miniPronoun,
|
||||||
|
adjusted: {
|
||||||
|
kids: body.kids.filter((x) => x !== miniPronoun),
|
||||||
|
blocks: body.blocks,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function spreadOutPoss(
|
||||||
|
body: {
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
},
|
||||||
|
pos: 0 | 1
|
||||||
|
): {
|
||||||
|
kids: T.ParsedKid[];
|
||||||
|
blocks: T.ParsedBlock[];
|
||||||
|
}[] {
|
||||||
|
const { miniPronoun, adjusted } = pullOutMiniPronoun(body, pos);
|
||||||
|
const people = getPeopleFromMiniPronouns([miniPronoun]);
|
||||||
|
// TODO: turn into reduce?
|
||||||
|
// TODO: allow possesives for sandwiches
|
||||||
|
return adjusted.blocks
|
||||||
|
.flatMap((x, i) => {
|
||||||
|
if (
|
||||||
|
(x.type === "NP" && canTakeShrunkenPossesor(x.selection)) ||
|
||||||
|
(x.type === "AP" && canTakeShrunkenPossesor(x))
|
||||||
|
) {
|
||||||
|
return addPossesiveAtIndex(people, adjusted.blocks, i);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map((xb) => ({
|
||||||
|
kids: adjusted.kids,
|
||||||
|
blocks: xb,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function addPossesiveAtIndex(
|
||||||
|
people: T.Person[],
|
||||||
|
blocks: T.ParsedBlock[],
|
||||||
|
i: number
|
||||||
|
): T.ParsedBlock[][] {
|
||||||
|
return people.map((person) => {
|
||||||
|
return blocks.map((x, j) => {
|
||||||
|
if (i !== j) return x;
|
||||||
|
// TODO: this is redundant ?
|
||||||
|
if (x.type === "NP" && canTakeShrunkenPossesor(x.selection)) {
|
||||||
|
return {
|
||||||
|
...x,
|
||||||
|
selection: addShrunkenPossesor(x.selection, person),
|
||||||
|
};
|
||||||
|
} else if (x.type === "AP" && canTakeShrunkenPossesor(x)) {
|
||||||
|
return addShrunkenPossesor(x, person);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"improper index for adding possesor - addPossesiveAtIndex"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return blocks.flatMap((b) => {
|
||||||
|
const miniPronouns = getMiniPronouns(b.body.kids);
|
||||||
|
if (miniPronouns.length === 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tokens: b.tokens,
|
||||||
|
body: b.body,
|
||||||
|
errors: b.errors,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (miniPronouns.length === 1) {
|
||||||
|
const withFirstMiniAsPossesive = spreadOutPoss(b.body, 0);
|
||||||
|
return [b.body, ...withFirstMiniAsPossesive].map((x) => ({
|
||||||
|
tokens: b.tokens,
|
||||||
|
body: x,
|
||||||
|
errors: b.errors,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
const withFirstMiniAsPossesive = spreadOutPoss(b.body, 0);
|
||||||
|
const withSecondMiniAsPossesive = spreadOutPoss(b.body, 1);
|
||||||
|
return [
|
||||||
|
// using none of the mini-pronouns as possesives
|
||||||
|
b.body,
|
||||||
|
// using the first mini-pronoun as a possesive
|
||||||
|
...withFirstMiniAsPossesive,
|
||||||
|
// using the second mini-pronoun as a prossesive
|
||||||
|
...withSecondMiniAsPossesive,
|
||||||
|
// using both mini pronouns as possesives
|
||||||
|
...withFirstMiniAsPossesive.flatMap((x) => spreadOutPoss(x, 0)),
|
||||||
|
].map((x) => ({
|
||||||
|
tokens: b.tokens,
|
||||||
|
body: x,
|
||||||
|
errors: b.errors,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -174,3 +174,61 @@ export function startsVerbSection(b: T.ParsedBlock): boolean {
|
||||||
b.type === "negative"
|
b.type === "negative"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canTakeShrunkenPossesor(
|
||||||
|
block: T.NPSelection | T.APSelection
|
||||||
|
): boolean {
|
||||||
|
if (block.type === "NP") {
|
||||||
|
return block.selection.type !== "pronoun" && !block.selection.possesor;
|
||||||
|
}
|
||||||
|
if (block.selection.type === "sandwich") {
|
||||||
|
return canTakeShrunkenPossesor(block.selection.inside);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addShrunkenPossesor(
|
||||||
|
b: T.NPSelection,
|
||||||
|
person: T.Person
|
||||||
|
): T.NPSelection;
|
||||||
|
export function addShrunkenPossesor(
|
||||||
|
b: T.APSelection,
|
||||||
|
person: T.Person
|
||||||
|
): T.APSelection;
|
||||||
|
export function addShrunkenPossesor(
|
||||||
|
b: T.NPSelection | T.APSelection,
|
||||||
|
person: T.Person
|
||||||
|
): T.NPSelection | T.APSelection {
|
||||||
|
if (b.selection.type === "adverb" || b.selection.type === "pronoun") {
|
||||||
|
throw new Error("cannot add shrunken possesor");
|
||||||
|
}
|
||||||
|
if (b.type === "AP") {
|
||||||
|
return {
|
||||||
|
...b,
|
||||||
|
selection: {
|
||||||
|
...b.selection,
|
||||||
|
inside: addShrunkenPossesor(b.selection.inside, person),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (b.selection.possesor) {
|
||||||
|
throw new Error("cannot add another possesor");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...b,
|
||||||
|
selection: {
|
||||||
|
...b.selection,
|
||||||
|
possesor: {
|
||||||
|
shrunken: true,
|
||||||
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
|
type: "pronoun",
|
||||||
|
distance: "far",
|
||||||
|
person,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -252,7 +252,7 @@ function pronounPossEng(p: T.Person): string {
|
||||||
if (p === T.Person.ThirdSingFemale) {
|
if (p === T.Person.ThirdSingFemale) {
|
||||||
return "her/its";
|
return "her/its";
|
||||||
}
|
}
|
||||||
return `their ${gend(p)}`;
|
return `their (${gend(p)})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnglishFromRendered(
|
export function getEnglishFromRendered(
|
||||||
|
|
Loading…
Reference in New Issue