UNPKG

@qrvey/formula-lang

Version:

QFormula support for qrvey projects

90 lines 4.16 kB
import { getNodeValue } from '../utils'; import { createUnknownValue } from './syntax-errors'; import { getFunctionPrimitive } from '../utils/primitiveFunctions'; import { AST_PRIMITIVES, AST_TYPES } from '../constants'; import { FUNCTION_LIST, getFunctionDetail } from '../functions'; import { MissingParenthesisError } from '../errors'; export function transformFunctionExpression(program, node, inference, context, transformNodeFunction) { const fnIdentifier = node.getChild('FunctionIdentifier'); const fnName = getNodeValue(program, fnIdentifier); const fnString = getNodeValue(program, node); const parenthesisStart = node.getChild('ParenthesisStart'); const parenthesisEnd = node.getChild('ParenthesisEnd'); const args = getFunctionArguments(node, parenthesisStart, program, inference, context, transformNodeFunction); const functionIdentifier = createPositionASTFromSyntaxNode(fnIdentifier); const baseNode = { type: AST_TYPES.functionCall, name: getNodeValue(program, fnIdentifier), arguments: args, from: node.from, to: node.to, parenthesisStart: !!parenthesisStart, parenthesisEnd: !!parenthesisEnd, functionText: fnString, functionIdentifier, }; const functionExists = FUNCTION_LIST.includes(fnName); const functionDetail = functionExists ? getFunctionDetail(fnName) : undefined; const primitive = functionDetail ? getFunctionPrimitive(functionDetail, baseNode.arguments) : AST_PRIMITIVES.UNKNOWN; const resultNode = Object.assign(Object.assign({}, baseNode), { primitive }); if (functionExists && (!parenthesisStart || !parenthesisEnd)) { inference.errorList.push(new MissingParenthesisError(Object.assign(Object.assign({}, resultNode), { from: !parenthesisStart ? resultNode.from : resultNode.to }))); } inference.formulaFunctions.push(resultNode); return resultNode; } function getFunctionArguments(fnNode, parenthesisStart, program, inference, context, transformNodeFunction) { const allocatedArgs = []; const args = fnNode.getChild('FunctionArguments'); if (parenthesisStart) { allocatedArgs.push(...getFunctionStartingCommas(fnNode, program, parenthesisStart)); } allocatedArgs.push(...extractFunctionArguments(args, fnNode, program, inference, context, transformNodeFunction)); return allocatedArgs; } function extractFunctionArguments(args, fnNode, program, inference, context, transformNodeFunction) { const resultArgs = []; args === null || args === void 0 ? void 0 : args.cursor().iterate(({ node: argNode }) => { if (argNode.name === 'Expression' || argNode.type.isError) { if (argNode.from === fnNode.to) return false; const astNode = createCommonASTFromNode(program, argNode, inference, context, transformNodeFunction); if (astNode) resultArgs.push(astNode); return false; } }); return resultArgs; } function getFunctionStartingCommas(fnNode, program, parenthesisStart) { const resultArgs = []; fnNode === null || fnNode === void 0 ? void 0 : fnNode.cursor().iterate(({ node: fnNodeChild }) => { if (fnNodeChild.name === 'FunctionArguments') { return false; // Stop entering on function arguments } if (fnNodeChild.type.isError && getNodeValue(program, fnNodeChild) === ',' && fnNodeChild.from > parenthesisStart.from) { const errorNodeStart = parenthesisStart.from + 1; resultArgs.push(createUnknownValue({ from: errorNodeStart, to: fnNodeChild.from, })); } }); return resultArgs; } function createCommonASTFromNode(program, node, inference, context, transformNodeFunction) { if (node.type.isError) { return createUnknownValue(node); } return transformNodeFunction(program, node, inference, context); } export function createPositionASTFromSyntaxNode({ from, to, }) { return { from, to }; } //# sourceMappingURL=formula-parser.js.map