R: Replace enums with const objects

This commit is contained in:
Ivan 2025-03-14 20:44:23 +03:00
parent 10905fa5a5
commit 43015fb193
34 changed files with 554 additions and 581 deletions

View File

@ -8,6 +8,33 @@ import importPlugin from 'eslint-plugin-import';
import simpleImportSort from 'eslint-plugin-simple-import-sort'; import simpleImportSort from 'eslint-plugin-simple-import-sort';
import playwright from 'eslint-plugin-playwright'; import playwright from 'eslint-plugin-playwright';
const basicRules = {
'no-console': 'off',
'require-jsdoc': 'off',
'@typescript-eslint/consistent-type-imports': [
'warn',
{
fixStyle: 'inline-type-imports'
}
],
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_'
}
],
'simple-import-sort/exports': 'error',
'import/no-duplicates': 'warn'
};
export default [ export default [
...typescriptPlugin.configs.recommendedTypeChecked, ...typescriptPlugin.configs.recommendedTypeChecked,
...typescriptPlugin.configs.stylisticTypeChecked, ...typescriptPlugin.configs.stylisticTypeChecked,
@ -45,33 +72,9 @@ export default [
}, },
settings: { react: { version: 'detect' } }, settings: { react: { version: 'detect' } },
rules: { rules: {
'no-console': 'off', ...basicRules,
'require-jsdoc': 'off',
'react-compiler/react-compiler': 'error', 'react-compiler/react-compiler': 'error',
'react-refresh/only-export-components': ['off', { allowConstantExport: true }], 'react-refresh/only-export-components': ['off', { allowConstantExport: true }],
'@typescript-eslint/consistent-type-imports': [
'warn',
{
fixStyle: 'inline-type-imports'
}
],
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_'
}
],
'simple-import-sort/exports': 'error',
'import/no-duplicates': 'warn',
'simple-import-sort/imports': [ 'simple-import-sort/imports': [
'warn', 'warn',
{ {
@ -113,13 +116,8 @@ export default [
}, },
rules: { rules: {
...basicRules,
...playwright.configs['flat/recommended'].rules, ...playwright.configs['flat/recommended'].rules,
'no-console': 'off',
'require-jsdoc': 'off',
'simple-import-sort/exports': 'error',
'import/no-duplicates': 'warn',
'simple-import-sort/imports': 'warn' 'simple-import-sort/imports': 'warn'
} }
} }

View File

@ -5,17 +5,19 @@ import { errorMsg } from '@/utils/labels';
import { validateLocation } from '../models/library-api'; import { validateLocation } from '../models/library-api';
/** Represents type of library items. */ /** Represents type of library items. */
export enum LibraryItemType { export const LibraryItemType = {
RSFORM = 'rsform', RSFORM: 'rsform',
OSS = 'oss' OSS: 'oss'
} } as const;
export type LibraryItemType = (typeof LibraryItemType)[keyof typeof LibraryItemType];
/** Represents Access policy for library items.*/ /** Represents Access policy for library items.*/
export enum AccessPolicy { export const AccessPolicy = {
PUBLIC = 'public', PUBLIC: 'public',
PROTECTED = 'protected', PROTECTED: 'protected',
PRIVATE = 'private' PRIVATE: 'private'
} } as const;
export type AccessPolicy = (typeof AccessPolicy)[keyof typeof AccessPolicy];
/** Represents library item common data typical for all item types. */ /** Represents library item common data typical for all item types. */
export type ILibraryItem = z.infer<typeof schemaLibraryItem>; export type ILibraryItem = z.infer<typeof schemaLibraryItem>;
@ -53,17 +55,19 @@ export type IVersionCreateDTO = z.infer<typeof schemaVersionCreate>;
export type IVersionUpdateDTO = z.infer<typeof schemaVersionUpdate>; export type IVersionUpdateDTO = z.infer<typeof schemaVersionUpdate>;
// ======= SCHEMAS ========= // ======= SCHEMAS =========
export const schemaLibraryItemType = z.enum(Object.values(LibraryItemType) as [LibraryItemType, ...LibraryItemType[]]);
export const schemaAccessPolicy = z.enum(Object.values(AccessPolicy) as [AccessPolicy, ...AccessPolicy[]]);
export const schemaLibraryItem = z.strictObject({ export const schemaLibraryItem = z.strictObject({
id: z.coerce.number(), id: z.coerce.number(),
item_type: z.nativeEnum(LibraryItemType), item_type: schemaLibraryItemType,
title: z.string(), title: z.string(),
alias: z.string().nonempty(), alias: z.string().nonempty(),
comment: z.string(), comment: z.string(),
visible: z.boolean(), visible: z.boolean(),
read_only: z.boolean(), read_only: z.boolean(),
location: z.string(), location: z.string(),
access_policy: z.nativeEnum(AccessPolicy), access_policy: schemaAccessPolicy,
time_create: z.string().datetime({ offset: true }), time_create: z.string().datetime({ offset: true }),
time_update: z.string().datetime({ offset: true }), time_update: z.string().datetime({ offset: true }),
@ -94,14 +98,14 @@ export const schemaCloneLibraryItem = schemaLibraryItem
export const schemaCreateLibraryItem = z export const schemaCreateLibraryItem = z
.object({ .object({
item_type: z.nativeEnum(LibraryItemType), item_type: schemaLibraryItemType,
title: z.string().optional(), title: z.string().optional(),
alias: z.string().optional(), alias: z.string().optional(),
comment: z.string(), comment: z.string(),
visible: z.boolean(), visible: z.boolean(),
read_only: z.boolean(), read_only: z.boolean(),
location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }), location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation }),
access_policy: z.nativeEnum(AccessPolicy), access_policy: schemaAccessPolicy,
file: z.instanceof(File).optional(), file: z.instanceof(File).optional(),
fileName: z.string().optional() fileName: z.string().optional()
@ -117,7 +121,7 @@ export const schemaCreateLibraryItem = z
export const schemaUpdateLibraryItem = z.strictObject({ export const schemaUpdateLibraryItem = z.strictObject({
id: z.number(), id: z.number(),
item_type: z.nativeEnum(LibraryItemType), item_type: schemaLibraryItemType,
title: z.string().nonempty(errorMsg.requiredField), title: z.string().nonempty(errorMsg.requiredField),
alias: z.string().nonempty(errorMsg.requiredField), alias: z.string().nonempty(errorMsg.requiredField),
comment: z.string(), comment: z.string(),

View File

@ -5,12 +5,13 @@
/** /**
* Represents valid location headers. * Represents valid location headers.
*/ */
export enum LocationHead { export const LocationHead = {
USER = '/U', USER: '/U',
COMMON = '/S', COMMON: '/S',
PROJECTS = '/P', PROJECTS: '/P',
LIBRARY = '/L' LIBRARY: '/L'
} } as const;
export type LocationHead = (typeof LocationHead)[keyof typeof LocationHead];
export const BASIC_SCHEMAS = '/L/Базовые'; export const BASIC_SCHEMAS = '/L/Базовые';

View File

@ -8,10 +8,11 @@ import { errorMsg } from '@/utils/labels';
/** /**
* Represents {@link IOperation} type. * Represents {@link IOperation} type.
*/ */
export enum OperationType { export const OperationType = {
INPUT = 'input', INPUT: 'input',
SYNTHESIS = 'synthesis' SYNTHESIS: 'synthesis'
} } as const;
export type OperationType = (typeof OperationType)[keyof typeof OperationType];
/** Represents {@link ICstSubstitute} extended data. */ /** Represents {@link ICstSubstitute} extended data. */
export type ICstSubstituteInfo = z.infer<typeof schemaCstSubstituteInfo>; export type ICstSubstituteInfo = z.infer<typeof schemaCstSubstituteInfo>;
@ -57,10 +58,11 @@ export type ICstRelocateDTO = z.infer<typeof schemaCstRelocate>;
export type IConstituentaReference = z.infer<typeof schemaConstituentaReference>; export type IConstituentaReference = z.infer<typeof schemaConstituentaReference>;
// ====== Schemas ====== // ====== Schemas ======
export const schemaOperationType = z.enum(Object.values(OperationType) as [OperationType, ...OperationType[]]);
export const schemaOperation = z.strictObject({ export const schemaOperation = z.strictObject({
id: z.number(), id: z.number(),
operation_type: z.nativeEnum(OperationType), operation_type: schemaOperationType,
oss: z.number(), oss: z.number(),
alias: z.string(), alias: z.string(),
@ -103,7 +105,7 @@ export const schemaOperationCreate = z.strictObject({
positions: z.array(schemaOperationPosition), positions: z.array(schemaOperationPosition),
item_data: z.strictObject({ item_data: z.strictObject({
alias: z.string().nonempty(), alias: z.string().nonempty(),
operation_type: z.nativeEnum(OperationType), operation_type: schemaOperationType,
title: z.string(), title: z.string(),
comment: z.string(), comment: z.string(),
position_x: z.number(), position_x: z.number(),

View File

@ -33,10 +33,11 @@ export interface DlgCreateOperationProps {
onCreate?: (newID: number) => void; onCreate?: (newID: number) => void;
} }
enum TabID { export const TabID = {
INPUT = 0, INPUT: 0,
SYNTHESIS = 1 SYNTHESIS: 1
} } as const;
export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgCreateOperation() { export function DlgCreateOperation() {
const { operationCreate } = useOperationCreate(); const { operationCreate } = useOperationCreate();
@ -101,7 +102,12 @@ export function DlgCreateOperation() {
className='w-160 px-6 h-128' className='w-160 px-6 h-128'
helpTopic={HelpTopic.CC_OSS} helpTopic={HelpTopic.CC_OSS}
> >
<Tabs selectedTabClassName='clr-selected' className='grid' selectedIndex={activeTab} onSelect={handleSelectTab}> <Tabs
selectedTabClassName='clr-selected'
className='grid'
selectedIndex={activeTab}
onSelect={(index, last) => handleSelectTab(index as TabID, last as TabID)}
>
<TabList className='z-pop mx-auto -mb-5 flex border divide-x rounded-none bg-prim-200'> <TabList className='z-pop mx-auto -mb-5 flex border divide-x rounded-none bg-prim-200'>
<TabLabel <TabLabel
title={describeOperationType(OperationType.INPUT)} title={describeOperationType(OperationType.INPUT)}

View File

@ -30,11 +30,12 @@ export interface DlgEditOperationProps {
positions: IOperationPosition[]; positions: IOperationPosition[];
} }
enum TabID { export const TabID = {
CARD = 0, CARD: 0,
ARGUMENTS = 1, ARGUMENTS: 1,
SUBSTITUTION = 2 SUBSTITUTION: 2
} } as const;
export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgEditOperation() { export function DlgEditOperation() {
const { oss, target, positions } = useDialogsStore(state => state.props as DlgEditOperationProps); const { oss, target, positions } = useDialogsStore(state => state.props as DlgEditOperationProps);
@ -58,7 +59,7 @@ export function DlgEditOperation() {
}, },
mode: 'onChange' mode: 'onChange'
}); });
const [activeTab, setActiveTab] = useState(TabID.CARD); const [activeTab, setActiveTab] = useState<TabID>(TabID.CARD);
function onSubmit(data: IOperationUpdateDTO) { function onSubmit(data: IOperationUpdateDTO) {
return operationUpdate({ itemID: oss.id, data }); return operationUpdate({ itemID: oss.id, data });
@ -74,7 +75,12 @@ export function DlgEditOperation() {
helpTopic={HelpTopic.UI_SUBSTITUTIONS} helpTopic={HelpTopic.UI_SUBSTITUTIONS}
hideHelpWhen={() => activeTab !== TabID.SUBSTITUTION} hideHelpWhen={() => activeTab !== TabID.SUBSTITUTION}
> >
<Tabs selectedTabClassName='clr-selected' className='grid' selectedIndex={activeTab} onSelect={setActiveTab}> <Tabs
selectedTabClassName='clr-selected'
className='grid'
selectedIndex={activeTab}
onSelect={index => setActiveTab(index as TabID)}
>
<TabList className='mb-3 mx-auto w-fit flex border divide-x rounded-none bg-prim-200'> <TabList className='mb-3 mx-auto w-fit flex border divide-x rounded-none bg-prim-200'>
<TabLabel title='Текстовые поля' label='Карточка' className='w-32' /> <TabLabel title='Текстовые поля' label='Карточка' className='w-32' />
{target.operation_type === OperationType.SYNTHESIS ? ( {target.operation_type === OperationType.SYNTHESIS ? (

View File

@ -6,9 +6,7 @@ import { type Graph } from '@/models/graph';
import { type ICstSubstituteInfo, type IOperationDTO, type IOperationSchemaDTO } from '../backend/types'; import { type ICstSubstituteInfo, type IOperationDTO, type IOperationSchemaDTO } from '../backend/types';
/** /** Represents Operation. */
* Represents Operation.
*/
export interface IOperation extends IOperationDTO { export interface IOperation extends IOperationDTO {
is_owned: boolean; is_owned: boolean;
is_consolidation: boolean; // aka 'diamond synthesis' is_consolidation: boolean; // aka 'diamond synthesis'
@ -16,9 +14,7 @@ export interface IOperation extends IOperationDTO {
arguments: number[]; arguments: number[];
} }
/** /** Represents {@link IOperationSchema} statistics. */
* Represents {@link IOperationSchema} statistics.
*/
export interface IOperationSchemaStats { export interface IOperationSchemaStats {
count_operations: number; count_operations: number;
count_inputs: number; count_inputs: number;
@ -27,9 +23,7 @@ export interface IOperationSchemaStats {
count_owned: number; count_owned: number;
} }
/** /** Represents OperationSchema. */
* Represents OperationSchema.
*/
export interface IOperationSchema extends IOperationSchemaDTO { export interface IOperationSchema extends IOperationSchemaDTO {
items: IOperation[]; items: IOperation[];
@ -39,27 +33,25 @@ export interface IOperationSchema extends IOperationSchemaDTO {
operationByID: Map<number, IOperation>; operationByID: Map<number, IOperation>;
} }
/** /** Represents substitution error description. */
* Represents substitution error description.
*/
export interface ISubstitutionErrorDescription { export interface ISubstitutionErrorDescription {
errorType: SubstitutionErrorType; errorType: SubstitutionErrorType;
params: string[]; params: string[];
} }
/** /** Represents Substitution table error types. */
* Represents Substitution table error types. export const SubstitutionErrorType = {
*/ invalidIDs: 0,
export enum SubstitutionErrorType { incorrectCst: 1,
invalidIDs, invalidClasses: 2,
incorrectCst, invalidBasic: 3,
invalidClasses, invalidConstant: 4,
invalidBasic, typificationCycle: 5,
invalidConstant, baseSubstitutionNotSet: 6,
typificationCycle, unequalTypification: 7,
baseSubstitutionNotSet, unequalExpressions: 8,
unequalTypification, unequalArgsCount: 9,
unequalExpressions, unequalArgs: 10
unequalArgsCount, } as const;
unequalArgs
} export type SubstitutionErrorType = (typeof SubstitutionErrorType)[keyof typeof SubstitutionErrorType];

View File

@ -16,10 +16,11 @@ import { OperationType } from '../../backend/types';
import { useOssSuspense } from '../../backend/use-oss'; import { useOssSuspense } from '../../backend/use-oss';
import { type IOperation, type IOperationSchema } from '../../models/oss'; import { type IOperation, type IOperationSchema } from '../../models/oss';
export enum OssTabID { export const OssTabID = {
CARD = 0, CARD: 0,
GRAPH = 1 GRAPH: 1
} } as const;
export type OssTabID = (typeof OssTabID)[keyof typeof OssTabID];
export interface IOssEditContext { export interface IOssEditContext {
schema: IOperationSchema; schema: IOperationSchema;

View File

@ -50,7 +50,7 @@ export function OssTabs({ activeTab }: OssTabsProps) {
} }
} }
} }
navigateTab(index); navigateTab(index as OssTabID);
} }
return ( return (

View File

@ -5,37 +5,41 @@ import { schemaLibraryItem, schemaVersionInfo } from '@/features/library/backend
import { errorMsg } from '@/utils/labels'; import { errorMsg } from '@/utils/labels';
/** Represents {@link IConstituenta} type. */ /** Represents {@link IConstituenta} type. */
export enum CstType { export const CstType = {
BASE = 'basic', BASE: 'basic',
STRUCTURED = 'structure', STRUCTURED: 'structure',
TERM = 'term', TERM: 'term',
AXIOM = 'axiom', AXIOM: 'axiom',
FUNCTION = 'function', FUNCTION: 'function',
PREDICATE = 'predicate', PREDICATE: 'predicate',
CONSTANT = 'constant', CONSTANT: 'constant',
THEOREM = 'theorem' THEOREM: 'theorem'
} } as const;
export type CstType = (typeof CstType)[keyof typeof CstType];
/** Represents syntax type. */ /** Represents syntax type. */
export enum Syntax { export const Syntax = {
UNDEF = 'undefined', UNDEF: 'undefined',
ASCII = 'ascii', ASCII: 'ascii',
MATH = 'math' MATH: 'math'
} } as const;
export type Syntax = (typeof Syntax)[keyof typeof Syntax];
/** Represents computability class. */ /** Represents computability class. */
export enum ValueClass { export const ValueClass = {
INVALID = 'invalid', // incalculable INVALID: 'invalid', // incalculable
VALUE = 'value', VALUE: 'value',
PROPERTY = 'property' PROPERTY: 'property'
} } as const;
export type ValueClass = (typeof ValueClass)[keyof typeof ValueClass];
/** Represents parsing status. */ /** Represents parsing status. */
export enum ParsingStatus { export const ParsingStatus = {
UNDEF = 'undefined', UNDEF: 'undefined',
VERIFIED = 'verified', VERIFIED: 'verified',
INCORRECT = 'incorrect' INCORRECT: 'incorrect'
} } as const;
export type ParsingStatus = (typeof ParsingStatus)[keyof typeof ParsingStatus];
/** Represents Constituenta basic persistent data. */ /** Represents Constituenta basic persistent data. */
export type IConstituentaBasicsDTO = z.infer<typeof schemaConstituentaBasics>; export type IConstituentaBasicsDTO = z.infer<typeof schemaConstituentaBasics>;
@ -108,169 +112,178 @@ export type IExpressionParseDTO = z.infer<typeof schemaExpressionParse>;
export type IVersionCreatedResponse = z.infer<typeof schemaVersionCreatedResponse>; export type IVersionCreatedResponse = z.infer<typeof schemaVersionCreatedResponse>;
/** Represents RSLang token types. */ /** Represents RSLang token types. */
export enum TokenID { export const TokenID = {
// Global, local IDs and literals // Global, local IDs and literals
ID_LOCAL = 258, ID_LOCAL: 258,
ID_GLOBAL, ID_GLOBAL: 259,
ID_FUNCTION, ID_FUNCTION: 260,
ID_PREDICATE, ID_PREDICATE: 261,
ID_RADICAL, ID_RADICAL: 262,
LIT_INTEGER, LIT_INTEGER: 263,
LIT_WHOLE_NUMBERS, LIT_WHOLE_NUMBERS: 264,
LIT_EMPTYSET, LIT_EMPTYSET: 265,
// Arithmetic // Arithmetic
PLUS, PLUS: 266,
MINUS, MINUS: 267,
MULTIPLY, MULTIPLY: 268,
// Integer predicate symbols // Integer predicate symbols
GREATER, GREATER: 269,
LESSER, LESSER: 270,
GREATER_OR_EQ, GREATER_OR_EQ: 271,
LESSER_OR_EQ, LESSER_OR_EQ: 272,
// Equality comparison // Equality comparison
EQUAL, EQUAL: 273,
NOTEQUAL, NOTEQUAL: 274,
// Logic predicate symbols // Logic predicate symbols
QUANTOR_UNIVERSAL, QUANTOR_UNIVERSAL: 275,
QUANTOR_EXISTS, QUANTOR_EXISTS: 276,
LOGIC_NOT, LOGIC_NOT: 277,
LOGIC_EQUIVALENT, LOGIC_EQUIVALENT: 278,
LOGIC_IMPLICATION, LOGIC_IMPLICATION: 279,
LOGIC_OR, LOGIC_OR: 280,
LOGIC_AND, LOGIC_AND: 281,
// Set theory predicate symbols // Set theory predicate symbols
SET_IN, SET_IN: 282,
SET_NOT_IN, SET_NOT_IN: 283,
SUBSET, SUBSET: 284,
SUBSET_OR_EQ, SUBSET_OR_EQ: 285,
NOT_SUBSET, NOT_SUBSET: 286,
// Set theory operators // Set theory operators
DECART, DECART: 287,
SET_UNION, SET_UNION: 288,
SET_INTERSECTION, SET_INTERSECTION: 289,
SET_MINUS, SET_MINUS: 290,
SET_SYMMETRIC_MINUS, SET_SYMMETRIC_MINUS: 291,
BOOLEAN, BOOLEAN: 292,
// Structure operations // Structure operations
BIGPR, BIGPR: 293,
SMALLPR, SMALLPR: 294,
FILTER, FILTER: 295,
CARD, CARD: 296,
BOOL, BOOL: 297,
DEBOOL, DEBOOL: 298,
REDUCE, REDUCE: 299,
// Term constructions prefixes // Term constructions prefixes
DECLARATIVE, DECLARATIVE: 300,
RECURSIVE, RECURSIVE: 301,
IMPERATIVE, IMPERATIVE: 302,
ITERATE, ITERATE: 303,
ASSIGN, ASSIGN: 304,
// Punctuation // Punctuation
PUNCTUATION_DEFINE, PUNCTUATION_DEFINE: 305,
PUNCTUATION_STRUCT, PUNCTUATION_STRUCT: 306,
PUNCTUATION_PL, PUNCTUATION_PL: 307,
PUNCTUATION_PR, PUNCTUATION_PR: 308,
PUNCTUATION_CL, PUNCTUATION_CL: 309,
PUNCTUATION_CR, PUNCTUATION_CR: 310,
PUNCTUATION_SL, PUNCTUATION_SL: 311,
PUNCTUATION_SR, PUNCTUATION_SR: 312,
PUNCTUATION_BAR, PUNCTUATION_BAR: 313,
PUNCTUATION_COMMA, PUNCTUATION_COMMA: 314,
PUNCTUATION_SEMICOLON, PUNCTUATION_SEMICOLON: 315,
// ======= Non-terminal tokens ========= // ======= Non-terminal tokens =========
NT_ENUM_DECL, NT_ENUM_DECL: 316,
NT_TUPLE, NT_TUPLE: 317,
NT_ENUMERATION, NT_ENUMERATION: 318,
NT_TUPLE_DECL, NT_TUPLE_DECL: 319,
NT_ARG_DECL, NT_ARG_DECL: 320,
NT_FUNC_DEFINITION, NT_FUNC_DEFINITION: 321,
NT_ARGUMENTS, NT_ARGUMENTS: 322,
NT_FUNC_CALL, NT_FUNC_CALL: 323,
NT_DECLARATIVE_EXPR, NT_DECLARATIVE_EXPR: 324,
NT_IMPERATIVE_EXPR, NT_IMPERATIVE_EXPR: 325,
NT_RECURSIVE_FULL, NT_RECURSIVE_FULL: 326,
NT_RECURSIVE_SHORT, NT_RECURSIVE_SHORT: 327,
// ======= Helper tokens ======== // ======= Helper tokens ========
INTERRUPT, INTERRUPT: 328,
END END: 329
} } as const;
export type TokenID = (typeof TokenID)[keyof typeof TokenID];
/** Represents RSLang expression error types. */ /** Represents RSLang expression error types. */
export enum RSErrorType { export const RSErrorType = {
unknownSymbol = 33283, unknownSymbol: 33283,
syntax = 33792, syntax: 33792,
missingParenthesis = 33798, missingParenthesis: 33798,
missingCurlyBrace = 33799, missingCurlyBrace: 33799,
invalidQuantifier = 33800, invalidQuantifier: 33800,
invalidImperative = 33801, invalidImperative: 33801,
expectedArgDeclaration = 33812, expectedArgDeclaration: 33812,
expectedLocal = 33813, expectedLocal: 33813,
localDoubleDeclare = 10241, localDoubleDeclare: 10241,
localNotUsed = 10242, localNotUsed: 10242,
localUndeclared = 34817, localUndeclared: 34817,
localShadowing = 34818, localShadowing: 34818,
typesNotEqual = 34819, typesNotEqual: 34819,
globalNotTyped = 34820, globalNotTyped: 34820,
invalidDecart = 34821, invalidDecart: 34821,
invalidBoolean = 34822, invalidBoolean: 34822,
invalidTypeOperation = 34823, invalidTypeOperation: 34823,
invalidCard = 34824, invalidCard: 34824,
invalidDebool = 34825, invalidDebool: 34825,
globalFuncMissing = 34826, globalFuncMissing: 34826,
globalFuncWithoutArgs = 34827, globalFuncWithoutArgs: 34827,
invalidReduce = 34832, invalidReduce: 34832,
invalidProjectionTuple = 34833, invalidProjectionTuple: 34833,
invalidProjectionSet = 34834, invalidProjectionSet: 34834,
invalidEnumeration = 34835, invalidEnumeration: 34835,
invalidBinding = 34836, invalidBinding: 34836,
localOutOfScope = 34837, localOutOfScope: 34837,
invalidElementPredicate = 34838, invalidElementPredicate: 34838,
invalidEmptySetUsage = 34839, invalidEmptySetUsage: 34839,
invalidArgsArity = 34840, invalidArgsArity: 34840,
invalidArgumentType = 34841, invalidArgumentType: 34841,
globalStructure = 34844, globalStructure: 34844,
radicalUsage = 34849, radicalUsage: 34849,
invalidFilterArgumentType = 34850, invalidFilterArgumentType: 34850,
invalidFilterArity = 34851, invalidFilterArity: 34851,
arithmeticNotSupported = 34852, arithmeticNotSupported: 34852,
typesNotCompatible = 34853, typesNotCompatible: 34853,
orderingNotSupported = 34854, orderingNotSupported: 34854,
globalNoValue = 34880, globalNoValue: 34880,
invalidPropertyUsage = 34881, invalidPropertyUsage: 34881,
globalMissingAST = 34882, globalMissingAST: 34882,
globalFuncNoInterpretation = 34883, globalFuncNoInterpretation: 34883,
cstNonemptyBase = 34912, cstNonemptyBase: 34912,
cstEmptyDerived = 34913, cstEmptyDerived: 34913,
cstCallableNoArgs = 34914, cstCallableNoArgs: 34914,
cstNonCallableHasArgs = 34915, cstNonCallableHasArgs: 34915,
cstExpectedLogical = 34916, cstExpectedLogical: 34916,
cstExpectedTyped = 34917 cstExpectedTyped: 34917
} } as const;
export type RSErrorType = (typeof RSErrorType)[keyof typeof RSErrorType];
// ========= SCHEMAS ======== // ========= SCHEMAS ========
export const schemaCstType = z.enum(Object.values(CstType) as [CstType, ...CstType[]]);
export const schemaSyntax = z.enum(Object.values(Syntax) as [Syntax, ...Syntax[]]);
export const schemaValueClass = z.enum(Object.values(ValueClass) as [ValueClass, ...ValueClass[]]);
export const schemaParsingStatus = z.enum(Object.values(ParsingStatus) as [ParsingStatus, ...ParsingStatus[]]);
export const schemaTokenID = z.nativeEnum(TokenID);
export const schemaRSErrorType = z.nativeEnum(RSErrorType);
export const schemaConstituentaBasics = z.strictObject({ export const schemaConstituentaBasics = z.strictObject({
id: z.coerce.number(), id: z.coerce.number(),
alias: z.string().nonempty(errorMsg.requiredField), alias: z.string().nonempty(errorMsg.requiredField),
convention: z.string(), convention: z.string(),
cst_type: z.nativeEnum(CstType), cst_type: schemaCstType,
definition_formal: z.string(), definition_formal: z.string(),
definition_raw: z.string(), definition_raw: z.string(),
definition_resolved: z.string(), definition_resolved: z.string(),
@ -281,8 +294,8 @@ export const schemaConstituentaBasics = z.strictObject({
export const schemaConstituenta = schemaConstituentaBasics.extend({ export const schemaConstituenta = schemaConstituentaBasics.extend({
parse: z.strictObject({ parse: z.strictObject({
status: z.nativeEnum(ParsingStatus), status: schemaParsingStatus,
valueClass: z.nativeEnum(ValueClass), valueClass: schemaValueClass,
typification: z.string(), typification: z.string(),
syntaxTree: z.string(), syntaxTree: z.string(),
args: z.array(z.strictObject({ alias: z.string(), typification: z.string() })) args: z.array(z.strictObject({ alias: z.string(), typification: z.string() }))
@ -345,7 +358,7 @@ export const schemaCstUpdate = z.strictObject({
export const schemaCstRename = z.strictObject({ export const schemaCstRename = z.strictObject({
target: z.number(), target: z.number(),
alias: z.string(), alias: z.string(),
cst_type: z.nativeEnum(CstType) cst_type: schemaCstType
}); });
export const schemaProduceStructureResponse = z.strictObject({ export const schemaProduceStructureResponse = z.strictObject({
@ -370,7 +383,7 @@ export const schemaInlineSynthesis = z.strictObject({
}); });
export const schemaRSErrorDescription = z.strictObject({ export const schemaRSErrorDescription = z.strictObject({
errorType: z.nativeEnum(RSErrorType), errorType: schemaRSErrorType,
position: z.number(), position: z.number(),
isCritical: z.boolean(), isCritical: z.boolean(),
params: z.array(z.string()) params: z.array(z.string())
@ -379,16 +392,16 @@ export const schemaRSErrorDescription = z.strictObject({
export const schemaExpressionParse = z.strictObject({ export const schemaExpressionParse = z.strictObject({
parseResult: z.boolean(), parseResult: z.boolean(),
prefixLen: z.number(), prefixLen: z.number(),
syntax: z.nativeEnum(Syntax), syntax: schemaSyntax,
typification: z.string(), typification: z.string(),
valueClass: z.nativeEnum(ValueClass), valueClass: schemaValueClass,
errors: z.array(schemaRSErrorDescription), errors: z.array(schemaRSErrorDescription),
astText: z.string(), astText: z.string(),
ast: z.array( ast: z.array(
z.strictObject({ z.strictObject({
uid: z.number(), uid: z.number(),
parent: z.number(), parent: z.number(),
typeID: z.nativeEnum(TokenID), typeID: schemaTokenID,
start: z.number(), start: z.number(),
finish: z.number(), finish: z.number(),
data: z.strictObject({ dataType: z.string(), value: z.unknown().refine(value => value !== undefined) }) data: z.strictObject({ dataType: z.string(), value: z.unknown().refine(value => value !== undefined) })

View File

@ -2,15 +2,13 @@ import { APP_COLORS } from '@/styling/colors';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
import { TokenID } from './backend/types'; import { TokenID } from './backend/types';
import { type GramData, Grammeme, NounGrams, PartOfSpeech, VerbGrams } from './models/language'; import { Grammeme, NounGrams, PartOfSpeech, VerbGrams } from './models/language';
import { CstClass, ExpressionStatus, type IConstituenta } from './models/rsform'; import { CstClass, ExpressionStatus, type IConstituenta } from './models/rsform';
import { type ISyntaxTreeNode } from './models/rslang'; import { type ISyntaxTreeNode } from './models/rslang';
import { type TypificationGraphNode } from './models/typification-graph'; import { type TypificationGraphNode } from './models/typification-graph';
import { type GraphColoring } from './stores/term-graph'; import { type GraphColoring } from './stores/term-graph';
/** /** Represents Brackets highlights theme. */
* Represents Brackets highlights theme.
*/
export const BRACKETS_THEME = { export const BRACKETS_THEME = {
'.cc-nonmatchingBracket': { '.cc-nonmatchingBracket': {
color: APP_COLORS.fgRed, color: APP_COLORS.fgRed,
@ -22,9 +20,7 @@ export const BRACKETS_THEME = {
} }
}; };
/** /** Determines background color for {@link ISyntaxTreeNode} based on its type. */
* Determines background color for {@link ISyntaxTreeNode} based on its type.
*/
export function colorBgSyntaxTree(node: ISyntaxTreeNode): string { export function colorBgSyntaxTree(node: ISyntaxTreeNode): string {
switch (node.typeID) { switch (node.typeID) {
case TokenID.PUNCTUATION_DEFINE: case TokenID.PUNCTUATION_DEFINE:
@ -158,9 +154,7 @@ export function colorBgSyntaxTree(node: ISyntaxTreeNode): string {
return APP_COLORS.bgPurple; return APP_COLORS.bgPurple;
} }
/** /** Determines background color for {@link ExpressionStatus}. */
* Determines background color for {@link ExpressionStatus}.
*/
export function colorBgCstStatus(status: ExpressionStatus): string { export function colorBgCstStatus(status: ExpressionStatus): string {
// prettier-ignore // prettier-ignore
switch (status) { switch (status) {
@ -173,9 +167,7 @@ export function colorBgCstStatus(status: ExpressionStatus): string {
} }
} }
/** /** Determines statusbar color for {@link ExpressionStatus}. */
* Determines statusbar color for {@link ExpressionStatus}.
*/
export function colorStatusBar(status: ExpressionStatus): string { export function colorStatusBar(status: ExpressionStatus): string {
// prettier-ignore // prettier-ignore
switch (status) { switch (status) {
@ -188,9 +180,7 @@ export function colorStatusBar(status: ExpressionStatus): string {
} }
} }
/** /** Determines foreground color for {@link ExpressionStatus}. */
* Determines foreground color for {@link ExpressionStatus}.
*/
export function colorFgCstStatus(status: ExpressionStatus): string { export function colorFgCstStatus(status: ExpressionStatus): string {
// prettier-ignore // prettier-ignore
switch (status) { switch (status) {
@ -203,9 +193,7 @@ export function colorFgCstStatus(status: ExpressionStatus): string {
} }
} }
/** /** Determines background color for {@link IConstituenta} depending on its {@link CstClass}. */
* Determines background color for {@link IConstituenta} depending on its {@link CstClass}.
*/
export function colorBgCstClass(cstClass: CstClass): string { export function colorBgCstClass(cstClass: CstClass): string {
// prettier-ignore // prettier-ignore
switch (cstClass) { switch (cstClass) {
@ -216,9 +204,7 @@ export function colorBgCstClass(cstClass: CstClass): string {
} }
} }
/** /** Determines background color for {@link IConstituenta} depending on its parent schema index. */
* Determines background color for {@link IConstituenta} depending on its parent schema index.
*/
export function colorBgSchemas(schema_index: number): string { export function colorBgSchemas(schema_index: number): string {
if (schema_index === 0) { if (schema_index === 0) {
return APP_COLORS.bgGreen; return APP_COLORS.bgGreen;
@ -233,29 +219,25 @@ export function colorBgSchemas(schema_index: number): string {
return APP_COLORS.bgBlue; return APP_COLORS.bgBlue;
} }
/** /** Determines foreground color for {@link Grammeme}. */
* Determines foreground color for {@link GramData}. export function colorFgGrammeme(gram: Grammeme): string {
*/ if (PartOfSpeech.includes(gram)) {
export function colorFgGrammeme(gram: GramData): string {
if (PartOfSpeech.includes(gram as Grammeme)) {
return APP_COLORS.fgBlue; return APP_COLORS.fgBlue;
} }
if (NounGrams.includes(gram as Grammeme)) { if (NounGrams.includes(gram)) {
return APP_COLORS.fgGreen; return APP_COLORS.fgGreen;
} }
if (VerbGrams.includes(gram as Grammeme)) { if (VerbGrams.includes(gram)) {
return APP_COLORS.fgTeal; return APP_COLORS.fgTeal;
} }
if (!Object.values(Grammeme).includes(gram as Grammeme)) { if (!Object.values(Grammeme).includes(gram)) {
return APP_COLORS.fgRed; return APP_COLORS.fgRed;
} else { } else {
return APP_COLORS.fgPurple; return APP_COLORS.fgPurple;
} }
} }
/** /** Determines graph color for {@link IConstituenta}. */
* Determines graph color for {@link IConstituenta}.
*/
export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColoring): string { export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColoring): string {
if (coloringScheme === 'type') { if (coloringScheme === 'type') {
return colorBgCstClass(cst.cst_class); return colorBgCstClass(cst.cst_class);
@ -269,9 +251,7 @@ export function colorBgGraphNode(cst: IConstituenta, coloringScheme: GraphColori
return APP_COLORS.bgGreen50; return APP_COLORS.bgGreen50;
} }
/** /** Determines m-graph color for {@link TypificationGraphNode}. */
* Determines m-graph color for {@link TypificationGraphNode}.
*/
export function colorBgTMGraphNode(node: TypificationGraphNode): string { export function colorBgTMGraphNode(node: TypificationGraphNode): string {
if (node.rank === 0) { if (node.rank === 0) {
return APP_COLORS.bgControls; return APP_COLORS.bgControls;

View File

@ -1,10 +1,10 @@
import { colorFgGrammeme } from '../colors'; import { colorFgGrammeme } from '../colors';
import { labelGrammeme } from '../labels'; import { labelGrammeme } from '../labels';
import { type GramData } from '../models/language'; import { type Grammeme } from '../models/language';
interface BadgeGrammemeProps { interface BadgeGrammemeProps {
/** Grammeme to display. */ /** Grammeme to display. */
grammeme: GramData; grammeme: Grammeme;
} }
/** /**

View File

@ -1,18 +1,20 @@
// This file was generated by lezer-generator. You probably shouldn't edit it. // This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr" import { LRParser } from '@lezer/lr';
import {highlighting} from "./highlight" import { highlighting } from './highlight';
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "$nQVQPOOObQQO'#C^OOQO'#Cl'#ClOjQPO'#CuOxQPO'#CdOOQO'#Ce'#CeOOQO'#Ck'#CkOOQO'#Cf'#CfQVQPOOO}QPO,58xO!SQPO,58{OOQO,59a,59aO!XQPO,59OOOQO-E6d-E6dO!^QSO1G.dO!cQPO1G.gOOQO1G.j1G.jO!hQQO'#CpOOQO'#C`'#C`O!pQPO7+$OOOQO'#Cg'#CgO!uQPO'#CcO!}QPO7+$RO!^QSO,59[OOQO<<Gj<<GjOOQO-E6e-E6eOOQO<<Gm<<GmOOQO1G.v1G.v", states:
stateData: "#V~O^OS~ObPOgROhSO~ORXOUYO~OgRO[iXbiXhiX~OgRO~Oc^O~Oc_O~Oh`O~OeaO~OgdO~OfgOadX~OahO~OgdOaVX~OajO~Og^~", "$nQVQPOOObQQO'#C^OOQO'#Cl'#ClOjQPO'#CuOxQPO'#CdOOQO'#Ce'#CeOOQO'#Ck'#CkOOQO'#Cf'#CfQVQPOOO}QPO,58xO!SQPO,58{OOQO,59a,59aO!XQPO,59OOOQO-E6d-E6dO!^QSO1G.dO!cQPO1G.gOOQO1G.j1G.jO!hQQO'#CpOOQO'#C`'#C`O!pQPO7+$OOOQO'#Cg'#CgO!uQPO'#CcO!}QPO7+$RO!^QSO,59[OOQO<<Gj<<GjOOQO-E6e-E6eOOQO<<Gm<<GmOOQO1G.v1G.v",
goto: "!kjPPkPokPruuy!PPPP!VuPPP!ZPPPP!aTQOWRc^Rf_TUOWQWOR]WQe_RieTVOWQb^RkgSTOWQZRR[S", stateData: '#V~O^OS~ObPOgROhSO~ORXOUYO~OgRO[iXbiXhiX~OgRO~Oc^O~Oc_O~Oh`O~OeaO~OgdO~OfgOadX~OahO~OgdOaVX~OajO~Og^~',
nodeNames: "⚠ Text RefEntity Global Grams RefSyntactic Offset Nominal Error Filler", goto: '!kjPPkPokPruuy!PPPP!VuPPP!ZPPPP!aTQOWRc^Rf_TUOWQWOR]WQe_RieTVOWQb^RkgSTOWQZRR[S',
nodeNames: '⚠ Text RefEntity Global Grams RefSyntactic Offset Nominal Error Filler',
maxTerm: 25, maxTerm: 25,
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0], skippedNodes: [0],
repeatNodeCount: 2, repeatNodeCount: 2,
tokenData: ".V~R!UOX$eXZ%VZ^%z^p$epq%Vqr'sr|$e|}'x}!O(f!O!Q$e!Q!R)i!R![*i![!b$e!b!c+k!c!d+v!d!e)i!e!f+v!f!g+v!g!h)i!h!i+v!i!r)i!r!s+v!s!t)i!t!u+v!u!v+v!v!w+v!w!z)i!z!{+v!{!})i!}#T$e#T#o)i#p#q-{#q#r.Q#r#y$e#y#z%z#z$f$e$f$g%z$g#BY$e#BY#BZ%z#BZ$IS$e$IS$I_%z$I_$I|$e$I|$JO%z$JO$JT$e$JT$JU%z$JU$KV$e$KV$KW%z$KW&FU$e&FU&FV%z&FV;'S$e;'S;=`%P<%lO$eP$jVgPOX$eZp$er!b$e!c#o$e#r;'S$e;'S;=`%P<%lO$eP%SP;=`<%l$e~%[Y^~X^%Vpq%V#y#z%V$f$g%V#BY#BZ%V$IS$I_%V$I|$JO%V$JT$JU%V$KV$KW%V&FU&FV%V~&RjgP^~OX$eXZ%VZ^%z^p$epq%Vr!b$e!c#o$e#r#y$e#y#z%z#z$f$e$f$g%z$g#BY$e#BY#BZ%z#BZ$IS$e$IS$I_%z$I_$I|$e$I|$JO%z$JO$JT$e$JT$JU%z$JU$KV$e$KV$KW%z$KW&FU$e&FU&FV%z&FV;'S$e;'S;=`%P<%lO$e~'xOh~R(PVfQgPOX$eZp$er!b$e!c#o$e#r;'S$e;'S;=`%P<%lO$eV(m^eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q!R)i!R![*i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eT)p]eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![)i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eV*r]UQeSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![*i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$e~+nP#o#p+q~+vOb~V+}^eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q!R)i!R![,y![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eV-S]RQeSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![,y![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$e~.QOc~~.VOa~", tokenData:
".V~R!UOX$eXZ%VZ^%z^p$epq%Vqr'sr|$e|}'x}!O(f!O!Q$e!Q!R)i!R![*i![!b$e!b!c+k!c!d+v!d!e)i!e!f+v!f!g+v!g!h)i!h!i+v!i!r)i!r!s+v!s!t)i!t!u+v!u!v+v!v!w+v!w!z)i!z!{+v!{!})i!}#T$e#T#o)i#p#q-{#q#r.Q#r#y$e#y#z%z#z$f$e$f$g%z$g#BY$e#BY#BZ%z#BZ$IS$e$IS$I_%z$I_$I|$e$I|$JO%z$JO$JT$e$JT$JU%z$JU$KV$e$KV$KW%z$KW&FU$e&FU&FV%z&FV;'S$e;'S;=`%P<%lO$eP$jVgPOX$eZp$er!b$e!c#o$e#r;'S$e;'S;=`%P<%lO$eP%SP;=`<%l$e~%[Y^~X^%Vpq%V#y#z%V$f$g%V#BY#BZ%V$IS$I_%V$I|$JO%V$JT$JU%V$KV$KW%V&FU&FV%V~&RjgP^~OX$eXZ%VZ^%z^p$epq%Vr!b$e!c#o$e#r#y$e#y#z%z#z$f$e$f$g%z$g#BY$e#BY#BZ%z#BZ$IS$e$IS$I_%z$I_$I|$e$I|$JO%z$JO$JT$e$JT$JU%z$JU$KV$e$KV$KW%z$KW&FU$e&FU&FV%z&FV;'S$e;'S;=`%P<%lO$e~'xOh~R(PVfQgPOX$eZp$er!b$e!c#o$e#r;'S$e;'S;=`%P<%lO$eV(m^eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q!R)i!R![*i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eT)p]eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![)i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eV*r]UQeSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![*i![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$e~+nP#o#p+q~+vOb~V+}^eSgPOX$eZp$er}$e}!O)i!O!Q$e!Q!R)i!R![,y![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$eV-S]RQeSgPOX$eZp$er}$e}!O)i!O!Q$e!Q![,y![!b$e!c!})i!}#T$e#T#o)i#r;'S$e;'S;=`%P<%lO$e~.QOc~~.VOa~",
tokenizers: [0, 1, 2], tokenizers: [0, 1, 2],
topRules: {"Text":[0,1]}, topRules: { Text: [0, 1] },
tokenPrec: 96 tokenPrec: 96
}) });

View File

@ -1,18 +1,22 @@
// This file was generated by lezer-generator. You probably shouldn't edit it. // This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr" import { LRParser } from '@lezer/lr';
import {highlighting} from "./highlight" import { highlighting } from './highlight';
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "3UO!sQPOOOOQO'#C`'#C`O#lQPO'#DoOOQO'#Do'#DoO%yQPO'#DdOVQPO'#DpO'_QPO'#DrO'fQPO'#DsO'nQQO'#DtO'sQPO'#DuO'xQPO'#DvO'}QPO'#DxOOQO'#Dq'#DqO(SQPO'#DqO)pQQO'#C{OOQO'#C{'#C{OOQO'#Dk'#DkO)uQPO'#DkO)zQPO'#DkO*PQPO'#DfOVQPO'#EQO*XQPO'#EQO*^QPO'#EQO*fQPO'#DdOOQO'#De'#DeO*wQPO'#ETQOQPOOO*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:QO+TQPO'#DjO+[QPO,5:[O,oQPO,5:SO,wQPO'#DiO,|QPO,5:PO-_QPO,5:aO.QQPO'#DjO*|QPO'#DpO._QPO,5:^OOQO'#Dj'#DjO*|QPO,5:_OOQO,5:_,5:_O.gQPO,5:`O*^QPO,5:aO*|QPO,5:bO*^QPO,5:dOOQO,59g,59gO*|QPO,5:VO*|QPO,5:VO$lQPO'#DfOOQO,5:l,5:lO*|QPO,5:lO*|QPO'#DhOOQO'#Dg'#DgOOQO'#ER'#ERO.lQPO,5:lOVQPO,5:nOVQPO,5:nOVQPO,5:nOVQPO,5:nO.tQPO'#EVOOQO'#EU'#EUO.yQPO,5:oOOQO1G/v1G/vO2jQPO1G/vO2qQPO1G/vO6aQPO1G/vO:PQPO1G/vO:WQPO1G/vO:_QPO1G/vO:fQPO1G/vO>QQPO1G/lOOQO1G/n1G/nO*|QPO,5:TOOQO1G/k1G/kO*|QPO1G/{OOQO1G/x1G/xO>qQPO1G/yO*|QPO1G/zO>xQPO1G/{O>}QPO1G/|O?UQPO1G0OO?ZQPO1G/qO?cQPO1G/qO?jQPO1G0WO*^QPO,5:mO*|QPO1G0WOOQO1G0Y1G0YO@^QPO1G0YO@eQPO1G0YO@lQPO1G0YO*|QPO,5:qO*wQPO,5:pOVQPO1G0ZOAZQPO1G/oOAkQPO7+%gOOQO7+%e7+%eOArQPO7+%fO*|QPO7+%gOVQPO7+%hO*|QPO7+%jOOQO7+%]7+%]OOQO7+%r7+%rOOQO1G0X1G0XOAzQPO7+%rOBhQPO1G0]OOQO1G0[1G0[OOQO7+%u7+%uOVQPO<<IROBrQPO<<IQOBwQPO<<IROCOQPO'#DwOCdQPO<<ISOClQPO<<IUOCsQPO<<I^ODbQPOAN>mO*|QPOAN>lOVQPOAN>mOVQPO,5:cOOQOAN>nAN>nOVQPOAN>pOOQOG24XG24XODsQPOG24WODzQPOG24XOE]QPO1G/}OEqQPOG24[OExQPOG24[OOQOLD)rLD)rOOQOLD)sLD)sOOQOLD)vLD)vO*|QPOLD)vOFZQPO!$'MbOOQO!)9B|!)9B|", states:
stateData: "Fs~O!VOS~OQQORTOTROURO`UObVOcWOiXOjYOlZOnaO{dO|eO}fO!OfO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OeiO~PVOV!cXW!cXX!cXY!cXZ!cX[!cX]!cX^!cX!s!cXa!cX~Og!cXm!ZXp!ZXq!cXr!cXs!cXt!cXu!cXv!cXw!cXx!cXy!cXz!cX!T!cX~P!zOVkOWlOXmOYnOZoO[pO]qO^rOgsOqsOrsOssOtsOusOvsOwsOxsOysOzsO~O!T!WX~P$lOR{OTROURO`UObVOcWOiXOjYOlZOnaO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OQyO~P&QOR!OObVO~Od!QO~O`!RO~O`!SO~O`!TO~OV!eXW!eXX!eXY!eXZ!eX[!eX]!eX^!eXg!eXm!ZXp!ZXq!eXr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX!T!eX!s!eXa!eX~Od!UO~Oe!VO~OR!WO~OmsOpsO~Oe!ZO~OQ!]OR![O~O!P!`O!Q!aO!R!bO!S!cO!T!WX~OQ!dO~OQRO~P&QO!s!^X~P$lO_!gOV!_XW!_XX!_XY!_XZ!_X[!_X]!_X^!_Xg!_Xq!_Xr!_Xs!_Xt!_Xu!_Xv!_Xw!_Xx!_Xy!_Xz!_X!s!_X~O_!pO!s!^X~O!s!qO~O_!rO!P!`O!Q!aO!R!bO!S!cO~Og!sO~P!zOVkOWlOXmOYnOZoO[pO]qO^rO~Oa!^X!s!^Xf!^X~P-fOa!tO!s!qO~Oe!vO~Og#OO!s!}O~Og#TO~Of#VO!s#UO~OVkOX!diY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OW!di~P/ROWlO~P/ROVkOWlOXmO^rOZ!di[!di]!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OY!di~P2xOVkOWlOXmOYnO]qO^rO[!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OZ!di~P6hOZoO~P6hOYnO~P2xOVkOWlOXmOY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~O!P!Yi!Q!Yi!R!Yi!S!Yi!T!Yi_!Yia!Yik!Yih!Yi~P-fO_#YO~P-fOg#[O~Oh#]O~P-fOm#^O~Of#_O!s!qO~O_#_O~P-fOf#`O!s!qO~O!P!`O!R!vi!S!vi!T!vi_!via!vik!vih!vi~O!Q!vi~P?rO!Q!aO~P?rO!P!`O!Q!aO!R!bO!S!vi!T!vi_!via!vik!vih!vi~O_!]i!s!]ia!]if!]i~P-fOh#fO~P-fOf#gO!s!qO~OVkOWlOXmOYnOZoO[pO]qO^rO~PVOf!yi!s!yi~P-fOR#nO~Oh#oO~P-fO!P!`O!Q!aO!R!bO!S!cOa!kXk!kX~Oa#qOk#pO~Oh#rO~P-fO!P!`O!Q!aO!R!bO!S!cO!T!ty_!tya!tyk!tyh!ty~Oa#sO!P!`O!Q!aO!R!bO!S!cO~O_#yO~P-fOa#zO!P!`O!Q!aO!R!bO!S!cO~O!P!`O!Q!aO!R!bO!S!cOa!kik!ki~Oa#{O~P$lOh#|O!P!`O!Q!aO!R!bO!S!cO~Oa$OO~P-fOc!m|nTU!o!p!q!r!nQljij~", "3UO!sQPOOOOQO'#C`'#C`O#lQPO'#DoOOQO'#Do'#DoO%yQPO'#DdOVQPO'#DpO'_QPO'#DrO'fQPO'#DsO'nQQO'#DtO'sQPO'#DuO'xQPO'#DvO'}QPO'#DxOOQO'#Dq'#DqO(SQPO'#DqO)pQQO'#C{OOQO'#C{'#C{OOQO'#Dk'#DkO)uQPO'#DkO)zQPO'#DkO*PQPO'#DfOVQPO'#EQO*XQPO'#EQO*^QPO'#EQO*fQPO'#DdOOQO'#De'#DeO*wQPO'#ETQOQPOOO*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:[O*|QPO,5:QO+TQPO'#DjO+[QPO,5:[O,oQPO,5:SO,wQPO'#DiO,|QPO,5:PO-_QPO,5:aO.QQPO'#DjO*|QPO'#DpO._QPO,5:^OOQO'#Dj'#DjO*|QPO,5:_OOQO,5:_,5:_O.gQPO,5:`O*^QPO,5:aO*|QPO,5:bO*^QPO,5:dOOQO,59g,59gO*|QPO,5:VO*|QPO,5:VO$lQPO'#DfOOQO,5:l,5:lO*|QPO,5:lO*|QPO'#DhOOQO'#Dg'#DgOOQO'#ER'#ERO.lQPO,5:lOVQPO,5:nOVQPO,5:nOVQPO,5:nOVQPO,5:nO.tQPO'#EVOOQO'#EU'#EUO.yQPO,5:oOOQO1G/v1G/vO2jQPO1G/vO2qQPO1G/vO6aQPO1G/vO:PQPO1G/vO:WQPO1G/vO:_QPO1G/vO:fQPO1G/vO>QQPO1G/lOOQO1G/n1G/nO*|QPO,5:TOOQO1G/k1G/kO*|QPO1G/{OOQO1G/x1G/xO>qQPO1G/yO*|QPO1G/zO>xQPO1G/{O>}QPO1G/|O?UQPO1G0OO?ZQPO1G/qO?cQPO1G/qO?jQPO1G0WO*^QPO,5:mO*|QPO1G0WOOQO1G0Y1G0YO@^QPO1G0YO@eQPO1G0YO@lQPO1G0YO*|QPO,5:qO*wQPO,5:pOVQPO1G0ZOAZQPO1G/oOAkQPO7+%gOOQO7+%e7+%eOArQPO7+%fO*|QPO7+%gOVQPO7+%hO*|QPO7+%jOOQO7+%]7+%]OOQO7+%r7+%rOOQO1G0X1G0XOAzQPO7+%rOBhQPO1G0]OOQO1G0[1G0[OOQO7+%u7+%uOVQPO<<IROBrQPO<<IQOBwQPO<<IROCOQPO'#DwOCdQPO<<ISOClQPO<<IUOCsQPO<<I^ODbQPOAN>mO*|QPOAN>lOVQPOAN>mOVQPO,5:cOOQOAN>nAN>nOVQPOAN>pOOQOG24XG24XODsQPOG24WODzQPOG24XOE]QPO1G/}OEqQPOG24[OExQPOG24[OOQOLD)rLD)rOOQOLD)sLD)sOOQOLD)vLD)vO*|QPOLD)vOFZQPO!$'MbOOQO!)9B|!)9B|",
stateData:
'Fs~O!VOS~OQQORTOTROURO`UObVOcWOiXOjYOlZOnaO{dO|eO}fO!OfO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OeiO~PVOV!cXW!cXX!cXY!cXZ!cX[!cX]!cX^!cX!s!cXa!cX~Og!cXm!ZXp!ZXq!cXr!cXs!cXt!cXu!cXv!cXw!cXx!cXy!cXz!cX!T!cX~P!zOVkOWlOXmOYnOZoO[pO]qO^rOgsOqsOrsOssOtsOusOvsOwsOxsOysOzsO~O!T!WX~P$lOR{OTROURO`UObVOcWOiXOjYOlZOnaO!`PO!aPO!bPO!m^O!n^O!o_O!p_O!q_O!r_O~OQyO~P&QOR!OObVO~Od!QO~O`!RO~O`!SO~O`!TO~OV!eXW!eXX!eXY!eXZ!eX[!eX]!eX^!eXg!eXm!ZXp!ZXq!eXr!eXs!eXt!eXu!eXv!eXw!eXx!eXy!eXz!eX!T!eX!s!eXa!eX~Od!UO~Oe!VO~OR!WO~OmsOpsO~Oe!ZO~OQ!]OR![O~O!P!`O!Q!aO!R!bO!S!cO!T!WX~OQ!dO~OQRO~P&QO!s!^X~P$lO_!gOV!_XW!_XX!_XY!_XZ!_X[!_X]!_X^!_Xg!_Xq!_Xr!_Xs!_Xt!_Xu!_Xv!_Xw!_Xx!_Xy!_Xz!_X!s!_X~O_!pO!s!^X~O!s!qO~O_!rO!P!`O!Q!aO!R!bO!S!cO~Og!sO~P!zOVkOWlOXmOYnOZoO[pO]qO^rO~Oa!^X!s!^Xf!^X~P-fOa!tO!s!qO~Oe!vO~Og#OO!s!}O~Og#TO~Of#VO!s#UO~OVkOX!diY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OW!di~P/ROWlO~P/ROVkOWlOXmO^rOZ!di[!di]!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OY!di~P2xOVkOWlOXmOYnO]qO^rO[!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~OZ!di~P6hOZoO~P6hOYnO~P2xOVkOWlOXmOY!diZ!di[!di]!di^!dig!diq!dir!dis!dit!diu!div!diw!dix!diy!diz!di!T!di_!di!s!dia!di!P!di!Q!di!R!di!S!dih!dif!diQ!diR!diT!diU!di`!dib!dic!dii!dij!dil!din!di{!di|!di}!di!O!di!`!di!a!di!b!di!m!di!n!di!o!di!p!di!q!di!r!dik!di~O!P!Yi!Q!Yi!R!Yi!S!Yi!T!Yi_!Yia!Yik!Yih!Yi~P-fO_#YO~P-fOg#[O~Oh#]O~P-fOm#^O~Of#_O!s!qO~O_#_O~P-fOf#`O!s!qO~O!P!`O!R!vi!S!vi!T!vi_!via!vik!vih!vi~O!Q!vi~P?rO!Q!aO~P?rO!P!`O!Q!aO!R!bO!S!vi!T!vi_!via!vik!vih!vi~O_!]i!s!]ia!]if!]i~P-fOh#fO~P-fOf#gO!s!qO~OVkOWlOXmOYnOZoO[pO]qO^rO~PVOf!yi!s!yi~P-fOR#nO~Oh#oO~P-fO!P!`O!Q!aO!R!bO!S!cOa!kXk!kX~Oa#qOk#pO~Oh#rO~P-fO!P!`O!Q!aO!R!bO!S!cO!T!ty_!tya!tyk!tyh!ty~Oa#sO!P!`O!Q!aO!R!bO!S!cO~O_#yO~P-fOa#zO!P!`O!Q!aO!R!bO!S!cO~O!P!`O!Q!aO!R!bO!S!cOa!kik!ki~Oa#{O~P$lOh#|O!P!`O!Q!aO!R!bO!S!cO~Oa$OO~P-fOc!m|nTU!o!p!q!r!nQljij~',
goto: "-l!zPPPP!{PPPPPPPPPPPPPPPPPPPPPPPPPP#wPPPPPPPPPPPPPPPPPPPPPP$s$y%s&T&q'u(Q(cPPP!{*a!{+_,Z+_+_+_-Y+_PPPPPPP%s-]%s-`-c-f!s`OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!sbOTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|QjOR#e#VSgO#VQxTQ!YdQ#P!`Q#Q!aQ#R!bQ#S!cQ#i#]Q#l#bQ#m#fQ#u#oQ#v#pR#x#rmhOTd!`!a!b!c#V#]#b#f#o#p#rlcOTd!`!a!b!c#V#]#b#f#o#p#rQ!^fQ!w!RQ!y!TR#a!}!U[Uklmnopqrs{!O!S!V!W!Z![!q!s!v#O#T#[#^#n#|l]OTd!`!a!b!c#V#]#b#f#o#p#rX!]f!R!T!}UvT{![X}U!V!Z!vUwT{![Q|UQ!z!VQ!|!ZR#Z!vSSO#VQtT[zU{!V!Z![!vd!Xd!`!a!b!c#]#b#f#o#pQ!gkQ!hlQ!imQ!jnQ!koQ!lpQ!mqQ!nrQ!osQ!u!OQ!x!SQ!{!WQ#W!qQ#X!sQ#b#OQ#c#TQ#h#[Q#k#^Q#t#nQ#w#rR#}#|!n`OUdklmnopqrs!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|TuT{!s[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!r[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|R!PVR#j#]R!_fRjOR!fiQ!eiR#d#U", goto: "-l!zPPPP!{PPPPPPPPPPPPPPPPPPPPPPPPPP#wPPPPPPPPPPPPPPPPPPPPPP$s$y%s&T&q'u(Q(cPPP!{*a!{+_,Z+_+_+_-Y+_PPPPPPP%s-]%s-`-c-f!s`OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!sbOTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|QjOR#e#VSgO#VQxTQ!YdQ#P!`Q#Q!aQ#R!bQ#S!cQ#i#]Q#l#bQ#m#fQ#u#oQ#v#pR#x#rmhOTd!`!a!b!c#V#]#b#f#o#p#rlcOTd!`!a!b!c#V#]#b#f#o#p#rQ!^fQ!w!RQ!y!TR#a!}!U[Uklmnopqrs{!O!S!V!W!Z![!q!s!v#O#T#[#^#n#|l]OTd!`!a!b!c#V#]#b#f#o#p#rX!]f!R!T!}UvT{![X}U!V!Z!vUwT{![Q|UQ!z!VQ!|!ZR#Z!vSSO#VQtT[zU{!V!Z![!vd!Xd!`!a!b!c#]#b#f#o#pQ!gkQ!hlQ!imQ!jnQ!koQ!lpQ!mqQ!nrQ!osQ!u!OQ!x!SQ!{!WQ#W!qQ#X!sQ#b#OQ#c#TQ#h#[Q#k#^Q#t#nQ#w#rR#}#|!n`OUdklmnopqrs!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|TuT{!s[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|!r[OTUdklmnopqrs{!O!S!V!W!Z![!`!a!b!c!q!s!v#O#T#V#[#]#^#b#f#n#o#p#r#|R!PVR#j#]R!_fRjOR!fiQ!eiR#d#U",
nodeNames: "⚠ Expression Local ( Literal Global Radical + - * \\ ∆ ∩ × ) { } Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ &", nodeNames:
'⚠ Expression Local ( Literal Global Radical + - * \\ ∆ ∩ × ) { } Filter ComplexIndex [ ] ∈ | PrefixD PrefixI ; PrefixR := Function TextFunction :∈ ∉ ⊆ ⊄ ⊂ > ≥ < ≤ ≠ = ¬ Predicate ∀ ∃ ⇔ ⇒ &',
maxTerm: 87, maxTerm: 87,
propSources: [highlighting], propSources: [highlighting],
skippedNodes: [0], skippedNodes: [0],
repeatNodeCount: 0, repeatNodeCount: 0,
tokenData: "6P~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+s#V#W-c#W#X/O#X#d+]#d#e1h#e#f+]#f#g2^#g#o+]#o#p3h#p#q3m#q#r3r#y#z%s$f$g%s$r$s3w%o%p3|5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m4R%%Y%%Z4W%%[%%]4]%&Y%&Z4b%&]%&^4g%&_%&`4l%&`%&a4q%&b%&c4v%&c%&d4{%'S%'T5Q%'T%'U5V%'U%'V5[%(^%(_5a%(b%(c5f%(c%(d5k%)Q%)R5p%)S%)T5u%)U%)V5z&FU&FV%s~%xY!V~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!S~~&rOR~~&wO_~~&|OX~~'ROV~~'WO!s~~']OW~P'bP!`P!Q![']R'lQdQ!`P|}'r!Q!['eQ'uP!R!['xQ'}QdQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOm~~(hOp~~(mOk~~(rOw~~(wOz~~(|Ou~~)PP!Q![)S~)XPT~!Q![)S~)aPi~!Q![)S~)gQ!Q![)m#]#^)u~)rPn~!Q![)m~)zOc~~*POj~~*SQ!Q![*Y#f#g*b~*_P|~!Q![*Y~*gO!m~~*lPl~!Q![*o~*tPU~!Q![*o~*|O!b~~+ROe~~+WOZ~~+]Of~~+bRQ~!Q![+k#T#o+]5i6S+]~+pPQ~!Q![+k~+xTQ~!Q![+k#T#c+]#c#d,X#d#o+]5i6S+]~,^TQ~!Q![+k#T#c+]#c#d,m#d#o+]5i6S+]~,rTQ~!Q![+k#T#`+]#`#a-R#a#o+]5i6S+]~-YR!p~Q~!Q![+k#T#o+]5i6S+]~-hSQ~!Q![+k#T#U-t#U#o+]5i6S+]~-yTQ~!Q![+k#T#f+]#f#g.Y#g#o+]5i6S+]~._TQ~!Q![+k#T#W+]#W#X.n#X#o+]5i6S+]~.uR!o~Q~!Q![+k#T#o+]5i6S+]~/TTQ~!Q![+k#T#X+]#X#Y/d#Y#o+]5i6S+]~/iTQ~!Q![+k#T#U+]#U#V/x#V#o+]5i6S+]~/}TQ~!Q![+k#T#c+]#c#d0^#d#o+]5i6S+]~0cTQ~!Q![+k#T#c+]#c#d0r#d#o+]5i6S+]~0wTQ~!Q![+k#T#`+]#`#a1W#a#o+]5i6S+]~1_R!q~Q~!Q![+k#T#o+]5i6S+]~1mTQ~!Q![+k#T#f+]#f#g1|#g#o+]5i6S+]~2TR!n~Q~!Q![+k#T#o+]5i6S+]~2cTQ~!Q![+k#T#X+]#X#Y2r#Y#o+]5i6S+]~2wTQ~!Q![+k#T#W+]#W#X3W#X#o+]5i6S+]~3_R!r~Q~!Q![+k#T#o+]5i6S+]~3mO`~~3rOh~~3wOa~~3|O{~~4RO^~~4WOb~~4]O!Q~~4bO!P~~4gO}~~4lO!O~~4qO!a~~4vO[~~4{Og~~5QOq~~5VO!R~~5[O]~~5aOY~~5fOy~~5kOx~~5pOv~~5uOt~~5zOs~~6POr~", tokenData:
"6P~R!jX^%spq%svw&hxy&myz&rz{&w{|&||}'R}!O'W!Q!R']!R!['e![!](T!]!^(h!^!_(m!_!`(r!`!a(w!c!d(|!e!f(|!f!g)[!h!i)d!k!l)z!r!s*P!t!u*g!u!v(|!v!w(|!z!{(|!|!}*w!}#O*|#O#P+R#P#Q+W#R#S+]#T#U+]#U#V+s#V#W-c#W#X/O#X#d+]#d#e1h#e#f+]#f#g2^#g#o+]#o#p3h#p#q3m#q#r3r#y#z%s$f$g%s$r$s3w%o%p3|5i6S+]#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s% l% m4R%%Y%%Z4W%%[%%]4]%&Y%&Z4b%&]%&^4g%&_%&`4l%&`%&a4q%&b%&c4v%&c%&d4{%'S%'T5Q%'T%'U5V%'U%'V5[%(^%(_5a%(b%(c5f%(c%(d5k%)Q%)R5p%)S%)T5u%)U%)V5z&FU&FV%s~%xY!V~X^%spq%s#y#z%s$f$g%s#BY#BZ%s$IS$I_%s$I|$JO%s$JT$JU%s$KV$KW%s&FU&FV%s~&mO!S~~&rOR~~&wO_~~&|OX~~'ROV~~'WO!s~~']OW~P'bP!`P!Q![']R'lQdQ!`P|}'r!Q!['eQ'uP!R!['xQ'}QdQ|}'r!Q!['x~(WQ!_!`(^%&b%&c(c~(cOm~~(hOp~~(mOk~~(rOw~~(wOz~~(|Ou~~)PP!Q![)S~)XPT~!Q![)S~)aPi~!Q![)S~)gQ!Q![)m#]#^)u~)rPn~!Q![)m~)zOc~~*POj~~*SQ!Q![*Y#f#g*b~*_P|~!Q![*Y~*gO!m~~*lPl~!Q![*o~*tPU~!Q![*o~*|O!b~~+ROe~~+WOZ~~+]Of~~+bRQ~!Q![+k#T#o+]5i6S+]~+pPQ~!Q![+k~+xTQ~!Q![+k#T#c+]#c#d,X#d#o+]5i6S+]~,^TQ~!Q![+k#T#c+]#c#d,m#d#o+]5i6S+]~,rTQ~!Q![+k#T#`+]#`#a-R#a#o+]5i6S+]~-YR!p~Q~!Q![+k#T#o+]5i6S+]~-hSQ~!Q![+k#T#U-t#U#o+]5i6S+]~-yTQ~!Q![+k#T#f+]#f#g.Y#g#o+]5i6S+]~._TQ~!Q![+k#T#W+]#W#X.n#X#o+]5i6S+]~.uR!o~Q~!Q![+k#T#o+]5i6S+]~/TTQ~!Q![+k#T#X+]#X#Y/d#Y#o+]5i6S+]~/iTQ~!Q![+k#T#U+]#U#V/x#V#o+]5i6S+]~/}TQ~!Q![+k#T#c+]#c#d0^#d#o+]5i6S+]~0cTQ~!Q![+k#T#c+]#c#d0r#d#o+]5i6S+]~0wTQ~!Q![+k#T#`+]#`#a1W#a#o+]5i6S+]~1_R!q~Q~!Q![+k#T#o+]5i6S+]~1mTQ~!Q![+k#T#f+]#f#g1|#g#o+]5i6S+]~2TR!n~Q~!Q![+k#T#o+]5i6S+]~2cTQ~!Q![+k#T#X+]#X#Y2r#Y#o+]5i6S+]~2wTQ~!Q![+k#T#W+]#W#X3W#X#o+]5i6S+]~3_R!r~Q~!Q![+k#T#o+]5i6S+]~3mO`~~3rOh~~3wOa~~3|O{~~4RO^~~4WOb~~4]O!Q~~4bO!P~~4gO}~~4lO!O~~4qO!a~~4vO[~~4{Og~~5QOq~~5VO!R~~5[O]~~5aOY~~5fOy~~5kOx~~5pOv~~5uOt~~5zOs~~6POr~",
tokenizers: [0, 1], tokenizers: [0, 1],
topRules: {"Expression":[0,1]}, topRules: { Expression: [0, 1] },
tokenPrec: 1720 tokenPrec: 1720
}) });

View File

@ -12,9 +12,9 @@ interface SelectMultiGrammemeProps extends Omit<SelectMultiProps<IGrammemeOption
export function SelectMultiGrammeme({ value, onChange, ...restProps }: SelectMultiGrammemeProps) { export function SelectMultiGrammeme({ value, onChange, ...restProps }: SelectMultiGrammemeProps) {
const compatible = getCompatibleGrams( const compatible = getCompatibleGrams(
value.filter(data => Object.values(Grammeme).includes(data.value as Grammeme)).map(data => data.value as Grammeme) value.filter(data => Object.values(Grammeme).includes(data.value)).map(data => data.value)
); );
const options = supportedGrammeOptions.filter(({ value }) => compatible.includes(value as Grammeme)); const options = supportedGrammeOptions.filter(({ value }) => compatible.includes(value));
return ( return (
<SelectMulti <SelectMulti

View File

@ -36,7 +36,7 @@ interface SelectWordFormProps extends Styling {
export function SelectWordForm({ value, onChange, className, ...restProps }: SelectWordFormProps) { export function SelectWordForm({ value, onChange, className, ...restProps }: SelectWordFormProps) {
function handleSelect(grams: Grammeme[]) { function handleSelect(grams: Grammeme[]) {
onChange(supportedGrammeOptions.filter(({ value }) => grams.includes(value as Grammeme))); onChange(supportedGrammeOptions.filter(({ value }) => grams.includes(value)));
} }
return ( return (
@ -47,7 +47,7 @@ export function SelectWordForm({ value, onChange, className, ...restProps }: Sel
text={data.text} text={data.text}
example={data.example} example={data.example}
grams={data.grams} grams={data.grams}
isSelected={data.grams.every(gram => value.find(item => (item.value as Grammeme) === gram))} isSelected={data.grams.every(gram => value.find(item => item.value === gram))}
onSelectGrams={handleSelect} onSelectGrams={handleSelect}
/> />
))} ))}

View File

@ -27,11 +27,12 @@ export interface DlgCstTemplateProps {
insertAfter?: number; insertAfter?: number;
} }
enum TabID { export const TabID = {
TEMPLATE = 0, TEMPLATE: 0,
ARGUMENTS = 1, ARGUMENTS: 1,
CONSTITUENTA = 2 CONSTITUENTA: 2
} } as const;
export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgCstTemplate() { export function DlgCstTemplate() {
const { schema, onCreate, insertAfter } = useDialogsStore(state => state.props as DlgCstTemplateProps); const { schema, onCreate, insertAfter } = useDialogsStore(state => state.props as DlgCstTemplateProps);
@ -54,7 +55,7 @@ export function DlgCstTemplate() {
const cst_type = useWatch({ control: methods.control, name: 'cst_type' }); const cst_type = useWatch({ control: methods.control, name: 'cst_type' });
const isValid = validateNewAlias(alias, cst_type, schema); const isValid = validateNewAlias(alias, cst_type, schema);
const [activeTab, setActiveTab] = useState(TabID.TEMPLATE); const [activeTab, setActiveTab] = useState<TabID>(TabID.TEMPLATE);
function onSubmit(data: ICstCreateDTO) { function onSubmit(data: ICstCreateDTO) {
return cstCreate({ itemID: schema.id, data }).then(onCreate); return cstCreate({ itemID: schema.id, data }).then(onCreate);
@ -69,7 +70,12 @@ export function DlgCstTemplate() {
onSubmit={event => void methods.handleSubmit(onSubmit)(event)} onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
helpTopic={HelpTopic.RSL_TEMPLATES} helpTopic={HelpTopic.RSL_TEMPLATES}
> >
<Tabs selectedTabClassName='clr-selected' className='grid' selectedIndex={activeTab} onSelect={setActiveTab}> <Tabs
selectedTabClassName='clr-selected'
className='grid'
selectedIndex={activeTab}
onSelect={index => setActiveTab(index as TabID)}
>
<TabList className='mb-3 mx-auto flex border divide-x rounded-none bg-prim-200'> <TabList className='mb-3 mx-auto flex border divide-x rounded-none bg-prim-200'>
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' /> <TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' />
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' /> <TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' />

View File

@ -12,7 +12,7 @@ import { TabLabel, TabList, TabPanel, Tabs } from '@/components/tabs';
import { useDialogsStore } from '@/stores/dialogs'; import { useDialogsStore } from '@/stores/dialogs';
import { labelReferenceType } from '../../labels'; import { labelReferenceType } from '../../labels';
import { type IReference, ReferenceType } from '../../models/language'; import { type IReference, ReferenceType, schemaGrammemeOption, schemaReferenceType } from '../../models/language';
import { import {
parseEntityReference, parseEntityReference,
parseGrammemes, parseGrammemes,
@ -34,10 +34,10 @@ export interface IReferenceInputState {
const schemaEditReferenceState = z const schemaEditReferenceState = z
.object({ .object({
type: z.nativeEnum(ReferenceType), type: schemaReferenceType,
entity: z.strictObject({ entity: z.strictObject({
entity: z.string(), entity: z.string(),
grams: z.array(z.strictObject({ value: z.string(), label: z.string() })) grams: z.array(schemaGrammemeOption)
}), }),
syntactic: z.strictObject({ offset: z.coerce.number(), nominal: z.string() }) syntactic: z.strictObject({ offset: z.coerce.number(), nominal: z.string() })
}) })
@ -56,10 +56,11 @@ export interface DlgEditReferenceProps {
onCancel: () => void; onCancel: () => void;
} }
enum TabID { const TabID = {
ENTITY = 0, ENTITY: 0,
SYNTACTIC = 1 SYNTACTIC: 1
} } as const;
type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgEditReference() { export function DlgEditReference() {
const { initial, onSave, onCancel } = useDialogsStore(state => state.props as DlgEditReferenceProps); const { initial, onSave, onCancel } = useDialogsStore(state => state.props as DlgEditReferenceProps);
@ -89,9 +90,9 @@ export function DlgEditReference() {
} }
} }
function handleChangeTab(tab: TabID) { function handleChangeTab(tab: number) {
methods.setValue('type', tab === TabID.ENTITY ? ReferenceType.ENTITY : ReferenceType.SYNTACTIC); methods.setValue('type', tab === TabID.ENTITY ? ReferenceType.ENTITY : ReferenceType.SYNTACTIC);
setActiveTab(tab); setActiveTab(tab as TabID);
} }
return ( return (

View File

@ -17,7 +17,7 @@ import { useIsProcessingCctext } from '../../backend/cctext/use-is-processing-cc
import { useParseText } from '../../backend/cctext/use-parse-text'; import { useParseText } from '../../backend/cctext/use-parse-text';
import { useCstUpdate } from '../../backend/use-cst-update'; import { useCstUpdate } from '../../backend/use-cst-update';
import { SelectMultiGrammeme } from '../../components/select-multi-grammeme'; import { SelectMultiGrammeme } from '../../components/select-multi-grammeme';
import { type Grammeme, type IGrammemeOption, type IWordForm, supportedGrammemes } from '../../models/language'; import { type IGrammemeOption, type IWordForm, supportedGrammemes } from '../../models/language';
import { parseGrammemes, supportedGrammeOptions, wordFormEquals } from '../../models/language-api'; import { parseGrammemes, supportedGrammeOptions, wordFormEquals } from '../../models/language-api';
import { type IConstituenta } from '../../models/rsform'; import { type IConstituenta } from '../../models/rsform';
@ -98,9 +98,7 @@ export function DlgEditWordForms() {
void generateLexeme({ text: inputText }).then(response => { void generateLexeme({ text: inputText }).then(response => {
const lexeme: IWordForm[] = []; const lexeme: IWordForm[] = [];
response.items.forEach(form => { response.items.forEach(form => {
const grams = parseGrammemes(form.grams).filter(gram => const grams = parseGrammemes(form.grams).filter(gram => supportedGrammemes.find(item => item === gram));
supportedGrammemes.find(item => item === (gram as Grammeme))
);
const newForm: IWordForm = { const newForm: IWordForm = {
text: form.text, text: form.text,
grams: grams grams: grams

View File

@ -22,15 +22,16 @@ export interface DlgInlineSynthesisProps {
onSynthesis: () => void; onSynthesis: () => void;
} }
enum TabID { export const TabID = {
SCHEMA = 0, SCHEMA: 0,
SELECTIONS = 1, SELECTIONS: 1,
SUBSTITUTIONS = 2 SUBSTITUTIONS: 2
} } as const;
export type TabID = (typeof TabID)[keyof typeof TabID];
export function DlgInlineSynthesis() { export function DlgInlineSynthesis() {
const { receiver, onSynthesis } = useDialogsStore(state => state.props as DlgInlineSynthesisProps); const { receiver, onSynthesis } = useDialogsStore(state => state.props as DlgInlineSynthesisProps);
const [activeTab, setActiveTab] = useState(TabID.SCHEMA); const [activeTab, setActiveTab] = useState<TabID>(TabID.SCHEMA);
const { inlineSynthesis } = useInlineSynthesis(); const { inlineSynthesis } = useInlineSynthesis();
const methods = useForm<IInlineSynthesisDTO>({ const methods = useForm<IInlineSynthesisDTO>({
@ -57,7 +58,12 @@ export function DlgInlineSynthesis() {
canSubmit={methods.formState.isValid && sourceID !== null} canSubmit={methods.formState.isValid && sourceID !== null}
onSubmit={event => void methods.handleSubmit(onSubmit)(event)} onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
> >
<Tabs selectedTabClassName='clr-selected' className='grid' selectedIndex={activeTab} onSelect={setActiveTab}> <Tabs
selectedTabClassName='clr-selected'
className='grid'
selectedIndex={activeTab}
onSelect={index => setActiveTab(index as TabID)}
>
<TabList className='mb-3 mx-auto flex border divide-x rounded-none bg-prim-200'> <TabList className='mb-3 mx-auto flex border divide-x rounded-none bg-prim-200'>
<TabLabel <TabLabel
label='Схема' // label='Схема' //

View File

@ -9,7 +9,7 @@ import { type IVersionInfo } from '../library/backend/types';
import { type CurrentVersion } from '../library/models/library'; import { type CurrentVersion } from '../library/models/library';
import { CstType, type IRSErrorDescription, ParsingStatus, RSErrorType, TokenID } from './backend/types'; import { CstType, type IRSErrorDescription, ParsingStatus, RSErrorType, TokenID } from './backend/types';
import { type GramData, Grammeme, ReferenceType } from './models/language'; import { Grammeme, ReferenceType } from './models/language';
import { CstClass, ExpressionStatus, type IConstituenta } from './models/rsform'; import { CstClass, ExpressionStatus, type IConstituenta } from './models/rsform';
import { type IArgumentInfo, type ISyntaxTreeNode } from './models/rslang'; import { type IArgumentInfo, type ISyntaxTreeNode } from './models/rslang';
import { CstMatchMode, DependencyMode } from './stores/cst-search'; import { CstMatchMode, DependencyMode } from './stores/cst-search';
@ -285,6 +285,7 @@ export function describeExpressionStatus(status: ExpressionStatus): string {
* Retrieves label for {@link CstType}. * Retrieves label for {@link CstType}.
*/ */
export function labelCstType(target: CstType): string { export function labelCstType(target: CstType): string {
console.log(1);
// prettier-ignore // prettier-ignore
switch (target) { switch (target) {
case CstType.BASE: return 'Базисное множество'; case CstType.BASE: return 'Базисное множество';
@ -457,10 +458,10 @@ export function labelSyntaxTree(node: ISyntaxTreeNode): string {
/** /**
* Generates label for grammeme. * Generates label for grammeme.
*/ */
export function labelGrammeme(gram: GramData): string { export function labelGrammeme(gram: Grammeme): string {
// prettier-ignore // prettier-ignore
switch (gram as Grammeme) { switch (gram) {
default: return `Неизв: ${gram}`; default: return `Неизв: ${gram as string}`;
case Grammeme.NOUN: return 'ЧР: сущ'; case Grammeme.NOUN: return 'ЧР: сущ';
case Grammeme.VERB: return 'ЧР: глагол'; case Grammeme.VERB: return 'ЧР: глагол';

View File

@ -40,22 +40,9 @@ describe('Testing wordform equality', () => {
expect(wordFormEquals({ text: '', grams: ['nomn', 'sing'] }, { text: '', grams: ['nomn'] })).toEqual(false); expect(wordFormEquals({ text: '', grams: ['nomn', 'sing'] }, { text: '', grams: ['nomn'] })).toEqual(false);
expect(wordFormEquals({ text: '', grams: ['nomn', 'nomn'] }, { text: '', grams: ['nomn'] })).toEqual(false); expect(wordFormEquals({ text: '', grams: ['nomn', 'nomn'] }, { text: '', grams: ['nomn'] })).toEqual(false);
}); });
test('custom grammemes', () => {
expect(wordFormEquals({ text: '', grams: ['с1'] }, { text: '', grams: ['с1'] })).toEqual(true);
expect(wordFormEquals({ text: '', grams: ['с1'] }, { text: '', grams: ['с2'] })).toEqual(false);
expect(wordFormEquals({ text: '', grams: ['sing'] }, { text: '', grams: ['с1'] })).toEqual(false);
});
}); });
describe('Testing grammeme ordering', () => { describe('Testing grammeme ordering', () => {
test('empty input', () => {
expect(grammemeCompare('', '')).toEqual(0);
expect(grammemeCompare(' ', ' ')).toEqual(0);
expect(grammemeCompare('', '123')).toBeLessThan(0);
expect(grammemeCompare('123', '')).toBeGreaterThan(0);
});
test('regular grammemes', () => { test('regular grammemes', () => {
expect(grammemeCompare('NOUN', 'NOUN')).toEqual(0); expect(grammemeCompare('NOUN', 'NOUN')).toEqual(0);
expect(grammemeCompare('NOUN', Grammeme.NOUN)).toEqual(0); expect(grammemeCompare('NOUN', Grammeme.NOUN)).toEqual(0);
@ -75,16 +62,6 @@ describe('Testing grammeme ordering', () => {
expect(grammemeCompare('datv', 'gent')).toBeGreaterThan(0); expect(grammemeCompare('datv', 'gent')).toBeGreaterThan(0);
expect(grammemeCompare('gent', 'nomn')).toBeGreaterThan(0); expect(grammemeCompare('gent', 'nomn')).toBeGreaterThan(0);
}); });
test('custom grammemes', () => {
expect(grammemeCompare('noun', 'noun')).toEqual(0);
expect(grammemeCompare('NOUN', 'noun')).toBeLessThan(0);
expect(grammemeCompare('PRTF', 'noun')).toBeLessThan(0);
expect(grammemeCompare('noun', 'NOUN')).toBeGreaterThan(0);
expect(grammemeCompare('aab', 'aaa')).toBeGreaterThan(0);
expect(grammemeCompare('aaa', 'aab')).toBeLessThan(0);
expect(grammemeCompare('test', 'abcd')).toBeGreaterThan(0);
});
}); });
describe('Testing grammeme parsing', () => { describe('Testing grammeme parsing', () => {

View File

@ -5,7 +5,6 @@
import { labelGrammeme } from '../labels'; import { labelGrammeme } from '../labels';
import { import {
type GramData,
Grammeme, Grammeme,
GrammemeGroups, GrammemeGroups,
type IEntityReference, type IEntityReference,
@ -35,11 +34,11 @@ export function wordFormEquals(left: IWordForm, right: IWordForm): boolean {
} }
/** /**
* Compares {@link GramData} based on Grammeme enum and alpha order for strings. * Compares {@link Grammeme} based on Grammeme enum and alpha order for strings.
*/ */
export function grammemeCompare(left: GramData, right: GramData): number { export function grammemeCompare(left: Grammeme, right: Grammeme): number {
const indexLeft = Object.values(Grammeme).findIndex(gram => gram === (left as Grammeme)); const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left);
const indexRight = Object.values(Grammeme).findIndex(gram => gram === (right as Grammeme)); const indexRight = Object.values(Grammeme).findIndex(gram => gram === right);
if (indexLeft === -1 && indexRight === -1) { if (indexLeft === -1 && indexRight === -1) {
return left.localeCompare(right); return left.localeCompare(right);
} else if (indexLeft === -1 && indexRight !== -1) { } else if (indexLeft === -1 && indexRight !== -1) {
@ -52,15 +51,15 @@ export function grammemeCompare(left: GramData, right: GramData): number {
} }
/** /**
* Transforms {@link Grammeme} enumeration to {@link GramData}. * Transforms {@link Grammeme} enumeration to {@link Grammeme}.
*/ */
export function parseGrammemes(termForm: string): GramData[] { export function parseGrammemes(termForm: string): Grammeme[] {
const result: GramData[] = []; const result: Grammeme[] = [];
const chunks = termForm.split(','); const chunks = termForm.split(',');
chunks.forEach(chunk => { chunks.forEach(chunk => {
const gram = chunk.trim(); const gram = chunk.trim();
if (gram !== '') { if (gram !== '') {
result.push(gram); result.push(gram as Grammeme);
} }
}); });
return result.sort(grammemeCompare); return result.sort(grammemeCompare);

View File

@ -8,64 +8,66 @@ import { z } from 'zod';
* Represents single unit of language Morphology. * Represents single unit of language Morphology.
*/ */
// prettier-ignore // prettier-ignore
export enum Grammeme { export const Grammeme = {
// Части речи // Части речи
NOUN = 'NOUN', ADJF = 'ADJF', ADJS = 'ADJS', COMP = 'COMP', NOUN: 'NOUN', ADJF: 'ADJF', ADJS: 'ADJS', COMP: 'COMP',
VERB = 'VERB', INFN = 'INFN', PRTF = 'PRTF', PRTS = 'PRTS', VERB: 'VERB', INFN: 'INFN', PRTF: 'PRTF', PRTS: 'PRTS',
GRND = 'GRND', NUMR = 'NUMR', ADVB = 'ADVB', NPRO = 'NPRO', GRND: 'GRND', NUMR: 'NUMR', ADVB: 'ADVB', NPRO: 'NPRO',
PRED = 'PRED', PREP = 'PREP', CONJ = 'CONJ', PRCL = 'PRCL', PRED: 'PRED', PREP: 'PREP', CONJ: 'CONJ', PRCL: 'PRCL',
INTJ = 'INTJ', INTJ: 'INTJ',
// Одушевленность // Одушевленность
anim = 'anim', inan = 'inan', anim: 'anim', inan: 'inan',
// Род // Род
masc = 'masc', femn = 'femn', neut = 'neut', masc: 'masc', femn: 'femn', neut: 'neut',
// Число // Число
sing = 'sing', plur = 'plur', sing: 'sing', plur: 'plur',
// Падеж (основные) // Падеж (основные)
nomn = 'nomn', gent = 'gent', datv = 'datv', nomn: 'nomn', gent: 'gent', datv: 'datv',
accs = 'accs', ablt = 'ablt', loct = 'loct', accs: 'accs', ablt: 'ablt', loct: 'loct',
// Совершенный / несовершенный вид // Совершенный / несовершенный вид
perf = 'perf', impf = 'impf', perf: 'perf', impf: 'impf',
// Переходность // Переходность
tran = 'tran', intr = 'intr', tran: 'tran', intr: 'intr',
// Время // Время
pres = 'pres', past = 'past', futr = 'futr', pres: 'pres', past: 'past', futr: 'futr',
// Лицо // Лицо
per1 = '1per', per2 = '2per', per3 = '3per', per1: '1per', per2: '2per', per3: '3per',
// Наклонение // Наклонение
indc = 'indc', impr = 'impr', indc: 'indc', impr: 'impr',
// Включение говорящего в действие // Включение говорящего в действие
incl = 'incl', excl = 'excl', incl: 'incl', excl: 'excl',
// Залог // Залог
actv = 'actv', pssv = 'pssv', actv: 'actv', pssv: 'pssv',
// Стиль речи // Стиль речи
Infr = 'Infr', // Неформальный Infr: 'Infr', // Неформальный
Slng = 'Slng', // Жаргон Slng: 'Slng', // Жаргон
Arch = 'Arch', // Устаревший Arch: 'Arch', // Устаревший
Litr = 'Litr', // Литературный Litr: 'Litr', // Литературный
// Аббревиатура // Аббревиатура
Abbr = 'Abbr' Abbr: 'Abbr'
} } as const;
export type Grammeme = (typeof Grammeme)[keyof typeof Grammeme];
export const schemaGrammeme = z.enum(Object.values(Grammeme) as [Grammeme, ...Grammeme[]]);
/** /**
* Represents part of speech language concept. * Represents part of speech language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const PartOfSpeech = [ export const PartOfSpeech: Grammeme[] = [
Grammeme.NOUN, Grammeme.NOUN,
Grammeme.ADJF, Grammeme.ADJF,
Grammeme.ADJS, Grammeme.ADJS,
@ -82,84 +84,91 @@ export const PartOfSpeech = [
Grammeme.CONJ, Grammeme.CONJ,
Grammeme.PRCL, Grammeme.PRCL,
Grammeme.INTJ Grammeme.INTJ
]; ] as const;
/** /**
* Represents gender language concept. * Represents gender language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Gender = [Grammeme.masc, Grammeme.femn, Grammeme.neut]; export const Gender: Grammeme[] = [Grammeme.masc, Grammeme.femn, Grammeme.neut] as const;
/** /**
* Represents case language concept. * Represents case language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Case = [Grammeme.nomn, Grammeme.gent, Grammeme.datv, Grammeme.accs, Grammeme.ablt, Grammeme.loct]; export const Case: Grammeme[] = [
Grammeme.nomn,
Grammeme.gent,
Grammeme.datv,
Grammeme.accs,
Grammeme.ablt,
Grammeme.loct
] as const;
/** /**
* Represents plurality language concept. * Represents plurality language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Plurality = [Grammeme.sing, Grammeme.plur]; export const Plurality: Grammeme[] = [Grammeme.sing, Grammeme.plur] as const;
/** /**
* Represents verb perfectivity language concept. * Represents verb perfectivity language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Perfectivity = [Grammeme.perf, Grammeme.impf]; export const Perfectivity: Grammeme[] = [Grammeme.perf, Grammeme.impf] as const;
/** /**
* Represents verb transitivity language concept. * Represents verb transitivity language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Transitivity = [Grammeme.tran, Grammeme.intr]; export const Transitivity: Grammeme[] = [Grammeme.tran, Grammeme.intr] as const;
/** /**
* Represents verb mood language concept. * Represents verb mood language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Mood = [Grammeme.indc, Grammeme.impr]; export const Mood: Grammeme[] = [Grammeme.indc, Grammeme.impr] as const;
/** /**
* Represents verb self-inclusion language concept. * Represents verb self-inclusion language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Inclusion = [Grammeme.incl, Grammeme.excl]; export const Inclusion: Grammeme[] = [Grammeme.incl, Grammeme.excl] as const;
/** /**
* Represents verb voice language concept. * Represents verb voice language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Voice = [Grammeme.actv, Grammeme.pssv]; export const Voice: Grammeme[] = [Grammeme.actv, Grammeme.pssv] as const;
/** /**
* Represents verb tense language concept. * Represents verb tense language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Tense = [Grammeme.pres, Grammeme.past, Grammeme.futr]; export const Tense: Grammeme[] = [Grammeme.pres, Grammeme.past, Grammeme.futr] as const;
/** /**
* Represents verb person language concept. * Represents verb person language concept.
* *
* Implemented as a list of mutually exclusive {@link Grammeme}s. * Implemented as a list of mutually exclusive {@link Grammeme}s.
*/ */
export const Person = [Grammeme.per1, Grammeme.per2, Grammeme.per3]; export const Person: Grammeme[] = [Grammeme.per1, Grammeme.per2, Grammeme.per3] as const;
/** /**
* Represents complete list of language concepts. * Represents complete list of language concepts.
* *
* Implemented as a list of lists of {@link Grammeme}s. * Implemented as a list of lists of {@link Grammeme}s.
*/ */
export const GrammemeGroups = [ export const GrammemeGroups: Grammeme[][] = [
PartOfSpeech, PartOfSpeech,
Gender, Gender,
Case, Case,
@ -171,7 +180,7 @@ export const GrammemeGroups = [
Voice, Voice,
Tense, Tense,
Person Person
]; ] as const;
/** /**
* Represents NOUN-ish list of language concepts. * Represents NOUN-ish list of language concepts.
@ -180,7 +189,7 @@ export const GrammemeGroups = [
* *
* Implemented as a list of lists of {@link Grammeme}s. * Implemented as a list of lists of {@link Grammeme}s.
*/ */
export const NounGrams = [Grammeme.NOUN, Grammeme.ADJF, Grammeme.ADJS, ...Case, ...Plurality]; export const NounGrams: Grammeme[] = [Grammeme.NOUN, Grammeme.ADJF, Grammeme.ADJS, ...Case, ...Plurality] as const;
/** /**
* Represents VERB-ish list of language concepts. * Represents VERB-ish list of language concepts.
@ -201,19 +210,14 @@ export const VerbGrams = [
...Voice, ...Voice,
...Tense, ...Tense,
...Person ...Person
]; ] as const;
/**
* Represents {@link Grammeme} parse data.
*/
export type GramData = Grammeme | string;
/** /**
* Represents specific wordform attached to {@link Grammeme}s. * Represents specific wordform attached to {@link Grammeme}s.
*/ */
export interface IWordForm { export interface IWordForm {
text: string; text: string;
grams: GramData[]; grams: Grammeme[];
} }
/** /**
@ -224,51 +228,45 @@ export const supportedGrammemes = [
Grammeme.sing, Grammeme.plur, Grammeme.sing, Grammeme.plur,
Grammeme.nomn, Grammeme.gent, Grammeme.datv, Grammeme.nomn, Grammeme.gent, Grammeme.datv,
Grammeme.accs, Grammeme.ablt, Grammeme.loct, Grammeme.accs, Grammeme.ablt, Grammeme.loct,
]; ] as const;
/** export const schemaGrammemeOption = z.strictObject({
* Represents single option for {@link Grammeme} selector. value: schemaGrammeme,
*/ label: z.string()
export interface IGrammemeOption { });
value: GramData;
label: string; export type IGrammemeOption = z.infer<typeof schemaGrammemeOption>;
}
// ====== Reference resolution ===== // ====== Reference resolution =====
/** /** Represents text reference type. */
* Represents text reference type. export const ReferenceType = {
*/ ENTITY: 'entity',
export enum ReferenceType { SYNTACTIC: 'syntax'
ENTITY = 'entity', } as const;
SYNTACTIC = 'syntax' export type ReferenceType = (typeof ReferenceType)[keyof typeof ReferenceType];
}
/** /** Represents entity reference payload. */
* Represents entity reference payload.
*/
export interface IEntityReference { export interface IEntityReference {
entity: string; entity: string;
form: string; form: string;
} }
/** /** Represents syntactic reference payload. */
* Represents syntactic reference payload.
*/
export interface ISyntacticReference { export interface ISyntacticReference {
offset: number; offset: number;
nominal: string; nominal: string;
} }
export const schemaReferenceType = z.enum(Object.values(ReferenceType) as [ReferenceType, ...ReferenceType[]]);
export const schemaReference = z.strictObject({ export const schemaReference = z.strictObject({
type: z.nativeEnum(ReferenceType), type: schemaReferenceType,
data: z.union([ data: z.union([
z.strictObject({ entity: z.string(), form: z.string() }), z.strictObject({ entity: z.string(), form: z.string() }),
z.strictObject({ offset: z.number(), nominal: z.string() }) z.strictObject({ offset: z.number(), nominal: z.string() })
]) ])
}); });
/** /** Represents abstract reference data. */
* Represents abstract reference data.
*/
export type IReference = z.infer<typeof schemaReference>; export type IReference = z.infer<typeof schemaReference>;

View File

@ -14,39 +14,33 @@ import { type IArgumentInfo } from './rslang';
// CstType constant for category dividers in TemplateSchemas // CstType constant for category dividers in TemplateSchemas
export const CATEGORY_CST_TYPE = CstType.THEOREM; export const CATEGORY_CST_TYPE = CstType.THEOREM;
/** /** Represents Constituenta classification in terms of system of concepts. */
* Represents Constituenta classification in terms of system of concepts. export const CstClass = {
*/ BASIC: 'basic',
export enum CstClass { DERIVED: 'derived',
BASIC = 'basic', STATEMENT: 'statement',
DERIVED = 'derived', TEMPLATE: 'template'
STATEMENT = 'statement', } as const;
TEMPLATE = 'template' export type CstClass = (typeof CstClass)[keyof typeof CstClass];
}
/** /** Represents formal expression Status. */
* Represents formal expression Status. export const ExpressionStatus = {
*/ VERIFIED: 'verified',
export enum ExpressionStatus { INCORRECT: 'incorrect',
VERIFIED = 'verified', INCALCULABLE: 'incalculable',
INCORRECT = 'incorrect', PROPERTY: 'property',
INCALCULABLE = 'incalculable', UNDEFINED: 'undefined',
PROPERTY = 'property', UNKNOWN: 'unknown'
UNDEFINED = 'undefined', } as const;
UNKNOWN = 'unknown' export type ExpressionStatus = (typeof ExpressionStatus)[keyof typeof ExpressionStatus];
}
/** /** Represents word form for natural language. */
* Represents word form for natural language.
*/
export interface TermForm { export interface TermForm {
text: string; text: string;
tags: string; tags: string;
} }
/** /** Represents Constituenta. */
* Represents Constituenta.
*/
export interface IConstituenta { export interface IConstituenta {
id: number; id: number;
alias: string; alias: string;
@ -101,9 +95,7 @@ export interface IConstituenta {
spawn_alias: string[]; spawn_alias: string[];
} }
/** /** Represents {@link IRSForm} statistics. */
* Represents {@link IRSForm} statistics.
*/
export interface IRSFormStats { export interface IRSFormStats {
count_all: number; count_all: number;
count_errors: number; count_errors: number;
@ -125,9 +117,7 @@ export interface IRSFormStats {
count_theorem: number; count_theorem: number;
} }
/** /** Represents inheritance data for {@link IRSForm}. */
* Represents inheritance data for {@link IRSForm}.
*/
export interface IInheritanceInfo { export interface IInheritanceInfo {
child: number; child: number;
child_source: number; child_source: number;
@ -135,9 +125,7 @@ export interface IInheritanceInfo {
parent_source: number; parent_source: number;
} }
/** /** Represents formal explication for set of concepts. */
* Represents formal explication for set of concepts.
*/
export interface IRSForm extends ILibraryItemData { export interface IRSForm extends ILibraryItemData {
version: CurrentVersion; version: CurrentVersion;
versions: IVersionInfo[]; versions: IVersionInfo[];

View File

@ -2,20 +2,14 @@
* Module: Models for RSLanguage. * Module: Models for RSLanguage.
*/ */
import { type TokenID } from '../backend/types'; /** Represents alias mapping. */
/**
* Represents alias mapping.
*/
export type AliasMapping = Record<string, string>; export type AliasMapping = Record<string, string>;
/** /** Represents AST node. */
* Represents AST node.
*/
export interface ISyntaxTreeNode { export interface ISyntaxTreeNode {
uid: number; uid: number;
parent: number; parent: number;
typeID: TokenID; typeID: number;
start: number; start: number;
finish: number; finish: number;
data: { data: {
@ -24,14 +18,10 @@ export interface ISyntaxTreeNode {
}; };
} }
/** /** Represents Syntax tree for RSLang expression. */
* Represents Syntax tree for RSLang expression.
*/
export type SyntaxTree = ISyntaxTreeNode[]; export type SyntaxTree = ISyntaxTreeNode[];
/** /** Represents function argument definition. */
* Represents function argument definition.
*/
export interface IArgumentInfo { export interface IArgumentInfo {
alias: string; alias: string;
typification: string; typification: string;
@ -44,17 +34,16 @@ export interface ITypeInfo {
args: IArgumentInfo[]; args: IArgumentInfo[];
} }
/** /** Represents function argument value. */
* Represents function argument value.
*/
export interface IArgumentValue extends IArgumentInfo { export interface IArgumentValue extends IArgumentInfo {
value?: string; value?: string;
} }
/** Represents error class. */ /** Represents error class. */
export enum RSErrorClass { export const RSErrorClass = {
LEXER, LEXER: 0,
PARSER, PARSER: 1,
SEMANTIC, SEMANTIC: 2,
UNKNOWN UNKNOWN: 3
} } as const;
export type RSErrorClass = (typeof RSErrorClass)[keyof typeof RSErrorClass];

View File

@ -22,12 +22,13 @@ import { useRSFormSuspense } from '../../backend/use-rsform';
import { type IConstituenta, type IRSForm } from '../../models/rsform'; import { type IConstituenta, type IRSForm } from '../../models/rsform';
import { generateAlias } from '../../models/rsform-api'; import { generateAlias } from '../../models/rsform-api';
export enum RSTabID { export const RSTabID = {
CARD = 0, CARD: 0,
CST_LIST = 1, CST_LIST: 1,
CST_EDIT = 2, CST_EDIT: 2,
TERM_GRAPH = 3 TERM_GRAPH: 3
} } as const;
export type RSTabID = (typeof RSTabID)[keyof typeof RSTabID];
export interface IRSEditContext { export interface IRSEditContext {
schema: IRSForm; schema: IRSForm;

View File

@ -17,7 +17,7 @@ import { useModificationStore } from '@/stores/modification';
import { ConstituentaTooltip } from '../../components/constituenta-tooltip'; import { ConstituentaTooltip } from '../../components/constituenta-tooltip';
import { RSEditState, RSTabID } from './rsedit-context'; import { RSEditState, RSTabID } from './rsedit-context';
import { RSTabs } from './rstabs1'; import { RSTabs } from './rstabs';
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
id: z.coerce.number(), id: z.coerce.number(),

View File

@ -66,7 +66,7 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) {
} }
} }
} }
navigateRSForm({ tab: index, activeID: selected.length > 0 ? selected.at(-1) : undefined }); navigateRSForm({ tab: index as RSTabID, activeID: selected.length > 0 ? selected.at(-1) : undefined });
} }
return ( return (

View File

@ -1,27 +1,25 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { persist } from 'zustand/middleware'; import { persist } from 'zustand/middleware';
/** /** Represents graph dependency mode. */
* Represents graph dependency mode. export const DependencyMode = {
*/ ALL: 0,
export enum DependencyMode { OUTPUTS: 1,
ALL = 0, INPUTS: 2,
OUTPUTS, EXPAND_OUTPUTS: 3,
INPUTS, EXPAND_INPUTS: 4
EXPAND_OUTPUTS, } as const;
EXPAND_INPUTS export type DependencyMode = (typeof DependencyMode)[keyof typeof DependencyMode];
}
/** /** Represents {@link IConstituenta} matching mode. */
* Represents {@link IConstituenta} matching mode. export const CstMatchMode = {
*/ ALL: 1,
export enum CstMatchMode { EXPR: 2,
ALL = 1, TERM: 3,
EXPR, TEXT: 4,
TERM, NAME: 5
TEXT, } as const;
NAME export type CstMatchMode = (typeof CstMatchMode)[keyof typeof CstMatchMode];
}
interface CstSearchStore { interface CstSearchStore {
query: string; query: string;

View File

@ -1,15 +1,15 @@
import { create } from 'zustand'; import { create } from 'zustand';
/** /** Represents user access mode. */
* Represents user access mode. export const UserRole = {
*/ READER: 0,
export enum UserRole { EDITOR: 1,
READER = 0, OWNER: 2,
EDITOR, ADMIN: 3
OWNER, } as const;
ADMIN export type UserRole = (typeof UserRole)[keyof typeof UserRole];
}
/** Represents user access mode flags. */
export interface RoleFlags { export interface RoleFlags {
isOwner: boolean; isOwner: boolean;
isEditor: boolean; isEditor: boolean;

View File

@ -23,34 +23,33 @@ import { type DlgShowTypeGraphProps } from '@/features/rsform/dialogs/dlg-show-t
import { type DlgSubstituteCstProps } from '@/features/rsform/dialogs/dlg-substitute-cst'; import { type DlgSubstituteCstProps } from '@/features/rsform/dialogs/dlg-substitute-cst';
import { type DlgUploadRSFormProps } from '@/features/rsform/dialogs/dlg-upload-rsform'; import { type DlgUploadRSFormProps } from '@/features/rsform/dialogs/dlg-upload-rsform';
/** /** Represents global dialog. */
* Represents global dialog. export const DialogType = {
*/ CONSTITUENTA_TEMPLATE: 1,
export enum DialogType { CREATE_CONSTITUENTA: 2,
CONSTITUENTA_TEMPLATE = 1, CREATE_OPERATION: 3,
CREATE_CONSTITUENTA, DELETE_CONSTITUENTA: 4,
CREATE_OPERATION, EDIT_EDITORS: 5,
DELETE_CONSTITUENTA, EDIT_OPERATION: 6,
EDIT_EDITORS, EDIT_REFERENCE: 7,
EDIT_OPERATION, EDIT_VERSIONS: 8,
EDIT_REFERENCE, EDIT_WORD_FORMS: 9,
EDIT_VERSIONS, INLINE_SYNTHESIS: 10,
EDIT_WORD_FORMS, SHOW_AST: 11,
INLINE_SYNTHESIS, SHOW_TYPE_GRAPH: 12,
SHOW_AST, CHANGE_INPUT_SCHEMA: 13,
SHOW_TYPE_GRAPH, CHANGE_LOCATION: 14,
CHANGE_INPUT_SCHEMA, CLONE_LIBRARY_ITEM: 15,
CHANGE_LOCATION, CREATE_VERSION: 16,
CLONE_LIBRARY_ITEM, DELETE_OPERATION: 17,
CREATE_VERSION, GRAPH_PARAMETERS: 18,
DELETE_OPERATION, RELOCATE_CONSTITUENTS: 19,
GRAPH_PARAMETERS, RENAME_CONSTITUENTA: 20,
RELOCATE_CONSTITUENTS, SHOW_QR_CODE: 21,
RENAME_CONSTITUENTA, SUBSTITUTE_CONSTITUENTS: 22,
SHOW_QR_CODE, UPLOAD_RSFORM: 23
SUBSTITUTE_CONSTITUENTS, } as const;
UPLOAD_RSFORM export type DialogType = (typeof DialogType)[keyof typeof DialogType];
}
interface DialogProps { interface DialogProps {
onHide?: () => void; onHide?: () => void;

View File

@ -1,6 +1,6 @@
import { type Page } from '@playwright/test'; import { type Page } from '@playwright/test';
import { type ICurrentUser, IUserLoginDTO } from '../../src/features/auth/backend/types'; import { type ICurrentUser, type IUserLoginDTO } from '../../src/features/auth/backend/types';
import { BACKEND_URL } from './constants'; import { BACKEND_URL } from './constants';
const dataAnonymousAuth: ICurrentUser = { const dataAnonymousAuth: ICurrentUser = {

View File

@ -7,14 +7,17 @@
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
/* Bundler mode */ /* Language features */
"moduleResolution": "bundler", "erasableSyntaxOnly": true,
"allowImportingTsExtensions": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
/* Bundler mode */
"allowImportingTsExtensions": true,
"moduleResolution": "bundler",
"noEmit": true,
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,