UNPKG

jexl

Version:

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

224 lines (221 loc) 5.03 kB
"use strict"; /* * Jexl * Copyright 2020 Tom Shawver */ var h = require('./handlers'); /** * A mapping of all states in the finite state machine to a set of instructions * for handling or transitioning into other states. Each state can be handled * in one of two schemes: a tokenType map, or a subHandler. * * Standard expression elements are handled through the tokenType object. This * is an object map of all legal token types to encounter in this state (and * any unexpected token types will generate a thrown error) to an options * object that defines how they're handled. The available options are: * * {string} toState: The name of the state to which to transition * immediately after handling this token * {string} handler: The handler function to call when this token type is * encountered in this state. If omitted, the default handler * matching the token's "type" property will be called. If the handler * function does not exist, no call will be made and no error will be * generated. This is useful for tokens whose sole purpose is to * transition to other states. * * States that consume a subexpression should define a subHandler, the * function to be called with an expression tree argument when the * subexpression is complete. Completeness is determined through the * endStates object, which maps tokens on which an expression should end to the * state to which to transition once the subHandler function has been called. * * Additionally, any state in which it is legal to mark the AST as completed * should have a 'completable' property set to boolean true. Attempting to * call {@link Parser#complete} in any state without this property will result * in a thrown Error. * * @type {{}} */ exports.states = { expectOperand: { tokenTypes: { literal: { toState: 'expectBinOp' }, identifier: { toState: 'identifier' }, unaryOp: {}, openParen: { toState: 'subExpression' }, openCurl: { toState: 'expectObjKey', handler: h.objStart }, dot: { toState: 'traverse' }, openBracket: { toState: 'arrayVal', handler: h.arrayStart } } }, expectBinOp: { tokenTypes: { binaryOp: { toState: 'expectOperand' }, pipe: { toState: 'expectTransform' }, dot: { toState: 'traverse' }, question: { toState: 'ternaryMid', handler: h.ternaryStart } }, completable: true }, expectTransform: { tokenTypes: { identifier: { toState: 'postTransform', handler: h.transform } } }, expectObjKey: { tokenTypes: { identifier: { toState: 'expectKeyValSep', handler: h.objKey }, closeCurl: { toState: 'expectBinOp' } } }, expectKeyValSep: { tokenTypes: { colon: { toState: 'objVal' } } }, postTransform: { tokenTypes: { openParen: { toState: 'argVal' }, binaryOp: { toState: 'expectOperand' }, dot: { toState: 'traverse' }, openBracket: { toState: 'filter' }, pipe: { toState: 'expectTransform' } }, completable: true }, postArgs: { tokenTypes: { binaryOp: { toState: 'expectOperand' }, dot: { toState: 'traverse' }, openBracket: { toState: 'filter' }, pipe: { toState: 'expectTransform' } }, completable: true }, identifier: { tokenTypes: { binaryOp: { toState: 'expectOperand' }, dot: { toState: 'traverse' }, openBracket: { toState: 'filter' }, openParen: { toState: 'argVal', handler: h.functionCall }, pipe: { toState: 'expectTransform' }, question: { toState: 'ternaryMid', handler: h.ternaryStart } }, completable: true }, traverse: { tokenTypes: { identifier: { toState: 'identifier' } } }, filter: { subHandler: h.filter, endStates: { closeBracket: 'identifier' } }, subExpression: { subHandler: h.subExpression, endStates: { closeParen: 'expectBinOp' } }, argVal: { subHandler: h.argVal, endStates: { comma: 'argVal', closeParen: 'postArgs' } }, objVal: { subHandler: h.objVal, endStates: { comma: 'expectObjKey', closeCurl: 'expectBinOp' } }, arrayVal: { subHandler: h.arrayVal, endStates: { comma: 'arrayVal', closeBracket: 'expectBinOp' } }, ternaryMid: { subHandler: h.ternaryMid, endStates: { colon: 'ternaryEnd' } }, ternaryEnd: { subHandler: h.ternaryEnd, completable: true } };