@rsconcept/domain 1.7.1 → 1.7.2
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/rslang/parser/syntax-errors/index.js +1 -1
- package/dist/rslang/semantic/analyzer.js +1 -1
- package/dist/{syntax-errors-pCI6RicF.js → syntax-errors-B6c2vsan.js} +28 -6
- package/dist/syntax-errors-B6c2vsan.js.map +1 -0
- package/package.json +1 -1
- package/src/rslang/parser/parser.test.ts +1 -1
- package/src/rslang/parser/syntax-errors/expression-errors.ts +20 -2
- package/src/rslang/parser/syntax-errors/generators.ts +8 -0
- package/src/rslang/parser/syntax-errors/incomplete-formal.ts +0 -8
- package/src/rslang/parser/syntax-errors/index.ts +1 -1
- package/dist/syntax-errors-pCI6RicF.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as extractSyntaxErrors } from "../../../syntax-errors-
|
|
1
|
+
import { t as extractSyntaxErrors } from "../../../syntax-errors-B6c2vsan.js";
|
|
2
2
|
export { extractSyntaxErrors };
|
|
@@ -7,7 +7,7 @@ import { TypeID, basic, bool, constant, debool } from "./typification.js";
|
|
|
7
7
|
import { labelType } from "../labels.js";
|
|
8
8
|
import { parser } from "../parser/parser.js";
|
|
9
9
|
import { normalizeAST } from "../parser/normalize.js";
|
|
10
|
-
import { t as extractSyntaxErrors } from "../../syntax-errors-
|
|
10
|
+
import { t as extractSyntaxErrors } from "../../syntax-errors-B6c2vsan.js";
|
|
11
11
|
import { getTypeClass } from "./typification-api.js";
|
|
12
12
|
import { TypeAuditor } from "./type-auditor.js";
|
|
13
13
|
import { ValueClass } from "./value-class.js";
|
|
@@ -139,6 +139,9 @@ function isTextToken(node, expression, text) {
|
|
|
139
139
|
//#endregion
|
|
140
140
|
//#region src/rslang/parser/syntax-errors/generators.ts
|
|
141
141
|
const classifyIncompleteGenerator = (node, expression) => detectIncompleteDeclarative(node, expression) ?? detectIncompleteImperative(node, expression) ?? detectIncompleteRecursion(node, expression);
|
|
142
|
+
function isIncompleteGeneratorBodyCode(code) {
|
|
143
|
+
return code === RSErrorCode.expectedDeclarativeBody || code === RSErrorCode.expectedImperativeBody || code === RSErrorCode.expectedRecursiveBody;
|
|
144
|
+
}
|
|
142
145
|
function detectIncompleteDeclarative(node, expression) {
|
|
143
146
|
return detectIncompleteGeneratorBody(node, expression, findAncestor(node, (target) => target.typeID === 60 || target.typeID === TokenID.NT_DECLARATIVE_EXPR), RSErrorCode.expectedDeclarativeBody, (slot) => isIncompleteDeclarativeBody(slot.nodes));
|
|
144
147
|
}
|
|
@@ -338,9 +341,6 @@ function detectIncompleteQuantifier(node, expression) {
|
|
|
338
341
|
}
|
|
339
342
|
});
|
|
340
343
|
}
|
|
341
|
-
function isIncompleteGeneratorBodyCode(code) {
|
|
342
|
-
return code === RSErrorCode.expectedDeclarativeBody || code === RSErrorCode.expectedImperativeBody || code === RSErrorCode.expectedRecursiveBody;
|
|
343
|
-
}
|
|
344
344
|
//#endregion
|
|
345
345
|
//#region src/rslang/parser/syntax-errors/incomplete-operands.ts
|
|
346
346
|
const classifyIncompleteOperands = (node, expression) => detectIncompleteUnaryOperand(node, expression) ?? detectIncompleteBinaryOperand(node, expression) ?? detectIncompleteBooleanOperand(node, expression);
|
|
@@ -574,8 +574,30 @@ function collapseContiguousUnknownSyntax(errors) {
|
|
|
574
574
|
const unknowns = errors.filter((error) => error.code === RSErrorCode.unknownSyntax);
|
|
575
575
|
if (unknowns.length <= 1) return errors;
|
|
576
576
|
const others = errors.filter((error) => error.code !== RSErrorCode.unknownSyntax);
|
|
577
|
-
const
|
|
578
|
-
|
|
577
|
+
const sorted = [...unknowns].sort((left, right) => left.from - right.from || left.to - right.to);
|
|
578
|
+
const merged = [];
|
|
579
|
+
let clusterFrom = sorted[0].from;
|
|
580
|
+
let clusterTo = sorted[0].to;
|
|
581
|
+
for (let index = 1; index < sorted.length; index++) {
|
|
582
|
+
const error = sorted[index];
|
|
583
|
+
if (error.from <= clusterTo) {
|
|
584
|
+
clusterTo = Math.max(clusterTo, error.to);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
merged.push({
|
|
588
|
+
code: RSErrorCode.unknownSyntax,
|
|
589
|
+
from: clusterFrom,
|
|
590
|
+
to: clusterTo
|
|
591
|
+
});
|
|
592
|
+
clusterFrom = error.from;
|
|
593
|
+
clusterTo = error.to;
|
|
594
|
+
}
|
|
595
|
+
merged.push({
|
|
596
|
+
code: RSErrorCode.unknownSyntax,
|
|
597
|
+
from: clusterFrom,
|
|
598
|
+
to: clusterTo
|
|
599
|
+
});
|
|
600
|
+
return [...others, ...merged];
|
|
579
601
|
}
|
|
580
602
|
function rangesOverlap(a, b) {
|
|
581
603
|
return a.from < b.to && b.from < a.to;
|
|
@@ -686,4 +708,4 @@ function extractInternal(node, expression, collect, hasBracketErrors, options) {
|
|
|
686
708
|
//#endregion
|
|
687
709
|
export { extractSyntaxErrors as t };
|
|
688
710
|
|
|
689
|
-
//# sourceMappingURL=syntax-errors-
|
|
711
|
+
//# sourceMappingURL=syntax-errors-B6c2vsan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syntax-errors-B6c2vsan.js","names":["TypeClassEnum"],"sources":["../src/rslang/parser/syntax-errors/context.ts","../src/rslang/parser/syntax-errors/ast-utils.ts","../src/rslang/parser/syntax-errors/function-calls.ts","../src/rslang/parser/syntax-errors/error-builders.ts","../src/rslang/parser/syntax-errors/generators.ts","../src/rslang/parser/syntax-errors/trailing-slot.ts","../src/rslang/parser/syntax-errors/incomplete-formal.ts","../src/rslang/parser/syntax-errors/incomplete-operands.ts","../src/rslang/parser/syntax-errors/classify.ts","../src/rslang/parser/syntax-errors/expression-errors.ts","../src/rslang/parser/syntax-errors/index.ts"],"sourcesContent":["/**\n * Types for the parse-error classifier pipeline.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport type { RSErrorDescription } from '../../error';\nimport type { TypeClass } from '../../semantic/typification';\n\n/** Shared state passed through parse-error classifiers. */\nexport interface ClassifyContext {\n hasBracketErrors: boolean;\n expected?: TypeClass;\n}\n\n/** Classifies a single ERROR node into a specific syntax error, if possible. */\nexport type ErrorClassifier = (\n node: AstNode,\n expression: string,\n context: ClassifyContext\n) => RSErrorDescription | null;\n\n/** Skips classifiers that conflict with bracket-level diagnostics. */\nexport function whenNoBracketErrors(classifier: ErrorClassifier): ErrorClassifier {\n return (node, expression, context) => (context.hasBracketErrors ? null : classifier(node, expression, context));\n}\n","/**\n * AST navigation helpers and node-type predicates for classifiers.\n *\n * Predicates accept grammar terms **or** {@link TokenID} because `normalizeAST` runs before\n * error extraction and leaves `hasError` subtrees unnormalized — see `parser/README.md`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { Filter, Function, Function_decl, Logic_quantor, Predicate } from '../parser.terms';\nimport { TokenID } from '../token';\n\nexport function 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\nexport function 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\nexport function isDescendantOf(ancestor: AstNode, node: AstNode): boolean {\n let current: AstNode | null = node.parent;\n while (current !== null) {\n if (current === ancestor) {\n return true;\n }\n current = current.parent;\n }\n return false;\n}\n\nexport function subtreeHasError(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n return node.children.some(subtreeHasError);\n}\n\nexport function isFunctionDeclNode(node: AstNode): boolean {\n return node.typeID === Function_decl || node.typeID === TokenID.NT_FUNC_DEFINITION;\n}\n\nexport function isQuantifierNode(node: AstNode): boolean {\n return node.typeID === Logic_quantor;\n}\n\nexport function isFunctionNode(node: AstNode): boolean {\n return node.typeID === Function || node.typeID === TokenID.ID_FUNCTION;\n}\n\nexport function isPredicateNode(node: AstNode): boolean {\n return node.typeID === Predicate || node.typeID === TokenID.ID_PREDICATE;\n}\n\nexport function isFilterNode(node: AstNode): boolean {\n return node.typeID === Filter || node.typeID === TokenID.FILTER;\n}\n\nexport function findMatchingCloseBracket(expression: string, openPos: number): number {\n if (expression[openPos] !== '[') {\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\nexport function getErrorOperandNode(node: AstNode): AstNode | null {\n if (node.typeID === TokenID.ERROR) {\n return node;\n }\n if (node.children.length === 1) {\n return getErrorOperandNode(node.children[0]);\n }\n return null;\n}\n\nexport function isErrorPlaceholder(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n if (node.children.length === 0) {\n return false;\n }\n return node.children.every(child => isErrorPlaceholder(child));\n}\n","/**\n * Malformed calls: `Fi…(…)`, `F1` / `P1` without or with wrong argument brackets.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\n\nimport {\n findAncestor,\n findMatchingCloseBracket,\n findRelatedNode,\n isFilterNode,\n isFunctionNode,\n isPredicateNode\n} from './ast-utils';\nimport type { ErrorClassifier } from './context';\n\nexport const classifyFilterParenMismatch: ErrorClassifier = (node, expression) => {\n const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);\n if (filterNode === null || expression[filterNode.to] !== '(') {\n return null;\n }\n\n return {\n code: RSErrorCode.invalidFilterSyntax,\n from: filterNode.from,\n to: filterNode.to + 1\n };\n};\n\nexport const classifyGlobalFuncCall: ErrorClassifier = (node, expression) => {\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 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 if (/^\\s*$/.test(rest)) {\n return withoutArgs;\n }\n\n if (/^\\s*\\(/.test(rest)) {\n return {\n code: RSErrorCode.globalFuncParenCall,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n }\n\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 && rest.slice(openBracket[0].length, closeIdx).trim().length === 0) {\n return withoutArgs;\n }\n\n return null;\n}\n","/**\n * Small helpers for building `RSErrorDescription` values from AST nodes.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { type RSErrorCode, type RSErrorDescription } from '../../error';\n\nexport function errorAt(node: AstNode, code: RSErrorCode, params?: readonly string[]): RSErrorDescription {\n return {\n code,\n from: node.from,\n to: node.to,\n params\n };\n}\n\nexport function hasOnlyClosingSuffix(expression: string, from: number): boolean {\n const suffix = expression.slice(from).trim();\n return suffix.length === 0 || /^[\\]\\)\\}]*$/.test(suffix);\n}\n\nexport function sliceText(node: AstNode, expression: string): string {\n return expression.slice(node.from, node.to);\n}\n\nexport function isTextToken(node: AstNode, expression: string, text: string): boolean {\n return sliceText(node, expression) === text;\n}\n","/**\n * Incomplete generator bodies: declarative `D{…}`, imperative `I{…}`, recursive `R{…}`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Declarative, Imp_blocks, Imperative, Recursion, Setexpr } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport { findAncestor, isDescendantOf, isErrorPlaceholder, subtreeHasError } from './ast-utils';\nimport type { ErrorClassifier } from './context';\nimport { errorAt, isTextToken } from './error-builders';\n\nexport const classifyIncompleteGenerator: ErrorClassifier = (node, expression) =>\n detectIncompleteDeclarative(node, expression) ??\n detectIncompleteImperative(node, expression) ??\n detectIncompleteRecursion(node, expression);\n\nexport function isIncompleteGeneratorBodyCode(code: RSErrorCode): boolean {\n return (\n code === RSErrorCode.expectedDeclarativeBody ||\n code === RSErrorCode.expectedImperativeBody ||\n code === RSErrorCode.expectedRecursiveBody\n );\n}\n\ninterface GeneratorBodySlot {\n nodes: AstNode[];\n headerEndIndex: number;\n}\n\nfunction detectIncompleteDeclarative(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(\n node,\n target => target.typeID === Declarative || target.typeID === TokenID.NT_DECLARATIVE_EXPR\n );\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedDeclarativeBody, slot =>\n isIncompleteDeclarativeBody(slot.nodes)\n );\n}\n\nfunction detectIncompleteImperative(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(\n node,\n target => target.typeID === Imperative || target.typeID === TokenID.NT_IMPERATIVE_EXPR\n );\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedImperativeBody, slot =>\n isIncompleteImperativeBody(slot, expression)\n );\n}\n\nfunction detectIncompleteRecursion(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(node, target => target.typeID === Recursion);\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedRecursiveBody, slot =>\n isIncompleteRecursionBody(slot.nodes)\n );\n}\n\nfunction detectIncompleteGeneratorBody(\n node: AstNode,\n expression: string,\n generatorNode: AstNode | null,\n code: RSErrorCode,\n isIncomplete: (slot: GeneratorBodySlot) => boolean\n): RSErrorDescription | null {\n if (generatorNode === null || expression.slice(generatorNode.to).trim().length > 0) {\n return null;\n }\n\n const slot = getGeneratorBodySlot(generatorNode, expression);\n if (slot === null || !isIncomplete(slot) || !generatorHeaderIsValid(generatorNode, expression, slot.headerEndIndex)) {\n return null;\n }\n\n if (!isErrorInBodySlot(node, slot, generatorNode)) {\n return null;\n }\n\n return errorAt(node, code);\n}\n\nfunction getGeneratorBodySlot(generatorNode: AstNode, expression: string): GeneratorBodySlot | null {\n if (generatorNode.typeID === Declarative || generatorNode.typeID === TokenID.NT_DECLARATIVE_EXPR) {\n return getDeclarativeBodySlot(generatorNode, expression);\n }\n if (generatorNode.typeID === Imperative || generatorNode.typeID === TokenID.NT_IMPERATIVE_EXPR) {\n return getImperativeBodySlot(generatorNode, expression);\n }\n if (generatorNode.typeID === Recursion) {\n return getRecursionBodySlot(generatorNode, expression);\n }\n return null;\n}\n\nfunction getDeclarativeBodySlot(declNode: AstNode, expression: string): GeneratorBodySlot | null {\n const pipeIndex = declNode.children.findIndex(child => isTextToken(child, expression, '|'));\n if (pipeIndex >= 0) {\n return {\n nodes: contentChildren(declNode, expression, pipeIndex + 1),\n headerEndIndex: pipeIndex + 1\n };\n }\n\n const domainNode = findDeclarativeDomain(declNode, expression);\n if (domainNode === null) {\n return null;\n }\n\n const domainIndex = declNode.children.indexOf(domainNode);\n return {\n nodes: contentChildren(declNode, expression, domainIndex + 1),\n headerEndIndex: domainIndex + 1\n };\n}\n\nfunction getImperativeBodySlot(impNode: AstNode, expression: string): GeneratorBodySlot | null {\n const pipeIndex = impNode.children.findIndex(child => isTextToken(child, expression, '|'));\n if (pipeIndex >= 0) {\n return {\n nodes: contentChildren(impNode, expression, pipeIndex + 1),\n headerEndIndex: pipeIndex + 1\n };\n }\n\n const tupleNode = findImperativeTuple(impNode);\n if (tupleNode === null) {\n return null;\n }\n\n const tupleIndex = impNode.children.indexOf(tupleNode);\n return {\n nodes: contentChildren(impNode, expression, tupleIndex + 1),\n headerEndIndex: tupleIndex + 1\n };\n}\n\nfunction getRecursionBodySlot(recNode: AstNode, expression: string): GeneratorBodySlot | null {\n const initNode = findRecursionInit(recNode, expression);\n if (initNode === null) {\n return null;\n }\n\n const initIndex = recNode.children.indexOf(initNode);\n const afterInit = contentChildren(recNode, expression, initIndex + 1);\n const lastPipeIndex = findLastPipeIndex(afterInit, expression);\n if (lastPipeIndex < 0) {\n return {\n nodes: afterInit,\n headerEndIndex: initIndex + 1\n };\n }\n\n return {\n nodes: afterInit.slice(lastPipeIndex + 1),\n headerEndIndex: recNode.children.indexOf(afterInit[lastPipeIndex]) + 1\n };\n}\n\nfunction contentChildren(generatorNode: AstNode, expression: string, fromIndex: number): AstNode[] {\n return generatorNode.children.slice(fromIndex).filter(child => !isClosingBrace(child, expression));\n}\n\nfunction findDeclarativeDomain(declNode: AstNode, expression: string): AstNode | null {\n const inIndex = declNode.children.findIndex(child => isTextToken(child, expression, '∈'));\n if (inIndex < 0) {\n return null;\n }\n\n for (let index = inIndex + 1; index < declNode.children.length; index++) {\n const child = declNode.children[index];\n if (isTextToken(child, expression, '|') || isClosingBrace(child, expression)) {\n break;\n }\n if (child.typeID === Setexpr) {\n return child;\n }\n }\n\n return null;\n}\n\nfunction findImperativeTuple(impNode: AstNode): AstNode | null {\n for (const child of impNode.children) {\n if (child.typeID === Setexpr) {\n return child;\n }\n }\n return null;\n}\n\nfunction findLastPipeIndex(nodes: AstNode[], expression: string): number {\n for (let index = nodes.length - 1; index >= 0; index--) {\n if (isTextToken(nodes[index], expression, '|')) {\n return index;\n }\n }\n return -1;\n}\n\nfunction generatorHeaderIsValid(generatorNode: AstNode, expression: string, headerEndIndex: number): boolean {\n for (let index = 0; index < headerEndIndex; index++) {\n const child = generatorNode.children[index];\n if (child.typeID === TokenID.ERROR) {\n return false;\n }\n if (isStructuralGeneratorToken(child, expression)) {\n continue;\n }\n if (subtreeHasError(child)) {\n return false;\n }\n }\n return true;\n}\n\nfunction isIncompleteDeclarativeBody(nodes: AstNode[]): boolean {\n return isEmptyOrErrorOnlyBody(nodes);\n}\n\nfunction isIncompleteImperativeBody(slot: GeneratorBodySlot, expression: string): boolean {\n if (slot.nodes.length === 0) {\n return true;\n }\n if (slot.nodes.length === 1 && slot.nodes[0].typeID === Imp_blocks) {\n return isImpBlocksIncomplete(slot.nodes[0], expression);\n }\n return isEmptyOrErrorOnlyBody(slot.nodes);\n}\n\nfunction isIncompleteRecursionBody(nodes: AstNode[]): boolean {\n return isEmptyOrErrorOnlyBody(nodes);\n}\n\nfunction isEmptyOrErrorOnlyBody(nodes: AstNode[]): boolean {\n if (nodes.length === 0) {\n return true;\n }\n if (nodes.length === 1) {\n return isErrorPlaceholder(nodes[0]);\n }\n return false;\n}\n\nfunction isImpBlocksIncomplete(blocksNode: AstNode, expression: string): boolean {\n if (blocksNode.children.length === 0) {\n return true;\n }\n\n const lastChild = blocksNode.children[blocksNode.children.length - 1];\n if (lastChild.typeID === TokenID.ERROR) {\n return true;\n }\n if (isTextToken(lastChild, expression, ';')) {\n return true;\n }\n if (lastChild.typeID === Setexpr && isErrorPlaceholder(lastChild)) {\n return true;\n }\n\n return false;\n}\n\nfunction isErrorInBodySlot(errorNode: AstNode, slot: GeneratorBodySlot, generatorNode: AstNode): boolean {\n if (slot.nodes.length === 0) {\n const bodyStart = generatorNode.children[slot.headerEndIndex]?.from ?? generatorNode.from;\n return errorNode.from >= bodyStart;\n }\n\n for (const bodyNode of slot.nodes) {\n if (errorNode === bodyNode || isDescendantOf(bodyNode, errorNode)) {\n if (isErrorPlaceholder(bodyNode)) {\n return true;\n }\n if (bodyNode.typeID === Imp_blocks && isImpBlocksTailError(bodyNode, errorNode)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nfunction isImpBlocksTailError(blocksNode: AstNode, errorNode: AstNode): boolean {\n const lastChild = blocksNode.children[blocksNode.children.length - 1];\n return lastChild.typeID === TokenID.ERROR && (errorNode === lastChild || isDescendantOf(lastChild, errorNode));\n}\n\nfunction findRecursionInit(recursionNode: AstNode, expression: string): AstNode | null {\n const assignIndex = recursionNode.children.findIndex(child => isTextToken(child, expression, ':='));\n if (assignIndex < 0) {\n return null;\n }\n\n for (let index = assignIndex + 1; index < recursionNode.children.length; index++) {\n const child = recursionNode.children[index];\n if (child.typeID === TokenID.ERROR) {\n break;\n }\n if (isTextToken(child, expression, '|') || isClosingBrace(child, expression)) {\n continue;\n }\n return child;\n }\n\n return null;\n}\n\nfunction isClosingBrace(node: AstNode, expression: string): boolean {\n return node.typeID !== TokenID.ERROR && isTextToken(node, expression, '}');\n}\n\nfunction isStructuralGeneratorToken(node: AstNode, expression: string): boolean {\n const text = expression.slice(node.from, node.to);\n return text === '{' || text === '}' || text === '|' || text === '∈' || text === ':=' || text === ';';\n}\n","/**\n * Reusable pattern: container header is valid, last child is `ERROR`, input ends here.\n *\n * @see incomplete-formal.ts — function declarations, quantifiers\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { type RSErrorCode, type RSErrorDescription } from '../../error';\nimport { TokenID } from '../token';\n\nimport { errorAt } from './error-builders';\n\nexport function detectTrailingErrorSlot(\n node: AstNode,\n expression: string,\n container: AstNode | null,\n options: {\n headerValid?: (container: AstNode) => boolean;\n code: RSErrorCode | ((container: AstNode, bodyChild: AstNode) => RSErrorCode | null);\n }\n): RSErrorDescription | null {\n if (container === null) {\n return null;\n }\n\n const bodyChild = container.children[container.children.length - 1];\n if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) {\n return null;\n }\n\n if (expression.slice(container.to).trim().length > 0) {\n return null;\n }\n\n if (options.headerValid !== undefined && !options.headerValid(container)) {\n return null;\n }\n\n const code = typeof options.code === 'function' ? options.code(container, bodyChild) : options.code;\n if (code === null) {\n return null;\n }\n\n return errorAt(bodyChild, code);\n}\n","/**\n * Incomplete formal headers: `[α∈…]` declarations and quantifiers (`∀α∈…`).\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { TypeClass as TypeClassEnum } from '../../semantic/typification';\nimport { Arguments, Variable_pack } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport { findAncestor, isFunctionDeclNode, isQuantifierNode, subtreeHasError } from './ast-utils';\nimport type { ClassifyContext, ErrorClassifier } from './context';\nimport { detectTrailingErrorSlot } from './trailing-slot';\n\nexport const classifyIncompleteFormal: ErrorClassifier = (node, expression, context) =>\n detectIncompleteFunctionDecl(node, expression, context.expected) ?? detectIncompleteQuantifier(node, expression);\n\nfunction detectIncompleteFunctionDecl(\n node: AstNode,\n expression: string,\n expected?: ClassifyContext['expected']\n): RSErrorDescription | null {\n return detectTrailingErrorSlot(node, expression, findAncestor(node, isFunctionDeclNode), {\n headerValid: container => {\n const argsNode = container.children.find(\n child => child.typeID === Arguments || child.typeID === TokenID.NT_ARGUMENTS\n );\n return argsNode !== undefined && !subtreeHasError(argsNode);\n },\n code: () => incompleteFormalExpressionCode(expected)\n });\n}\n\nfunction incompleteFormalExpressionCode(expected?: ClassifyContext['expected']): 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 detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorDescription | null {\n return detectTrailingErrorSlot(node, expression, findAncestor(node, isQuantifierNode), {\n headerValid: container => {\n const varPack = container.children.find(\n child => child.typeID === Variable_pack || child.typeID === TokenID.NT_ENUM_DECL\n );\n return varPack !== undefined && !subtreeHasError(varPack);\n },\n code: (container, bodyChild) => {\n const inIndex = container.children.findIndex(child => expression.slice(child.from, child.to) === '∈');\n if (inIndex < 0) {\n return RSErrorCode.expectedQuantifierDomain;\n }\n\n const domainChild = container.children[inIndex + 1];\n if (domainChild === undefined || domainChild === bodyChild || subtreeHasError(domainChild)) {\n return RSErrorCode.expectedQuantifierDomain;\n }\n\n return RSErrorCode.expectedQuantifierBody;\n }\n });\n}\n","/**\n * Incomplete operators and bracket argument lists (`P1[S1, ]`).\n *\n * Tuple enums `(α,β,)` intentionally stay `unknownSyntax` — not `expectedArgument`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Boolean, Expr_enum_min2, Logic_binary, Logic_predicates, Logic_unary, Setexpr_binary } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport {\n findAncestor,\n findMatchingCloseBracket,\n getErrorOperandNode,\n isFilterNode,\n isFunctionNode,\n isPredicateNode,\n subtreeHasError\n} from './ast-utils';\nimport type { ErrorClassifier } from './context';\nimport { errorAt, hasOnlyClosingSuffix, isTextToken, sliceText } from './error-builders';\n\nexport const classifyIncompleteOperands: ErrorClassifier = (node, expression) =>\n detectIncompleteUnaryOperand(node, expression) ??\n detectIncompleteBinaryOperand(node, expression) ??\n detectIncompleteBooleanOperand(node, expression);\n\nexport const classifyIncompleteArgument: ErrorClassifier = (node, expression) =>\n detectIncompleteArgument(node, expression);\n\nfunction detectIncompleteUnaryOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const unaryNode = findAncestor(node, target => target.typeID === Logic_unary);\n if (unaryNode === null) {\n return null;\n }\n\n const operandChild = unaryNode.children[unaryNode.children.length - 1];\n if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {\n return null;\n }\n\n if (expression.slice(unaryNode.to).trim().length > 0) {\n return null;\n }\n\n const operatorChild = unaryNode.children[0];\n if (operatorChild === undefined || operatorChild === operandChild) {\n return null;\n }\n\n if (!isTextToken(operatorChild, expression, '¬')) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedUnaryOperand);\n}\n\nfunction detectIncompleteBinaryOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const binaryNode = findAncestor(\n node,\n target => target.typeID === Logic_binary || target.typeID === Logic_predicates || target.typeID === Setexpr_binary\n );\n if (binaryNode === null) {\n return null;\n }\n\n const operandChild = binaryNode.children[binaryNode.children.length - 1];\n if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {\n return null;\n }\n\n if (expression.slice(binaryNode.to).trim().length > 0) {\n return null;\n }\n\n if (binaryNode.children.length < 2) {\n return null;\n }\n\n const leftChild = binaryNode.children[0];\n if (leftChild.typeID === TokenID.ERROR || subtreeHasError(leftChild)) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedRightOperand);\n}\n\nfunction detectIncompleteBooleanOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const booleanNode = findAncestor(node, target => target.typeID === Boolean);\n if (booleanNode === null) {\n return null;\n }\n\n const operandChild = findTrailingErrorOperand(booleanNode, expression);\n if (operandChild === null || node !== operandChild) {\n return null;\n }\n\n if (!hasOnlyClosingSuffix(expression, booleanNode.to)) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedRightOperand);\n}\n\nfunction detectIncompleteArgument(node: AstNode, expression: string): RSErrorDescription | null {\n const enumNode = findAncestor(node, target => target.typeID === Expr_enum_min2);\n if (enumNode === null || !isLegitimateArgumentEnum(enumNode, expression)) {\n return null;\n }\n\n const errorChild = findEnumArgumentError(enumNode, expression);\n if (errorChild === null || node !== errorChild || !hasOnlyClosingSuffix(expression, enumNode.to)) {\n return null;\n }\n\n return errorAt(errorChild, RSErrorCode.expectedArgument);\n}\n\nfunction findTrailingErrorOperand(container: AstNode, expression: string): AstNode | null {\n for (let index = container.children.length - 1; index >= 0; index--) {\n const child = container.children[index];\n if (isOperandStructuralToken(child, expression)) {\n continue;\n }\n return getErrorOperandNode(child);\n }\n return null;\n}\n\nfunction findEnumArgumentError(enumNode: AstNode, expression: string): AstNode | null {\n for (const child of enumNode.children) {\n if (isTextToken(child, expression, ',')) {\n continue;\n }\n const errorNode = getErrorOperandNode(child);\n if (errorNode !== null) {\n return errorNode;\n }\n }\n return null;\n}\n\nfunction isOperandStructuralToken(node: AstNode, expression: string): boolean {\n const text = sliceText(node, expression);\n return text === '(' || text === ')' || text === 'ℬ';\n}\n\nfunction isLegitimateArgumentEnum(enumNode: AstNode, expression: string): boolean {\n return findCallHostForBracketEnum(enumNode, expression) !== null;\n}\n\nfunction findCallHostForBracketEnum(enumNode: AstNode, expression: string): AstNode | null {\n let current: AstNode | null = enumNode.parent;\n while (current !== null) {\n for (const child of current.children) {\n if (!isFunctionNode(child) && !isPredicateNode(child) && !isFilterNode(child)) {\n continue;\n }\n if (isEnumInCallBrackets(enumNode, child, expression)) {\n return child;\n }\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction isEnumInCallBrackets(enumNode: AstNode, nameNode: AstNode, expression: string): boolean {\n const rest = expression.slice(nameNode.to);\n const match = /^\\s*\\[/.exec(rest);\n if (match === null) {\n return false;\n }\n\n const openPos = nameNode.to + match.index + match[0].indexOf('[');\n const closePos = findMatchingCloseBracket(expression, openPos);\n if (closePos < 0) {\n return false;\n }\n\n return enumNode.from > openPos && enumNode.from < closePos;\n}\n","/**\n * Parse-error classification: ordered classifier chain and P8400 fallback.\n *\n * Register new detectors in `PARSE_ERROR_CLASSIFIERS` (first match wins).\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Variable } from '../parser.terms';\n\nimport type { ClassifyContext, ErrorClassifier } from './context';\nimport { whenNoBracketErrors } from './context';\nimport { classifyFilterParenMismatch, classifyGlobalFuncCall } from './function-calls';\nimport { classifyIncompleteGenerator } from './generators';\nimport { classifyIncompleteFormal } from './incomplete-formal';\nimport { classifyIncompleteArgument, classifyIncompleteOperands } from './incomplete-operands';\n\nconst PARSE_ERROR_CLASSIFIERS: ErrorClassifier[] = [\n classifyIncompleteFormal,\n classifyIncompleteGenerator,\n whenNoBracketErrors(classifyIncompleteOperands),\n whenNoBracketErrors(classifyIncompleteArgument),\n classifyFilterParenMismatch,\n classifyGlobalFuncCall\n];\n\n/** Runs classifiers in priority order for one `ERROR` AST node. */\nexport function classifyParseError(\n node: AstNode,\n expression: string,\n context: ClassifyContext\n): RSErrorDescription | null {\n for (const classifier of PARSE_ERROR_CLASSIFIERS) {\n const error = classifier(node, expression, context);\n if (error !== null) {\n return error;\n }\n }\n return null;\n}\n\n/** Default rules when no classifier matched: `expectedLocal` or `unknownSyntax`. */\nexport function classifyFallbackError(\n node: AstNode,\n ignoreUnknownErrors: boolean\n): { error: RSErrorDescription; target: AstNode } | null {\n const parent = node.parent;\n if (parent === null) {\n return ignoreUnknownErrors\n ? null\n : { error: { code: RSErrorCode.unknownSyntax, from: node.from, to: node.to }, target: node };\n }\n\n if (parent.typeID === Variable) {\n return {\n error: { code: RSErrorCode.expectedLocal, from: parent.from, to: parent.to },\n target: parent\n };\n }\n\n if (ignoreUnknownErrors) {\n return null;\n }\n\n const target = node.from === node.to ? parent : node;\n return {\n error: { code: RSErrorCode.unknownSyntax, from: target.from, to: target.to },\n target\n };\n}\n","/**\n * Expression-level diagnostics (no AST required) and error deduplication.\n */\n\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\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\nexport function 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\nexport function 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\nexport function 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 const filtered = result.filter(\n error => error.code !== RSErrorCode.unknownSyntax || !specific.some(item => rangesOverlap(error, item))\n );\n return collapseContiguousUnknownSyntax(filtered);\n}\n\nfunction collapseContiguousUnknownSyntax(errors: RSErrorDescription[]): RSErrorDescription[] {\n const unknowns = errors.filter(error => error.code === RSErrorCode.unknownSyntax);\n if (unknowns.length <= 1) {\n return errors;\n }\n\n const others = errors.filter(error => error.code !== RSErrorCode.unknownSyntax);\n const sorted = [...unknowns].sort((left, right) => left.from - right.from || left.to - right.to);\n const merged: RSErrorDescription[] = [];\n\n let clusterFrom = sorted[0].from;\n let clusterTo = sorted[0].to;\n\n for (let index = 1; index < sorted.length; index++) {\n const error = sorted[index];\n if (error.from <= clusterTo) {\n clusterTo = Math.max(clusterTo, error.to);\n continue;\n }\n\n merged.push({ code: RSErrorCode.unknownSyntax, from: clusterFrom, to: clusterTo });\n clusterFrom = error.from;\n clusterTo = error.to;\n }\n\n merged.push({ code: RSErrorCode.unknownSyntax, from: clusterFrom, to: clusterTo });\n return [...others, ...merged];\n}\n\nfunction rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {\n return a.from < b.to && b.from < a.to;\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","/**\n * Syntax error extraction — public entry point.\n *\n * Expects the **hybrid** AST produced by `normalizeAST` (see `parser/README.md`).\n * See {@link ./README.md} for pipeline, classifier order, and how to add codes.\n *\n * @module rslang/parser/syntax-errors\n */\n\nimport { type AstNode, visitAstDFS } from '../../../parsing';\nimport { annotateError } from '../../ast-annotations';\nimport { type ErrorReporter, type RSErrorDescription } from '../../error';\nimport { type TypeClass } from '../../semantic/typification';\nimport { TokenID } from '../token';\n\nimport { classifyFallbackError, classifyParseError } from './classify';\nimport { deduplicateErrors, extractBracketErrors, extractForbiddenCharacterErrors } from './expression-errors';\nimport { isIncompleteGeneratorBodyCode } from './generators';\n\n/** When set, refines incomplete formal headers (`[α∈…]`, quantifiers). */\nexport interface SyntaxErrorOptions {\n expected?: TypeClass;\n}\n\n/**\n * Walks a parsed expression AST and reports syntax errors.\n *\n * @param ast - Root AST from `buildTree(parser.parse(expression))`\n * @param expression - Original source text (positions must match the AST)\n * @param reporter - Called once per deduplicated error\n * @param annotateErrors - When true, also calls `annotateError` on the triggering node\n * @param options - Optional typification hint for incomplete formal expressions\n */\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 const hasBracketErrors = bracketError !== null;\n visitAstDFS(ast, node => extractInternal(node, expression, collect, hasBracketErrors, options));\n\n const hasIncompleteGenerator = collected.some(error => isIncompleteGeneratorBodyCode(error.code));\n if (bracketError !== null && !hasIncompleteGenerator) {\n collect(bracketError, ast);\n }\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\nfunction extractInternal(\n node: AstNode,\n expression: string,\n collect: (error: RSErrorDescription, target: AstNode) => void,\n hasBracketErrors: boolean,\n options?: SyntaxErrorOptions\n) {\n if (node.typeID !== TokenID.ERROR) {\n return;\n }\n\n const classified = classifyParseError(node, expression, { hasBracketErrors, expected: options?.expected });\n if (classified !== null) {\n collect(classified, node);\n return;\n }\n\n const fallback = classifyFallbackError(node, hasBracketErrors);\n if (fallback !== null) {\n collect(fallback.error, fallback.target);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -134,7 +134,7 @@ const testUnknownSyntaxData = [
|
|
|
134
134
|
['P1[,S1]', { code: RSErrorCode.unknownSyntax, from: 3, to: 4 }],
|
|
135
135
|
['(,β)', { code: RSErrorCode.unknownSyntax, from: 1, to: 1 }],
|
|
136
136
|
['(α,β,)', { code: RSErrorCode.unknownSyntax, from: 1, to: 5 }],
|
|
137
|
-
['F1[S1][S2]', { code: RSErrorCode.unknownSyntax, from: 6, to:
|
|
137
|
+
['F1[S1][S2]', { code: RSErrorCode.unknownSyntax, from: 6, to: 10 }],
|
|
138
138
|
[':∈X1', { code: RSErrorCode.unknownSyntax, from: 0, to: 2 }]
|
|
139
139
|
] as const;
|
|
140
140
|
|
|
@@ -156,8 +156,26 @@ function collapseContiguousUnknownSyntax(errors: RSErrorDescription[]): RSErrorD
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
const others = errors.filter(error => error.code !== RSErrorCode.unknownSyntax);
|
|
159
|
-
const
|
|
160
|
-
|
|
159
|
+
const sorted = [...unknowns].sort((left, right) => left.from - right.from || left.to - right.to);
|
|
160
|
+
const merged: RSErrorDescription[] = [];
|
|
161
|
+
|
|
162
|
+
let clusterFrom = sorted[0].from;
|
|
163
|
+
let clusterTo = sorted[0].to;
|
|
164
|
+
|
|
165
|
+
for (let index = 1; index < sorted.length; index++) {
|
|
166
|
+
const error = sorted[index];
|
|
167
|
+
if (error.from <= clusterTo) {
|
|
168
|
+
clusterTo = Math.max(clusterTo, error.to);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
merged.push({ code: RSErrorCode.unknownSyntax, from: clusterFrom, to: clusterTo });
|
|
173
|
+
clusterFrom = error.from;
|
|
174
|
+
clusterTo = error.to;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
merged.push({ code: RSErrorCode.unknownSyntax, from: clusterFrom, to: clusterTo });
|
|
178
|
+
return [...others, ...merged];
|
|
161
179
|
}
|
|
162
180
|
|
|
163
181
|
function rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {
|
|
@@ -16,6 +16,14 @@ export const classifyIncompleteGenerator: ErrorClassifier = (node, expression) =
|
|
|
16
16
|
detectIncompleteImperative(node, expression) ??
|
|
17
17
|
detectIncompleteRecursion(node, expression);
|
|
18
18
|
|
|
19
|
+
export function isIncompleteGeneratorBodyCode(code: RSErrorCode): boolean {
|
|
20
|
+
return (
|
|
21
|
+
code === RSErrorCode.expectedDeclarativeBody ||
|
|
22
|
+
code === RSErrorCode.expectedImperativeBody ||
|
|
23
|
+
code === RSErrorCode.expectedRecursiveBody
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
interface GeneratorBodySlot {
|
|
20
28
|
nodes: AstNode[];
|
|
21
29
|
headerEndIndex: number;
|
|
@@ -66,11 +66,3 @@ function detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorD
|
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
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
|
-
}
|
|
@@ -15,7 +15,7 @@ import { TokenID } from '../token';
|
|
|
15
15
|
|
|
16
16
|
import { classifyFallbackError, classifyParseError } from './classify';
|
|
17
17
|
import { deduplicateErrors, extractBracketErrors, extractForbiddenCharacterErrors } from './expression-errors';
|
|
18
|
-
import { isIncompleteGeneratorBodyCode } from './
|
|
18
|
+
import { isIncompleteGeneratorBodyCode } from './generators';
|
|
19
19
|
|
|
20
20
|
/** When set, refines incomplete formal headers (`[α∈…]`, quantifiers). */
|
|
21
21
|
export interface SyntaxErrorOptions {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syntax-errors-pCI6RicF.js","names":["TypeClassEnum"],"sources":["../src/rslang/parser/syntax-errors/context.ts","../src/rslang/parser/syntax-errors/ast-utils.ts","../src/rslang/parser/syntax-errors/function-calls.ts","../src/rslang/parser/syntax-errors/error-builders.ts","../src/rslang/parser/syntax-errors/generators.ts","../src/rslang/parser/syntax-errors/trailing-slot.ts","../src/rslang/parser/syntax-errors/incomplete-formal.ts","../src/rslang/parser/syntax-errors/incomplete-operands.ts","../src/rslang/parser/syntax-errors/classify.ts","../src/rslang/parser/syntax-errors/expression-errors.ts","../src/rslang/parser/syntax-errors/index.ts"],"sourcesContent":["/**\n * Types for the parse-error classifier pipeline.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport type { RSErrorDescription } from '../../error';\nimport type { TypeClass } from '../../semantic/typification';\n\n/** Shared state passed through parse-error classifiers. */\nexport interface ClassifyContext {\n hasBracketErrors: boolean;\n expected?: TypeClass;\n}\n\n/** Classifies a single ERROR node into a specific syntax error, if possible. */\nexport type ErrorClassifier = (\n node: AstNode,\n expression: string,\n context: ClassifyContext\n) => RSErrorDescription | null;\n\n/** Skips classifiers that conflict with bracket-level diagnostics. */\nexport function whenNoBracketErrors(classifier: ErrorClassifier): ErrorClassifier {\n return (node, expression, context) => (context.hasBracketErrors ? null : classifier(node, expression, context));\n}\n","/**\n * AST navigation helpers and node-type predicates for classifiers.\n *\n * Predicates accept grammar terms **or** {@link TokenID} because `normalizeAST` runs before\n * error extraction and leaves `hasError` subtrees unnormalized — see `parser/README.md`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { Filter, Function, Function_decl, Logic_quantor, Predicate } from '../parser.terms';\nimport { TokenID } from '../token';\n\nexport function 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\nexport function 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\nexport function isDescendantOf(ancestor: AstNode, node: AstNode): boolean {\n let current: AstNode | null = node.parent;\n while (current !== null) {\n if (current === ancestor) {\n return true;\n }\n current = current.parent;\n }\n return false;\n}\n\nexport function subtreeHasError(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n return node.children.some(subtreeHasError);\n}\n\nexport function isFunctionDeclNode(node: AstNode): boolean {\n return node.typeID === Function_decl || node.typeID === TokenID.NT_FUNC_DEFINITION;\n}\n\nexport function isQuantifierNode(node: AstNode): boolean {\n return node.typeID === Logic_quantor;\n}\n\nexport function isFunctionNode(node: AstNode): boolean {\n return node.typeID === Function || node.typeID === TokenID.ID_FUNCTION;\n}\n\nexport function isPredicateNode(node: AstNode): boolean {\n return node.typeID === Predicate || node.typeID === TokenID.ID_PREDICATE;\n}\n\nexport function isFilterNode(node: AstNode): boolean {\n return node.typeID === Filter || node.typeID === TokenID.FILTER;\n}\n\nexport function findMatchingCloseBracket(expression: string, openPos: number): number {\n if (expression[openPos] !== '[') {\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\nexport function getErrorOperandNode(node: AstNode): AstNode | null {\n if (node.typeID === TokenID.ERROR) {\n return node;\n }\n if (node.children.length === 1) {\n return getErrorOperandNode(node.children[0]);\n }\n return null;\n}\n\nexport function isErrorPlaceholder(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n if (node.children.length === 0) {\n return false;\n }\n return node.children.every(child => isErrorPlaceholder(child));\n}\n","/**\n * Malformed calls: `Fi…(…)`, `F1` / `P1` without or with wrong argument brackets.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\n\nimport {\n findAncestor,\n findMatchingCloseBracket,\n findRelatedNode,\n isFilterNode,\n isFunctionNode,\n isPredicateNode\n} from './ast-utils';\nimport type { ErrorClassifier } from './context';\n\nexport const classifyFilterParenMismatch: ErrorClassifier = (node, expression) => {\n const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);\n if (filterNode === null || expression[filterNode.to] !== '(') {\n return null;\n }\n\n return {\n code: RSErrorCode.invalidFilterSyntax,\n from: filterNode.from,\n to: filterNode.to + 1\n };\n};\n\nexport const classifyGlobalFuncCall: ErrorClassifier = (node, expression) => {\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 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 if (/^\\s*$/.test(rest)) {\n return withoutArgs;\n }\n\n if (/^\\s*\\(/.test(rest)) {\n return {\n code: RSErrorCode.globalFuncParenCall,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n }\n\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 && rest.slice(openBracket[0].length, closeIdx).trim().length === 0) {\n return withoutArgs;\n }\n\n return null;\n}\n","/**\n * Small helpers for building `RSErrorDescription` values from AST nodes.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { type RSErrorCode, type RSErrorDescription } from '../../error';\n\nexport function errorAt(node: AstNode, code: RSErrorCode, params?: readonly string[]): RSErrorDescription {\n return {\n code,\n from: node.from,\n to: node.to,\n params\n };\n}\n\nexport function hasOnlyClosingSuffix(expression: string, from: number): boolean {\n const suffix = expression.slice(from).trim();\n return suffix.length === 0 || /^[\\]\\)\\}]*$/.test(suffix);\n}\n\nexport function sliceText(node: AstNode, expression: string): string {\n return expression.slice(node.from, node.to);\n}\n\nexport function isTextToken(node: AstNode, expression: string, text: string): boolean {\n return sliceText(node, expression) === text;\n}\n","/**\n * Incomplete generator bodies: declarative `D{…}`, imperative `I{…}`, recursive `R{…}`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Declarative, Imp_blocks, Imperative, Recursion, Setexpr } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport { findAncestor, isDescendantOf, isErrorPlaceholder, subtreeHasError } from './ast-utils';\nimport type { ErrorClassifier } from './context';\nimport { errorAt, isTextToken } from './error-builders';\n\nexport const classifyIncompleteGenerator: ErrorClassifier = (node, expression) =>\n detectIncompleteDeclarative(node, expression) ??\n detectIncompleteImperative(node, expression) ??\n detectIncompleteRecursion(node, expression);\n\ninterface GeneratorBodySlot {\n nodes: AstNode[];\n headerEndIndex: number;\n}\n\nfunction detectIncompleteDeclarative(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(\n node,\n target => target.typeID === Declarative || target.typeID === TokenID.NT_DECLARATIVE_EXPR\n );\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedDeclarativeBody, slot =>\n isIncompleteDeclarativeBody(slot.nodes)\n );\n}\n\nfunction detectIncompleteImperative(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(\n node,\n target => target.typeID === Imperative || target.typeID === TokenID.NT_IMPERATIVE_EXPR\n );\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedImperativeBody, slot =>\n isIncompleteImperativeBody(slot, expression)\n );\n}\n\nfunction detectIncompleteRecursion(node: AstNode, expression: string): RSErrorDescription | null {\n const generatorNode = findAncestor(node, target => target.typeID === Recursion);\n return detectIncompleteGeneratorBody(node, expression, generatorNode, RSErrorCode.expectedRecursiveBody, slot =>\n isIncompleteRecursionBody(slot.nodes)\n );\n}\n\nfunction detectIncompleteGeneratorBody(\n node: AstNode,\n expression: string,\n generatorNode: AstNode | null,\n code: RSErrorCode,\n isIncomplete: (slot: GeneratorBodySlot) => boolean\n): RSErrorDescription | null {\n if (generatorNode === null || expression.slice(generatorNode.to).trim().length > 0) {\n return null;\n }\n\n const slot = getGeneratorBodySlot(generatorNode, expression);\n if (slot === null || !isIncomplete(slot) || !generatorHeaderIsValid(generatorNode, expression, slot.headerEndIndex)) {\n return null;\n }\n\n if (!isErrorInBodySlot(node, slot, generatorNode)) {\n return null;\n }\n\n return errorAt(node, code);\n}\n\nfunction getGeneratorBodySlot(generatorNode: AstNode, expression: string): GeneratorBodySlot | null {\n if (generatorNode.typeID === Declarative || generatorNode.typeID === TokenID.NT_DECLARATIVE_EXPR) {\n return getDeclarativeBodySlot(generatorNode, expression);\n }\n if (generatorNode.typeID === Imperative || generatorNode.typeID === TokenID.NT_IMPERATIVE_EXPR) {\n return getImperativeBodySlot(generatorNode, expression);\n }\n if (generatorNode.typeID === Recursion) {\n return getRecursionBodySlot(generatorNode, expression);\n }\n return null;\n}\n\nfunction getDeclarativeBodySlot(declNode: AstNode, expression: string): GeneratorBodySlot | null {\n const pipeIndex = declNode.children.findIndex(child => isTextToken(child, expression, '|'));\n if (pipeIndex >= 0) {\n return {\n nodes: contentChildren(declNode, expression, pipeIndex + 1),\n headerEndIndex: pipeIndex + 1\n };\n }\n\n const domainNode = findDeclarativeDomain(declNode, expression);\n if (domainNode === null) {\n return null;\n }\n\n const domainIndex = declNode.children.indexOf(domainNode);\n return {\n nodes: contentChildren(declNode, expression, domainIndex + 1),\n headerEndIndex: domainIndex + 1\n };\n}\n\nfunction getImperativeBodySlot(impNode: AstNode, expression: string): GeneratorBodySlot | null {\n const pipeIndex = impNode.children.findIndex(child => isTextToken(child, expression, '|'));\n if (pipeIndex >= 0) {\n return {\n nodes: contentChildren(impNode, expression, pipeIndex + 1),\n headerEndIndex: pipeIndex + 1\n };\n }\n\n const tupleNode = findImperativeTuple(impNode);\n if (tupleNode === null) {\n return null;\n }\n\n const tupleIndex = impNode.children.indexOf(tupleNode);\n return {\n nodes: contentChildren(impNode, expression, tupleIndex + 1),\n headerEndIndex: tupleIndex + 1\n };\n}\n\nfunction getRecursionBodySlot(recNode: AstNode, expression: string): GeneratorBodySlot | null {\n const initNode = findRecursionInit(recNode, expression);\n if (initNode === null) {\n return null;\n }\n\n const initIndex = recNode.children.indexOf(initNode);\n const afterInit = contentChildren(recNode, expression, initIndex + 1);\n const lastPipeIndex = findLastPipeIndex(afterInit, expression);\n if (lastPipeIndex < 0) {\n return {\n nodes: afterInit,\n headerEndIndex: initIndex + 1\n };\n }\n\n return {\n nodes: afterInit.slice(lastPipeIndex + 1),\n headerEndIndex: recNode.children.indexOf(afterInit[lastPipeIndex]) + 1\n };\n}\n\nfunction contentChildren(generatorNode: AstNode, expression: string, fromIndex: number): AstNode[] {\n return generatorNode.children.slice(fromIndex).filter(child => !isClosingBrace(child, expression));\n}\n\nfunction findDeclarativeDomain(declNode: AstNode, expression: string): AstNode | null {\n const inIndex = declNode.children.findIndex(child => isTextToken(child, expression, '∈'));\n if (inIndex < 0) {\n return null;\n }\n\n for (let index = inIndex + 1; index < declNode.children.length; index++) {\n const child = declNode.children[index];\n if (isTextToken(child, expression, '|') || isClosingBrace(child, expression)) {\n break;\n }\n if (child.typeID === Setexpr) {\n return child;\n }\n }\n\n return null;\n}\n\nfunction findImperativeTuple(impNode: AstNode): AstNode | null {\n for (const child of impNode.children) {\n if (child.typeID === Setexpr) {\n return child;\n }\n }\n return null;\n}\n\nfunction findLastPipeIndex(nodes: AstNode[], expression: string): number {\n for (let index = nodes.length - 1; index >= 0; index--) {\n if (isTextToken(nodes[index], expression, '|')) {\n return index;\n }\n }\n return -1;\n}\n\nfunction generatorHeaderIsValid(generatorNode: AstNode, expression: string, headerEndIndex: number): boolean {\n for (let index = 0; index < headerEndIndex; index++) {\n const child = generatorNode.children[index];\n if (child.typeID === TokenID.ERROR) {\n return false;\n }\n if (isStructuralGeneratorToken(child, expression)) {\n continue;\n }\n if (subtreeHasError(child)) {\n return false;\n }\n }\n return true;\n}\n\nfunction isIncompleteDeclarativeBody(nodes: AstNode[]): boolean {\n return isEmptyOrErrorOnlyBody(nodes);\n}\n\nfunction isIncompleteImperativeBody(slot: GeneratorBodySlot, expression: string): boolean {\n if (slot.nodes.length === 0) {\n return true;\n }\n if (slot.nodes.length === 1 && slot.nodes[0].typeID === Imp_blocks) {\n return isImpBlocksIncomplete(slot.nodes[0], expression);\n }\n return isEmptyOrErrorOnlyBody(slot.nodes);\n}\n\nfunction isIncompleteRecursionBody(nodes: AstNode[]): boolean {\n return isEmptyOrErrorOnlyBody(nodes);\n}\n\nfunction isEmptyOrErrorOnlyBody(nodes: AstNode[]): boolean {\n if (nodes.length === 0) {\n return true;\n }\n if (nodes.length === 1) {\n return isErrorPlaceholder(nodes[0]);\n }\n return false;\n}\n\nfunction isImpBlocksIncomplete(blocksNode: AstNode, expression: string): boolean {\n if (blocksNode.children.length === 0) {\n return true;\n }\n\n const lastChild = blocksNode.children[blocksNode.children.length - 1];\n if (lastChild.typeID === TokenID.ERROR) {\n return true;\n }\n if (isTextToken(lastChild, expression, ';')) {\n return true;\n }\n if (lastChild.typeID === Setexpr && isErrorPlaceholder(lastChild)) {\n return true;\n }\n\n return false;\n}\n\nfunction isErrorInBodySlot(errorNode: AstNode, slot: GeneratorBodySlot, generatorNode: AstNode): boolean {\n if (slot.nodes.length === 0) {\n const bodyStart = generatorNode.children[slot.headerEndIndex]?.from ?? generatorNode.from;\n return errorNode.from >= bodyStart;\n }\n\n for (const bodyNode of slot.nodes) {\n if (errorNode === bodyNode || isDescendantOf(bodyNode, errorNode)) {\n if (isErrorPlaceholder(bodyNode)) {\n return true;\n }\n if (bodyNode.typeID === Imp_blocks && isImpBlocksTailError(bodyNode, errorNode)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nfunction isImpBlocksTailError(blocksNode: AstNode, errorNode: AstNode): boolean {\n const lastChild = blocksNode.children[blocksNode.children.length - 1];\n return lastChild.typeID === TokenID.ERROR && (errorNode === lastChild || isDescendantOf(lastChild, errorNode));\n}\n\nfunction findRecursionInit(recursionNode: AstNode, expression: string): AstNode | null {\n const assignIndex = recursionNode.children.findIndex(child => isTextToken(child, expression, ':='));\n if (assignIndex < 0) {\n return null;\n }\n\n for (let index = assignIndex + 1; index < recursionNode.children.length; index++) {\n const child = recursionNode.children[index];\n if (child.typeID === TokenID.ERROR) {\n break;\n }\n if (isTextToken(child, expression, '|') || isClosingBrace(child, expression)) {\n continue;\n }\n return child;\n }\n\n return null;\n}\n\nfunction isClosingBrace(node: AstNode, expression: string): boolean {\n return node.typeID !== TokenID.ERROR && isTextToken(node, expression, '}');\n}\n\nfunction isStructuralGeneratorToken(node: AstNode, expression: string): boolean {\n const text = expression.slice(node.from, node.to);\n return text === '{' || text === '}' || text === '|' || text === '∈' || text === ':=' || text === ';';\n}\n","/**\n * Reusable pattern: container header is valid, last child is `ERROR`, input ends here.\n *\n * @see incomplete-formal.ts — function declarations, quantifiers\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { type RSErrorCode, type RSErrorDescription } from '../../error';\nimport { TokenID } from '../token';\n\nimport { errorAt } from './error-builders';\n\nexport function detectTrailingErrorSlot(\n node: AstNode,\n expression: string,\n container: AstNode | null,\n options: {\n headerValid?: (container: AstNode) => boolean;\n code: RSErrorCode | ((container: AstNode, bodyChild: AstNode) => RSErrorCode | null);\n }\n): RSErrorDescription | null {\n if (container === null) {\n return null;\n }\n\n const bodyChild = container.children[container.children.length - 1];\n if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) {\n return null;\n }\n\n if (expression.slice(container.to).trim().length > 0) {\n return null;\n }\n\n if (options.headerValid !== undefined && !options.headerValid(container)) {\n return null;\n }\n\n const code = typeof options.code === 'function' ? options.code(container, bodyChild) : options.code;\n if (code === null) {\n return null;\n }\n\n return errorAt(bodyChild, code);\n}\n","/**\n * Incomplete formal headers: `[α∈…]` declarations and quantifiers (`∀α∈…`).\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { TypeClass as TypeClassEnum } from '../../semantic/typification';\nimport { Arguments, Variable_pack } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport { findAncestor, isFunctionDeclNode, isQuantifierNode, subtreeHasError } from './ast-utils';\nimport type { ClassifyContext, ErrorClassifier } from './context';\nimport { detectTrailingErrorSlot } from './trailing-slot';\n\nexport const classifyIncompleteFormal: ErrorClassifier = (node, expression, context) =>\n detectIncompleteFunctionDecl(node, expression, context.expected) ?? detectIncompleteQuantifier(node, expression);\n\nfunction detectIncompleteFunctionDecl(\n node: AstNode,\n expression: string,\n expected?: ClassifyContext['expected']\n): RSErrorDescription | null {\n return detectTrailingErrorSlot(node, expression, findAncestor(node, isFunctionDeclNode), {\n headerValid: container => {\n const argsNode = container.children.find(\n child => child.typeID === Arguments || child.typeID === TokenID.NT_ARGUMENTS\n );\n return argsNode !== undefined && !subtreeHasError(argsNode);\n },\n code: () => incompleteFormalExpressionCode(expected)\n });\n}\n\nfunction incompleteFormalExpressionCode(expected?: ClassifyContext['expected']): 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 detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorDescription | null {\n return detectTrailingErrorSlot(node, expression, findAncestor(node, isQuantifierNode), {\n headerValid: container => {\n const varPack = container.children.find(\n child => child.typeID === Variable_pack || child.typeID === TokenID.NT_ENUM_DECL\n );\n return varPack !== undefined && !subtreeHasError(varPack);\n },\n code: (container, bodyChild) => {\n const inIndex = container.children.findIndex(child => expression.slice(child.from, child.to) === '∈');\n if (inIndex < 0) {\n return RSErrorCode.expectedQuantifierDomain;\n }\n\n const domainChild = container.children[inIndex + 1];\n if (domainChild === undefined || domainChild === bodyChild || subtreeHasError(domainChild)) {\n return RSErrorCode.expectedQuantifierDomain;\n }\n\n return RSErrorCode.expectedQuantifierBody;\n }\n });\n}\n\nexport function isIncompleteGeneratorBodyCode(code: RSErrorCode): boolean {\n return (\n code === RSErrorCode.expectedDeclarativeBody ||\n code === RSErrorCode.expectedImperativeBody ||\n code === RSErrorCode.expectedRecursiveBody\n );\n}\n","/**\n * Incomplete operators and bracket argument lists (`P1[S1, ]`).\n *\n * Tuple enums `(α,β,)` intentionally stay `unknownSyntax` — not `expectedArgument`.\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Boolean, Expr_enum_min2, Logic_binary, Logic_predicates, Logic_unary, Setexpr_binary } from '../parser.terms';\nimport { TokenID } from '../token';\n\nimport {\n findAncestor,\n findMatchingCloseBracket,\n getErrorOperandNode,\n isFilterNode,\n isFunctionNode,\n isPredicateNode,\n subtreeHasError\n} from './ast-utils';\nimport type { ErrorClassifier } from './context';\nimport { errorAt, hasOnlyClosingSuffix, isTextToken, sliceText } from './error-builders';\n\nexport const classifyIncompleteOperands: ErrorClassifier = (node, expression) =>\n detectIncompleteUnaryOperand(node, expression) ??\n detectIncompleteBinaryOperand(node, expression) ??\n detectIncompleteBooleanOperand(node, expression);\n\nexport const classifyIncompleteArgument: ErrorClassifier = (node, expression) =>\n detectIncompleteArgument(node, expression);\n\nfunction detectIncompleteUnaryOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const unaryNode = findAncestor(node, target => target.typeID === Logic_unary);\n if (unaryNode === null) {\n return null;\n }\n\n const operandChild = unaryNode.children[unaryNode.children.length - 1];\n if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {\n return null;\n }\n\n if (expression.slice(unaryNode.to).trim().length > 0) {\n return null;\n }\n\n const operatorChild = unaryNode.children[0];\n if (operatorChild === undefined || operatorChild === operandChild) {\n return null;\n }\n\n if (!isTextToken(operatorChild, expression, '¬')) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedUnaryOperand);\n}\n\nfunction detectIncompleteBinaryOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const binaryNode = findAncestor(\n node,\n target => target.typeID === Logic_binary || target.typeID === Logic_predicates || target.typeID === Setexpr_binary\n );\n if (binaryNode === null) {\n return null;\n }\n\n const operandChild = binaryNode.children[binaryNode.children.length - 1];\n if (operandChild?.typeID !== TokenID.ERROR || node !== operandChild) {\n return null;\n }\n\n if (expression.slice(binaryNode.to).trim().length > 0) {\n return null;\n }\n\n if (binaryNode.children.length < 2) {\n return null;\n }\n\n const leftChild = binaryNode.children[0];\n if (leftChild.typeID === TokenID.ERROR || subtreeHasError(leftChild)) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedRightOperand);\n}\n\nfunction detectIncompleteBooleanOperand(node: AstNode, expression: string): RSErrorDescription | null {\n const booleanNode = findAncestor(node, target => target.typeID === Boolean);\n if (booleanNode === null) {\n return null;\n }\n\n const operandChild = findTrailingErrorOperand(booleanNode, expression);\n if (operandChild === null || node !== operandChild) {\n return null;\n }\n\n if (!hasOnlyClosingSuffix(expression, booleanNode.to)) {\n return null;\n }\n\n return errorAt(operandChild, RSErrorCode.expectedRightOperand);\n}\n\nfunction detectIncompleteArgument(node: AstNode, expression: string): RSErrorDescription | null {\n const enumNode = findAncestor(node, target => target.typeID === Expr_enum_min2);\n if (enumNode === null || !isLegitimateArgumentEnum(enumNode, expression)) {\n return null;\n }\n\n const errorChild = findEnumArgumentError(enumNode, expression);\n if (errorChild === null || node !== errorChild || !hasOnlyClosingSuffix(expression, enumNode.to)) {\n return null;\n }\n\n return errorAt(errorChild, RSErrorCode.expectedArgument);\n}\n\nfunction findTrailingErrorOperand(container: AstNode, expression: string): AstNode | null {\n for (let index = container.children.length - 1; index >= 0; index--) {\n const child = container.children[index];\n if (isOperandStructuralToken(child, expression)) {\n continue;\n }\n return getErrorOperandNode(child);\n }\n return null;\n}\n\nfunction findEnumArgumentError(enumNode: AstNode, expression: string): AstNode | null {\n for (const child of enumNode.children) {\n if (isTextToken(child, expression, ',')) {\n continue;\n }\n const errorNode = getErrorOperandNode(child);\n if (errorNode !== null) {\n return errorNode;\n }\n }\n return null;\n}\n\nfunction isOperandStructuralToken(node: AstNode, expression: string): boolean {\n const text = sliceText(node, expression);\n return text === '(' || text === ')' || text === 'ℬ';\n}\n\nfunction isLegitimateArgumentEnum(enumNode: AstNode, expression: string): boolean {\n return findCallHostForBracketEnum(enumNode, expression) !== null;\n}\n\nfunction findCallHostForBracketEnum(enumNode: AstNode, expression: string): AstNode | null {\n let current: AstNode | null = enumNode.parent;\n while (current !== null) {\n for (const child of current.children) {\n if (!isFunctionNode(child) && !isPredicateNode(child) && !isFilterNode(child)) {\n continue;\n }\n if (isEnumInCallBrackets(enumNode, child, expression)) {\n return child;\n }\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction isEnumInCallBrackets(enumNode: AstNode, nameNode: AstNode, expression: string): boolean {\n const rest = expression.slice(nameNode.to);\n const match = /^\\s*\\[/.exec(rest);\n if (match === null) {\n return false;\n }\n\n const openPos = nameNode.to + match.index + match[0].indexOf('[');\n const closePos = findMatchingCloseBracket(expression, openPos);\n if (closePos < 0) {\n return false;\n }\n\n return enumNode.from > openPos && enumNode.from < closePos;\n}\n","/**\n * Parse-error classification: ordered classifier chain and P8400 fallback.\n *\n * Register new detectors in `PARSE_ERROR_CLASSIFIERS` (first match wins).\n */\n\nimport type { AstNode } from '../../../parsing';\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\nimport { Variable } from '../parser.terms';\n\nimport type { ClassifyContext, ErrorClassifier } from './context';\nimport { whenNoBracketErrors } from './context';\nimport { classifyFilterParenMismatch, classifyGlobalFuncCall } from './function-calls';\nimport { classifyIncompleteGenerator } from './generators';\nimport { classifyIncompleteFormal } from './incomplete-formal';\nimport { classifyIncompleteArgument, classifyIncompleteOperands } from './incomplete-operands';\n\nconst PARSE_ERROR_CLASSIFIERS: ErrorClassifier[] = [\n classifyIncompleteFormal,\n classifyIncompleteGenerator,\n whenNoBracketErrors(classifyIncompleteOperands),\n whenNoBracketErrors(classifyIncompleteArgument),\n classifyFilterParenMismatch,\n classifyGlobalFuncCall\n];\n\n/** Runs classifiers in priority order for one `ERROR` AST node. */\nexport function classifyParseError(\n node: AstNode,\n expression: string,\n context: ClassifyContext\n): RSErrorDescription | null {\n for (const classifier of PARSE_ERROR_CLASSIFIERS) {\n const error = classifier(node, expression, context);\n if (error !== null) {\n return error;\n }\n }\n return null;\n}\n\n/** Default rules when no classifier matched: `expectedLocal` or `unknownSyntax`. */\nexport function classifyFallbackError(\n node: AstNode,\n ignoreUnknownErrors: boolean\n): { error: RSErrorDescription; target: AstNode } | null {\n const parent = node.parent;\n if (parent === null) {\n return ignoreUnknownErrors\n ? null\n : { error: { code: RSErrorCode.unknownSyntax, from: node.from, to: node.to }, target: node };\n }\n\n if (parent.typeID === Variable) {\n return {\n error: { code: RSErrorCode.expectedLocal, from: parent.from, to: parent.to },\n target: parent\n };\n }\n\n if (ignoreUnknownErrors) {\n return null;\n }\n\n const target = node.from === node.to ? parent : node;\n return {\n error: { code: RSErrorCode.unknownSyntax, from: target.from, to: target.to },\n target\n };\n}\n","/**\n * Expression-level diagnostics (no AST required) and error deduplication.\n */\n\nimport { RSErrorCode, type RSErrorDescription } from '../../error';\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\nexport function 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\nexport function 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\nexport function 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 const filtered = result.filter(\n error => error.code !== RSErrorCode.unknownSyntax || !specific.some(item => rangesOverlap(error, item))\n );\n return collapseContiguousUnknownSyntax(filtered);\n}\n\nfunction collapseContiguousUnknownSyntax(errors: RSErrorDescription[]): RSErrorDescription[] {\n const unknowns = errors.filter(error => error.code === RSErrorCode.unknownSyntax);\n if (unknowns.length <= 1) {\n return errors;\n }\n\n const others = errors.filter(error => error.code !== RSErrorCode.unknownSyntax);\n const first = [...unknowns].sort((left, right) => left.from - right.from)[0];\n return [...others, first];\n}\n\nfunction rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {\n return a.from < b.to && b.from < a.to;\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","/**\n * Syntax error extraction — public entry point.\n *\n * Expects the **hybrid** AST produced by `normalizeAST` (see `parser/README.md`).\n * See {@link ./README.md} for pipeline, classifier order, and how to add codes.\n *\n * @module rslang/parser/syntax-errors\n */\n\nimport { type AstNode, visitAstDFS } from '../../../parsing';\nimport { annotateError } from '../../ast-annotations';\nimport { type ErrorReporter, type RSErrorDescription } from '../../error';\nimport { type TypeClass } from '../../semantic/typification';\nimport { TokenID } from '../token';\n\nimport { classifyFallbackError, classifyParseError } from './classify';\nimport { deduplicateErrors, extractBracketErrors, extractForbiddenCharacterErrors } from './expression-errors';\nimport { isIncompleteGeneratorBodyCode } from './incomplete-formal';\n\n/** When set, refines incomplete formal headers (`[α∈…]`, quantifiers). */\nexport interface SyntaxErrorOptions {\n expected?: TypeClass;\n}\n\n/**\n * Walks a parsed expression AST and reports syntax errors.\n *\n * @param ast - Root AST from `buildTree(parser.parse(expression))`\n * @param expression - Original source text (positions must match the AST)\n * @param reporter - Called once per deduplicated error\n * @param annotateErrors - When true, also calls `annotateError` on the triggering node\n * @param options - Optional typification hint for incomplete formal expressions\n */\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 const hasBracketErrors = bracketError !== null;\n visitAstDFS(ast, node => extractInternal(node, expression, collect, hasBracketErrors, options));\n\n const hasIncompleteGenerator = collected.some(error => isIncompleteGeneratorBodyCode(error.code));\n if (bracketError !== null && !hasIncompleteGenerator) {\n collect(bracketError, ast);\n }\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\nfunction extractInternal(\n node: AstNode,\n expression: string,\n collect: (error: RSErrorDescription, target: AstNode) => void,\n hasBracketErrors: boolean,\n options?: SyntaxErrorOptions\n) {\n if (node.typeID !== TokenID.ERROR) {\n return;\n }\n\n const classified = classifyParseError(node, expression, { hasBracketErrors, expected: options?.expected });\n if (classified !== null) {\n collect(classified, node);\n return;\n }\n\n const fallback = classifyFallbackError(node, hasBracketErrors);\n if (fallback !== null) {\n collect(fallback.error, fallback.target);\n }\n}\n"],"mappings":"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"}
|