UNPKG

@firehammer/jexl

Version:

Javascript Expression Language: Powerful context-based expression parser and evaluator

221 lines (218 loc) 5.76 kB
"use strict"; /* * Jexl * Copyright 2020 Tom Shawver */ /* eslint eqeqeq:0 */ exports.getGrammar = function () { return { /** * A map of all expression elements to their properties. Note that changes * here may require changes in the Lexer or Parser. * @type {{}} */ elements: { ".": { type: "dot" }, "[": { type: "openBracket" }, "]": { type: "closeBracket" }, "|": { type: "pipe" }, "{": { type: "openCurl" }, "}": { type: "closeCurl" }, ":": { type: "colon" }, ",": { type: "comma" }, "(": { type: "openParen" }, ")": { type: "closeParen" }, "?": { type: "question" }, "+": { type: "binaryOp", precedence: 30, eval: function _eval(left, right) { return left + right; } }, "-": { type: "binaryOp", precedence: 30, eval: function _eval(left, right) { return left - right; } }, "*": { type: "binaryOp", precedence: 40, eval: function _eval(left, right) { return left * right; } }, "/": { type: "binaryOp", precedence: 40, eval: function _eval(left, right) { return left / right; } }, "//": { type: "binaryOp", precedence: 40, eval: function _eval(left, right) { return Math.floor(left / right); } }, "%": { type: "binaryOp", precedence: 50, eval: function _eval(left, right) { return left % right; } }, "^": { type: "binaryOp", precedence: 50, eval: function _eval(left, right) { return Math.pow(left, right); } }, "==": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left == right; } }, "!=": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left != right; } }, ">": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left > right; } }, ">=": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left >= right; } }, "<": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left < right; } }, "<=": { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { return left <= right; } }, "&&": { type: "binaryOp", precedence: 10, evalOnDemand: function evalOnDemand(left, right) { return left.eval().then(function (leftVal) { if (!leftVal) return leftVal; return right.eval(); }); } }, "||": { type: "binaryOp", precedence: 10, evalOnDemand: function evalOnDemand(left, right) { return left.eval().then(function (leftVal) { if (leftVal) return leftVal; return right.eval(); }); } }, in: { type: "binaryOp", precedence: 20, eval: function _eval(left, right) { if (typeof right === "string") { return right.indexOf(left) !== -1; } if (Array.isArray(right)) { return right.some(function (elem) { return elem === left; }); } return false; } }, "!": { type: "unaryOp", precedence: Infinity, eval: function _eval(right) { return !right; } } }, /** * A map of function names to javascript functions. A Jexl function * takes zero ore more arguemnts: * * - {*} ...args: A variable number of arguments passed to this function. * All of these are pre-evaluated to their actual values before calling * the function. * * The Jexl function should return either the transformed value, or * a Promises/A+ Promise object that resolves with the value and rejects * or throws only when an unrecoverable error occurs. Functions should * generally return undefined when they don't make sense to be used on the * given value type, rather than throw/reject. An error is only * appropriate when the function would normally return a value, but * cannot due to some other failure. */ functions: {}, /** * A map of transform names to transform functions. A transform function * takes one ore more arguemnts: * * - {*} val: A value to be transformed * - {*} ...args: A variable number of arguments passed to this transform. * All of these are pre-evaluated to their actual values before calling * the function. * * The transform function should return either the transformed value, or * a Promises/A+ Promise object that resolves with the value and rejects * or throws only when an unrecoverable error occurs. Transforms should * generally return undefined when they don't make sense to be used on the * given value type, rather than throw/reject. An error is only * appropriate when the transform would normally return a value, but * cannot due to some other failure. */ transforms: {} }; };