From 9f060ba2e06ed940166e975b1449bd1985e47291 Mon Sep 17 00:00:00 2001 From: sennjeffrey Date: Fri, 9 Jul 2021 10:47:06 -0400 Subject: [PATCH] allow functional override of "." for property read use new Parser({overrideMember:function}). Parsers with overridden "." will not simply "." expressions --- src/evaluate.js | 7 ++++++- src/functions.js | 4 ++++ src/parser.js | 8 +++++++- src/simplify.js | 3 ++- test/functions.js | 13 +++++++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/evaluate.js b/src/evaluate.js index 80a63a2..de44bd4 100644 --- a/src/evaluate.js +++ b/src/evaluate.js @@ -100,7 +100,12 @@ export default function evaluate(tokens, expr, values) { nstack.push(item); } else if (type === IMEMBER) { n1 = nstack.pop(); - nstack.push(n1[item.value]); + f = expr.binaryOps['.'] + if(f.apply && f.call) { + nstack.push(f.apply(undefined, [n1, item.value])); + } else { + throw new Error(f + ' is not a function'); + } } else if (type === IENDSTATEMENT) { nstack.pop(); } else if (type === IARRAY) { diff --git a/src/functions.js b/src/functions.js index c3c5d20..3602786 100644 --- a/src/functions.js +++ b/src/functions.js @@ -254,6 +254,10 @@ export function arrayIndex(array, index) { return array[index | 0]; } +export function member(object, name) { + return object[name]; +} + export function max(array) { if (arguments.length === 1 && Array.isArray(array)) { return Math.max.apply(Math, array); diff --git a/src/parser.js b/src/parser.js index 9fc7bdd..fb7b6b5 100644 --- a/src/parser.js +++ b/src/parser.js @@ -37,6 +37,7 @@ import { roundTo, setVar, arrayIndex, + member, max, min, arrayMap, @@ -108,9 +109,14 @@ export function Parser(options) { or: orOperator, 'in': inOperator, '=': setVar, - '[': arrayIndex + '[': arrayIndex, + '.': member }; + if(this.options.overrideMember) { + this.binaryOps['.'] = this.options.overrideMember + } + this.ternaryOps = { '?': condition }; diff --git a/src/simplify.js b/src/simplify.js index 307cf67..22becee 100644 --- a/src/simplify.js +++ b/src/simplify.js @@ -1,4 +1,5 @@ import { Instruction, INUMBER, IOP1, IOP2, IOP3, IVAR, IVARNAME, IEXPR, IMEMBER, IARRAY } from './instruction'; +import { member } from './functions'; export default function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) { var nstack = []; @@ -46,7 +47,7 @@ export default function simplify(tokens, unaryOps, binaryOps, ternaryOps, values newexpression.push(nstack.shift()); } newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values))); - } else if (type === IMEMBER && nstack.length > 0) { + } else if (type === IMEMBER && nstack.length > 0 && member === binaryOps['.']) { //check if member overridden n1 = nstack.pop(); nstack.push(new Instruction(INUMBER, n1.value[item.value])); } /* else if (type === IARRAY && nstack.length >= item.value) { diff --git a/test/functions.js b/test/functions.js index 7b4f1de..ba63aec 100644 --- a/test/functions.js +++ b/test/functions.js @@ -485,4 +485,17 @@ describe('Functions', function () { assert.strictEqual(parser.evaluate('sum([1, 2])'), 3); }); }); + + describe('member(value,name)', function () { + it('basic', function () { + var parser = new Parser(); + assert.strictEqual(parser.evaluate('a.something', {a : {something: 123}}), 123); + }); + + it('able to override', function () { + var parser = new Parser({overrideMember:function(v,n) { return 456; }}); + assert.strictEqual(parser.evaluate('a.anything', {a : {}}), 456); + }); + }); + });