@qrvey/formula-lang
Version:
QFormula support for qrvey projects
109 lines • 5.21 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPositionASTFromSyntaxNode = exports.transformFunctionExpression = void 0;
const utils_1 = require("../utils");
const syntax_errors_1 = require("./syntax-errors");
const primitiveFunctions_1 = require("../utils/primitiveFunctions");
const constants_1 = require("../constants");
const functions_1 = require("../functions");
const errors_1 = require("../errors");
const isAggregate_1 = require("../utils/isAggregate");
function transformFunctionExpression(program, node, inference, context, transformNodeFunction) {
const fnIdentifier = node.getChild('FunctionIdentifier');
const fnName = (0, utils_1.getNodeValue)(program, fnIdentifier);
const fnString = (0, utils_1.getNodeValue)(program, node);
const parenthesisStart = node.getChild('ParenthesisStart');
const parenthesisEnd = node.getChild('ParenthesisEnd');
const functionExists = functions_1.FUNCTION_LIST.includes(fnName);
const functionDetail = functionExists
? (0, functions_1.getFunctionDetail)(fnName)
: undefined;
const isAggregated = functionDetail
? functionDetail.operationScope === constants_1.OPERATION_SCOPE.AGGREGATE
: false;
const args = getFunctionArguments(node, parenthesisStart, program, inference, context, transformNodeFunction);
const functionIdentifier = createPositionASTFromSyntaxNode(fnIdentifier);
const baseNode = {
type: constants_1.AST_TYPES.functionCall,
name: (0, utils_1.getNodeValue)(program, fnIdentifier),
arguments: args,
from: node.from,
to: node.to,
isValidAggregate: isValidAggFunction(isAggregated, context, args),
parenthesisStart: !!parenthesisStart,
parenthesisEnd: !!parenthesisEnd,
functionText: fnString,
functionIdentifier,
};
const primitive = functionDetail
? (0, primitiveFunctions_1.getFunctionPrimitive)(functionDetail, baseNode.arguments)
: constants_1.AST_PRIMITIVES.UNKNOWN;
const resultNode = Object.assign(Object.assign({}, baseNode), { primitive, functionScope: isAggregated
? constants_1.OPERATION_SCOPE.AGGREGATE
: constants_1.OPERATION_SCOPE.RAW });
if (functionExists && (!parenthesisStart || !parenthesisEnd)) {
inference.errorList.push(new errors_1.MissingParenthesisError(Object.assign(Object.assign({}, resultNode), { from: !parenthesisStart ? resultNode.from : resultNode.to })));
}
inference.formulaFunctions.push(resultNode);
return resultNode;
}
exports.transformFunctionExpression = transformFunctionExpression;
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 &&
(0, utils_1.getNodeValue)(program, fnNodeChild) === ',' &&
fnNodeChild.from > parenthesisStart.from) {
const errorNodeStart = parenthesisStart.from + 1;
resultArgs.push((0, syntax_errors_1.createUnknownValue)({
from: errorNodeStart,
to: fnNodeChild.from,
}));
}
});
return resultArgs;
}
function createCommonASTFromNode(program, node, inference, context, transformNodeFunction) {
if (node.type.isError) {
return (0, syntax_errors_1.createUnknownValue)(node);
}
return transformNodeFunction(program, node, inference, context);
}
function createPositionASTFromSyntaxNode({ from, to, }) {
return { from, to };
}
exports.createPositionASTFromSyntaxNode = createPositionASTFromSyntaxNode;
function isValidAggFunction(isAggregated, context, args) {
if (!(0, isAggregate_1.isAggregateScope)(context))
return true;
if (isAggregated)
return true;
return args.every((arg) => arg.isValidAggregate);
}
//# sourceMappingURL=formula-parser.js.map