2023-07-30 00:47:07 +03:00
|
|
|
|
import { LayoutTypes } from 'reagraph';
|
|
|
|
|
|
2023-08-15 21:22:21 +03:00
|
|
|
|
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
|
2023-07-29 03:31:21 +03:00
|
|
|
|
import { resolveErrorClass,RSErrorClass, RSErrorType, TokenID } from './enums';
|
2023-08-16 00:39:16 +03:00
|
|
|
|
import { CstClass, CstMatchMode, CstType, DependencyMode, ExpressionStatus, IConstituenta,
|
2023-08-06 23:13:45 +03:00
|
|
|
|
IFunctionArg,IRSErrorDescription, IRSForm,
|
|
|
|
|
ISyntaxTreeNode, ParsingStatus, ValueClass
|
|
|
|
|
} from './models';
|
2023-07-20 17:11:03 +03:00
|
|
|
|
|
|
|
|
|
export interface IRSButtonData {
|
|
|
|
|
text: string
|
|
|
|
|
tooltip: string
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-16 00:39:16 +03:00
|
|
|
|
export interface IFormatInfo {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
text: string
|
|
|
|
|
color: string
|
|
|
|
|
tooltip: string
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-02 18:24:17 +03:00
|
|
|
|
export function getCstDescription(cst: IConstituenta): string {
|
|
|
|
|
if (cst.cstType === CstType.STRUCTURED) {
|
|
|
|
|
return (
|
|
|
|
|
cst.term.resolved || cst.term.raw ||
|
|
|
|
|
cst.definition.text.resolved || cst.definition.text.raw ||
|
|
|
|
|
cst.convention ||
|
|
|
|
|
cst.definition.formal
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
|
|
|
|
cst.term.resolved || cst.term.raw ||
|
|
|
|
|
cst.definition.text.resolved || cst.definition.text.raw ||
|
|
|
|
|
cst.definition.formal ||
|
|
|
|
|
cst.convention
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCstLabel(cst: IConstituenta) {
|
|
|
|
|
return `${cst.alias}: ${getCstDescription(cst)}`;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-31 22:38:58 +03:00
|
|
|
|
export function getCstTypePrefix(type: CstType) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case CstType.BASE: return 'X';
|
|
|
|
|
case CstType.CONSTANT: return 'C';
|
|
|
|
|
case CstType.STRUCTURED: return 'S';
|
|
|
|
|
case CstType.AXIOM: return 'A';
|
|
|
|
|
case CstType.TERM: return 'D';
|
|
|
|
|
case CstType.FUNCTION: return 'F';
|
|
|
|
|
case CstType.PREDICATE: return 'P';
|
|
|
|
|
case CstType.THEOREM: return 'T';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCstExpressionPrefix(cst: IConstituenta): string {
|
|
|
|
|
return cst.alias + (cst.cstType === CstType.STRUCTURED ? '::=' : ':==');
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-20 17:11:03 +03:00
|
|
|
|
export function getRSButtonData(id: TokenID): IRSButtonData {
|
2023-07-25 20:27:29 +03:00
|
|
|
|
switch (id) {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
case TokenID.BOOLEAN: return {
|
2023-07-22 03:18:48 +03:00
|
|
|
|
text: 'ℬ()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Булеан [Alt + E]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.DECART: return {
|
|
|
|
|
text: '×',
|
2023-07-29 03:31:21 +03:00
|
|
|
|
tooltip: 'Декартово произведение [Shift + 8 / Alt + Shift + E]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.PUNC_PL: return {
|
|
|
|
|
text: '( )',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Скобки вокруг выражения [ Alt + Shift + 9 ]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.PUNC_SL: return {
|
|
|
|
|
text: '[ ]',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Скобки вокруг выражения [ Alt + [ ]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.FORALL: return {
|
|
|
|
|
text: '∀',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Квантор всеобщности [`]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.EXISTS: return {
|
|
|
|
|
text: '∃',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Квантор существования [Shift + `]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NOT: return {
|
|
|
|
|
text: '¬',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Отрицание [Alt + `]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.AND: return {
|
|
|
|
|
text: '&',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Конъюнкция [Alt + 3 ~ Shift + 7]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.OR: return {
|
|
|
|
|
text: '∨',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'дизъюнкция [Alt + Shift + 3]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.IMPLICATION: return {
|
|
|
|
|
text: '⇒',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'импликация [Alt + 4]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.EQUIVALENT: return {
|
|
|
|
|
text: '⇔',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'эквивалентность [Alt + Shift + 4]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.LIT_EMPTYSET: return {
|
|
|
|
|
text: '∅',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'пустое множество [Alt + X]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.LIT_INTSET: return {
|
|
|
|
|
text: 'Z',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'целые числа [Alt + Z]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.EQUAL: return {
|
|
|
|
|
text: '=',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'равенство'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NOTEQUAL: return {
|
|
|
|
|
text: '≠',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'неравенство [Alt + Shift + `]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.GREATER_OR_EQ: return {
|
|
|
|
|
text: '≥',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'больше или равно'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.LESSER_OR_EQ: return {
|
|
|
|
|
text: '≤',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'меньше или равно'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.IN: return {
|
|
|
|
|
text: '∈',
|
2023-07-31 22:38:58 +03:00
|
|
|
|
tooltip: 'быть элементом (принадлежит) [Alt + 1]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NOTIN: return {
|
|
|
|
|
text: '∉',
|
2023-07-31 22:38:58 +03:00
|
|
|
|
tooltip: 'не принадлежит [Alt + Shift + 1]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.SUBSET_OR_EQ: return {
|
|
|
|
|
text: '⊆',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'быть частью (нестрогое подмножество) [Alt + 2]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.SUBSET: return {
|
|
|
|
|
text: '⊂',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'строгое подмножество [Alt + ;]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NOTSUBSET: return {
|
|
|
|
|
text: '⊄',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'не подмножество [Alt + Shift + 2]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.INTERSECTION: return {
|
|
|
|
|
text: '∩',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'пересечение [Alt + Y]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.UNION: return {
|
|
|
|
|
text: '∪',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'объединение [Alt + U]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
2023-07-22 03:18:48 +03:00
|
|
|
|
case TokenID.SET_MINUS: return {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
text: '\\',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Разность множеств [Alt + 5]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.SYMMINUS: return {
|
|
|
|
|
text: '∆',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Симметрическая разность [Alt + Shift + 5]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NT_DECLARATIVE_EXPR: return {
|
|
|
|
|
text: 'D{}',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'Декларативная форма определения терма [Alt + D]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NT_IMPERATIVE_EXPR: return {
|
|
|
|
|
text: 'I{}',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'императивная форма определения терма [Alt + G]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.NT_RECURSIVE_FULL: return {
|
|
|
|
|
text: 'R{}',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'рекурсивная (цикличная) форма определения терма [Alt + T]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.BIGPR: return {
|
|
|
|
|
text: 'Pr1()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'большая проекция [Alt + Q]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.SMALLPR: return {
|
|
|
|
|
text: 'pr1()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'малая проекция [Alt + W]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.FILTER: return {
|
2023-07-22 03:18:48 +03:00
|
|
|
|
text: 'Fi1[]()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'фильтр [Alt + F]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.REDUCE: return {
|
|
|
|
|
text: 'red()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'множество-сумма [Alt + R]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.CARD: return {
|
|
|
|
|
text: 'card()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'мощность [Alt + C]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.BOOL: return {
|
|
|
|
|
text: 'bool()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'синглетон [Alt + B]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.DEBOOL: return {
|
|
|
|
|
text: 'debool()',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'десинглетон [Alt + V]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.PUNC_ASSIGN: return {
|
|
|
|
|
text: ':=',
|
2023-07-31 22:38:58 +03:00
|
|
|
|
tooltip: 'присвоение (императивный синтаксис) [Alt + Shift + 6]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
case TokenID.PUNC_ITERATE: return {
|
|
|
|
|
text: ':∈',
|
2023-07-31 22:38:58 +03:00
|
|
|
|
tooltip: 'перебор элементов множества (императивный синтаксис) [Alt + 6]'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
text: 'undefined',
|
2023-07-25 20:27:29 +03:00
|
|
|
|
tooltip: 'undefined'
|
2023-07-20 17:11:03 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCstTypeLabel(type: CstType) {
|
2023-07-25 20:27:29 +03:00
|
|
|
|
switch (type) {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
case CstType.BASE: return 'Базисное множество';
|
|
|
|
|
case CstType.CONSTANT: return 'Константное множество';
|
|
|
|
|
case CstType.STRUCTURED: return 'Родовая структура';
|
|
|
|
|
case CstType.AXIOM: return 'Аксиома';
|
|
|
|
|
case CstType.TERM: return 'Терм';
|
|
|
|
|
case CstType.FUNCTION: return 'Терм-функция';
|
|
|
|
|
case CstType.PREDICATE: return 'Предикат-функция';
|
|
|
|
|
case CstType.THEOREM: return 'Теорема';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-26 23:11:00 +03:00
|
|
|
|
export function getCstTypeShortcut(type: CstType) {
|
|
|
|
|
const prefix = getCstTypeLabel(type) + ' [Alt + ';
|
|
|
|
|
switch (type) {
|
|
|
|
|
case CstType.BASE: return prefix + '1]';
|
|
|
|
|
case CstType.STRUCTURED: return prefix + '2]';
|
|
|
|
|
case CstType.TERM: return prefix + '3]';
|
|
|
|
|
case CstType.AXIOM: return prefix + '4]';
|
|
|
|
|
case CstType.FUNCTION: return prefix + 'Q]';
|
|
|
|
|
case CstType.PREDICATE: return prefix + 'W]';
|
|
|
|
|
case CstType.CONSTANT: return prefix + '5]';
|
|
|
|
|
case CstType.THEOREM: return prefix + '6]';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 15:23:01 +03:00
|
|
|
|
export const CstTypeSelector = (Object.values(CstType)).map(
|
|
|
|
|
(typeStr) => {
|
|
|
|
|
const type = typeStr as CstType;
|
2023-07-25 20:27:29 +03:00
|
|
|
|
return { value: type, label: getCstTypeLabel(type) };
|
2023-07-30 00:47:07 +03:00
|
|
|
|
});
|
|
|
|
|
|
2023-08-02 21:35:24 +03:00
|
|
|
|
export function getCstCompareLabel(mode: CstMatchMode): string {
|
|
|
|
|
switch(mode) {
|
|
|
|
|
case CstMatchMode.ALL: return 'везде';
|
|
|
|
|
case CstMatchMode.EXPR: return 'ФВ';
|
|
|
|
|
case CstMatchMode.TERM: return 'термин';
|
|
|
|
|
case CstMatchMode.TEXT: return 'текст';
|
|
|
|
|
case CstMatchMode.NAME: return 'ID';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getDependencyLabel(mode: DependencyMode): string {
|
|
|
|
|
switch(mode) {
|
|
|
|
|
case DependencyMode.ALL: return 'вся схема';
|
|
|
|
|
case DependencyMode.EXPRESSION: return 'выражение';
|
|
|
|
|
case DependencyMode.OUTPUTS: return 'потребители';
|
|
|
|
|
case DependencyMode.INPUTS: return 'поставщики';
|
|
|
|
|
case DependencyMode.EXPAND_INPUTS: return 'влияющие';
|
|
|
|
|
case DependencyMode.EXPAND_OUTPUTS: return 'зависимые';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-30 00:47:07 +03:00
|
|
|
|
export const GraphLayoutSelector: {value: LayoutTypes, label: string}[] = [
|
2023-08-15 21:22:21 +03:00
|
|
|
|
{ value: 'treeTd2d', label: 'Граф: ДеревоВ 2D'},
|
|
|
|
|
{ value: 'treeTd3d', label: 'Граф: ДеревоВ 3D'},
|
|
|
|
|
{ value: 'forceatlas2', label: 'Граф: Атлас 2D'},
|
|
|
|
|
{ value: 'forceDirected2d', label: 'Граф: Силы 2D'},
|
|
|
|
|
{ value: 'forceDirected3d', label: 'Граф: Силы 3D'},
|
|
|
|
|
{ value: 'treeLr2d', label: 'Граф: ДеревоГ 2D'},
|
|
|
|
|
{ value: 'treeLr3d', label: 'Граф: ДеревоГ 3D'},
|
|
|
|
|
{ value: 'radialOut2d', label: 'Граф: Радиальная 2D'},
|
|
|
|
|
{ value: 'radialOut3d', label: 'Граф: Радиальная 3D'},
|
2023-07-31 22:38:58 +03:00
|
|
|
|
// { value: 'circular2d', label: 'circular2d'},
|
|
|
|
|
// { value: 'nooverlap', label: 'nooverlap'},
|
|
|
|
|
// { value: 'hierarchicalTd', label: 'hierarchicalTd'},
|
|
|
|
|
// { value: 'hierarchicalLr', label: 'hierarchicalLr'}
|
2023-07-30 00:47:07 +03:00
|
|
|
|
];
|
2023-07-23 15:23:01 +03:00
|
|
|
|
|
2023-08-15 21:22:21 +03:00
|
|
|
|
export const mapLayoutLabels: Map<string, string> = new Map([
|
|
|
|
|
['forceatlas2', 'Граф: Атлас 2D'],
|
|
|
|
|
['forceDirected2d', 'Граф: Силы 2D'],
|
|
|
|
|
['forceDirected3d', 'Граф: Силы 3D'],
|
|
|
|
|
['treeTd2d', 'Граф: ДеревоВерт 2D'],
|
|
|
|
|
['treeTd3d', 'Граф: ДеревоВерт 3D'],
|
|
|
|
|
['treeLr2d', 'Граф: ДеревоГор 2D'],
|
|
|
|
|
['treeLr3d', 'Граф: ДеревоГор 3D'],
|
|
|
|
|
['radialOut2d', 'Граф: Радиальная 2D'],
|
|
|
|
|
['radialOut3d', 'Граф: Радиальная 3D'],
|
|
|
|
|
['circular2d', 'Граф: Круговая'],
|
|
|
|
|
['hierarchicalTd', 'Граф: ИерархияВерт'],
|
|
|
|
|
['hierarchicalLr', 'Граф: ИерархияГор'],
|
|
|
|
|
['nooverlap', 'Граф: Без перекрытия']
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
export const mapColoringLabels: Map<string, string> = new Map([
|
|
|
|
|
['none', 'Цвет: моно'],
|
|
|
|
|
['status', 'Цвет: статус'],
|
2023-08-16 00:39:16 +03:00
|
|
|
|
['type', 'Цвет: класс'],
|
2023-08-15 21:22:21 +03:00
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
export const GraphColoringSelector: {value: ColoringScheme, label: string}[] = [
|
|
|
|
|
{ value: 'none', label: 'Цвет: моно'},
|
|
|
|
|
{ value: 'status', label: 'Цвет: статус'},
|
2023-08-16 00:39:16 +03:00
|
|
|
|
{ value: 'type', label: 'Цвет: класс'},
|
2023-08-15 21:22:21 +03:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export function getCstStatusColor(status: ExpressionStatus, darkMode: boolean): string {
|
|
|
|
|
switch (status) {
|
|
|
|
|
case ExpressionStatus.VERIFIED: return darkMode ? '#2b8000': '#aaff80';
|
|
|
|
|
case ExpressionStatus.INCORRECT: return darkMode ? '#592b2b': '#ffc9c9';
|
|
|
|
|
case ExpressionStatus.INCALCULABLE: return darkMode ? '#964600': '#ffbb80';
|
|
|
|
|
case ExpressionStatus.PROPERTY: return darkMode ? '#36899e': '#a5e9fa';
|
|
|
|
|
case ExpressionStatus.UNKNOWN: return darkMode ? '#1e00b3': '#b3bdff';
|
|
|
|
|
case ExpressionStatus.UNDEFINED: return darkMode ? '#1e00b3': '#b3bdff';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-16 00:39:16 +03:00
|
|
|
|
export const mapStatusInfo: Map<ExpressionStatus, IFormatInfo> = new Map([
|
2023-07-31 22:38:58 +03:00
|
|
|
|
[ ExpressionStatus.VERIFIED, {
|
|
|
|
|
text: 'ок',
|
|
|
|
|
color: 'bg-[#aaff80] dark:bg-[#2b8000]',
|
|
|
|
|
tooltip: 'выражение корректно и вычислимо'
|
|
|
|
|
}],
|
|
|
|
|
[ ExpressionStatus.INCORRECT, {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
text: 'ошибка',
|
2023-07-31 22:38:58 +03:00
|
|
|
|
color: 'bg-[#ffc9c9] dark:bg-[#592b2b]',
|
2023-07-20 17:11:03 +03:00
|
|
|
|
tooltip: 'ошибка в выражении'
|
2023-07-31 22:38:58 +03:00
|
|
|
|
}],
|
|
|
|
|
[ ExpressionStatus.INCALCULABLE, {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
text: 'невыч',
|
|
|
|
|
color: 'bg-[#ffbb80] dark:bg-[#964600]',
|
2023-08-16 13:48:46 +03:00
|
|
|
|
tooltip: 'выражение не вычислимо'
|
2023-07-31 22:38:58 +03:00
|
|
|
|
}],
|
|
|
|
|
[ ExpressionStatus.PROPERTY, {
|
2023-07-20 17:11:03 +03:00
|
|
|
|
text: 'св-во',
|
|
|
|
|
color: 'bg-[#a5e9fa] dark:bg-[#36899e]',
|
|
|
|
|
tooltip: 'можно проверить принадлежность, но нельзя получить значение'
|
2023-07-31 22:38:58 +03:00
|
|
|
|
}],
|
|
|
|
|
[ ExpressionStatus.UNKNOWN, {
|
|
|
|
|
text: 'неизв',
|
|
|
|
|
color: 'bg-[#b3bdff] dark:bg-[#1e00b3]',
|
|
|
|
|
tooltip: 'требует проверки выражения'
|
|
|
|
|
}],
|
|
|
|
|
[ ExpressionStatus.UNDEFINED, {
|
|
|
|
|
text: 'N/A',
|
|
|
|
|
color: 'bg-[#b3bdff] dark:bg-[#1e00b3]',
|
|
|
|
|
tooltip: 'произошла ошибка при проверке выражения'
|
|
|
|
|
}],
|
|
|
|
|
]);
|
2023-07-20 17:11:03 +03:00
|
|
|
|
|
2023-08-16 00:39:16 +03:00
|
|
|
|
export function getCstClassColor(cstClass: CstClass, darkMode: boolean): string {
|
|
|
|
|
switch (cstClass) {
|
|
|
|
|
case CstClass.TEMPLATE: return darkMode ? '#36899e': '#a5e9fa';
|
|
|
|
|
case CstClass.BASIC: return darkMode ? '#2b8000': '#aaff80';
|
|
|
|
|
case CstClass.DERIVED: return darkMode ? '#1e00b3': '#b3bdff';
|
|
|
|
|
case CstClass.STATEMENT: return darkMode ? '#592b2b': '#ffc9c9';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const mapCstClassInfo: Map<CstClass, IFormatInfo> = new Map([
|
|
|
|
|
[ CstClass.BASIC, {
|
|
|
|
|
text: 'базовый',
|
|
|
|
|
color: 'bg-[#aaff80] dark:bg-[#2b8000]',
|
|
|
|
|
tooltip: 'неопределяемое понятие, требует конвенции'
|
|
|
|
|
}],
|
|
|
|
|
[ CstClass.DERIVED, {
|
|
|
|
|
text: 'производный',
|
|
|
|
|
color: 'bg-[#b3bdff] dark:bg-[#1e00b3]',
|
|
|
|
|
tooltip: 'выводимое понятие, задаваемое определением'
|
|
|
|
|
}],
|
|
|
|
|
[ CstClass.STATEMENT, {
|
|
|
|
|
text: 'утверждение',
|
|
|
|
|
color: 'bg-[#ffc9c9] dark:bg-[#592b2b]',
|
|
|
|
|
tooltip: 'неопределяемое понятие, требует конвенции'
|
|
|
|
|
}],
|
|
|
|
|
[ CstClass.TEMPLATE, {
|
|
|
|
|
text: 'шаблон',
|
|
|
|
|
color: 'bg-[#a5e9fa] dark:bg-[#36899e]',
|
|
|
|
|
tooltip: 'параметризованный шаблон определения'
|
|
|
|
|
}],
|
|
|
|
|
]);
|
|
|
|
|
|
2023-07-23 15:23:01 +03:00
|
|
|
|
export function createAliasFor(type: CstType, schema: IRSForm): string {
|
2023-07-25 20:27:29 +03:00
|
|
|
|
const prefix = getCstTypePrefix(type);
|
2023-07-25 00:20:37 +03:00
|
|
|
|
if (!schema.items || schema.items.length <= 0) {
|
|
|
|
|
return `${prefix}1`;
|
2023-07-23 15:23:01 +03:00
|
|
|
|
}
|
2023-07-25 00:20:37 +03:00
|
|
|
|
const index = schema.items.reduce((prev, cst, index) => {
|
|
|
|
|
if (cst.cstType !== type) {
|
|
|
|
|
return prev;
|
|
|
|
|
}
|
|
|
|
|
index = Number(cst.alias.slice(1 - cst.alias.length)) + 1;
|
|
|
|
|
return Math.max(prev, index);
|
|
|
|
|
}, 1);
|
|
|
|
|
return `${prefix}${index}`;
|
2023-07-25 20:27:29 +03:00
|
|
|
|
}
|
2023-07-26 23:11:00 +03:00
|
|
|
|
|
|
|
|
|
export function getMockConstituenta(id: number, alias: string, type: CstType, comment: string): IConstituenta {
|
|
|
|
|
return {
|
|
|
|
|
id: id,
|
|
|
|
|
alias: alias,
|
|
|
|
|
convention: comment,
|
|
|
|
|
cstType: type,
|
|
|
|
|
term: {
|
|
|
|
|
raw: '',
|
|
|
|
|
resolved: '',
|
|
|
|
|
forms: []
|
|
|
|
|
},
|
|
|
|
|
definition: {
|
|
|
|
|
formal: '',
|
|
|
|
|
text: {
|
|
|
|
|
raw: '',
|
|
|
|
|
resolved: ''
|
|
|
|
|
}
|
|
|
|
|
},
|
2023-07-31 22:38:58 +03:00
|
|
|
|
status: ExpressionStatus.INCORRECT,
|
2023-08-16 00:39:16 +03:00
|
|
|
|
isTemplate: false,
|
|
|
|
|
cstClass: CstClass.DERIVED,
|
2023-07-26 23:11:00 +03:00
|
|
|
|
parse: {
|
|
|
|
|
status: ParsingStatus.INCORRECT,
|
|
|
|
|
valueClass: ValueClass.INVALID,
|
|
|
|
|
typification: 'N/A',
|
2023-08-06 23:13:45 +03:00
|
|
|
|
syntaxTree: '',
|
|
|
|
|
args: []
|
2023-07-26 23:11:00 +03:00
|
|
|
|
}
|
|
|
|
|
};
|
2023-07-28 01:37:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCloneTitle(schema: IRSForm): string {
|
|
|
|
|
if (!schema.title.includes('[клон]')) {
|
|
|
|
|
return schema.title + ' [клон]';
|
|
|
|
|
} else {
|
|
|
|
|
return (schema.title + '+');
|
|
|
|
|
}
|
2023-07-29 03:31:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 23:13:45 +03:00
|
|
|
|
export function getTypificationLabel({isValid, resultType, args}: {
|
|
|
|
|
isValid: boolean,
|
|
|
|
|
resultType: string,
|
|
|
|
|
args: IFunctionArg[]
|
|
|
|
|
}): string {
|
|
|
|
|
if (!isValid) {
|
|
|
|
|
return 'N/A';
|
|
|
|
|
}
|
|
|
|
|
if (resultType === '') {
|
|
|
|
|
resultType = 'Логический'
|
|
|
|
|
}
|
|
|
|
|
if (args.length === 0) {
|
|
|
|
|
return resultType;
|
|
|
|
|
}
|
|
|
|
|
const argsText = args.map(arg => arg.typification).join(', ');
|
|
|
|
|
return `${resultType} 🠔 [${argsText}]`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCstTypificationLabel(cst: IConstituenta): string {
|
|
|
|
|
return getTypificationLabel({
|
|
|
|
|
isValid: cst.parse.status === ParsingStatus.VERIFIED,
|
|
|
|
|
resultType: cst.parse.typification,
|
|
|
|
|
args: cst.parse.args
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 03:31:21 +03:00
|
|
|
|
export function getRSErrorPrefix(error: IRSErrorDescription): string {
|
|
|
|
|
const id = error.errorType.toString(16)
|
|
|
|
|
switch(resolveErrorClass(error.errorType)) {
|
|
|
|
|
case RSErrorClass.LEXER: return 'L' + id;
|
|
|
|
|
case RSErrorClass.PARSER: return 'P' + id;
|
|
|
|
|
case RSErrorClass.SEMANTIC: return 'S' + id;
|
|
|
|
|
case RSErrorClass.UNKNOWN: return 'U' + id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getRSErrorMessage(error: IRSErrorDescription): string {
|
|
|
|
|
switch (error.errorType) {
|
|
|
|
|
case RSErrorType.syntax:
|
|
|
|
|
return 'UNKNOWN SYNTAX ERROR';
|
|
|
|
|
case RSErrorType.missingParanthesis:
|
|
|
|
|
return 'Некорректная конструкция языка родов структур, проверьте структуру выражения';
|
|
|
|
|
case RSErrorType.missingCurlyBrace:
|
|
|
|
|
return "Пропущен символ '}'";
|
|
|
|
|
case RSErrorType.invalidQuantifier:
|
|
|
|
|
return 'Некорректная кванторная декларация';
|
|
|
|
|
case RSErrorType.expectedArgDeclaration:
|
|
|
|
|
return 'Ожидалось объявление аргументов терм-функции';
|
|
|
|
|
case RSErrorType.expectedLocal:
|
|
|
|
|
return 'Ожидалось имя локальной переменной';
|
|
|
|
|
|
|
|
|
|
case RSErrorType.localDoubleDeclare:
|
|
|
|
|
return `Предупреждение! Повторное объявление локальной переменной ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.localNotUsed:
|
2023-07-31 22:38:58 +03:00
|
|
|
|
return `Предупреждение! Переменная объявлена, но не использована: ${error.params[0]}`;
|
2023-07-29 03:31:21 +03:00
|
|
|
|
case RSErrorType.localShadowing:
|
|
|
|
|
return `Повторное объявление переменной: ${error.params[0]}`;
|
|
|
|
|
|
|
|
|
|
case RSErrorType.typesNotEqual:
|
|
|
|
|
return `Типизация операндов не совпадает! ${error.params[0]} != ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.globalNotTyped:
|
|
|
|
|
return `Типизация конституенты не определена: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidDecart:
|
|
|
|
|
return `τ(α×b) = ℬ(𝔇τ(α)×𝔇τ(b)). Некорректная типизация аргумента: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidBoolean:
|
|
|
|
|
return `τ(ℬ(a)) = ℬℬ𝔇τ(a). Некорректная типизация аргумента: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidTypeOperation:
|
|
|
|
|
return `Типизация операнда теоретико-множественной операции не корректна: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidCard:
|
|
|
|
|
return `Некорректная типизация аргумента операции мощности: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidDebool:
|
|
|
|
|
return `τ(debool(a)) = 𝔇τ(a). Некорректная типизация аргумента: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.globalFuncMissing:
|
|
|
|
|
return `Неизвестное имя функции: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.globalFuncWithoutArgs:
|
|
|
|
|
return `Некорректное использование имени функции без аргументов: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidReduce:
|
|
|
|
|
return `τ(red(a)) = ℬ𝔇𝔇τ(a). Некорректная типизация аргумента: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidProjectionTuple:
|
|
|
|
|
return `Проекция не определена: ${error.params[0]} -> ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.invalidProjectionSet:
|
|
|
|
|
return `τ(Pri(a)) = ℬ𝒞i𝔇τ(a). Некорректная типизация аргумента: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidEnumeration:
|
|
|
|
|
return `Типизация аргументов перечисления не совпадает: ${error.params[0]} != ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.ivalidBinding:
|
|
|
|
|
return `Количество переменных в кортеже не соответствует размерности декартова произведения`;
|
|
|
|
|
case RSErrorType.localOutOfScope:
|
|
|
|
|
return `Использование имени переменной вне области действия: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidElementPredicat:
|
|
|
|
|
return `Несоответствие типизаций операндов для оператора: ${error.params[0]}${error.params[1]}${error.params[2]}`;
|
|
|
|
|
case RSErrorType.invalidArgsArtity:
|
|
|
|
|
return `Неверное число аргументов терм-функции: ${error.params[0]} != ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.invalidArgumentType:
|
|
|
|
|
return `Типизация аргумента терм-функции не соответствует объявленной: ${error.params[0]} != ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.invalidEqualsEmpty:
|
|
|
|
|
return `Только множества можно сравнивать с пустым множеством: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.globalStructure:
|
|
|
|
|
return `Выражение родовой структуры должно быть ступенью`;
|
|
|
|
|
case RSErrorType.globalExpectedFunction:
|
|
|
|
|
return `Ожидалось выражение объявления функции`;
|
|
|
|
|
case RSErrorType.emptySetUsage:
|
|
|
|
|
return `Запрещено использование пустого множества как типизированного выражения`;
|
|
|
|
|
case RSErrorType.radicalUsage:
|
|
|
|
|
return `Радикалы запрещены вне деклараций терм-функци: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidFilterArgumentType:
|
|
|
|
|
return `Типизация аргумента фильтра не корректна: ${error.params[0]}(${error.params[1]})`;
|
|
|
|
|
case RSErrorType.invalidFilterArity:
|
|
|
|
|
return `Количество параметров фильтра не соответствует количеству индексов`;
|
|
|
|
|
case RSErrorType.arithmeticNotSupported:
|
|
|
|
|
return `Тип не поддерживает арифметические операторы: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.typesNotCompatible:
|
|
|
|
|
return `Типы не совместимы для выбранной операции: ${error.params[0]} и ${error.params[1]}`;
|
|
|
|
|
case RSErrorType.orderingNotSupported:
|
|
|
|
|
return `Тип не поддерживает предикаты порядка: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.globalNoValue:
|
|
|
|
|
return `Используется неинтерпретируемый глобальный идентификатор: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.invalidPropertyUsage:
|
|
|
|
|
return `Использование неитерируемого множества в качестве значения`;
|
|
|
|
|
case RSErrorType.globalMissingAST:
|
|
|
|
|
return `Не удалось получить дерево разбора для глобального идентификатора: ${error.params[0]}`;
|
|
|
|
|
case RSErrorType.globalFuncNoInterpretation:
|
|
|
|
|
return `Функция не интерпретируется для данных аргументов`;
|
|
|
|
|
}
|
|
|
|
|
return 'UNKNOWN ERROR';
|
|
|
|
|
}
|
2023-08-01 21:55:18 +03:00
|
|
|
|
|
|
|
|
|
export function getNodeLabel(node: ISyntaxTreeNode): string {
|
|
|
|
|
switch(node.typeID) {
|
|
|
|
|
case TokenID.ID_LOCAL: return node.data.value as string;
|
|
|
|
|
case TokenID.ID_GLOBAL: return node.data.value as string;
|
|
|
|
|
case TokenID.ID_FUNCTION: return node.data.value as string;
|
|
|
|
|
case TokenID.ID_PREDICATE: return node.data.value as string;
|
|
|
|
|
case TokenID.ID_RADICAL: return node.data.value as string;
|
|
|
|
|
|
|
|
|
|
case TokenID.LIT_INTEGER: return String(node.data.value as number);
|
|
|
|
|
|
|
|
|
|
case TokenID.BIGPR: return 'Pr' + (node.data.value as string[]).toString();
|
|
|
|
|
case TokenID.SMALLPR: return 'pr' + (node.data.value as string[]).toString();
|
|
|
|
|
case TokenID.FILTER: return 'Fi' + (node.data.value as string[]).toString();
|
|
|
|
|
|
|
|
|
|
case TokenID.PLUS: return '+'
|
|
|
|
|
case TokenID.MINUS: return '-'
|
|
|
|
|
case TokenID.MULTIPLY: return '*'
|
|
|
|
|
case TokenID.GREATER: return '>'
|
|
|
|
|
case TokenID.LESSER: return '<'
|
|
|
|
|
|
|
|
|
|
case TokenID.NT_TUPLE: return 'TUPLE'
|
|
|
|
|
case TokenID.NT_ENUMERATION: return 'ENUM'
|
|
|
|
|
|
|
|
|
|
case TokenID.NT_ENUM_DECL: return 'ENUM_DECLARATION'
|
|
|
|
|
case TokenID.NT_TUPLE_DECL: return 'TUPLE_DECLARATION'
|
|
|
|
|
case TokenID.PUNC_DEFINE: return 'DEFINITION'
|
|
|
|
|
|
|
|
|
|
case TokenID.NT_ARG_DECL: return 'ARG'
|
|
|
|
|
case TokenID.NT_FUNC_CALL: return 'CALL'
|
|
|
|
|
case TokenID.NT_ARGUMENTS: return 'ARGS'
|
|
|
|
|
|
|
|
|
|
case TokenID.NT_FUNC_DEFINITION: return 'FUNCTION_DEFINITION'
|
|
|
|
|
case TokenID.NT_IMP_DECLARE: return 'IDECLARE'
|
|
|
|
|
case TokenID.NT_IMP_ASSIGN: return 'IASSIGN'
|
|
|
|
|
case TokenID.NT_IMP_LOGIC: return 'ICHECK'
|
|
|
|
|
|
|
|
|
|
case TokenID.NT_RECURSIVE_SHORT: return getRSButtonData(TokenID.NT_RECURSIVE_FULL).text;
|
|
|
|
|
|
|
|
|
|
case TokenID.BOOLEAN:
|
|
|
|
|
case TokenID.DECART:
|
|
|
|
|
case TokenID.FORALL:
|
|
|
|
|
case TokenID.EXISTS:
|
|
|
|
|
case TokenID.NOT:
|
|
|
|
|
case TokenID.AND:
|
|
|
|
|
case TokenID.OR:
|
|
|
|
|
case TokenID.IMPLICATION:
|
|
|
|
|
case TokenID.EQUIVALENT:
|
|
|
|
|
case TokenID.LIT_EMPTYSET:
|
|
|
|
|
case TokenID.LIT_INTSET:
|
|
|
|
|
case TokenID.EQUAL:
|
|
|
|
|
case TokenID.NOTEQUAL:
|
|
|
|
|
case TokenID.GREATER_OR_EQ:
|
|
|
|
|
case TokenID.LESSER_OR_EQ:
|
|
|
|
|
case TokenID.IN:
|
|
|
|
|
case TokenID.NOTIN:
|
|
|
|
|
case TokenID.SUBSET_OR_EQ:
|
|
|
|
|
case TokenID.SUBSET:
|
|
|
|
|
case TokenID.NOTSUBSET:
|
|
|
|
|
case TokenID.INTERSECTION:
|
|
|
|
|
case TokenID.UNION:
|
|
|
|
|
case TokenID.SET_MINUS:
|
|
|
|
|
case TokenID.SYMMINUS:
|
|
|
|
|
case TokenID.NT_DECLARATIVE_EXPR:
|
|
|
|
|
case TokenID.NT_IMPERATIVE_EXPR:
|
|
|
|
|
case TokenID.NT_RECURSIVE_FULL:
|
|
|
|
|
case TokenID.REDUCE:
|
|
|
|
|
case TokenID.CARD:
|
|
|
|
|
case TokenID.BOOL:
|
|
|
|
|
case TokenID.DEBOOL:
|
|
|
|
|
case TokenID.PUNC_ASSIGN:
|
|
|
|
|
case TokenID.PUNC_ITERATE:
|
|
|
|
|
return getRSButtonData(node.typeID).text;
|
|
|
|
|
}
|
|
|
|
|
// node
|
|
|
|
|
return 'UNKNOWN ' + String(node.typeID);
|
|
|
|
|
}
|