@rsconcept/domain 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{analyzer-camCAEkQ.d.ts → analyzer-QxWs73gP.d.ts} +2 -2
- package/dist/{ast-annotations-DiXmFraa.d.ts → ast-annotations-CtF7C9uK.d.ts} +2 -2
- package/dist/{calculator-BuVooqpb.d.ts → calculator-REeX2ZS1.d.ts} +2 -2
- package/dist/{error-CZXO5Y6a.d.ts → error-toW0TUHF.d.ts} +10 -1
- package/dist/index.d.ts +4 -4
- package/dist/library/rsengine.d.ts +1 -1
- package/dist/library/rsform-api.d.ts +1 -1
- package/dist/library/rsform.d.ts +1 -1
- package/dist/rslang/ast-annotations.d.ts +1 -1
- package/dist/rslang/error.d.ts +1 -1
- package/dist/rslang/error.js +9 -0
- package/dist/rslang/error.js.map +1 -1
- package/dist/rslang/eval/calculator.d.ts +1 -1
- package/dist/rslang/eval/evaluator.d.ts +1 -1
- package/dist/rslang/index.d.ts +4 -4
- package/dist/rslang/labels.d.ts +1 -1
- package/dist/rslang/labels.js +1 -1
- package/dist/rslang/labels.js.map +1 -1
- package/dist/rslang/parser/normalize.js +5 -1
- package/dist/rslang/parser/normalize.js.map +1 -1
- package/dist/rslang/parser/syntax-errors/index.d.ts +22 -0
- package/dist/rslang/parser/syntax-errors/index.js +2 -0
- package/dist/rslang/semantic/analyzer.d.ts +1 -1
- package/dist/rslang/semantic/analyzer.js +1 -1
- package/dist/rslang/semantic/type-auditor.d.ts +1 -1
- package/dist/rslang/semantic/value-auditor.d.ts +1 -1
- package/dist/syntax-errors-pCI6RicF.js +689 -0
- package/dist/syntax-errors-pCI6RicF.js.map +1 -0
- package/package.json +1 -1
- package/src/rslang/error.ts +9 -0
- package/src/rslang/labels.ts +1 -1
- package/src/rslang/parser/README.md +73 -0
- package/src/rslang/parser/normalize.ts +5 -1
- package/src/rslang/parser/parser.test.ts +92 -6
- package/src/rslang/parser/syntax-errors/README.md +61 -0
- package/src/rslang/parser/syntax-errors/ast-utils.ts +112 -0
- package/src/rslang/parser/syntax-errors/classify.ts +70 -0
- package/src/rslang/parser/syntax-errors/context.ts +25 -0
- package/src/rslang/parser/syntax-errors/error-builders.ts +28 -0
- package/src/rslang/parser/syntax-errors/expression-errors.ts +237 -0
- package/src/rslang/parser/syntax-errors/function-calls.ts +76 -0
- package/src/rslang/parser/syntax-errors/generators.ts +307 -0
- package/src/rslang/parser/syntax-errors/incomplete-formal.ts +76 -0
- package/src/rslang/parser/syntax-errors/incomplete-operands.ts +184 -0
- package/src/rslang/parser/syntax-errors/index.ts +102 -0
- package/src/rslang/parser/syntax-errors/trailing-slot.ts +45 -0
- package/dist/rslang/parser/syntax-errors.d.ts +0 -14
- package/dist/rslang/parser/syntax-errors.js +0 -311
- package/dist/rslang/parser/syntax-errors.js.map +0 -1
- package/src/rslang/parser/syntax-errors.ts +0 -511
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
import { annotateError } from "../ast-annotations.js";
|
|
2
|
-
import { RSErrorCode } from "../error.js";
|
|
3
|
-
import { visitAstDFS } from "../../parsing/ast.js";
|
|
4
|
-
import "../../parsing/index.js";
|
|
5
|
-
import { TokenID } from "./token.js";
|
|
6
|
-
import { TypeClass } from "../semantic/typification.js";
|
|
7
|
-
import "./parser.terms.js";
|
|
8
|
-
//#region src/rslang/parser/syntax-errors.ts
|
|
9
|
-
/**
|
|
10
|
-
* Module: Syntactic errors reporting.
|
|
11
|
-
*/
|
|
12
|
-
/** Extracts syntax errors from an AST. */
|
|
13
|
-
function extractSyntaxErrors(ast, expression, reporter, annotateErrors = false, options) {
|
|
14
|
-
const forbiddenErrors = extractForbiddenCharacterErrors(expression);
|
|
15
|
-
if (forbiddenErrors.length > 0) {
|
|
16
|
-
for (const error of forbiddenErrors) {
|
|
17
|
-
reporter(error);
|
|
18
|
-
if (annotateErrors) annotateError(ast, error.code, error.params);
|
|
19
|
-
}
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const collected = [];
|
|
23
|
-
const annotationTargets = /* @__PURE__ */ new Map();
|
|
24
|
-
const collect = (error, target) => {
|
|
25
|
-
collected.push(error);
|
|
26
|
-
if (target !== void 0) annotationTargets.set(error, target);
|
|
27
|
-
};
|
|
28
|
-
const bracketError = extractBracketErrors(expression);
|
|
29
|
-
if (bracketError !== null) collect(bracketError, ast);
|
|
30
|
-
const hasBracketErrors = bracketError !== null;
|
|
31
|
-
visitAstDFS(ast, (node) => extractInternal(node, expression, collect, hasBracketErrors, options));
|
|
32
|
-
for (const error of deduplicateErrors(collected)) {
|
|
33
|
-
reporter(error);
|
|
34
|
-
if (annotateErrors) {
|
|
35
|
-
const target = annotationTargets.get(error);
|
|
36
|
-
if (target !== void 0) annotateError(target, error.code, error.params);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function extractInternal(node, expression, collect, ignoreUnknownErrors, options) {
|
|
41
|
-
if (node.typeID !== TokenID.ERROR) return;
|
|
42
|
-
function emit(target, code, params) {
|
|
43
|
-
collect({
|
|
44
|
-
code,
|
|
45
|
-
from: target.from,
|
|
46
|
-
to: target.to,
|
|
47
|
-
params
|
|
48
|
-
}, target);
|
|
49
|
-
}
|
|
50
|
-
const classified = classifyParseError(node, expression, options);
|
|
51
|
-
if (classified !== null) {
|
|
52
|
-
collect(classified, node);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const parent = node.parent;
|
|
56
|
-
if (parent === null) {
|
|
57
|
-
if (!ignoreUnknownErrors) return emit(node, RSErrorCode.unknownSyntax);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (parent.typeID === 4) return emit(parent, RSErrorCode.expectedLocal);
|
|
61
|
-
if (!ignoreUnknownErrors) emit(node.from === node.to ? parent : node, RSErrorCode.unknownSyntax);
|
|
62
|
-
}
|
|
63
|
-
function classifyParseError(node, expression, options) {
|
|
64
|
-
const incompleteFunctionDecl = detectIncompleteFunctionDecl(node, expression, options?.expected);
|
|
65
|
-
if (incompleteFunctionDecl !== null) return incompleteFunctionDecl;
|
|
66
|
-
const filterParen = detectFilterParenMismatch(node, expression);
|
|
67
|
-
if (filterParen !== null) return filterParen;
|
|
68
|
-
return detectGlobalFuncWithoutArgs(node, expression);
|
|
69
|
-
}
|
|
70
|
-
function detectIncompleteFunctionDecl(node, expression, expected) {
|
|
71
|
-
const funcDecl = findAncestor(node, isFunctionDeclNode);
|
|
72
|
-
if (funcDecl === null) return null;
|
|
73
|
-
const bodyChild = funcDecl.children[funcDecl.children.length - 1];
|
|
74
|
-
if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) return null;
|
|
75
|
-
const argsNode = funcDecl.children.find((child) => child.typeID === 77 || child.typeID === TokenID.NT_ARGUMENTS);
|
|
76
|
-
if (argsNode === void 0 || subtreeHasError(argsNode)) return null;
|
|
77
|
-
if (expression.slice(funcDecl.to).trim().length > 0) return null;
|
|
78
|
-
return {
|
|
79
|
-
code: incompleteFormalExpressionCode(expected),
|
|
80
|
-
from: bodyChild.from,
|
|
81
|
-
to: bodyChild.to
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function incompleteFormalExpressionCode(expected) {
|
|
85
|
-
switch (expected) {
|
|
86
|
-
case TypeClass.function: return RSErrorCode.expectedExpressionBody;
|
|
87
|
-
case TypeClass.predicate:
|
|
88
|
-
case TypeClass.logic: return RSErrorCode.expectedLogicBody;
|
|
89
|
-
default: return RSErrorCode.expectedFunctionBody;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function subtreeHasError(node) {
|
|
93
|
-
if (node.typeID === TokenID.ERROR) return true;
|
|
94
|
-
return node.children.some(subtreeHasError);
|
|
95
|
-
}
|
|
96
|
-
function detectFilterParenMismatch(node, expression) {
|
|
97
|
-
const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);
|
|
98
|
-
if (filterNode === null) return null;
|
|
99
|
-
if (expression[filterNode.to] === "(") return {
|
|
100
|
-
code: RSErrorCode.invalidFilterSyntax,
|
|
101
|
-
from: filterNode.from,
|
|
102
|
-
to: filterNode.to + 1
|
|
103
|
-
};
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
function detectGlobalFuncWithoutArgs(node, expression) {
|
|
107
|
-
const funcNode = findAncestor(node, (n) => isFunctionNode(n) || isPredicateNode(n)) ?? findRelatedNode(node, (n) => isFunctionNode(n) || isPredicateNode(n));
|
|
108
|
-
if (funcNode === null) return null;
|
|
109
|
-
return classifyFuncWithoutArgs(funcNode, expression);
|
|
110
|
-
}
|
|
111
|
-
function findRelatedNode(node, predicate) {
|
|
112
|
-
let current = node.parent;
|
|
113
|
-
while (current !== null) {
|
|
114
|
-
for (const child of current.children) if (predicate(child)) return child;
|
|
115
|
-
current = current.parent;
|
|
116
|
-
}
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
function classifyFuncWithoutArgs(funcNode, expression) {
|
|
120
|
-
const name = expression.slice(funcNode.from, funcNode.to);
|
|
121
|
-
const rest = expression.slice(funcNode.to);
|
|
122
|
-
const withoutArgs = {
|
|
123
|
-
code: RSErrorCode.globalFuncWithoutArgs,
|
|
124
|
-
from: funcNode.from,
|
|
125
|
-
to: funcNode.to,
|
|
126
|
-
params: [name]
|
|
127
|
-
};
|
|
128
|
-
if (/^\s*$/.test(rest)) return withoutArgs;
|
|
129
|
-
const openBracket = /^\s*\[/.exec(rest);
|
|
130
|
-
if (openBracket === null) return null;
|
|
131
|
-
const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);
|
|
132
|
-
if (closeIdx >= 0) {
|
|
133
|
-
if (rest.slice(openBracket[0].length, closeIdx).trim().length === 0) return withoutArgs;
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
function findAncestor(node, predicate) {
|
|
138
|
-
let current = node;
|
|
139
|
-
while (current !== null) {
|
|
140
|
-
if (predicate(current)) return current;
|
|
141
|
-
current = current.parent;
|
|
142
|
-
}
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
function isFunctionDeclNode(node) {
|
|
146
|
-
return node.typeID === 76 || node.typeID === TokenID.NT_FUNC_DEFINITION;
|
|
147
|
-
}
|
|
148
|
-
function isFunctionNode(node) {
|
|
149
|
-
return node.typeID === 69 || node.typeID === TokenID.ID_FUNCTION;
|
|
150
|
-
}
|
|
151
|
-
function isPredicateNode(node) {
|
|
152
|
-
return node.typeID === 26 || node.typeID === TokenID.ID_PREDICATE;
|
|
153
|
-
}
|
|
154
|
-
function isFilterNode(node) {
|
|
155
|
-
return node.typeID === 59 || node.typeID === TokenID.FILTER;
|
|
156
|
-
}
|
|
157
|
-
function findMatchingCloseBracket(expression, openPos) {
|
|
158
|
-
if (expression[openPos] !== "[") return -1;
|
|
159
|
-
let depth = 0;
|
|
160
|
-
for (let index = openPos; index < expression.length; index++) {
|
|
161
|
-
const symbol = expression[index];
|
|
162
|
-
if (symbol === "[") depth++;
|
|
163
|
-
else if (symbol === "]") {
|
|
164
|
-
depth--;
|
|
165
|
-
if (depth === 0) return index;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return -1;
|
|
169
|
-
}
|
|
170
|
-
function deduplicateErrors(errors) {
|
|
171
|
-
const result = [];
|
|
172
|
-
for (const error of errors) {
|
|
173
|
-
if (result.some((existing) => existing.code === error.code && existing.from === error.from && existing.to === error.to)) continue;
|
|
174
|
-
if (error.code !== RSErrorCode.unknownSyntax) {
|
|
175
|
-
for (let index = result.length - 1; index >= 0; index--) if (result[index].code === RSErrorCode.unknownSyntax && rangesOverlap(error, result[index])) result.splice(index, 1);
|
|
176
|
-
}
|
|
177
|
-
result.push(error);
|
|
178
|
-
}
|
|
179
|
-
const specific = result.filter((error) => error.code !== RSErrorCode.unknownSyntax);
|
|
180
|
-
return result.filter((error) => error.code !== RSErrorCode.unknownSyntax || !specific.some((item) => rangesOverlap(error, item)));
|
|
181
|
-
}
|
|
182
|
-
function rangesOverlap(a, b) {
|
|
183
|
-
return a.from < b.to && b.from < a.to;
|
|
184
|
-
}
|
|
185
|
-
const ALLOWED_EXPRESSION_CHARS = buildAllowedExpressionChars();
|
|
186
|
-
function buildAllowedExpressionChars() {
|
|
187
|
-
const chars = /* @__PURE__ */ new Set();
|
|
188
|
-
for (const chunk of [
|
|
189
|
-
"0123456789",
|
|
190
|
-
"abcdefghijklmnopqrstuvwxyz",
|
|
191
|
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
192
|
-
"_",
|
|
193
|
-
"∅¬∀∃⇔⇒∨&ℬ+-*∪\\∆∩×∈∉⊆⊄⊂<>≥≤≠=,:;|[]{}()"
|
|
194
|
-
]) for (const symbol of chunk) chars.add(symbol);
|
|
195
|
-
for (let codePoint = 945; codePoint <= 969; codePoint++) chars.add(String.fromCodePoint(codePoint));
|
|
196
|
-
return chars;
|
|
197
|
-
}
|
|
198
|
-
function isAllowedExpressionChar(symbol) {
|
|
199
|
-
return /\s/u.test(symbol) || ALLOWED_EXPRESSION_CHARS.has(symbol);
|
|
200
|
-
}
|
|
201
|
-
function extractForbiddenCharacterErrors(expression) {
|
|
202
|
-
const errors = [];
|
|
203
|
-
let pos = 0;
|
|
204
|
-
while (pos < expression.length) {
|
|
205
|
-
const symbol = expression[pos];
|
|
206
|
-
if (isAllowedExpressionChar(symbol)) {
|
|
207
|
-
pos++;
|
|
208
|
-
continue;
|
|
209
|
-
}
|
|
210
|
-
const start = pos;
|
|
211
|
-
while (pos < expression.length && !isAllowedExpressionChar(expression[pos])) pos++;
|
|
212
|
-
errors.push({
|
|
213
|
-
code: RSErrorCode.forbiddenCharacter,
|
|
214
|
-
from: start,
|
|
215
|
-
to: pos,
|
|
216
|
-
params: [expression.slice(start, pos)]
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
return errors;
|
|
220
|
-
}
|
|
221
|
-
function extractBracketErrors(expression) {
|
|
222
|
-
const stack = [];
|
|
223
|
-
for (let pos = 0; pos < expression.length; pos++) {
|
|
224
|
-
const symbol = expression[pos];
|
|
225
|
-
if (isOpenBracket(symbol)) {
|
|
226
|
-
if (isDoubleParenthesis(expression, pos)) return {
|
|
227
|
-
code: RSErrorCode.doubleParenthesis,
|
|
228
|
-
from: pos,
|
|
229
|
-
to: pos + 2
|
|
230
|
-
};
|
|
231
|
-
stack.push({
|
|
232
|
-
bracket: symbol,
|
|
233
|
-
index: pos
|
|
234
|
-
});
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
if (!isCloseBracket(symbol)) continue;
|
|
238
|
-
const expectedOpen = closeToOpen(symbol);
|
|
239
|
-
const top = stack[stack.length - 1];
|
|
240
|
-
if (top === void 0) return {
|
|
241
|
-
code: RSErrorCode.missingOpenBracket,
|
|
242
|
-
from: pos,
|
|
243
|
-
to: pos + 1,
|
|
244
|
-
params: [symbol]
|
|
245
|
-
};
|
|
246
|
-
if (top.bracket !== expectedOpen) return {
|
|
247
|
-
code: RSErrorCode.bracketMismatch,
|
|
248
|
-
from: pos,
|
|
249
|
-
to: pos + 1,
|
|
250
|
-
params: [openToClose(top.bracket), symbol]
|
|
251
|
-
};
|
|
252
|
-
stack.pop();
|
|
253
|
-
}
|
|
254
|
-
if (stack.length > 0) {
|
|
255
|
-
const unclosed = stack[0];
|
|
256
|
-
return {
|
|
257
|
-
code: RSErrorCode.missingCloseBracket,
|
|
258
|
-
from: unclosed.index,
|
|
259
|
-
to: unclosed.index + 1,
|
|
260
|
-
params: [unclosed.bracket]
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
function isOpenBracket(symbol) {
|
|
266
|
-
return symbol === "(" || symbol === "[" || symbol === "{";
|
|
267
|
-
}
|
|
268
|
-
function isCloseBracket(symbol) {
|
|
269
|
-
return symbol === ")" || symbol === "]" || symbol === "}";
|
|
270
|
-
}
|
|
271
|
-
function openToClose(symbol) {
|
|
272
|
-
switch (symbol) {
|
|
273
|
-
case "(": return ")";
|
|
274
|
-
case "[": return "]";
|
|
275
|
-
case "{": return "}";
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
function closeToOpen(symbol) {
|
|
279
|
-
switch (symbol) {
|
|
280
|
-
case ")": return "(";
|
|
281
|
-
case "]": return "[";
|
|
282
|
-
case "}": return "{";
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
function isDoubleParenthesis(expression, pos) {
|
|
286
|
-
if (!(expression[pos] === "(" && expression[pos + 1] === "(")) return false;
|
|
287
|
-
const outerClose = findMatchingCloseParen(expression, pos);
|
|
288
|
-
const innerClose = findMatchingCloseParen(expression, pos + 1);
|
|
289
|
-
if (outerClose < 0 || innerClose < 0) return false;
|
|
290
|
-
return outerClose === innerClose + 1;
|
|
291
|
-
}
|
|
292
|
-
function findMatchingCloseParen(expression, openPos) {
|
|
293
|
-
if (expression[openPos] !== "(") return -1;
|
|
294
|
-
const stack = [];
|
|
295
|
-
for (let index = openPos; index < expression.length; index++) {
|
|
296
|
-
const symbol = expression[index];
|
|
297
|
-
if (isOpenBracket(symbol)) {
|
|
298
|
-
stack.push(symbol);
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
if (!isCloseBracket(symbol)) continue;
|
|
302
|
-
const top = stack.pop();
|
|
303
|
-
if (top === void 0 || top !== closeToOpen(symbol)) return -1;
|
|
304
|
-
if (stack.length === 0) return index;
|
|
305
|
-
}
|
|
306
|
-
return -1;
|
|
307
|
-
}
|
|
308
|
-
//#endregion
|
|
309
|
-
export { extractSyntaxErrors };
|
|
310
|
-
|
|
311
|
-
//# sourceMappingURL=syntax-errors.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syntax-errors.js","names":["TypeClassEnum"],"sources":["../../../src/rslang/parser/syntax-errors.ts"],"sourcesContent":["/**\n * Module: Syntactic errors reporting.\n */\n\nimport { type AstNode, visitAstDFS } from '../../parsing';\nimport { annotateError } from '../ast-annotations';\nimport { type ErrorReporter, RSErrorCode, type RSErrorDescription } from '../error';\nimport { type TypeClass, TypeClass as TypeClassEnum } from '../semantic/typification';\n\nimport { Arguments, Filter, Function, Function_decl, Predicate, Variable } from './parser.terms';\nimport { TokenID } from './token';\n\n/** Options for syntax error extraction. */\nexport interface SyntaxErrorOptions {\n expected?: TypeClass;\n}\n\n/** Extracts syntax errors from an AST. */\nexport function extractSyntaxErrors(\n ast: AstNode,\n expression: string,\n reporter: ErrorReporter,\n annotateErrors: boolean = false,\n options?: SyntaxErrorOptions\n) {\n const forbiddenErrors = extractForbiddenCharacterErrors(expression);\n if (forbiddenErrors.length > 0) {\n for (const error of forbiddenErrors) {\n reporter(error);\n if (annotateErrors) {\n annotateError(ast, error.code, error.params);\n }\n }\n return;\n }\n\n const collected: RSErrorDescription[] = [];\n const annotationTargets = new Map<RSErrorDescription, AstNode>();\n const collect = (error: RSErrorDescription, target?: AstNode) => {\n collected.push(error);\n if (target !== undefined) {\n annotationTargets.set(error, target);\n }\n };\n\n const bracketError = extractBracketErrors(expression);\n if (bracketError !== null) {\n collect(bracketError, ast);\n }\n const hasBracketErrors = bracketError !== null;\n visitAstDFS(ast, node => extractInternal(node, expression, collect, hasBracketErrors, options));\n\n for (const error of deduplicateErrors(collected)) {\n reporter(error);\n if (annotateErrors) {\n const target = annotationTargets.get(error);\n if (target !== undefined) {\n annotateError(target, error.code, error.params);\n }\n }\n }\n}\n\n// ====== Internals =========\nfunction extractInternal(\n node: AstNode,\n expression: string,\n collect: (error: RSErrorDescription, target: AstNode) => void,\n ignoreUnknownErrors: boolean,\n options?: SyntaxErrorOptions\n) {\n if (node.typeID !== TokenID.ERROR) {\n return;\n }\n\n function emit(target: AstNode, code: RSErrorCode, params?: readonly string[]) {\n collect({ code: code, from: target.from, to: target.to, params }, target);\n }\n\n const classified = classifyParseError(node, expression, options);\n if (classified !== null) {\n collect(classified, node);\n return;\n }\n\n const parent = node.parent;\n if (parent === null) {\n if (!ignoreUnknownErrors) {\n return emit(node, RSErrorCode.unknownSyntax);\n }\n return;\n }\n\n if (parent.typeID === Variable) {\n return emit(parent, RSErrorCode.expectedLocal);\n }\n\n if (!ignoreUnknownErrors) {\n emit(node.from === node.to ? parent : node, RSErrorCode.unknownSyntax);\n }\n}\n\nfunction classifyParseError(\n node: AstNode,\n expression: string,\n options?: SyntaxErrorOptions\n): RSErrorDescription | null {\n const incompleteFunctionDecl = detectIncompleteFunctionDecl(node, expression, options?.expected);\n if (incompleteFunctionDecl !== null) {\n return incompleteFunctionDecl;\n }\n\n const filterParen = detectFilterParenMismatch(node, expression);\n if (filterParen !== null) {\n return filterParen;\n }\n\n return detectGlobalFuncWithoutArgs(node, expression);\n}\n\nfunction detectIncompleteFunctionDecl(\n node: AstNode,\n expression: string,\n expected?: TypeClass\n): RSErrorDescription | null {\n const funcDecl = findAncestor(node, isFunctionDeclNode);\n if (funcDecl === null) {\n return null;\n }\n\n const bodyChild = funcDecl.children[funcDecl.children.length - 1];\n if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) {\n return null;\n }\n\n const argsNode = funcDecl.children.find(child => child.typeID === Arguments || child.typeID === TokenID.NT_ARGUMENTS);\n if (argsNode === undefined || subtreeHasError(argsNode)) {\n return null;\n }\n\n if (expression.slice(funcDecl.to).trim().length > 0) {\n return null;\n }\n\n return {\n code: incompleteFormalExpressionCode(expected),\n from: bodyChild.from,\n to: bodyChild.to\n };\n}\n\nfunction incompleteFormalExpressionCode(expected?: TypeClass): RSErrorCode {\n switch (expected) {\n case TypeClassEnum.function:\n return RSErrorCode.expectedExpressionBody;\n case TypeClassEnum.predicate:\n case TypeClassEnum.logic:\n return RSErrorCode.expectedLogicBody;\n default:\n return RSErrorCode.expectedFunctionBody;\n }\n}\n\nfunction subtreeHasError(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n return node.children.some(subtreeHasError);\n}\n\nfunction detectFilterParenMismatch(node: AstNode, expression: string): RSErrorDescription | null {\n const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);\n if (filterNode === null) {\n return null;\n }\n\n const nextChar = expression[filterNode.to];\n if (nextChar === '(') {\n return {\n code: RSErrorCode.invalidFilterSyntax,\n from: filterNode.from,\n to: filterNode.to + 1\n };\n }\n return null;\n}\n\nfunction detectGlobalFuncWithoutArgs(node: AstNode, expression: string): RSErrorDescription | null {\n const funcNode =\n findAncestor(node, n => isFunctionNode(n) || isPredicateNode(n)) ??\n findRelatedNode(node, n => isFunctionNode(n) || isPredicateNode(n));\n if (funcNode === null) {\n return null;\n }\n return classifyFuncWithoutArgs(funcNode, expression);\n}\n\nfunction findRelatedNode(node: AstNode, predicate: (target: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node.parent;\n while (current !== null) {\n for (const child of current.children) {\n if (predicate(child)) {\n return child;\n }\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction classifyFuncWithoutArgs(funcNode: AstNode, expression: string): RSErrorDescription | null {\n const name = expression.slice(funcNode.from, funcNode.to);\n const rest = expression.slice(funcNode.to);\n\n const withoutArgs: RSErrorDescription = {\n code: RSErrorCode.globalFuncWithoutArgs,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n\n // Function with nothing (or only whitespace) after it is genuinely called without arguments.\n if (/^\\s*$/.test(rest)) {\n return withoutArgs;\n }\n\n // Anything other than a bracketed argument form (e.g. parentheses or braces) is malformed call\n // syntax: defer to the bracket/syntax error handling instead of reporting a missing-arguments error.\n const openBracket = /^\\s*\\[/.exec(rest);\n if (openBracket === null) {\n return null;\n }\n\n const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);\n if (closeIdx >= 0) {\n const inner = rest.slice(openBracket[0].length, closeIdx).trim();\n if (inner.length === 0) {\n return withoutArgs;\n }\n }\n\n return null;\n}\n\nfunction findAncestor(node: AstNode, predicate: (node: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node;\n while (current !== null) {\n if (predicate(current)) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction isFunctionDeclNode(node: AstNode): boolean {\n return node.typeID === Function_decl || node.typeID === TokenID.NT_FUNC_DEFINITION;\n}\n\nfunction isFunctionNode(node: AstNode): boolean {\n return node.typeID === Function || node.typeID === TokenID.ID_FUNCTION;\n}\n\nfunction isPredicateNode(node: AstNode): boolean {\n return node.typeID === Predicate || node.typeID === TokenID.ID_PREDICATE;\n}\n\nfunction isFilterNode(node: AstNode): boolean {\n return node.typeID === Filter || node.typeID === TokenID.FILTER;\n}\n\nfunction findMatchingCloseBracket(expression: string, openPos: number): number {\n const open = expression[openPos];\n if (open !== '[') {\n return -1;\n }\n\n let depth = 0;\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (symbol === '[') {\n depth++;\n } else if (symbol === ']') {\n depth--;\n if (depth === 0) {\n return index;\n }\n }\n }\n return -1;\n}\n\nfunction deduplicateErrors(errors: RSErrorDescription[]): RSErrorDescription[] {\n const result: RSErrorDescription[] = [];\n\n for (const error of errors) {\n const duplicate = result.some(\n existing => existing.code === error.code && existing.from === error.from && existing.to === error.to\n );\n if (duplicate) {\n continue;\n }\n\n if (error.code !== RSErrorCode.unknownSyntax) {\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index].code === RSErrorCode.unknownSyntax && rangesOverlap(error, result[index])) {\n result.splice(index, 1);\n }\n }\n }\n\n result.push(error);\n }\n\n const specific = result.filter(error => error.code !== RSErrorCode.unknownSyntax);\n return result.filter(\n error => error.code !== RSErrorCode.unknownSyntax || !specific.some(item => rangesOverlap(error, item))\n );\n}\n\nfunction rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {\n return a.from < b.to && b.from < a.to;\n}\n\ntype OpenBracket = '(' | '[' | '{';\ntype CloseBracket = ')' | ']' | '}';\n\ninterface BracketFrame {\n bracket: OpenBracket;\n index: number;\n}\n\nconst ALLOWED_EXPRESSION_CHARS = buildAllowedExpressionChars();\n\nfunction buildAllowedExpressionChars(): Set<string> {\n const chars = new Set<string>();\n for (const chunk of [\n '0123456789',\n 'abcdefghijklmnopqrstuvwxyz',\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',\n '_',\n '∅¬∀∃⇔⇒∨&ℬ+-*∪\\\\∆∩×∈∉⊆⊄⊂<>≥≤≠=,:;|[]{}()'\n ]) {\n for (const symbol of chunk) {\n chars.add(symbol);\n }\n }\n for (let codePoint = 0x03b1; codePoint <= 0x03c9; codePoint++) {\n chars.add(String.fromCodePoint(codePoint));\n }\n return chars;\n}\n\nfunction isAllowedExpressionChar(symbol: string): boolean {\n return /\\s/u.test(symbol) || ALLOWED_EXPRESSION_CHARS.has(symbol);\n}\n\nfunction extractForbiddenCharacterErrors(expression: string): RSErrorDescription[] {\n const errors: RSErrorDescription[] = [];\n let pos = 0;\n\n while (pos < expression.length) {\n const symbol = expression[pos];\n if (isAllowedExpressionChar(symbol)) {\n pos++;\n continue;\n }\n\n const start = pos;\n while (pos < expression.length && !isAllowedExpressionChar(expression[pos])) {\n pos++;\n }\n\n errors.push({\n code: RSErrorCode.forbiddenCharacter,\n from: start,\n to: pos,\n params: [expression.slice(start, pos)]\n });\n }\n\n return errors;\n}\n\nfunction extractBracketErrors(expression: string): RSErrorDescription | null {\n const stack: BracketFrame[] = [];\n\n for (let pos = 0; pos < expression.length; pos++) {\n const symbol = expression[pos];\n if (isOpenBracket(symbol)) {\n if (isDoubleParenthesis(expression, pos)) {\n return {\n code: RSErrorCode.doubleParenthesis,\n from: pos,\n to: pos + 2\n };\n }\n stack.push({ bracket: symbol, index: pos });\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n\n const expectedOpen = closeToOpen(symbol);\n const top = stack[stack.length - 1];\n if (top === undefined) {\n return {\n code: RSErrorCode.missingOpenBracket,\n from: pos,\n to: pos + 1,\n params: [symbol]\n };\n }\n\n if (top.bracket !== expectedOpen) {\n return {\n code: RSErrorCode.bracketMismatch,\n from: pos,\n to: pos + 1,\n params: [openToClose(top.bracket), symbol]\n };\n }\n\n stack.pop();\n }\n\n if (stack.length > 0) {\n const unclosed = stack[0];\n return {\n code: RSErrorCode.missingCloseBracket,\n from: unclosed.index,\n to: unclosed.index + 1,\n params: [unclosed.bracket]\n };\n }\n\n return null;\n}\n\nfunction isOpenBracket(symbol: string): symbol is OpenBracket {\n return symbol === '(' || symbol === '[' || symbol === '{';\n}\n\nfunction isCloseBracket(symbol: string): symbol is CloseBracket {\n return symbol === ')' || symbol === ']' || symbol === '}';\n}\n\nfunction openToClose(symbol: OpenBracket): CloseBracket {\n switch (symbol) {\n case '(':\n return ')';\n case '[':\n return ']';\n case '{':\n return '}';\n }\n}\n\nfunction closeToOpen(symbol: CloseBracket): OpenBracket {\n switch (symbol) {\n case ')':\n return '(';\n case ']':\n return '[';\n case '}':\n return '{';\n }\n}\n\nfunction isDoubleParenthesis(expression: string, pos: number): boolean {\n const isOpenDoubleParenthesis = expression[pos] === '(' && expression[pos + 1] === '(';\n if (!isOpenDoubleParenthesis) {\n return false;\n }\n\n const outerClose = findMatchingCloseParen(expression, pos);\n const innerClose = findMatchingCloseParen(expression, pos + 1);\n if (outerClose < 0 || innerClose < 0) {\n return false;\n }\n\n return outerClose === innerClose + 1;\n}\n\nfunction findMatchingCloseParen(expression: string, openPos: number): number {\n if (expression[openPos] !== '(') {\n return -1;\n }\n\n const stack: OpenBracket[] = [];\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (isOpenBracket(symbol)) {\n stack.push(symbol);\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n const top = stack.pop();\n if (top === undefined || top !== closeToOpen(symbol)) {\n return -1;\n }\n if (stack.length === 0) {\n return index;\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
|