some error messages
This commit is contained in:
parent
c38e0645d3
commit
6aec2dfeb2
|
@ -7,16 +7,19 @@ import { tokenizer } from "../lib/src/parsing/tokenizer";
|
|||
function ParserDemo({ opts }: { opts: T.TextOptions }) {
|
||||
const [text, setText] = useState<string>("");
|
||||
const [result, setResult] = useState<string>("");
|
||||
const [errors, setErrors] = useState<string[]>([]);
|
||||
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const value = e.target.value;
|
||||
if (!value) {
|
||||
setText("");
|
||||
setResult("");
|
||||
setErrors([]);
|
||||
return;
|
||||
}
|
||||
const r = parsePhrase(tokenizer(value), lookup);
|
||||
const { success, errors } = parsePhrase(tokenizer(value), lookup);
|
||||
setText(value);
|
||||
setResult(JSON.stringify(r, null, " "));
|
||||
setErrors(errors);
|
||||
setResult(JSON.stringify(success, null, " "));
|
||||
}
|
||||
return (
|
||||
<div className="mt-3" style={{ marginBottom: "1000px" }}>
|
||||
|
@ -32,6 +35,13 @@ function ParserDemo({ opts }: { opts: T.TextOptions }) {
|
|||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
{result === "[]" && errors.length > 0 && (
|
||||
<div className="alert alert-danger" role="alert">
|
||||
{errors.map((e) => (
|
||||
<div key={Math.random()}>{e}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<samp>
|
||||
<pre>{result}</pre>
|
||||
</samp>
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
isPattern,
|
||||
isPattern5Entry,
|
||||
isPattern4Entry,
|
||||
isPattern6FemEntry,
|
||||
} from "../type-predicates";
|
||||
import { equals } from "rambda";
|
||||
|
||||
|
@ -135,6 +136,14 @@ export function getInflectionQueries(
|
|||
predicate: (e) => isPattern2Entry(e) || isPattern3Entry(e),
|
||||
},
|
||||
});
|
||||
queries.push({
|
||||
search: { p: s },
|
||||
details: {
|
||||
inflection: [0],
|
||||
gender: ["fem"],
|
||||
predicate: isPattern6FemEntry,
|
||||
},
|
||||
});
|
||||
} else if (s.endsWith("و")) {
|
||||
queries.push({
|
||||
search: { p: s.slice(0, -1) },
|
||||
|
@ -179,6 +188,24 @@ export function getInflectionQueries(
|
|||
predicate: isPattern3Entry,
|
||||
},
|
||||
});
|
||||
if (includeNouns) {
|
||||
queries.push({
|
||||
search: { p: s.slice(0, -1) + "ي" },
|
||||
details: {
|
||||
inflection: [1],
|
||||
gender: ["fem"],
|
||||
predicate: isPattern6FemEntry,
|
||||
},
|
||||
});
|
||||
queries.push({
|
||||
search: { p: s },
|
||||
details: {
|
||||
inflection: [0, 1],
|
||||
gender: ["fem"],
|
||||
predicate: isPattern3Entry,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const coallated: ReturnType<typeof getInflectionQueries> = [];
|
||||
|
|
|
@ -313,7 +313,12 @@ describe("parsing adjectives", () => {
|
|||
cases.forEach(({ input, output }) => {
|
||||
const tokens = tokenizer(input);
|
||||
const possibilities = parseAdjective(tokens, lookup).map((x) => x[1]);
|
||||
expect(possibilities).toEqual(output);
|
||||
expect(
|
||||
possibilities.map((x) => {
|
||||
const { given, ...rest } = x;
|
||||
return rest;
|
||||
})
|
||||
).toEqual(output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ export function parseAdjective(
|
|||
{
|
||||
inflection: (0 | 1 | 2)[];
|
||||
gender: T.Gender[];
|
||||
given: string;
|
||||
selection: T.AdjectiveSelection;
|
||||
}
|
||||
][] {
|
||||
|
@ -32,6 +33,7 @@ export function parseAdjective(
|
|||
selection,
|
||||
inflection: deets.inflection,
|
||||
gender: deets.gender,
|
||||
given: first,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -15,17 +15,28 @@ export function parseNoun(
|
|||
adjectives: {
|
||||
inflection: (0 | 1 | 2)[];
|
||||
gender: T.Gender[];
|
||||
given: string;
|
||||
selection: T.AdjectiveSelection;
|
||||
}[]
|
||||
): [string[], { inflection: (0 | 1 | 2)[]; selection: T.NounSelection }][] {
|
||||
): {
|
||||
success: [
|
||||
string[],
|
||||
{ inflection: (0 | 1 | 2)[]; selection: T.NounSelection }
|
||||
][];
|
||||
errors: string[];
|
||||
} {
|
||||
if (tokens.length === 0) {
|
||||
return [];
|
||||
return {
|
||||
success: [],
|
||||
errors: [],
|
||||
};
|
||||
}
|
||||
const adjRes = parseAdjective(tokens, lookup);
|
||||
const withAdj = adjRes.flatMap(([tkns, adj]) =>
|
||||
const withAdj = adjRes.map(([tkns, adj]) =>
|
||||
parseNoun(tkns, lookup, [...adjectives, adj])
|
||||
);
|
||||
const w: ReturnType<typeof parseNoun> = [];
|
||||
const success: ReturnType<typeof parseNoun>["success"] = [];
|
||||
const errors: string[] = [];
|
||||
const [first, ...rest] = tokens;
|
||||
|
||||
const searches = getInflectionQueries(first, true);
|
||||
|
@ -34,11 +45,15 @@ export function parseNoun(
|
|||
details.forEach((deets) => {
|
||||
const fittingEntries = nounEntries.filter(deets.predicate);
|
||||
fittingEntries.forEach((entry) => {
|
||||
console.log({ entry, deets });
|
||||
if (isUnisexNounEntry(entry)) {
|
||||
deets.gender.forEach((gender) => {
|
||||
if (adjsMatch(adjectives, gender, deets.inflection)) {
|
||||
w.push([
|
||||
const { ok, error } = adjsMatch(
|
||||
adjectives,
|
||||
gender,
|
||||
deets.inflection
|
||||
);
|
||||
if (ok) {
|
||||
success.push([
|
||||
rest,
|
||||
{
|
||||
inflection: deets.inflection,
|
||||
|
@ -49,11 +64,16 @@ export function parseNoun(
|
|||
},
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
error.forEach((e) => {
|
||||
errors.push(e);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (isMascNounEntry(entry) && deets.gender.includes("masc")) {
|
||||
if (adjsMatch(adjectives, "masc", deets.inflection)) {
|
||||
w.push([
|
||||
const { ok, error } = adjsMatch(adjectives, "masc", deets.inflection);
|
||||
if (ok) {
|
||||
success.push([
|
||||
rest,
|
||||
{
|
||||
inflection: deets.inflection,
|
||||
|
@ -63,10 +83,15 @@ export function parseNoun(
|
|||
},
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
error.forEach((e) => {
|
||||
errors.push(e);
|
||||
});
|
||||
}
|
||||
} else if (isFemNounEntry(entry) && deets.gender.includes("fem")) {
|
||||
if (adjsMatch(adjectives, "fem", deets.inflection)) {
|
||||
w.push([
|
||||
const { ok, error } = adjsMatch(adjectives, "fem", deets.inflection);
|
||||
if (ok) {
|
||||
success.push([
|
||||
rest,
|
||||
{
|
||||
inflection: deets.inflection,
|
||||
|
@ -76,22 +101,63 @@ export function parseNoun(
|
|||
},
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
error.forEach((e) => {
|
||||
errors.push(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return [...withAdj, ...w];
|
||||
return {
|
||||
success: [...withAdj.map((x) => x.success).flat(), ...success],
|
||||
errors: [...withAdj.map((x) => x.errors).flat(), ...errors],
|
||||
};
|
||||
}
|
||||
|
||||
function adjsMatch(
|
||||
adjectives: Parameters<typeof parseNoun>[2],
|
||||
gender: T.Gender,
|
||||
inflection: (0 | 1 | 2)[]
|
||||
): boolean {
|
||||
return adjectives.every(
|
||||
): { ok: boolean; error: string[] } {
|
||||
const unmatching = adjectives.filter(
|
||||
(adj) =>
|
||||
adj.gender.includes(gender) &&
|
||||
adj.inflection.some((i) => inflection.includes(i))
|
||||
!adj.gender.includes(gender) ||
|
||||
!adj.inflection.some((i) => inflection.includes(i))
|
||||
);
|
||||
if (unmatching.length) {
|
||||
return {
|
||||
ok: false,
|
||||
error: unmatching.map((x) => {
|
||||
const adjText =
|
||||
x.given === x.selection.entry.p
|
||||
? x.given
|
||||
: `${x.given} (${x.selection.entry.p})`;
|
||||
const inflectionIssue = !x.inflection.some((x) =>
|
||||
inflection.includes(x)
|
||||
)
|
||||
? ` should be ${showInflection(inflection)}`
|
||||
: ``;
|
||||
return `Adjective agreement error: ${adjText} should be ${inflectionIssue} ${gender}.`;
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
ok: true,
|
||||
error: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function showInflection(inf: (0 | 1 | 2)[]): string {
|
||||
const [last, ...rest] = inf.reverse();
|
||||
const template = rest.length
|
||||
? `${rest.join(", ")}, or ${last}`
|
||||
: last.toString();
|
||||
console.log(template);
|
||||
return template
|
||||
.replace("0", "plain")
|
||||
.replace("1", "first inflection")
|
||||
.replace("2", "second inflection");
|
||||
}
|
||||
|
|
|
@ -6,13 +6,19 @@ import { parseNoun } from "./parse-noun";
|
|||
export function parsePhrase(
|
||||
s: string[],
|
||||
lookup: (s: Partial<T.DictionaryEntry>) => T.DictionaryEntry[]
|
||||
): any[] {
|
||||
): {
|
||||
success: any[];
|
||||
errors: string[];
|
||||
} {
|
||||
const adjsRes = parseAdjective(s, lookup);
|
||||
const prnsRes = parsePronoun(s);
|
||||
const nounsRes = parseNoun(s, lookup, []);
|
||||
|
||||
const correct = [...adjsRes, ...prnsRes, ...nounsRes]
|
||||
const correct = [...adjsRes, ...prnsRes, ...nounsRes.success]
|
||||
.filter(([tkns]) => tkns.length === 0)
|
||||
.map((x) => x[1]);
|
||||
return correct;
|
||||
return {
|
||||
success: correct,
|
||||
errors: nounsRes.errors,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue