Skip to content

Commit

Permalink
Merge pull request #13 from alexharri/do-not-apply-impossible-declens…
Browse files Browse the repository at this point in the history
…ions

Do not apply declensions when they cannot apply to to the name
  • Loading branch information
alexharri committed Oct 12, 2023
2 parents 4a06584 + 9ebcf57 commit 5a2bb2e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
13 changes: 13 additions & 0 deletions lib/beygla.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,17 @@ describe("applyCase", () => {
expect(applyCase(_case, "Eldey")).toEqual(name);
}
});

test("it does not apply declensions that can not possibly apply to a name", () => {
// The name 'Maya' would previously match the declension for 'Tanya', which
// is '4;anya,önyu,önyu,önyu'.
//
// The subtraction of 4 would erase the entire name. Applying the declension
// is non-sensical.
expect(getDeclensionForName("Maya")).toEqual(null);

for (const caseStr of <const>["nf", "þf", "þgf", "ef"]) {
expect(applyCase(caseStr, "Maya")).toEqual("Maya");
}
});
});
34 changes: 31 additions & 3 deletions lib/beygla.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,18 @@ function getCaseIndex(caseStr: Case) {
return 0; // Fall back to 0 if an invalid case was provided
}

function declineName(name: string, declension: string, caseStr: Case): string {
function parseDeclension(declension: string) {
const [subtractString, appendicesString] = declension.split(";");

const subtraction = Number(subtractString);
const appendices = (appendicesString || "").split(",");

return [subtraction, appendices] as const;
}

function declineName(name: string, declension: string, caseStr: Case): string {
const [subtraction, appendices] = parseDeclension(declension);

const caseIndex = getCaseIndex(caseStr);

// Should not happen, but prefer being safe
Expand Down Expand Up @@ -59,7 +66,7 @@ function applyCaseToName(caseStr: Case, name: string) {
}

if (!postfix) {
const declension = extractDeclension(trie, name);
const declension = getDeclensionForName(name);
if (declension) name = declineName(name, declension, caseStr);
} else {
name += declineName(postfix[0], postfix[1], caseStr);
Expand Down Expand Up @@ -110,5 +117,26 @@ export function applyCase(caseStr: Case, name: string): string {
export function getDeclensionForName(name: string): string | null {
if (name.split(/\s+/).length > 1)
throw new Error("Name must not include whitespace");
return extractDeclension(trie, name);

const declension = extractDeclension(trie, name);
if (declension) {
// Ensure that the declension applies to the name. This guard is useful when
// the subtraction is longer than the path to the declension.
//
// For example, consider this:
//
// {
// "path": "ya",
// "children": {},
// "keys": ["Tanya"],
// "value": "4;anya,önyu,önyu,önyu"
// }
//
// The name 'Maya' matches this path, but applying the declension erases the
// entire name.
const [_subtraction, appendices] = parseDeclension(declension);
if (!name.endsWith(appendices[0])) return null;
}

return declension;
}

0 comments on commit 5a2bb2e

Please sign in to comment.