From 0e5b013e4e781e1b38b039a44cddfc6987e94977 Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:53:14 +0300 Subject: [PATCH] Refactor language API --- .../src/components/RefsInput/tooltip.ts | 2 +- .../src/dialogs/DlgEditReference/index.tsx | 7 +- .../frontend/src/dialogs/DlgEditWordForms.tsx | 6 +- rsconcept/frontend/src/models/language.ts | 114 ----------------- .../{language.test.ts => languageAPI.test.ts} | 3 +- rsconcept/frontend/src/models/languageAPI.ts | 118 ++++++++++++++++++ rsconcept/frontend/src/utils/codemirror.ts | 3 +- rsconcept/frontend/src/utils/selectors.ts | 3 +- 8 files changed, 129 insertions(+), 127 deletions(-) rename rsconcept/frontend/src/models/{language.test.ts => languageAPI.test.ts} (92%) create mode 100644 rsconcept/frontend/src/models/languageAPI.ts diff --git a/rsconcept/frontend/src/components/RefsInput/tooltip.ts b/rsconcept/frontend/src/components/RefsInput/tooltip.ts index d1b0978c..4c08eb6f 100644 --- a/rsconcept/frontend/src/components/RefsInput/tooltip.ts +++ b/rsconcept/frontend/src/components/RefsInput/tooltip.ts @@ -2,7 +2,7 @@ import { syntaxTree } from '@codemirror/language' import { Extension } from '@codemirror/state'; import { hoverTooltip } from '@codemirror/view'; -import { parseEntityReference, parseSyntacticReference } from '../../models/language'; +import { parseEntityReference, parseSyntacticReference } from '../../models/languageAPI'; import { IConstituenta } from '../../models/rsform'; import { domTooltipEntityReference, domTooltipSyntacticReference, findContainedNodes, findEnvelopingNodes } from '../../utils/codemirror'; import { IColorTheme } from '../../utils/color'; diff --git a/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx b/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx index aad4051a..ddf1ad97 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditReference/index.tsx @@ -8,11 +8,8 @@ import TextInput from '../../components/Common/TextInput'; import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl'; import { HelpIcon } from '../../components/Icons'; import ConstituentaPicker from '../../components/Shared/ConstituentaPicker'; -import { - getCompatibleGrams, Grammeme, - parseEntityReference, parseGrammemes, - parseSyntacticReference, ReferenceType -} from '../../models/language'; +import { Grammeme, ReferenceType } from '../../models/language'; +import { getCompatibleGrams, parseEntityReference, parseGrammemes, parseSyntacticReference } from '../../models/languageAPI'; import { CstMatchMode } from '../../models/miscelanious'; import { IConstituenta } from '../../models/rsform'; import { matchConstituenta } from '../../models/rsformAPI'; diff --git a/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx b/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx index 01bcc097..42deda4b 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditWordForms.tsx @@ -10,10 +10,8 @@ import HelpTerminologyControl from '../components/Help/HelpTerminologyControl'; import { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDoubleDownIcon, CrossIcon, HelpIcon } from '../components/Icons'; import { useConceptTheme } from '../context/ThemeContext'; import useConceptText from '../hooks/useConceptText'; -import { - getCompatibleGrams, Grammeme, ITextRequest, IWordForm, - IWordFormPlain, matchWordForm, parseGrammemes -} from '../models/language'; +import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '../models/language'; +import { getCompatibleGrams, matchWordForm, parseGrammemes } from '../models/languageAPI'; import { IConstituenta, TermForm } from '../models/rsform'; import { colorfgGrammeme } from '../utils/color'; import { labelGrammeme } from '../utils/labels'; diff --git a/rsconcept/frontend/src/models/language.ts b/rsconcept/frontend/src/models/language.ts index 241deaa4..61890b60 100644 --- a/rsconcept/frontend/src/models/language.ts +++ b/rsconcept/frontend/src/models/language.ts @@ -228,94 +228,6 @@ export interface ILexemeData { items: IWordFormPlain[] } -/** - * Equality comparator for {@link IWordForm}. Compares a set of Grammemes attached to wordforms - */ -export function matchWordForm(left: IWordForm, right: IWordForm): boolean { - if (left.grams.length !== right.grams.length) { - return false; - } - for (let index = 0; index < left.grams.length; ++index) { - if (left.grams[index] !== right.grams[index]) { - return false; - } - } - return true; -} - -function parseSingleGrammeme(text: string): GramData { - if (Object.values(Grammeme).includes(text as Grammeme)) { - return text as Grammeme; - } else { - return text; - } -} - -/** - * Compares {@link GramData} based on Grammeme enum and alpha order for strings. - */ -export function compareGrammemes(left: GramData, right: GramData): number { - const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left as Grammeme); - const indexRight = Object.values(Grammeme).findIndex(gram => gram === right as Grammeme); - if (indexLeft === -1 && indexRight === -1) { - return left.localeCompare(right); - } else if (indexLeft === -1 && indexRight !== -1) { - return 1; - } else if (indexLeft !== -1 && indexRight === -1) { - return -1; - } else { - return indexLeft - indexRight; - } -} - -/** - * Transforms {@link Grammeme} enumeration to {@link GramData}. - */ -export function parseGrammemes(termForm: string): GramData[] { - const result: GramData[] = []; - const chunks = termForm.split(','); - chunks.forEach(chunk => { - chunk = chunk.trim(); - if (chunk !== '') { - result.push(parseSingleGrammeme(chunk)); - } - }); - return result.sort(compareGrammemes); -} - -/** - * Creates a list of compatible {@link Grammeme}s. - */ -export function getCompatibleGrams(input: Grammeme[]): Grammeme[] { - let result: Grammeme[] = []; - input.forEach( - (gram) => { - if (!result.includes(gram)) { - if (NounGrams.includes(gram)) { - result.push(...NounGrams); - } - if (VerbGrams.includes(gram)) { - result.push(...VerbGrams); - } - } - }); - - input.forEach( - (gram) => GrammemeGroups.forEach( - (group) => { - if (group.includes(gram)) { - result = result.filter(item => !group.includes(item)); - } - })); - - if (result.length === 0) { - return [... new Set([...VerbGrams, ...NounGrams])]; - } else { - return result; - } -} - - // ====== Reference resolution ===== /** * Represents text request. @@ -380,29 +292,3 @@ export interface IResolutionData { output: string refs: IResolvedReference[] } - -/** - * Extracts {@link IEntityReference} from string representation. - * - * @param text - Reference text in a valid pattern. Must fit format '\@\{GLOBAL_ID|GRAMMEMES\}' - */ -export function parseEntityReference(text: string): IEntityReference { - const blocks = text.slice(2, text.length - 1).split('|'); - return { - entity: blocks[0].trim(), - form: blocks[1].trim() - } -} - -/** - * Extracts {@link ISyntacticReference} from string representation. - * - * @param text - Reference text in a valid pattern. Must fit format '\@\{OFFSET|NOMINAL_FORM\}' - */ -export function parseSyntacticReference(text: string): ISyntacticReference { - const blocks = text.slice(2, text.length - 1).split('|'); - return { - offset: Number(blocks[0].trim()), - nominal: blocks[1].trim() - } -} \ No newline at end of file diff --git a/rsconcept/frontend/src/models/language.test.ts b/rsconcept/frontend/src/models/languageAPI.test.ts similarity index 92% rename from rsconcept/frontend/src/models/language.test.ts rename to rsconcept/frontend/src/models/languageAPI.test.ts index f049e814..d3f6786e 100644 --- a/rsconcept/frontend/src/models/language.test.ts +++ b/rsconcept/frontend/src/models/languageAPI.test.ts @@ -1,4 +1,5 @@ -import { Grammeme, parseEntityReference, parseGrammemes, parseSyntacticReference } from './language'; +import { Grammeme } from './language'; +import { parseEntityReference, parseGrammemes, parseSyntacticReference } from './languageAPI'; describe('Testing grammeme parsing', () => { diff --git a/rsconcept/frontend/src/models/languageAPI.ts b/rsconcept/frontend/src/models/languageAPI.ts new file mode 100644 index 00000000..e3ca6760 --- /dev/null +++ b/rsconcept/frontend/src/models/languageAPI.ts @@ -0,0 +1,118 @@ +/** + * Module: Natural language model API. + */ + +import { GramData, Grammeme, GrammemeGroups, IEntityReference, ISyntacticReference, IWordForm, NounGrams, VerbGrams } from './language'; + +/** + * Equality comparator for {@link IWordForm}. Compares a set of Grammemes attached to wordforms + */ +export function matchWordForm(left: IWordForm, right: IWordForm): boolean { + if (left.grams.length !== right.grams.length) { + return false; + } + for (let index = 0; index < left.grams.length; ++index) { + if (left.grams[index] !== right.grams[index]) { + return false; + } + } + return true; +} + +function parseSingleGrammeme(text: string): GramData { + if (Object.values(Grammeme).includes(text as Grammeme)) { + return text as Grammeme; + } else { + return text; + } +} + +/** + * Compares {@link GramData} based on Grammeme enum and alpha order for strings. + */ +export function compareGrammemes(left: GramData, right: GramData): number { + const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left as Grammeme); + const indexRight = Object.values(Grammeme).findIndex(gram => gram === right as Grammeme); + if (indexLeft === -1 && indexRight === -1) { + return left.localeCompare(right); + } else if (indexLeft === -1 && indexRight !== -1) { + return 1; + } else if (indexLeft !== -1 && indexRight === -1) { + return -1; + } else { + return indexLeft - indexRight; + } +} + +/** + * Transforms {@link Grammeme} enumeration to {@link GramData}. + */ +export function parseGrammemes(termForm: string): GramData[] { + const result: GramData[] = []; + const chunks = termForm.split(','); + chunks.forEach(chunk => { + chunk = chunk.trim(); + if (chunk !== '') { + result.push(parseSingleGrammeme(chunk)); + } + }); + return result.sort(compareGrammemes); +} + +/** + * Creates a list of compatible {@link Grammeme}s. + */ +export function getCompatibleGrams(input: Grammeme[]): Grammeme[] { + let result: Grammeme[] = []; + input.forEach( + (gram) => { + if (!result.includes(gram)) { + if (NounGrams.includes(gram)) { + result.push(...NounGrams); + } + if (VerbGrams.includes(gram)) { + result.push(...VerbGrams); + } + } + }); + + input.forEach( + (gram) => GrammemeGroups.forEach( + (group) => { + if (group.includes(gram)) { + result = result.filter(item => !group.includes(item)); + } + })); + + if (result.length === 0) { + return [... new Set([...VerbGrams, ...NounGrams])]; + } else { + return result; + } +} + +/** + * Extracts {@link IEntityReference} from string representation. + * + * @param text - Reference text in a valid pattern. Must fit format '\@\{GLOBAL_ID|GRAMMEMES\}' + */ +export function parseEntityReference(text: string): IEntityReference { + const blocks = text.slice(2, text.length - 1).split('|'); + return { + entity: blocks[0].trim(), + form: blocks[1].trim() + } +} + +/** + * Extracts {@link ISyntacticReference} from string representation. + * + * @param text - Reference text in a valid pattern. Must fit format '\@\{OFFSET|NOMINAL_FORM\}' + */ +export function parseSyntacticReference(text: string): ISyntacticReference { + const blocks = text.slice(2, text.length - 1).split('|'); + return { + offset: Number(blocks[0].trim()), + nominal: blocks[1].trim() + } +} \ No newline at end of file diff --git a/rsconcept/frontend/src/utils/codemirror.ts b/rsconcept/frontend/src/utils/codemirror.ts index 637fc8dc..0d028d24 100644 --- a/rsconcept/frontend/src/utils/codemirror.ts +++ b/rsconcept/frontend/src/utils/codemirror.ts @@ -2,7 +2,8 @@ import { syntaxTree } from '@codemirror/language' import { NodeType, Tree, TreeCursor } from '@lezer/common' import { ReactCodeMirrorRef, SelectionRange } from '@uiw/react-codemirror' -import { IEntityReference, ISyntacticReference, parseGrammemes } from '../models/language' +import { IEntityReference, ISyntacticReference } from '../models/language' +import { parseGrammemes } from '../models/languageAPI' import { IConstituenta } from '../models/rsform' import { colorfgGrammeme,IColorTheme } from './color' import { describeConstituentaTerm, labelCstTypification, labelGrammeme } from './labels' diff --git a/rsconcept/frontend/src/utils/selectors.ts b/rsconcept/frontend/src/utils/selectors.ts index eed7803e..352ab492 100644 --- a/rsconcept/frontend/src/utils/selectors.ts +++ b/rsconcept/frontend/src/utils/selectors.ts @@ -1,7 +1,8 @@ // Module: Selector maps import { LayoutTypes } from 'reagraph'; -import { compareGrammemes,type GramData, Grammeme, ReferenceType } from '../models/language'; +import { type GramData, Grammeme, ReferenceType } from '../models/language'; +import { compareGrammemes } from '../models/languageAPI'; import { CstType } from '../models/rsform'; import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph'; import { labelGrammeme, labelReferenceType } from './labels';