@rsconcept/domain 2.1.1 → 2.1.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.
@@ -1,2 +1,2 @@
1
- import { t as extractSyntaxErrors } from "../../../syntax-errors-D_VV5hAM.js";
1
+ import { t as extractSyntaxErrors } from "../../../syntax-errors-DwPXhpVe.js";
2
2
  export { extractSyntaxErrors };
@@ -4,7 +4,7 @@ import { labelType } from "../labels.js";
4
4
  import { annotateError } from "../ast-annotations.js";
5
5
  import { RSErrorCode } from "../error.js";
6
6
  import { parseRSLangExpression } from "../api.js";
7
- import { t as extractSyntaxErrors } from "../../syntax-errors-D_VV5hAM.js";
7
+ import { t as extractSyntaxErrors } from "../../syntax-errors-DwPXhpVe.js";
8
8
  import { getTypeClass } from "./typification-api.js";
9
9
  import { TypeAuditor } from "./type-auditor.js";
10
10
  import { ValueClass } from "./value-class.js";
@@ -78,6 +78,12 @@ function isErrorPlaceholder(node) {
78
78
  if (node.children.length === 0) return false;
79
79
  return node.children.every((child) => isErrorPlaceholder(child));
80
80
  }
81
+ /** True when a body slot is missing or is only an ERROR placeholder (not a real expression + trailing junk). */
82
+ function isEmptyOrErrorOnlyBody(nodes) {
83
+ if (nodes.length === 0) return true;
84
+ if (nodes.length === 1) return isErrorPlaceholder(nodes[0]);
85
+ return false;
86
+ }
81
87
  //#endregion
82
88
  //#region src/rslang/parser/syntax-errors/function-calls.ts
83
89
  const classifyFilterParenMismatch = (node, expression) => {
@@ -248,11 +254,6 @@ function isIncompleteImperativeBody(slot, expression) {
248
254
  function isIncompleteRecursionBody(nodes) {
249
255
  return isEmptyOrErrorOnlyBody(nodes);
250
256
  }
251
- function isEmptyOrErrorOnlyBody(nodes) {
252
- if (nodes.length === 0) return true;
253
- if (nodes.length === 1) return isErrorPlaceholder(nodes[0]);
254
- return false;
255
- }
256
257
  function isImpBlocksIncomplete(blocksNode, expression) {
257
258
  if (blocksNode.children.length === 0) return true;
258
259
  const lastChild = blocksNode.children[blocksNode.children.length - 1];
@@ -302,6 +303,7 @@ function detectTrailingErrorSlot(node, expression, container, options) {
302
303
  if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) return null;
303
304
  if (expression.slice(container.to).trim().length > 0) return null;
304
305
  if (options.headerValid !== void 0 && !options.headerValid(container)) return null;
306
+ if (!isEmptyOrErrorOnlyBody(options.bodyNodes?.(container, bodyChild) ?? [bodyChild])) return null;
305
307
  const code = typeof options.code === "function" ? options.code(container, bodyChild) : options.code;
306
308
  if (code === null) return null;
307
309
  return errorAt(bodyChild, code);
@@ -315,9 +317,15 @@ function detectIncompleteFunctionDecl(node, expression, expected) {
315
317
  const argsNode = container.children.find((child) => child.typeID === 77 || child.typeID === TokenID.NT_ARGUMENTS);
316
318
  return argsNode !== void 0 && !subtreeHasError(argsNode);
317
319
  },
320
+ bodyNodes: (container, errorChild) => functionDeclBodyNodes(container, expression, errorChild),
318
321
  code: () => incompleteFormalExpressionCode(expected)
319
322
  });
320
323
  }
324
+ function functionDeclBodyNodes(container, expression, errorChild) {
325
+ const closeIndex = container.children.findIndex((child) => isTextToken(child, expression, "]"));
326
+ if (closeIndex < 0) return [errorChild];
327
+ return container.children.slice(closeIndex + 1);
328
+ }
321
329
  function incompleteFormalExpressionCode(expected) {
322
330
  switch (expected) {
323
331
  case TypeClass.function: return RSErrorCode.expectedExpressionBody;
@@ -332,6 +340,7 @@ function detectIncompleteQuantifier(node, expression) {
332
340
  const varPack = container.children.find((child) => child.typeID === 31 || child.typeID === TokenID.NT_ENUM_DECL);
333
341
  return varPack !== void 0 && !subtreeHasError(varPack);
334
342
  },
343
+ bodyNodes: (container, errorChild) => quantifierBodyNodes(container, expression, errorChild),
335
344
  code: (container, bodyChild) => {
336
345
  const inIndex = container.children.findIndex((child) => expression.slice(child.from, child.to) === "∈");
337
346
  if (inIndex < 0) return RSErrorCode.expectedQuantifierDomain;
@@ -341,6 +350,11 @@ function detectIncompleteQuantifier(node, expression) {
341
350
  }
342
351
  });
343
352
  }
353
+ function quantifierBodyNodes(container, expression, errorChild) {
354
+ const inIndex = container.children.findIndex((child) => isTextToken(child, expression, "∈"));
355
+ if (inIndex < 0) return [errorChild];
356
+ return container.children.slice(inIndex + 2);
357
+ }
344
358
  //#endregion
345
359
  //#region src/rslang/parser/syntax-errors/incomplete-operands.ts
346
360
  const classifyIncompleteOperands = (node, expression) => detectIncompleteUnaryOperand(node, expression) ?? detectIncompleteBinaryOperand(node, expression) ?? detectIncompleteBooleanOperand(node, expression);
@@ -708,4 +722,4 @@ function extractInternal(node, expression, collect, hasBracketErrors, options) {
708
722
  //#endregion
709
723
  export { extractSyntaxErrors as t };
710
724
 
711
- //# sourceMappingURL=syntax-errors-D_VV5hAM.js.map
725
+ //# sourceMappingURL=syntax-errors-DwPXhpVe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntax-errors-DwPXhpVe.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/** True when a body slot is missing or is only an ERROR placeholder (not a real expression + trailing junk). */\nexport function 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","/**\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, isEmptyOrErrorOnlyBody, 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 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, body slot is empty/ERROR-only, input ends here.\n *\n * Distinguishes a missing body (`[α∈X1]⚠`) from a real body with trailing junk\n * (`[α∈X1]1=1⚠)`), which must not report `expected*Body`.\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 { isEmptyOrErrorOnlyBody } from './ast-utils';\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 /** Nodes that form the body after the header. Defaults to the trailing ERROR only. */\n bodyNodes?: (container: AstNode, errorChild: AstNode) => AstNode[];\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 bodyNodes = options.bodyNodes?.(container, bodyChild) ?? [bodyChild];\n if (!isEmptyOrErrorOnlyBody(bodyNodes)) {\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 { isTextToken } from './error-builders';\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 bodyNodes: (container, errorChild) => functionDeclBodyNodes(container, expression, errorChild),\n code: () => incompleteFormalExpressionCode(expected)\n });\n}\n\nfunction functionDeclBodyNodes(container: AstNode, expression: string, errorChild: AstNode): AstNode[] {\n const closeIndex = container.children.findIndex(child => isTextToken(child, expression, ']'));\n if (closeIndex < 0) {\n return [errorChild];\n }\n return container.children.slice(closeIndex + 1);\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 bodyNodes: (container, errorChild) => quantifierBodyNodes(container, expression, errorChild),\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\nfunction quantifierBodyNodes(container: AstNode, expression: string, errorChild: AstNode): AstNode[] {\n const inIndex = container.children.findIndex(child => isTextToken(child, expression, '∈'));\n if (inIndex < 0) {\n return [errorChild];\n }\n // Domain is the child after ∈; body starts after the domain.\n return container.children.slice(inIndex + 2);\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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsconcept/domain",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Shared TypeScript domain for RS language, RSForm, RSModel, RSEngine, OSS, and concept-text helpers.",
5
5
  "license": "MIT",
6
6
  "author": "IRBorisov",
@@ -254,6 +254,21 @@ describe('Testing RSParser error data', () => {
254
254
  expect(errors.some(error => error.code === RSErrorCode.expectedDeclarativeBody)).toBe(false);
255
255
  });
256
256
 
257
+ it('Does not report missing function body when body exists with trailing junk', () => {
258
+ const input = '[α∈ℬℬ(Z×R1),β∈ℬℬ(R1)]∀α0∈α F7[α0]∈β & P7[α0])';
259
+ const tree = parser.parse(input);
260
+ const ast = buildTree(tree.cursor());
261
+ const errors: RSErrorDescription[] = [];
262
+ extractSyntaxErrors(ast, input, error => errors.push(error), false, { expected: TypeClass.predicate });
263
+ expect(errors.some(error => error.code === RSErrorCode.expectedLogicBody)).toBe(false);
264
+ expect(errors).toEqual([
265
+ expect.objectContaining({
266
+ code: RSErrorCode.missingOpenBracket,
267
+ params: [')']
268
+ })
269
+ ]);
270
+ });
271
+
257
272
  it('Reports incomplete quantifier only for innermost missing body', () => {
258
273
  const input = '∀α∈X1 ∀β∈X2';
259
274
  const tree = parser.parse(input);
@@ -110,3 +110,14 @@ export function isErrorPlaceholder(node: AstNode): boolean {
110
110
  }
111
111
  return node.children.every(child => isErrorPlaceholder(child));
112
112
  }
113
+
114
+ /** True when a body slot is missing or is only an ERROR placeholder (not a real expression + trailing junk). */
115
+ export function isEmptyOrErrorOnlyBody(nodes: AstNode[]): boolean {
116
+ if (nodes.length === 0) {
117
+ return true;
118
+ }
119
+ if (nodes.length === 1) {
120
+ return isErrorPlaceholder(nodes[0]);
121
+ }
122
+ return false;
123
+ }
@@ -7,7 +7,7 @@ import { RSErrorCode, type RSErrorDescription } from '../../error';
7
7
  import { Declarative, Imp_blocks, Imperative, Recursion, Setexpr } from '../parser.terms';
8
8
  import { TokenID } from '../token';
9
9
 
10
- import { findAncestor, isDescendantOf, isErrorPlaceholder, subtreeHasError } from './ast-utils';
10
+ import { findAncestor, isDescendantOf, isEmptyOrErrorOnlyBody, isErrorPlaceholder, subtreeHasError } from './ast-utils';
11
11
  import type { ErrorClassifier } from './context';
12
12
  import { errorAt, isTextToken } from './error-builders';
13
13
 
@@ -231,16 +231,6 @@ function isIncompleteRecursionBody(nodes: AstNode[]): boolean {
231
231
  return isEmptyOrErrorOnlyBody(nodes);
232
232
  }
233
233
 
234
- function isEmptyOrErrorOnlyBody(nodes: AstNode[]): boolean {
235
- if (nodes.length === 0) {
236
- return true;
237
- }
238
- if (nodes.length === 1) {
239
- return isErrorPlaceholder(nodes[0]);
240
- }
241
- return false;
242
- }
243
-
244
234
  function isImpBlocksIncomplete(blocksNode: AstNode, expression: string): boolean {
245
235
  if (blocksNode.children.length === 0) {
246
236
  return true;
@@ -10,6 +10,7 @@ import { TokenID } from '../token';
10
10
 
11
11
  import { findAncestor, isFunctionDeclNode, isQuantifierNode, subtreeHasError } from './ast-utils';
12
12
  import type { ClassifyContext, ErrorClassifier } from './context';
13
+ import { isTextToken } from './error-builders';
13
14
  import { detectTrailingErrorSlot } from './trailing-slot';
14
15
 
15
16
  export const classifyIncompleteFormal: ErrorClassifier = (node, expression, context) =>
@@ -27,10 +28,19 @@ function detectIncompleteFunctionDecl(
27
28
  );
28
29
  return argsNode !== undefined && !subtreeHasError(argsNode);
29
30
  },
31
+ bodyNodes: (container, errorChild) => functionDeclBodyNodes(container, expression, errorChild),
30
32
  code: () => incompleteFormalExpressionCode(expected)
31
33
  });
32
34
  }
33
35
 
36
+ function functionDeclBodyNodes(container: AstNode, expression: string, errorChild: AstNode): AstNode[] {
37
+ const closeIndex = container.children.findIndex(child => isTextToken(child, expression, ']'));
38
+ if (closeIndex < 0) {
39
+ return [errorChild];
40
+ }
41
+ return container.children.slice(closeIndex + 1);
42
+ }
43
+
34
44
  function incompleteFormalExpressionCode(expected?: ClassifyContext['expected']): RSErrorCode {
35
45
  switch (expected) {
36
46
  case TypeClassEnum.function:
@@ -51,6 +61,7 @@ function detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorD
51
61
  );
52
62
  return varPack !== undefined && !subtreeHasError(varPack);
53
63
  },
64
+ bodyNodes: (container, errorChild) => quantifierBodyNodes(container, expression, errorChild),
54
65
  code: (container, bodyChild) => {
55
66
  const inIndex = container.children.findIndex(child => expression.slice(child.from, child.to) === '∈');
56
67
  if (inIndex < 0) {
@@ -66,3 +77,12 @@ function detectIncompleteQuantifier(node: AstNode, expression: string): RSErrorD
66
77
  }
67
78
  });
68
79
  }
80
+
81
+ function quantifierBodyNodes(container: AstNode, expression: string, errorChild: AstNode): AstNode[] {
82
+ const inIndex = container.children.findIndex(child => isTextToken(child, expression, '∈'));
83
+ if (inIndex < 0) {
84
+ return [errorChild];
85
+ }
86
+ // Domain is the child after ∈; body starts after the domain.
87
+ return container.children.slice(inIndex + 2);
88
+ }
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Reusable pattern: container header is valid, last child is `ERROR`, input ends here.
2
+ * Reusable pattern: container header is valid, body slot is empty/ERROR-only, input ends here.
3
+ *
4
+ * Distinguishes a missing body (`[α∈X1]⚠`) from a real body with trailing junk
5
+ * (`[α∈X1]1=1⚠)`), which must not report `expected*Body`.
3
6
  *
4
7
  * @see incomplete-formal.ts — function declarations, quantifiers
5
8
  */
@@ -8,6 +11,7 @@ import type { AstNode } from '../../../parsing';
8
11
  import { type RSErrorCode, type RSErrorDescription } from '../../error';
9
12
  import { TokenID } from '../token';
10
13
 
14
+ import { isEmptyOrErrorOnlyBody } from './ast-utils';
11
15
  import { errorAt } from './error-builders';
12
16
 
13
17
  export function detectTrailingErrorSlot(
@@ -16,6 +20,8 @@ export function detectTrailingErrorSlot(
16
20
  container: AstNode | null,
17
21
  options: {
18
22
  headerValid?: (container: AstNode) => boolean;
23
+ /** Nodes that form the body after the header. Defaults to the trailing ERROR only. */
24
+ bodyNodes?: (container: AstNode, errorChild: AstNode) => AstNode[];
19
25
  code: RSErrorCode | ((container: AstNode, bodyChild: AstNode) => RSErrorCode | null);
20
26
  }
21
27
  ): RSErrorDescription | null {
@@ -36,6 +42,11 @@ export function detectTrailingErrorSlot(
36
42
  return null;
37
43
  }
38
44
 
45
+ const bodyNodes = options.bodyNodes?.(container, bodyChild) ?? [bodyChild];
46
+ if (!isEmptyOrErrorOnlyBody(bodyNodes)) {
47
+ return null;
48
+ }
49
+
39
50
  const code = typeof options.code === 'function' ? options.code(container, bodyChild) : options.code;
40
51
  if (code === null) {
41
52
  return null;
@@ -1 +0,0 @@
1
- {"version":3,"file":"syntax-errors-D_VV5hAM.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":";;;;;;;;;AAsBA,SAAgB,oBAAoB,YAA8C;CAChF,QAAQ,MAAM,YAAY,YAAa,QAAQ,mBAAmB,OAAO,WAAW,MAAM,YAAY,OAAO;AAC/G;;;ACbA,SAAgB,aAAa,MAAe,WAAuD;CACjG,IAAI,UAA0B;CAC9B,OAAO,YAAY,MAAM;EACvB,IAAI,UAAU,OAAO,GACnB,OAAO;EAET,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAgB,gBAAgB,MAAe,WAAyD;CACtG,IAAI,UAA0B,KAAK;CACnC,OAAO,YAAY,MAAM;EACvB,KAAK,MAAM,SAAS,QAAQ,UAC1B,IAAI,UAAU,KAAK,GACjB,OAAO;EAGX,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAgB,eAAe,UAAmB,MAAwB;CACxE,IAAI,UAA0B,KAAK;CACnC,OAAO,YAAY,MAAM;EACvB,IAAI,YAAY,UACd,OAAO;EAET,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAgB,gBAAgB,MAAwB;CACtD,IAAI,KAAK,WAAW,QAAQ,OAC1B,OAAO;CAET,OAAO,KAAK,SAAS,KAAK,eAAe;AAC3C;AAEA,SAAgB,mBAAmB,MAAwB;CACzD,OAAO,KAAK,WAAA,MAA4B,KAAK,WAAW,QAAQ;AAClE;AAEA,SAAgB,iBAAiB,MAAwB;CACvD,OAAO,KAAK,WAAA;AACd;AAEA,SAAgB,eAAe,MAAwB;CACrD,OAAO,KAAK,WAAA,MAAuB,KAAK,WAAW,QAAQ;AAC7D;AAEA,SAAgB,gBAAgB,MAAwB;CACtD,OAAO,KAAK,WAAA,MAAwB,KAAK,WAAW,QAAQ;AAC9D;AAEA,SAAgB,aAAa,MAAwB;CACnD,OAAO,KAAK,WAAA,MAAqB,KAAK,WAAW,QAAQ;AAC3D;AAEA,SAAgB,yBAAyB,YAAoB,SAAyB;CACpF,IAAI,WAAW,aAAa,KAC1B,OAAO;CAGT,IAAI,QAAQ;CACZ,KAAK,IAAI,QAAQ,SAAS,QAAQ,WAAW,QAAQ,SAAS;EAC5D,MAAM,SAAS,WAAW;EAC1B,IAAI,WAAW,KACb;OACK,IAAI,WAAW,KAAK;GACzB;GACA,IAAI,UAAU,GACZ,OAAO;EAEX;CACF;CACA,OAAO;AACT;AAEA,SAAgB,oBAAoB,MAA+B;CACjE,IAAI,KAAK,WAAW,QAAQ,OAC1B,OAAO;CAET,IAAI,KAAK,SAAS,WAAW,GAC3B,OAAO,oBAAoB,KAAK,SAAS,EAAE;CAE7C,OAAO;AACT;AAEA,SAAgB,mBAAmB,MAAwB;CACzD,IAAI,KAAK,WAAW,QAAQ,OAC1B,OAAO;CAET,IAAI,KAAK,SAAS,WAAW,GAC3B,OAAO;CAET,OAAO,KAAK,SAAS,OAAM,UAAS,mBAAmB,KAAK,CAAC;AAC/D;;;AC9FA,MAAa,+BAAgD,MAAM,eAAe;CAChF,MAAM,aAAa,aAAa,MAAM,YAAY,KAAK,gBAAgB,MAAM,YAAY;CACzF,IAAI,eAAe,QAAQ,WAAW,WAAW,QAAQ,KACvD,OAAO;CAGT,OAAO;EACL,MAAM,YAAY;EAClB,MAAM,WAAW;EACjB,IAAI,WAAW,KAAK;CACtB;AACF;AAEA,MAAa,0BAA2C,MAAM,eAAe;CAC3E,MAAM,WACJ,aAAa,OAAM,MAAK,eAAe,CAAC,KAAK,gBAAgB,CAAC,CAAC,KAC/D,gBAAgB,OAAM,MAAK,eAAe,CAAC,KAAK,gBAAgB,CAAC,CAAC;CACpE,IAAI,aAAa,MACf,OAAO;CAET,OAAO,wBAAwB,UAAU,UAAU;AACrD;AAEA,SAAS,wBAAwB,UAAmB,YAA+C;CACjG,MAAM,OAAO,WAAW,MAAM,SAAS,MAAM,SAAS,EAAE;CACxD,MAAM,OAAO,WAAW,MAAM,SAAS,EAAE;CAEzC,MAAM,cAAkC;EACtC,MAAM,YAAY;EAClB,MAAM,SAAS;EACf,IAAI,SAAS;EACb,QAAQ,CAAC,IAAI;CACf;CAEA,IAAI,QAAQ,KAAK,IAAI,GACnB,OAAO;CAGT,IAAI,SAAS,KAAK,IAAI,GACpB,OAAO;EACL,MAAM,YAAY;EAClB,MAAM,SAAS;EACf,IAAI,SAAS;EACb,QAAQ,CAAC,IAAI;CACf;CAGF,MAAM,cAAc,SAAS,KAAK,IAAI;CACtC,IAAI,gBAAgB,MAClB,OAAO;CAGT,MAAM,WAAW,yBAAyB,MAAM,YAAY,EAAE,CAAC,SAAS,CAAC;CACzE,IAAI,YAAY,KAAK,KAAK,MAAM,YAAY,EAAE,CAAC,QAAQ,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,GACjF,OAAO;CAGT,OAAO;AACT;;;ACpEA,SAAgB,QAAQ,MAAe,MAAmB,QAAgD;CACxG,OAAO;EACL;EACA,MAAM,KAAK;EACX,IAAI,KAAK;EACT;CACF;AACF;AAEA,SAAgB,qBAAqB,YAAoB,MAAuB;CAC9E,MAAM,SAAS,WAAW,MAAM,IAAI,CAAC,CAAC,KAAK;CAC3C,OAAO,OAAO,WAAW,KAAK,cAAc,KAAK,MAAM;AACzD;AAEA,SAAgB,UAAU,MAAe,YAA4B;CACnE,OAAO,WAAW,MAAM,KAAK,MAAM,KAAK,EAAE;AAC5C;AAEA,SAAgB,YAAY,MAAe,YAAoB,MAAuB;CACpF,OAAO,UAAU,MAAM,UAAU,MAAM;AACzC;;;ACdA,MAAa,+BAAgD,MAAM,eACjE,4BAA4B,MAAM,UAAU,KAC5C,2BAA2B,MAAM,UAAU,KAC3C,0BAA0B,MAAM,UAAU;AAE5C,SAAgB,8BAA8B,MAA4B;CACxE,OACE,SAAS,YAAY,2BACrB,SAAS,YAAY,0BACrB,SAAS,YAAY;AAEzB;AAOA,SAAS,4BAA4B,MAAe,YAA+C;CAKjG,OAAO,8BAA8B,MAAM,YAJrB,aACpB,OACA,WAAU,OAAO,WAAA,MAA0B,OAAO,WAAW,QAAQ,mBAEhB,GAAe,YAAY,0BAAyB,SACzG,4BAA4B,KAAK,KAAK,CACxC;AACF;AAEA,SAAS,2BAA2B,MAAe,YAA+C;CAKhG,OAAO,8BAA8B,MAAM,YAJrB,aACpB,OACA,WAAU,OAAO,WAAA,MAAyB,OAAO,WAAW,QAAQ,kBAEf,GAAe,YAAY,yBAAwB,SACxG,2BAA2B,MAAM,UAAU,CAC7C;AACF;AAEA,SAAS,0BAA0B,MAAe,YAA+C;CAE/F,OAAO,8BAA8B,MAAM,YADrB,aAAa,OAAM,WAAU,OAAO,WAAA,EACH,GAAe,YAAY,wBAAuB,SACvG,0BAA0B,KAAK,KAAK,CACtC;AACF;AAEA,SAAS,8BACP,MACA,YACA,eACA,MACA,cAC2B;CAC3B,IAAI,kBAAkB,QAAQ,WAAW,MAAM,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GAC/E,OAAO;CAGT,MAAM,OAAO,qBAAqB,eAAe,UAAU;CAC3D,IAAI,SAAS,QAAQ,CAAC,aAAa,IAAI,KAAK,CAAC,uBAAuB,eAAe,YAAY,KAAK,cAAc,GAChH,OAAO;CAGT,IAAI,CAAC,kBAAkB,MAAM,MAAM,aAAa,GAC9C,OAAO;CAGT,OAAO,QAAQ,MAAM,IAAI;AAC3B;AAEA,SAAS,qBAAqB,eAAwB,YAA8C;CAClG,IAAI,cAAc,WAAA,MAA0B,cAAc,WAAW,QAAQ,qBAC3E,OAAO,uBAAuB,eAAe,UAAU;CAEzD,IAAI,cAAc,WAAA,MAAyB,cAAc,WAAW,QAAQ,oBAC1E,OAAO,sBAAsB,eAAe,UAAU;CAExD,IAAI,cAAc,WAAA,IAChB,OAAO,qBAAqB,eAAe,UAAU;CAEvD,OAAO;AACT;AAEA,SAAS,uBAAuB,UAAmB,YAA8C;CAC/F,MAAM,YAAY,SAAS,SAAS,WAAU,UAAS,YAAY,OAAO,YAAY,GAAG,CAAC;CAC1F,IAAI,aAAa,GACf,OAAO;EACL,OAAO,gBAAgB,UAAU,YAAY,YAAY,CAAC;EAC1D,gBAAgB,YAAY;CAC9B;CAGF,MAAM,aAAa,sBAAsB,UAAU,UAAU;CAC7D,IAAI,eAAe,MACjB,OAAO;CAGT,MAAM,cAAc,SAAS,SAAS,QAAQ,UAAU;CACxD,OAAO;EACL,OAAO,gBAAgB,UAAU,YAAY,cAAc,CAAC;EAC5D,gBAAgB,cAAc;CAChC;AACF;AAEA,SAAS,sBAAsB,SAAkB,YAA8C;CAC7F,MAAM,YAAY,QAAQ,SAAS,WAAU,UAAS,YAAY,OAAO,YAAY,GAAG,CAAC;CACzF,IAAI,aAAa,GACf,OAAO;EACL,OAAO,gBAAgB,SAAS,YAAY,YAAY,CAAC;EACzD,gBAAgB,YAAY;CAC9B;CAGF,MAAM,YAAY,oBAAoB,OAAO;CAC7C,IAAI,cAAc,MAChB,OAAO;CAGT,MAAM,aAAa,QAAQ,SAAS,QAAQ,SAAS;CACrD,OAAO;EACL,OAAO,gBAAgB,SAAS,YAAY,aAAa,CAAC;EAC1D,gBAAgB,aAAa;CAC/B;AACF;AAEA,SAAS,qBAAqB,SAAkB,YAA8C;CAC5F,MAAM,WAAW,kBAAkB,SAAS,UAAU;CACtD,IAAI,aAAa,MACf,OAAO;CAGT,MAAM,YAAY,QAAQ,SAAS,QAAQ,QAAQ;CACnD,MAAM,YAAY,gBAAgB,SAAS,YAAY,YAAY,CAAC;CACpE,MAAM,gBAAgB,kBAAkB,WAAW,UAAU;CAC7D,IAAI,gBAAgB,GAClB,OAAO;EACL,OAAO;EACP,gBAAgB,YAAY;CAC9B;CAGF,OAAO;EACL,OAAO,UAAU,MAAM,gBAAgB,CAAC;EACxC,gBAAgB,QAAQ,SAAS,QAAQ,UAAU,cAAc,IAAI;CACvE;AACF;AAEA,SAAS,gBAAgB,eAAwB,YAAoB,WAA8B;CACjG,OAAO,cAAc,SAAS,MAAM,SAAS,CAAC,CAAC,QAAO,UAAS,CAAC,eAAe,OAAO,UAAU,CAAC;AACnG;AAEA,SAAS,sBAAsB,UAAmB,YAAoC;CACpF,MAAM,UAAU,SAAS,SAAS,WAAU,UAAS,YAAY,OAAO,YAAY,GAAG,CAAC;CACxF,IAAI,UAAU,GACZ,OAAO;CAGT,KAAK,IAAI,QAAQ,UAAU,GAAG,QAAQ,SAAS,SAAS,QAAQ,SAAS;EACvE,MAAM,QAAQ,SAAS,SAAS;EAChC,IAAI,YAAY,OAAO,YAAY,GAAG,KAAK,eAAe,OAAO,UAAU,GACzE;EAEF,IAAI,MAAM,WAAA,IACR,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAS,oBAAoB,SAAkC;CAC7D,KAAK,MAAM,SAAS,QAAQ,UAC1B,IAAI,MAAM,WAAA,IACR,OAAO;CAGX,OAAO;AACT;AAEA,SAAS,kBAAkB,OAAkB,YAA4B;CACvE,KAAK,IAAI,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAC7C,IAAI,YAAY,MAAM,QAAQ,YAAY,GAAG,GAC3C,OAAO;CAGX,OAAO;AACT;AAEA,SAAS,uBAAuB,eAAwB,YAAoB,gBAAiC;CAC3G,KAAK,IAAI,QAAQ,GAAG,QAAQ,gBAAgB,SAAS;EACnD,MAAM,QAAQ,cAAc,SAAS;EACrC,IAAI,MAAM,WAAW,QAAQ,OAC3B,OAAO;EAET,IAAI,2BAA2B,OAAO,UAAU,GAC9C;EAEF,IAAI,gBAAgB,KAAK,GACvB,OAAO;CAEX;CACA,OAAO;AACT;AAEA,SAAS,4BAA4B,OAA2B;CAC9D,OAAO,uBAAuB,KAAK;AACrC;AAEA,SAAS,2BAA2B,MAAyB,YAA6B;CACxF,IAAI,KAAK,MAAM,WAAW,GACxB,OAAO;CAET,IAAI,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,EAAE,CAAC,WAAA,IAC3C,OAAO,sBAAsB,KAAK,MAAM,IAAI,UAAU;CAExD,OAAO,uBAAuB,KAAK,KAAK;AAC1C;AAEA,SAAS,0BAA0B,OAA2B;CAC5D,OAAO,uBAAuB,KAAK;AACrC;AAEA,SAAS,uBAAuB,OAA2B;CACzD,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,IAAI,MAAM,WAAW,GACnB,OAAO,mBAAmB,MAAM,EAAE;CAEpC,OAAO;AACT;AAEA,SAAS,sBAAsB,YAAqB,YAA6B;CAC/E,IAAI,WAAW,SAAS,WAAW,GACjC,OAAO;CAGT,MAAM,YAAY,WAAW,SAAS,WAAW,SAAS,SAAS;CACnE,IAAI,UAAU,WAAW,QAAQ,OAC/B,OAAO;CAET,IAAI,YAAY,WAAW,YAAY,GAAG,GACxC,OAAO;CAET,IAAI,UAAU,WAAA,MAAsB,mBAAmB,SAAS,GAC9D,OAAO;CAGT,OAAO;AACT;AAEA,SAAS,kBAAkB,WAAoB,MAAyB,eAAiC;CACvG,IAAI,KAAK,MAAM,WAAW,GAAG;EAC3B,MAAM,YAAY,cAAc,SAAS,KAAK,eAAe,EAAE,QAAQ,cAAc;EACrF,OAAO,UAAU,QAAQ;CAC3B;CAEA,KAAK,MAAM,YAAY,KAAK,OAC1B,IAAI,cAAc,YAAY,eAAe,UAAU,SAAS,GAAG;EACjE,IAAI,mBAAmB,QAAQ,GAC7B,OAAO;EAET,IAAI,SAAS,WAAA,MAAyB,qBAAqB,UAAU,SAAS,GAC5E,OAAO;CAEX;CAGF,OAAO;AACT;AAEA,SAAS,qBAAqB,YAAqB,WAA6B;CAC9E,MAAM,YAAY,WAAW,SAAS,WAAW,SAAS,SAAS;CACnE,OAAO,UAAU,WAAW,QAAQ,UAAU,cAAc,aAAa,eAAe,WAAW,SAAS;AAC9G;AAEA,SAAS,kBAAkB,eAAwB,YAAoC;CACrF,MAAM,cAAc,cAAc,SAAS,WAAU,UAAS,YAAY,OAAO,YAAY,IAAI,CAAC;CAClG,IAAI,cAAc,GAChB,OAAO;CAGT,KAAK,IAAI,QAAQ,cAAc,GAAG,QAAQ,cAAc,SAAS,QAAQ,SAAS;EAChF,MAAM,QAAQ,cAAc,SAAS;EACrC,IAAI,MAAM,WAAW,QAAQ,OAC3B;EAEF,IAAI,YAAY,OAAO,YAAY,GAAG,KAAK,eAAe,OAAO,UAAU,GACzE;EAEF,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAS,eAAe,MAAe,YAA6B;CAClE,OAAO,KAAK,WAAW,QAAQ,SAAS,YAAY,MAAM,YAAY,GAAG;AAC3E;AAEA,SAAS,2BAA2B,MAAe,YAA6B;CAC9E,MAAM,OAAO,WAAW,MAAM,KAAK,MAAM,KAAK,EAAE;CAChD,OAAO,SAAS,OAAO,SAAS,OAAO,SAAS,OAAO,SAAS,OAAO,SAAS,QAAQ,SAAS;AACnG;;;AC9SA,SAAgB,wBACd,MACA,YACA,WACA,SAI2B;CAC3B,IAAI,cAAc,MAChB,OAAO;CAGT,MAAM,YAAY,UAAU,SAAS,UAAU,SAAS,SAAS;CACjE,IAAI,WAAW,WAAW,QAAQ,SAAS,SAAS,WAClD,OAAO;CAGT,IAAI,WAAW,MAAM,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GACjD,OAAO;CAGT,IAAI,QAAQ,gBAAgB,UAAa,CAAC,QAAQ,YAAY,SAAS,GACrE,OAAO;CAGT,MAAM,OAAO,OAAO,QAAQ,SAAS,aAAa,QAAQ,KAAK,WAAW,SAAS,IAAI,QAAQ;CAC/F,IAAI,SAAS,MACX,OAAO;CAGT,OAAO,QAAQ,WAAW,IAAI;AAChC;;;AC9BA,MAAa,4BAA6C,MAAM,YAAY,YAC1E,6BAA6B,MAAM,YAAY,QAAQ,QAAQ,KAAK,2BAA2B,MAAM,UAAU;AAEjH,SAAS,6BACP,MACA,YACA,UAC2B;CAC3B,OAAO,wBAAwB,MAAM,YAAY,aAAa,MAAM,kBAAkB,GAAG;EACvF,cAAa,cAAa;GACxB,MAAM,WAAW,UAAU,SAAS,MAClC,UAAS,MAAM,WAAA,MAAwB,MAAM,WAAW,QAAQ,YAClE;GACA,OAAO,aAAa,UAAa,CAAC,gBAAgB,QAAQ;EAC5D;EACA,YAAY,+BAA+B,QAAQ;CACrD,CAAC;AACH;AAEA,SAAS,+BAA+B,UAAqD;CAC3F,QAAQ,UAAR;EACE,KAAKA,UAAc,UACjB,OAAO,YAAY;EACrB,KAAKA,UAAc;EACnB,KAAKA,UAAc,OACjB,OAAO,YAAY;EACrB,SACE,OAAO,YAAY;CACvB;AACF;AAEA,SAAS,2BAA2B,MAAe,YAA+C;CAChG,OAAO,wBAAwB,MAAM,YAAY,aAAa,MAAM,gBAAgB,GAAG;EACrF,cAAa,cAAa;GACxB,MAAM,UAAU,UAAU,SAAS,MACjC,UAAS,MAAM,WAAA,MAA4B,MAAM,WAAW,QAAQ,YACtE;GACA,OAAO,YAAY,UAAa,CAAC,gBAAgB,OAAO;EAC1D;EACA,OAAO,WAAW,cAAc;GAC9B,MAAM,UAAU,UAAU,SAAS,WAAU,UAAS,WAAW,MAAM,MAAM,MAAM,MAAM,EAAE,MAAM,GAAG;GACpG,IAAI,UAAU,GACZ,OAAO,YAAY;GAGrB,MAAM,cAAc,UAAU,SAAS,UAAU;GACjD,IAAI,gBAAgB,UAAa,gBAAgB,aAAa,gBAAgB,WAAW,GACvF,OAAO,YAAY;GAGrB,OAAO,YAAY;EACrB;CACF,CAAC;AACH;;;AC5CA,MAAa,8BAA+C,MAAM,eAChE,6BAA6B,MAAM,UAAU,KAC7C,8BAA8B,MAAM,UAAU,KAC9C,+BAA+B,MAAM,UAAU;AAEjD,MAAa,8BAA+C,MAAM,eAChE,yBAAyB,MAAM,UAAU;AAE3C,SAAS,6BAA6B,MAAe,YAA+C;CAClG,MAAM,YAAY,aAAa,OAAM,WAAU,OAAO,WAAA,EAAsB;CAC5E,IAAI,cAAc,MAChB,OAAO;CAGT,MAAM,eAAe,UAAU,SAAS,UAAU,SAAS,SAAS;CACpE,IAAI,cAAc,WAAW,QAAQ,SAAS,SAAS,cACrD,OAAO;CAGT,IAAI,WAAW,MAAM,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GACjD,OAAO;CAGT,MAAM,gBAAgB,UAAU,SAAS;CACzC,IAAI,kBAAkB,UAAa,kBAAkB,cACnD,OAAO;CAGT,IAAI,CAAC,YAAY,eAAe,YAAY,GAAG,GAC7C,OAAO;CAGT,OAAO,QAAQ,cAAc,YAAY,oBAAoB;AAC/D;AAEA,SAAS,8BAA8B,MAAe,YAA+C;CACnG,MAAM,aAAa,aACjB,OACA,WAAU,OAAO,WAAA,MAA2B,OAAO,WAAA,KAA+B,OAAO,WAAA,EAC3F;CACA,IAAI,eAAe,MACjB,OAAO;CAGT,MAAM,eAAe,WAAW,SAAS,WAAW,SAAS,SAAS;CACtE,IAAI,cAAc,WAAW,QAAQ,SAAS,SAAS,cACrD,OAAO;CAGT,IAAI,WAAW,MAAM,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GAClD,OAAO;CAGT,IAAI,WAAW,SAAS,SAAS,GAC/B,OAAO;CAGT,MAAM,YAAY,WAAW,SAAS;CACtC,IAAI,UAAU,WAAW,QAAQ,SAAS,gBAAgB,SAAS,GACjE,OAAO;CAGT,OAAO,QAAQ,cAAc,YAAY,oBAAoB;AAC/D;AAEA,SAAS,+BAA+B,MAAe,YAA+C;CACpG,MAAM,cAAc,aAAa,OAAM,WAAU,OAAO,WAAA,EAAkB;CAC1E,IAAI,gBAAgB,MAClB,OAAO;CAGT,MAAM,eAAe,yBAAyB,aAAa,UAAU;CACrE,IAAI,iBAAiB,QAAQ,SAAS,cACpC,OAAO;CAGT,IAAI,CAAC,qBAAqB,YAAY,YAAY,EAAE,GAClD,OAAO;CAGT,OAAO,QAAQ,cAAc,YAAY,oBAAoB;AAC/D;AAEA,SAAS,yBAAyB,MAAe,YAA+C;CAC9F,MAAM,WAAW,aAAa,OAAM,WAAU,OAAO,WAAA,CAAyB;CAC9E,IAAI,aAAa,QAAQ,CAAC,yBAAyB,UAAU,UAAU,GACrE,OAAO;CAGT,MAAM,aAAa,sBAAsB,UAAU,UAAU;CAC7D,IAAI,eAAe,QAAQ,SAAS,cAAc,CAAC,qBAAqB,YAAY,SAAS,EAAE,GAC7F,OAAO;CAGT,OAAO,QAAQ,YAAY,YAAY,gBAAgB;AACzD;AAEA,SAAS,yBAAyB,WAAoB,YAAoC;CACxF,KAAK,IAAI,QAAQ,UAAU,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS;EACnE,MAAM,QAAQ,UAAU,SAAS;EACjC,IAAI,yBAAyB,OAAO,UAAU,GAC5C;EAEF,OAAO,oBAAoB,KAAK;CAClC;CACA,OAAO;AACT;AAEA,SAAS,sBAAsB,UAAmB,YAAoC;CACpF,KAAK,MAAM,SAAS,SAAS,UAAU;EACrC,IAAI,YAAY,OAAO,YAAY,GAAG,GACpC;EAEF,MAAM,YAAY,oBAAoB,KAAK;EAC3C,IAAI,cAAc,MAChB,OAAO;CAEX;CACA,OAAO;AACT;AAEA,SAAS,yBAAyB,MAAe,YAA6B;CAC5E,MAAM,OAAO,UAAU,MAAM,UAAU;CACvC,OAAO,SAAS,OAAO,SAAS,OAAO,SAAS;AAClD;AAEA,SAAS,yBAAyB,UAAmB,YAA6B;CAChF,OAAO,2BAA2B,UAAU,UAAU,MAAM;AAC9D;AAEA,SAAS,2BAA2B,UAAmB,YAAoC;CACzF,IAAI,UAA0B,SAAS;CACvC,OAAO,YAAY,MAAM;EACvB,KAAK,MAAM,SAAS,QAAQ,UAAU;GACpC,IAAI,CAAC,eAAe,KAAK,KAAK,CAAC,gBAAgB,KAAK,KAAK,CAAC,aAAa,KAAK,GAC1E;GAEF,IAAI,qBAAqB,UAAU,OAAO,UAAU,GAClD,OAAO;EAEX;EACA,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAS,qBAAqB,UAAmB,UAAmB,YAA6B;CAC/F,MAAM,OAAO,WAAW,MAAM,SAAS,EAAE;CACzC,MAAM,QAAQ,SAAS,KAAK,IAAI;CAChC,IAAI,UAAU,MACZ,OAAO;CAGT,MAAM,UAAU,SAAS,KAAK,MAAM,QAAQ,MAAM,EAAE,CAAC,QAAQ,GAAG;CAChE,MAAM,WAAW,yBAAyB,YAAY,OAAO;CAC7D,IAAI,WAAW,GACb,OAAO;CAGT,OAAO,SAAS,OAAO,WAAW,SAAS,OAAO;AACpD;;;ACtKA,MAAM,0BAA6C;CACjD;CACA;CACA,oBAAoB,0BAA0B;CAC9C,oBAAoB,0BAA0B;CAC9C;CACA;AACF;;AAGA,SAAgB,mBACd,MACA,YACA,SAC2B;CAC3B,KAAK,MAAM,cAAc,yBAAyB;EAChD,MAAM,QAAQ,WAAW,MAAM,YAAY,OAAO;EAClD,IAAI,UAAU,MACZ,OAAO;CAEX;CACA,OAAO;AACT;;AAGA,SAAgB,sBACd,MACA,qBACuD;CACvD,MAAM,SAAS,KAAK;CACpB,IAAI,WAAW,MACb,OAAO,sBACH,OACA;EAAE,OAAO;GAAE,MAAM,YAAY;GAAe,MAAM,KAAK;GAAM,IAAI,KAAK;EAAG;EAAG,QAAQ;CAAK;CAG/F,IAAI,OAAO,WAAA,GACT,OAAO;EACL,OAAO;GAAE,MAAM,YAAY;GAAe,MAAM,OAAO;GAAM,IAAI,OAAO;EAAG;EAC3E,QAAQ;CACV;CAGF,IAAI,qBACF,OAAO;CAGT,MAAM,SAAS,KAAK,SAAS,KAAK,KAAK,SAAS;CAChD,OAAO;EACL,OAAO;GAAE,MAAM,YAAY;GAAe,MAAM,OAAO;GAAM,IAAI,OAAO;EAAG;EAC3E;CACF;AACF;;;;;;ACvDA,MAAM,2BAA2B,4BAA4B;AAE7D,SAAS,8BAA2C;CAClD,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,SAAS;EAClB;EACA;EACA;EACA;EACA;CACF,GACE,KAAK,MAAM,UAAU,OACnB,MAAM,IAAI,MAAM;CAGpB,KAAK,IAAI,YAAY,KAAQ,aAAa,KAAQ,aAChD,MAAM,IAAI,OAAO,cAAc,SAAS,CAAC;CAE3C,OAAO;AACT;AAEA,SAAS,wBAAwB,QAAyB;CACxD,OAAO,MAAM,KAAK,MAAM,KAAK,yBAAyB,IAAI,MAAM;AAClE;AAEA,SAAgB,gCAAgC,YAA0C;CACxF,MAAM,SAA+B,CAAC;CACtC,IAAI,MAAM;CAEV,OAAO,MAAM,WAAW,QAAQ;EAC9B,MAAM,SAAS,WAAW;EAC1B,IAAI,wBAAwB,MAAM,GAAG;GACnC;GACA;EACF;EAEA,MAAM,QAAQ;EACd,OAAO,MAAM,WAAW,UAAU,CAAC,wBAAwB,WAAW,IAAI,GACxE;EAGF,OAAO,KAAK;GACV,MAAM,YAAY;GAClB,MAAM;GACN,IAAI;GACJ,QAAQ,CAAC,WAAW,MAAM,OAAO,GAAG,CAAC;EACvC,CAAC;CACH;CAEA,OAAO;AACT;AAEA,SAAgB,qBAAqB,YAA+C;CAClF,MAAM,QAAwB,CAAC;CAE/B,KAAK,IAAI,MAAM,GAAG,MAAM,WAAW,QAAQ,OAAO;EAChD,MAAM,SAAS,WAAW;EAC1B,IAAI,cAAc,MAAM,GAAG;GACzB,IAAI,oBAAoB,YAAY,GAAG,GACrC,OAAO;IACL,MAAM,YAAY;IAClB,MAAM;IACN,IAAI,MAAM;GACZ;GAEF,MAAM,KAAK;IAAE,SAAS;IAAQ,OAAO;GAAI,CAAC;GAC1C;EACF;EACA,IAAI,CAAC,eAAe,MAAM,GACxB;EAGF,MAAM,eAAe,YAAY,MAAM;EACvC,MAAM,MAAM,MAAM,MAAM,SAAS;EACjC,IAAI,QAAQ,QACV,OAAO;GACL,MAAM,YAAY;GAClB,MAAM;GACN,IAAI,MAAM;GACV,QAAQ,CAAC,MAAM;EACjB;EAGF,IAAI,IAAI,YAAY,cAClB,OAAO;GACL,MAAM,YAAY;GAClB,MAAM;GACN,IAAI,MAAM;GACV,QAAQ,CAAC,YAAY,IAAI,OAAO,GAAG,MAAM;EAC3C;EAGF,MAAM,IAAI;CACZ;CAEA,IAAI,MAAM,SAAS,GAAG;EACpB,MAAM,WAAW,MAAM;EACvB,OAAO;GACL,MAAM,YAAY;GAClB,MAAM,SAAS;GACf,IAAI,SAAS,QAAQ;GACrB,QAAQ,CAAC,SAAS,OAAO;EAC3B;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,kBAAkB,QAAoD;CACpF,MAAM,SAA+B,CAAC;CAEtC,KAAK,MAAM,SAAS,QAAQ;EAI1B,IAHkB,OAAO,MACvB,aAAY,SAAS,SAAS,MAAM,QAAQ,SAAS,SAAS,MAAM,QAAQ,SAAS,OAAO,MAAM,EAEhG,GACF;EAGF,IAAI,MAAM,SAAS,YAAY,eAC7B;QAAK,IAAI,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAC9C,IAAI,OAAO,MAAM,CAAC,SAAS,YAAY,iBAAiB,cAAc,OAAO,OAAO,MAAM,GACxF,OAAO,OAAO,OAAO,CAAC;EAE1B;EAGF,OAAO,KAAK,KAAK;CACnB;CAEA,MAAM,WAAW,OAAO,QAAO,UAAS,MAAM,SAAS,YAAY,aAAa;CAIhF,OAAO,gCAHU,OAAO,QACtB,UAAS,MAAM,SAAS,YAAY,iBAAiB,CAAC,SAAS,MAAK,SAAQ,cAAc,OAAO,IAAI,CAAC,CAEjE,CAAQ;AACjD;AAEA,SAAS,gCAAgC,QAAoD;CAC3F,MAAM,WAAW,OAAO,QAAO,UAAS,MAAM,SAAS,YAAY,aAAa;CAChF,IAAI,SAAS,UAAU,GACrB,OAAO;CAGT,MAAM,SAAS,OAAO,QAAO,UAAS,MAAM,SAAS,YAAY,aAAa;CAC9E,MAAM,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,MAAM,UAAU,KAAK,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,EAAE;CAC/F,MAAM,SAA+B,CAAC;CAEtC,IAAI,cAAc,OAAO,EAAE,CAAC;CAC5B,IAAI,YAAY,OAAO,EAAE,CAAC;CAE1B,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;EAClD,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,WAAW;GAC3B,YAAY,KAAK,IAAI,WAAW,MAAM,EAAE;GACxC;EACF;EAEA,OAAO,KAAK;GAAE,MAAM,YAAY;GAAe,MAAM;GAAa,IAAI;EAAU,CAAC;EACjF,cAAc,MAAM;EACpB,YAAY,MAAM;CACpB;CAEA,OAAO,KAAK;EAAE,MAAM,YAAY;EAAe,MAAM;EAAa,IAAI;CAAU,CAAC;CACjF,OAAO,CAAC,GAAG,QAAQ,GAAG,MAAM;AAC9B;AAEA,SAAS,cAAc,GAAuB,GAAgC;CAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;AACrC;AAEA,SAAS,cAAc,QAAuC;CAC5D,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW;AACxD;AAEA,SAAS,eAAe,QAAwC;CAC9D,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW;AACxD;AAEA,SAAS,YAAY,QAAmC;CACtD,QAAQ,QAAR;EACE,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;CACX;AACF;AAEA,SAAS,YAAY,QAAmC;CACtD,QAAQ,QAAR;EACE,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;CACX;AACF;AAEA,SAAS,oBAAoB,YAAoB,KAAsB;CAErE,IAAI,EAD4B,WAAW,SAAS,OAAO,WAAW,MAAM,OAAO,MAEjF,OAAO;CAGT,MAAM,aAAa,uBAAuB,YAAY,GAAG;CACzD,MAAM,aAAa,uBAAuB,YAAY,MAAM,CAAC;CAC7D,IAAI,aAAa,KAAK,aAAa,GACjC,OAAO;CAGT,OAAO,eAAe,aAAa;AACrC;AAEA,SAAS,uBAAuB,YAAoB,SAAyB;CAC3E,IAAI,WAAW,aAAa,KAC1B,OAAO;CAGT,MAAM,QAAuB,CAAC;CAC9B,KAAK,IAAI,QAAQ,SAAS,QAAQ,WAAW,QAAQ,SAAS;EAC5D,MAAM,SAAS,WAAW;EAC1B,IAAI,cAAc,MAAM,GAAG;GACzB,MAAM,KAAK,MAAM;GACjB;EACF;EACA,IAAI,CAAC,eAAe,MAAM,GACxB;EAEF,MAAM,MAAM,MAAM,IAAI;EACtB,IAAI,QAAQ,UAAa,QAAQ,YAAY,MAAM,GACjD,OAAO;EAET,IAAI,MAAM,WAAW,GACnB,OAAO;CAEX;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AC7NA,SAAgB,oBACd,KACA,YACA,UACA,iBAA0B,OAC1B,SACA;CACA,MAAM,kBAAkB,gCAAgC,UAAU;CAClE,IAAI,gBAAgB,SAAS,GAAG;EAC9B,KAAK,MAAM,SAAS,iBAAiB;GACnC,SAAS,KAAK;GACd,IAAI,gBACF,cAAc,KAAK,MAAM,MAAM,MAAM,MAAM;EAE/C;EACA;CACF;CAEA,MAAM,YAAkC,CAAC;CACzC,MAAM,oCAAoB,IAAI,IAAiC;CAC/D,MAAM,WAAW,OAA2B,WAAqB;EAC/D,UAAU,KAAK,KAAK;EACpB,IAAI,WAAW,QACb,kBAAkB,IAAI,OAAO,MAAM;CAEvC;CAEA,MAAM,eAAe,qBAAqB,UAAU;CACpD,MAAM,mBAAmB,iBAAiB;CAC1C,YAAY,MAAK,SAAQ,gBAAgB,MAAM,YAAY,SAAS,kBAAkB,OAAO,CAAC;CAE9F,MAAM,yBAAyB,UAAU,MAAK,UAAS,8BAA8B,MAAM,IAAI,CAAC;CAChG,IAAI,iBAAiB,QAAQ,CAAC,wBAC5B,QAAQ,cAAc,GAAG;CAG3B,KAAK,MAAM,SAAS,kBAAkB,SAAS,GAAG;EAChD,SAAS,KAAK;EACd,IAAI,gBAAgB;GAClB,MAAM,SAAS,kBAAkB,IAAI,KAAK;GAC1C,IAAI,WAAW,QACb,cAAc,QAAQ,MAAM,MAAM,MAAM,MAAM;EAElD;CACF;AACF;AAEA,SAAS,gBACP,MACA,YACA,SACA,kBACA,SACA;CACA,IAAI,KAAK,WAAW,QAAQ,OAC1B;CAGF,MAAM,aAAa,mBAAmB,MAAM,YAAY;EAAE;EAAkB,UAAU,SAAS;CAAS,CAAC;CACzG,IAAI,eAAe,MAAM;EACvB,QAAQ,YAAY,IAAI;EACxB;CACF;CAEA,MAAM,WAAW,sBAAsB,MAAM,gBAAgB;CAC7D,IAAI,aAAa,MACf,QAAQ,SAAS,OAAO,SAAS,MAAM;AAE3C"}