messy working with grammatically transitive verbs

This commit is contained in:
adueck 2023-08-31 19:16:31 +04:00
parent a3dbf550f0
commit 77d20ecf02
1 changed files with 477 additions and 347 deletions

View File

@ -29,6 +29,8 @@ import { LookupFunction } from "./lookup";
// TODO: learn how to yank / use plugin for JSON neovim // TODO: learn how to yank / use plugin for JSON neovim
// learn to use jq to edit selected json in vim ?? COOOL // learn to use jq to edit selected json in vim ?? COOOL
// TODO: test grammatically transitive stuff
export function parseVP( export function parseVP(
tokens: Readonly<T.Token[]>, tokens: Readonly<T.Token[]>,
lookup: LookupFunction lookup: LookupFunction
@ -74,42 +76,78 @@ export function parseVP(
} }
const tense = getTenseFromRootsStems(ba, verb.info.base, verb.info.aspect); const tense = getTenseFromRootsStems(ba, verb.info.base, verb.info.aspect);
const isPast = isPastTense(tense); const isPast = isPastTense(tense);
const transitivities = getTransitivities(verb.info.verb);
const results: T.ParseResult<T.VPSelectionComplete>[] = [];
// eww... pretty imperative way of doing this...
for (let transitivity of transitivities) {
const v: T.VerbSelectionComplete = {
type: "verb",
verb: verb.info.verb,
transitivity,
canChangeTransitivity: false,
canChangeStatDyn: false,
negative,
tense,
canChangeVoice: true,
isCompound: false,
voice: "active",
};
const v: T.VerbSelectionComplete = { const nps = blocks.filter((x): x is T.ParsedNP => x.type === "NP");
type: "verb", if (transitivity === "intransitive") {
verb: verb.info.verb, const errors: T.ParseError[] = [];
transitivity: verb.info.verb.entry.c.includes("intrans") if (getMiniPronouns(kids).length) {
? "intransitive" errors.push({
: "transitive", message: "unknown mini-pronoun",
canChangeTransitivity: false, });
canChangeStatDyn: false, }
negative, if (nps.length > 1) {
tense, continue;
canChangeVoice: true, }
isCompound: false, if (nps.length === 0) {
voice: "active", const blocks: T.VPSBlockComplete[] = [
}; {
key: 1,
const nps = blocks.filter((x): x is T.ParsedNP => x.type === "NP"); block: makeSubjectSelectionComplete({
// TODO: check that verb and PH match type: "NP",
if (verb.info.verb.entry.c.includes("intrans")) { selection: makePronounSelection(verb.person),
const errors: T.ParseError[] = []; }),
if (getMiniPronouns(kids).length) { },
errors.push({ {
message: "unknown mini-pronoun", key: 2,
}); block: {
} type: "objectSelection",
if (nps.length > 1) { selection: "none",
return []; },
} },
if (nps.length === 0) { ];
results.push({
tokens,
body: {
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: true,
shrinkServant: false,
},
} as T.VPSelectionComplete,
errors,
});
continue;
}
if (getPersonFromNP(nps[0].selection) !== verb.person) {
errors.push({ message: "subject must agree with intransitive verb" });
}
if (nps[0].inflected) {
errors.push({
message: "subject of intransitive verb must not be inflected",
});
}
const blocks: T.VPSBlockComplete[] = [ const blocks: T.VPSBlockComplete[] = [
{ {
key: 1, key: 1,
block: makeSubjectSelectionComplete({ block: makeSubjectSelectionComplete(nps[0].selection),
type: "NP",
selection: makePronounSelection(verb.person),
}),
}, },
{ {
key: 2, key: 2,
@ -119,292 +157,437 @@ export function parseVP(
}, },
}, },
]; ];
return returnParseResult( results.push({
tokens, tokens,
{ body: {
blocks, blocks,
verb: v, verb: v,
externalComplement: undefined, externalComplement: undefined,
form: { form: {
removeKing: true, removeKing: false,
shrinkServant: false, shrinkServant: false,
}, },
} as T.VPSelectionComplete, } as T.VPSelectionComplete,
errors errors,
);
}
if (getPersonFromNP(nps[0].selection) !== verb.person) {
errors.push({ message: "subject must agree with intransitive verb" });
}
if (nps[0].inflected) {
errors.push({
message: "subject of intransitive verb must not be inflected",
}); });
} continue;
const blocks: T.VPSBlockComplete[] = [ } else if (transitivity === "transitive") {
{ // transitive
key: 1, if (nps.length > 2) {
block: makeSubjectSelectionComplete(nps[0].selection), continue;
},
{
key: 2,
block: {
type: "objectSelection",
selection: "none",
},
},
];
return returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: false,
shrinkServant: false,
},
} as T.VPSelectionComplete,
errors
);
} else {
// transitive
if (nps.length > 2) {
return [];
}
if (nps.length === 0) {
// present:
// - no king (subject)
// - servant (object) is shrunken
// past:
// - no king (object)
// - servant (subject) is shrunken
const errors: T.ParseError[] = [];
const miniPronouns = getMiniPronouns(kids);
if (miniPronouns.length > 1) {
errors.push({
message: "unknown mini-pronoun in kid's section",
});
} }
const blockOpts: T.VPSBlockComplete[][] = getPeopleFromMiniPronouns( if (nps.length === 0) {
miniPronouns // present:
).map((person) => // - no king (subject)
!isPast // - servant (object) is shrunken
? [ // past:
{ // - no king (object)
key: 1, // - servant (subject) is shrunken
block: makeSubjectSelectionComplete({
type: "NP",
selection: makePronounSelection(verb.person),
}),
},
{
key: 2,
block: makeObjectSelectionComplete({
type: "NP",
selection: makePronounSelection(person),
}),
},
]
: [
{
key: 1,
block: makeSubjectSelectionComplete({
type: "NP",
selection: makePronounSelection(person),
}),
},
{
key: 2,
block: makeObjectSelectionComplete({
type: "NP",
selection: makePronounSelection(verb.person),
}),
},
]
);
return blockOpts.flatMap((blocks) =>
returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: true,
shrinkServant: true,
},
} as T.VPSelectionComplete,
pronounConflictInBlocks(blocks)
? [...errors, { message: "invalid subject/object combo" }]
: errors
)
);
}
if (nps.length === 1) {
const np = nps[0];
// possibilities
// present:
// - no king (np is servant)
// - shrunken servant (np is king)
// past:
// - no king (np is servant)
// - shrunken servant (np is king)
return (
[
{
removeKing: true,
shrinkServant: false,
},
{
removeKing: false,
shrinkServant: true,
},
] as const
).flatMap((form) => {
const errors: T.ParseError[] = []; const errors: T.ParseError[] = [];
const king: T.NPSelection = form.removeKing const miniPronouns = getMiniPronouns(kids);
? { if (miniPronouns.length > 1) {
type: "NP", errors.push({
selection: makePronounSelection(verb.person), message: "unknown mini-pronoun in kid's section",
} });
: np.selection;
const servants: T.NPSelection[] = form.shrinkServant
? getPeopleFromMiniPronouns(kids).map((person) => ({
type: "NP",
selection: makePronounSelection(person),
}))
: [np.selection];
// check for vp structure errors
if (form.removeKing) {
if (getMiniPronouns(kids).length) {
errors.push({
message: "unknown mini-pronoun in kid's section",
});
}
if (!isPast) {
if (isFirstOrSecondPersPronoun(np.selection))
if (!np.inflected) {
errors.push({
message:
"first or second pronoun object of non-past transitive verb must be inflected",
});
}
} else {
if (!np.inflected) {
errors.push({
message:
"object of non-past transitive verb must not be inflected",
});
}
}
} else {
if (np.inflected) {
errors.push({
message: !isPast
? "object of a past tense transitive verb should not be inflected"
: "subject of a non-past tense transitive verb should not be inflected",
});
}
if (getPersonFromNP(king) !== verb.person) {
errors.push({
message: `${
isPast ? "past tense" : "non-past tense"
} transitive verb must agree agree with ${
isPast ? "obect" : "subject"
}`,
});
}
} }
const blocksOps: T.VPSBlockComplete[][] = servants.map((servant) => const blockOpts: T.VPSBlockComplete[][] = getPeopleFromMiniPronouns(
miniPronouns
).map((person) =>
!isPast !isPast
? [ ? [
{ {
key: 1, key: 1,
block: makeSubjectSelectionComplete(king), block: makeSubjectSelectionComplete({
type: "NP",
selection: makePronounSelection(verb.person),
}),
}, },
{ {
key: 2, key: 2,
block: makeObjectSelectionComplete(servant), block: makeObjectSelectionComplete({
type: "NP",
selection: makePronounSelection(person),
}),
}, },
] ]
: [ : [
{ {
key: 1, key: 1,
block: makeSubjectSelectionComplete(servant), block: makeSubjectSelectionComplete({
type: "NP",
selection: makePronounSelection(person),
}),
}, },
{ {
key: 2, key: 2,
block: makeObjectSelectionComplete(king), block: makeObjectSelectionComplete({
type: "NP",
selection: makePronounSelection(verb.person),
}),
}, },
] ]
); );
return blocksOps.map((blocks) => ({ const toAdd = blockOpts.flatMap((blocks) =>
returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: true,
shrinkServant: true,
},
} as T.VPSelectionComplete,
pronounConflictInBlocks(blocks)
? [...errors, { message: "invalid subject/object combo" }]
: errors
)
);
toAdd.forEach((r) => results.push(r));
continue;
}
if (nps.length === 1) {
const np = nps[0];
// possibilities
// present:
// - no king (np is servant)
// - shrunken servant (np is king)
// past:
// - no king (np is servant)
// - shrunken servant (np is king)
const res = (
[
{
removeKing: true,
shrinkServant: false,
},
{
removeKing: false,
shrinkServant: true,
},
] as const
).flatMap((form) => {
const errors: T.ParseError[] = [];
const king: T.NPSelection = form.removeKing
? {
type: "NP",
selection: makePronounSelection(verb.person),
}
: np.selection;
const servants: T.NPSelection[] = form.shrinkServant
? getPeopleFromMiniPronouns(kids).map((person) => ({
type: "NP",
selection: makePronounSelection(person),
}))
: [np.selection];
// check for vp structure errors
if (form.removeKing) {
if (getMiniPronouns(kids).length) {
errors.push({
message: "unknown mini-pronoun in kid's section",
});
}
if (!isPast) {
if (isFirstOrSecondPersPronoun(np.selection))
if (!np.inflected) {
errors.push({
message:
"first or second pronoun object of non-past transitive verb must be inflected",
});
}
} else {
if (!np.inflected) {
errors.push({
message:
"object of non-past transitive verb must not be inflected",
});
}
}
} else {
if (np.inflected) {
errors.push({
message: !isPast
? "object of a past tense transitive verb should not be inflected"
: "subject of a non-past tense transitive verb should not be inflected",
});
}
if (getPersonFromNP(king) !== verb.person) {
errors.push({
message: `${
isPast ? "past tense" : "non-past tense"
} transitive verb must agree agree with ${
isPast ? "obect" : "subject"
}`,
});
}
}
const blocksOps: T.VPSBlockComplete[][] = servants.map((servant) =>
!isPast
? [
{
key: 1,
block: makeSubjectSelectionComplete(king),
},
{
key: 2,
block: makeObjectSelectionComplete(servant),
},
]
: [
{
key: 1,
block: makeSubjectSelectionComplete(servant),
},
{
key: 2,
block: makeObjectSelectionComplete(king),
},
]
);
return blocksOps.map((blocks) => ({
tokens,
body: {
blocks,
verb: v,
externalComplement: undefined,
form,
} as T.VPSelectionComplete,
errors: pronounConflictInBlocks(blocks)
? [...errors, { message: "invalid subject/object combo" }]
: errors,
}));
});
res.forEach((r) => results.push(r));
continue;
} else {
if (isPast) {
const res = (
[
[nps[0], nps[1], false],
[nps[1], nps[0], true],
] as const
).flatMap(([s, o, flip]) => {
const errors: T.ParseError[] = [];
if (
isInvalidSubjObjCombo(
getPersonFromNP(s.selection),
getPersonFromNP(o.selection)
)
) {
errors.push({
message: "invalid subject/object combo",
});
}
if (!s.inflected) {
errors.push({
message:
"subject of transitive past tense verb must be inflected",
});
}
if (o.inflected) {
errors.push({
message:
"object of past tense transitive verb must not be inflected",
});
}
if (getPersonFromNP(o.selection) !== verb.person) {
errors.push({
message:
"past tense transitive verb must agree with the object",
});
}
let blocks: T.VPSBlockComplete[] = [
{
key: 1,
block: makeSubjectSelectionComplete(s.selection),
},
{
key: 2,
block: makeObjectSelectionComplete(o.selection),
},
];
if (flip) {
blocks = blocks.reverse();
}
return returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: false,
shrinkServant: false,
},
} as T.VPSelectionComplete,
errors
);
});
res.forEach((r) => results.push(r));
continue;
} else {
const res = (
[
[nps[0], nps[1], false],
[nps[1], nps[0], true],
] as const
).flatMap(([s, o, flip]) => {
const errors: T.ParseError[] = [];
if (
isInvalidSubjObjCombo(
getPersonFromNP(s.selection),
getPersonFromNP(o.selection)
)
) {
errors.push({
message: "invalid subject/object combo",
});
}
if (isFirstOrSecondPersPronoun(o.selection)) {
if (!o.inflected) {
errors.push({
message:
"object of transitive non-past tense verb must be inflected when it's a first or second person pronoun",
});
}
} else {
if (o.inflected) {
errors.push({
message:
"object of transitive non-past tense verb must not be inflected",
});
}
}
if (s.inflected) {
errors.push({
message:
"subject of transitive non-past tense verb must not be inflected",
});
}
if (getPersonFromNP(s.selection) !== verb.person) {
errors.push({
message:
"non-past tense transitive verb must agree with the subject",
});
}
let blocks: T.VPSBlockComplete[] = [
{
key: 1,
block: makeSubjectSelectionComplete(s.selection),
},
{
key: 2,
block: makeObjectSelectionComplete(o.selection),
},
];
if (flip) {
blocks = blocks.reverse();
}
return returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: false,
shrinkServant: false,
},
} as T.VPSelectionComplete,
errors
);
});
res.forEach((r) => results.push(r));
continue;
}
}
} else {
// grammatically transitive
const errors: T.ParseError[] = [];
if (nps.length === 1) {
if (getMiniPronouns(kids).length) {
errors.push({
message: "unknown mini-pronoun",
});
}
if (verb.person !== T.Person.ThirdPlurMale) {
errors.push({
message:
"grammatically transitive verb must be 3rd pers. masc. plur.",
});
}
if (!nps[0].inflected) {
errors.push({
message:
"subject of grammatically transitive verb must be inflected",
});
}
const blocks: T.VPSBlockComplete[] = [
{
key: 1,
block: makeSubjectSelectionComplete(nps[0].selection),
},
{
key: 2,
block: {
type: "objectSelection",
selection: T.Person.ThirdPlurMale,
},
},
];
results.push({
tokens, tokens,
body: { body: {
blocks, blocks,
verb: v, verb: v,
externalComplement: undefined, externalComplement: undefined,
form, form: {
removeKing: false,
shrinkServant: false,
},
} as T.VPSelectionComplete, } as T.VPSelectionComplete,
errors: pronounConflictInBlocks(blocks) errors,
? [...errors, { message: "invalid subject/object combo" }] });
: errors, continue;
})); } else if (nps.length === 0) {
}); const miniPronouns = getMiniPronouns(kids);
} else { if (miniPronouns.length > 1) {
if (isPast) { errors.push({
return ( message: "unknown mini-pronoun",
[ });
[nps[0], nps[1], false], }
[nps[1], nps[0], true], if (miniPronouns.length === 0) {
] as const errors.push({
).flatMap(([s, o, flip]) => { message: "subject required for grammatically transitive verb",
const errors: T.ParseError[] = []; });
if ( }
isInvalidSubjObjCombo( if (verb.person !== T.Person.ThirdPlurMale) {
getPersonFromNP(s.selection), errors.push({
getPersonFromNP(o.selection) message:
) "grammatically transitive verb must be 3rd pers. masc. plur.",
) { });
errors.push({ }
message: "invalid subject/object combo", getPeopleFromMiniPronouns(kids).forEach((person) => {
}); const blocks: T.VPSBlockComplete[] = [
}
if (!s.inflected) {
errors.push({
message:
"subject of transitive past tense verb must be inflected",
});
}
if (o.inflected) {
errors.push({
message:
"object of past tense transitive verb must not be inflected",
});
}
if (getPersonFromNP(o.selection) !== verb.person) {
errors.push({
message:
"past tense transitive verb must agree with the object",
});
}
let blocks: T.VPSBlockComplete[] = [
{ {
key: 1, key: 1,
block: makeSubjectSelectionComplete(s.selection), block: makeSubjectSelectionComplete({
type: "NP",
selection: makePronounSelection(person),
}),
}, },
{ {
key: 2, key: 2,
block: makeObjectSelectionComplete(o.selection), block: {
type: "objectSelection",
selection: T.Person.ThirdPlurMale,
},
}, },
]; ];
if (flip) { results.push({
blocks = blocks.reverse();
}
return returnParseResult(
tokens, tokens,
{ body: {
blocks, blocks,
verb: v, verb: v,
externalComplement: undefined, externalComplement: undefined,
@ -413,84 +596,16 @@ export function parseVP(
shrinkServant: false, shrinkServant: false,
}, },
} as T.VPSelectionComplete, } as T.VPSelectionComplete,
errors errors,
); });
}); });
continue;
} else { } else {
return ( continue;
[
[nps[0], nps[1], false],
[nps[1], nps[0], true],
] as const
).flatMap(([s, o, flip]) => {
const errors: T.ParseError[] = [];
if (
isInvalidSubjObjCombo(
getPersonFromNP(s.selection),
getPersonFromNP(o.selection)
)
) {
errors.push({
message: "invalid subject/object combo",
});
}
if (isFirstOrSecondPersPronoun(o.selection)) {
if (!o.inflected) {
errors.push({
message:
"object of transitive non-past tense verb must be inflected when it's a first or second person pronoun",
});
}
} else {
if (o.inflected) {
errors.push({
message:
"object of transitive non-past tense verb must not be inflected",
});
}
}
if (s.inflected) {
errors.push({
message:
"subject of transitive non-past tense verb must not be inflected",
});
}
if (getPersonFromNP(s.selection) !== verb.person) {
errors.push({
message:
"non-past tense transitive verb must agree with the subject",
});
}
let blocks: T.VPSBlockComplete[] = [
{
key: 1,
block: makeSubjectSelectionComplete(s.selection),
},
{
key: 2,
block: makeObjectSelectionComplete(o.selection),
},
];
if (flip) {
blocks = blocks.reverse();
}
return returnParseResult(
tokens,
{
blocks,
verb: v,
externalComplement: undefined,
form: {
removeKing: false,
shrinkServant: false,
},
} as T.VPSelectionComplete,
errors
);
});
} }
} }
} }
return results;
}); });
} }
@ -588,3 +703,18 @@ function pronounConflictInBlocks(blocks: T.VPSBlockComplete[]): boolean {
} }
return isInvalidSubjObjCombo(subjPerson, objPerson); return isInvalidSubjObjCombo(subjPerson, objPerson);
} }
function getTransitivities(v: T.VerbEntry): T.Transitivity[] {
const transitivities: T.Transitivity[] = [];
const opts = v.entry.c.split("/");
opts.forEach((opt) => {
if (opt.includes("gramm. trans")) {
transitivities.push("grammatically transitive");
} else if (opt.includes("intran")) {
transitivities.push("intransitive");
} else if (opt.includes("trans")) {
transitivities.push("transitive");
}
});
return transitivities;
}