@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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incomplete formal headers: `[α∈…]` declarations and quantifiers (`∀α∈…`).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { AstNode } from '../../../parsing';
|
|
6
|
+
import { RSErrorCode, type RSErrorDescription } from '../../error';
|
|
7
|
+
import { TypeClass as TypeClassEnum } from '../../semantic/typification';
|
|
8
|
+
import { Arguments, Variable_pack } from '../parser.terms';
|
|
9
|
+
import { TokenID } from '../token';
|
|
10
|
+
|
|
11
|
+
import { findAncestor, isFunctionDeclNode, isQuantifierNode, subtreeHasError } from './ast-utils';
|
|
12
|
+
import type { ClassifyContext, ErrorClassifier } from './context';
|
|
13
|
+
import { detectTrailingErrorSlot } from './trailing-slot';
|
|
14
|
+
|
|
15
|
+
export const classifyIncompleteFormal: ErrorClassifier = (node, expression, context) =>
|
|
16
|
+
detectIncompleteFunctionDecl(node, expression, context.expected) ?? detectIncompleteQuantifier(node, expression);
|
|
17
|
+
|
|
18
|
+
function detectIncompleteFunctionDecl(
|
|
19
|
+
node: AstNode,
|
|
20
|
+
expression: string,
|
|
21
|
+
expected?: ClassifyContext['expected']
|
|
22
|
+
): RSErrorDescription | null {
|
|
23
|
+
return detectTrailingErrorSlot(node, expression, findAncestor(node, isFunctionDeclNode), {
|
|
24
|
+
headerValid: container => {
|
|
25
|
+
const argsNode = container.children.find(
|
|
26
|
+
child => child.typeID === Arguments || child.typeID === TokenID.NT_ARGUMENTS
|
|
27
|
+
);
|
|
28
|
+
return argsNode !== undefined && !subtreeHasError(argsNode);
|
|
29
|
+
},
|
|
30
|
+
code: () => incompleteFormalExpressionCode(expected)
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function incompleteFormalExpressionCode(expected?: ClassifyContext['expected']): RSErrorCode {
|
|
35
|
+
switch (expected) {
|
|
36
|
+
case TypeClassEnum.function:
|
|
37
|
+
return RSErrorCode.expectedExpressionBody;
|
|
38
|
+
case TypeClassEnum.predicate:
|
|
39
|
+
case TypeClassEnum.logic:
|
|
40
|
+
return RSErrorCode.expectedLogicBody;
|
|
41
|
+
default:
|
|
42
|
+
return RSErrorCode.expectedFunctionBody;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorDescription | null {
|
|
47
|
+
return detectTrailingErrorSlot(node, expression, findAncestor(node, isQuantifierNode), {
|
|
48
|
+
headerValid: container => {
|
|
49
|
+
const varPack = container.children.find(
|
|
50
|
+
child => child.typeID === Variable_pack || child.typeID === TokenID.NT_ENUM_DECL
|
|
51
|
+
);
|
|
52
|
+
return varPack !== undefined && !subtreeHasError(varPack);
|
|
53
|
+
},
|
|
54
|
+
code: (container, bodyChild) => {
|
|
55
|
+
const inIndex = container.children.findIndex(child => expression.slice(child.from, child.to) === '∈');
|
|
56
|
+
if (inIndex < 0) {
|
|
57
|
+
return RSErrorCode.expectedQuantifierDomain;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const domainChild = container.children[inIndex + 1];
|
|
61
|
+
if (domainChild === undefined || domainChild === bodyChild || subtreeHasError(domainChild)) {
|
|
62
|
+
return RSErrorCode.expectedQuantifierDomain;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return RSErrorCode.expectedQuantifierBody;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isIncompleteGeneratorBodyCode(code: RSErrorCode): boolean {
|
|
71
|
+
return (
|
|
72
|
+
code === RSErrorCode.expectedDeclarativeBody ||
|
|
73
|
+
code === RSErrorCode.expectedImperativeBody ||
|
|
74
|
+
code === RSErrorCode.expectedRecursiveBody
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incomplete operators and bracket argument lists (`P1[S1, ]`).
|
|
3
|
+
*
|
|
4
|
+
* Tuple enums `(α,β,)` intentionally stay `unknownSyntax` — not `expectedArgument`.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { AstNode } from '../../../parsing';
|
|
8
|
+
import { RSErrorCode, type RSErrorDescription } from '../../error';
|
|
9
|
+
import { Boolean, Expr_enum_min2, Logic_binary, Logic_predicates, Logic_unary, Setexpr_binary } from '../parser.terms';
|
|
10
|
+
import { TokenID } from '../token';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
findAncestor,
|
|
14
|
+
findMatchingCloseBracket,
|
|
15
|
+
getErrorOperandNode,
|
|
16
|
+
isFilterNode,
|
|
17
|
+
isFunctionNode,
|
|
18
|
+
isPredicateNode,
|
|
19
|
+
subtreeHasError
|
|
20
|
+
} from './ast-utils';
|
|
21
|
+
import type { ErrorClassifier } from './context';
|
|
22
|
+
import { errorAt, hasOnlyClosingSuffix, isTextToken, sliceText } from './error-builders';
|
|
23
|
+
|
|
24
|
+
export const classifyIncompleteOperands: ErrorClassifier = (node, expression) =>
|
|
25
|
+
detectIncompleteUnaryOperand(node, expression) ??
|
|
26
|
+
detectIncompleteBinaryOperand(node, expression) ??
|
|
27
|
+
detectIncompleteBooleanOperand(node, expression);
|
|
28
|
+
|
|
29
|
+
export const classifyIncompleteArgument: ErrorClassifier = (node, expression) =>
|
|
30
|
+
detectIncompleteArgument(node, expression);
|
|
31
|
+
|
|
32
|
+
function detectIncompleteUnaryOperand(node: AstNode, expression: string): RSErrorDescription | null {
|
|
33
|
+
const unaryNode = findAncestor(node, target => target.typeID === Logic_unary);
|
|
34
|
+
if (unaryNode === null) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const operandChild = unaryNode.children[unaryNode.children.length - 1];
|
|
39
|
+
if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (expression.slice(unaryNode.to).trim().length > 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const operatorChild = unaryNode.children[0];
|
|
48
|
+
if (operatorChild === undefined || operatorChild === operandChild) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!isTextToken(operatorChild, expression, '¬')) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return errorAt(operandChild, RSErrorCode.expectedUnaryOperand);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function detectIncompleteBinaryOperand(node: AstNode, expression: string): RSErrorDescription | null {
|
|
60
|
+
const binaryNode = findAncestor(
|
|
61
|
+
node,
|
|
62
|
+
target => target.typeID === Logic_binary || target.typeID === Logic_predicates || target.typeID === Setexpr_binary
|
|
63
|
+
);
|
|
64
|
+
if (binaryNode === null) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const operandChild = binaryNode.children[binaryNode.children.length - 1];
|
|
69
|
+
if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (expression.slice(binaryNode.to).trim().length > 0) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (binaryNode.children.length < 2) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const leftChild = binaryNode.children[0];
|
|
82
|
+
if (leftChild.typeID === TokenID.ERROR || subtreeHasError(leftChild)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return errorAt(operandChild, RSErrorCode.expectedRightOperand);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function detectIncompleteBooleanOperand(node: AstNode, expression: string): RSErrorDescription | null {
|
|
90
|
+
const booleanNode = findAncestor(node, target => target.typeID === Boolean);
|
|
91
|
+
if (booleanNode === null) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const operandChild = findTrailingErrorOperand(booleanNode, expression);
|
|
96
|
+
if (operandChild === null || node !== operandChild) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!hasOnlyClosingSuffix(expression, booleanNode.to)) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return errorAt(operandChild, RSErrorCode.expectedRightOperand);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function detectIncompleteArgument(node: AstNode, expression: string): RSErrorDescription | null {
|
|
108
|
+
const enumNode = findAncestor(node, target => target.typeID === Expr_enum_min2);
|
|
109
|
+
if (enumNode === null || !isLegitimateArgumentEnum(enumNode, expression)) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const errorChild = findEnumArgumentError(enumNode, expression);
|
|
114
|
+
if (errorChild === null || node !== errorChild || !hasOnlyClosingSuffix(expression, enumNode.to)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return errorAt(errorChild, RSErrorCode.expectedArgument);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function findTrailingErrorOperand(container: AstNode, expression: string): AstNode | null {
|
|
122
|
+
for (let index = container.children.length - 1; index >= 0; index--) {
|
|
123
|
+
const child = container.children[index];
|
|
124
|
+
if (isOperandStructuralToken(child, expression)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
return getErrorOperandNode(child);
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function findEnumArgumentError(enumNode: AstNode, expression: string): AstNode | null {
|
|
133
|
+
for (const child of enumNode.children) {
|
|
134
|
+
if (isTextToken(child, expression, ',')) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const errorNode = getErrorOperandNode(child);
|
|
138
|
+
if (errorNode !== null) {
|
|
139
|
+
return errorNode;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function isOperandStructuralToken(node: AstNode, expression: string): boolean {
|
|
146
|
+
const text = sliceText(node, expression);
|
|
147
|
+
return text === '(' || text === ')' || text === 'ℬ';
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function isLegitimateArgumentEnum(enumNode: AstNode, expression: string): boolean {
|
|
151
|
+
return findCallHostForBracketEnum(enumNode, expression) !== null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function findCallHostForBracketEnum(enumNode: AstNode, expression: string): AstNode | null {
|
|
155
|
+
let current: AstNode | null = enumNode.parent;
|
|
156
|
+
while (current !== null) {
|
|
157
|
+
for (const child of current.children) {
|
|
158
|
+
if (!isFunctionNode(child) && !isPredicateNode(child) && !isFilterNode(child)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (isEnumInCallBrackets(enumNode, child, expression)) {
|
|
162
|
+
return child;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
current = current.parent;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isEnumInCallBrackets(enumNode: AstNode, nameNode: AstNode, expression: string): boolean {
|
|
171
|
+
const rest = expression.slice(nameNode.to);
|
|
172
|
+
const match = /^\s*\[/.exec(rest);
|
|
173
|
+
if (match === null) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const openPos = nameNode.to + match.index + match[0].indexOf('[');
|
|
178
|
+
const closePos = findMatchingCloseBracket(expression, openPos);
|
|
179
|
+
if (closePos < 0) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return enumNode.from > openPos && enumNode.from < closePos;
|
|
184
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax error extraction — public entry point.
|
|
3
|
+
*
|
|
4
|
+
* Expects the **hybrid** AST produced by `normalizeAST` (see `parser/README.md`).
|
|
5
|
+
* See {@link ./README.md} for pipeline, classifier order, and how to add codes.
|
|
6
|
+
*
|
|
7
|
+
* @module rslang/parser/syntax-errors
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { type AstNode, visitAstDFS } from '../../../parsing';
|
|
11
|
+
import { annotateError } from '../../ast-annotations';
|
|
12
|
+
import { type ErrorReporter, type RSErrorDescription } from '../../error';
|
|
13
|
+
import { type TypeClass } from '../../semantic/typification';
|
|
14
|
+
import { TokenID } from '../token';
|
|
15
|
+
|
|
16
|
+
import { classifyFallbackError, classifyParseError } from './classify';
|
|
17
|
+
import { deduplicateErrors, extractBracketErrors, extractForbiddenCharacterErrors } from './expression-errors';
|
|
18
|
+
import { isIncompleteGeneratorBodyCode } from './incomplete-formal';
|
|
19
|
+
|
|
20
|
+
/** When set, refines incomplete formal headers (`[α∈…]`, quantifiers). */
|
|
21
|
+
export interface SyntaxErrorOptions {
|
|
22
|
+
expected?: TypeClass;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Walks a parsed expression AST and reports syntax errors.
|
|
27
|
+
*
|
|
28
|
+
* @param ast - Root AST from `buildTree(parser.parse(expression))`
|
|
29
|
+
* @param expression - Original source text (positions must match the AST)
|
|
30
|
+
* @param reporter - Called once per deduplicated error
|
|
31
|
+
* @param annotateErrors - When true, also calls `annotateError` on the triggering node
|
|
32
|
+
* @param options - Optional typification hint for incomplete formal expressions
|
|
33
|
+
*/
|
|
34
|
+
export function extractSyntaxErrors(
|
|
35
|
+
ast: AstNode,
|
|
36
|
+
expression: string,
|
|
37
|
+
reporter: ErrorReporter,
|
|
38
|
+
annotateErrors: boolean = false,
|
|
39
|
+
options?: SyntaxErrorOptions
|
|
40
|
+
) {
|
|
41
|
+
const forbiddenErrors = extractForbiddenCharacterErrors(expression);
|
|
42
|
+
if (forbiddenErrors.length > 0) {
|
|
43
|
+
for (const error of forbiddenErrors) {
|
|
44
|
+
reporter(error);
|
|
45
|
+
if (annotateErrors) {
|
|
46
|
+
annotateError(ast, error.code, error.params);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const collected: RSErrorDescription[] = [];
|
|
53
|
+
const annotationTargets = new Map<RSErrorDescription, AstNode>();
|
|
54
|
+
const collect = (error: RSErrorDescription, target?: AstNode) => {
|
|
55
|
+
collected.push(error);
|
|
56
|
+
if (target !== undefined) {
|
|
57
|
+
annotationTargets.set(error, target);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const bracketError = extractBracketErrors(expression);
|
|
62
|
+
const hasBracketErrors = bracketError !== null;
|
|
63
|
+
visitAstDFS(ast, node => extractInternal(node, expression, collect, hasBracketErrors, options));
|
|
64
|
+
|
|
65
|
+
const hasIncompleteGenerator = collected.some(error => isIncompleteGeneratorBodyCode(error.code));
|
|
66
|
+
if (bracketError !== null && !hasIncompleteGenerator) {
|
|
67
|
+
collect(bracketError, ast);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const error of deduplicateErrors(collected)) {
|
|
71
|
+
reporter(error);
|
|
72
|
+
if (annotateErrors) {
|
|
73
|
+
const target = annotationTargets.get(error);
|
|
74
|
+
if (target !== undefined) {
|
|
75
|
+
annotateError(target, error.code, error.params);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function extractInternal(
|
|
82
|
+
node: AstNode,
|
|
83
|
+
expression: string,
|
|
84
|
+
collect: (error: RSErrorDescription, target: AstNode) => void,
|
|
85
|
+
hasBracketErrors: boolean,
|
|
86
|
+
options?: SyntaxErrorOptions
|
|
87
|
+
) {
|
|
88
|
+
if (node.typeID !== TokenID.ERROR) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const classified = classifyParseError(node, expression, { hasBracketErrors, expected: options?.expected });
|
|
93
|
+
if (classified !== null) {
|
|
94
|
+
collect(classified, node);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const fallback = classifyFallbackError(node, hasBracketErrors);
|
|
99
|
+
if (fallback !== null) {
|
|
100
|
+
collect(fallback.error, fallback.target);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable pattern: container header is valid, last child is `ERROR`, input ends here.
|
|
3
|
+
*
|
|
4
|
+
* @see incomplete-formal.ts — function declarations, quantifiers
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { AstNode } from '../../../parsing';
|
|
8
|
+
import { type RSErrorCode, type RSErrorDescription } from '../../error';
|
|
9
|
+
import { TokenID } from '../token';
|
|
10
|
+
|
|
11
|
+
import { errorAt } from './error-builders';
|
|
12
|
+
|
|
13
|
+
export function detectTrailingErrorSlot(
|
|
14
|
+
node: AstNode,
|
|
15
|
+
expression: string,
|
|
16
|
+
container: AstNode | null,
|
|
17
|
+
options: {
|
|
18
|
+
headerValid?: (container: AstNode) => boolean;
|
|
19
|
+
code: RSErrorCode | ((container: AstNode, bodyChild: AstNode) => RSErrorCode | null);
|
|
20
|
+
}
|
|
21
|
+
): RSErrorDescription | null {
|
|
22
|
+
if (container === null) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const bodyChild = container.children[container.children.length - 1];
|
|
27
|
+
if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (expression.slice(container.to).trim().length > 0) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (options.headerValid !== undefined && !options.headerValid(container)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const code = typeof options.code === 'function' ? options.code(container, bodyChild) : options.code;
|
|
40
|
+
if (code === null) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return errorAt(bodyChild, code);
|
|
45
|
+
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { t as AstNode } from "../../ast-C8sIpKdL.js";
|
|
2
|
-
import { g as TypeClass } from "../../typification-Dk-fisgO.js";
|
|
3
|
-
import { t as ErrorReporter } from "../../error-CZXO5Y6a.js";
|
|
4
|
-
|
|
5
|
-
//#region src/rslang/parser/syntax-errors.d.ts
|
|
6
|
-
/** Options for syntax error extraction. */
|
|
7
|
-
interface SyntaxErrorOptions {
|
|
8
|
-
expected?: TypeClass;
|
|
9
|
-
}
|
|
10
|
-
/** Extracts syntax errors from an AST. */
|
|
11
|
-
declare function extractSyntaxErrors(ast: AstNode, expression: string, reporter: ErrorReporter, annotateErrors?: boolean, options?: SyntaxErrorOptions): void;
|
|
12
|
-
//#endregion
|
|
13
|
-
export { SyntaxErrorOptions, extractSyntaxErrors };
|
|
14
|
-
//# sourceMappingURL=syntax-errors.d.ts.map
|