I'm building a logic expression parser. I really like the way mongoDB structures their logic statements. However, I'm thinking if this is the best structure to store and parse logic expressions.
const logicPayload = [
{ varA: { $eq: "meow" } },
{ $and: [{ varB: { $lt: "varD" } }, { varB: { $gte: "varC" } }] },
{ $not: [{ varB: { $eq: "varA" } }] }
];
Given the payload above, how can i design a function to parse the expression. varA
, varB
varC
and varD
will be resolve at runtime.
A dummy resolve function is below.
const resovleValue = varID => {
switch (varID) {
case "varA":
return "meow";
break;
case "varB":
return 100;
case "varC":
return 100;
case "varD":
return 983;
}
};
I'm trying to create the logic function below
/**
* This logic function must only return true or false
*/
const logicFunction = logicPayload => {};
Any guidance is much appreciated. thanks.
Here's a logic parser that uses recursion to deal with the internal arrays of logic.
It'll stop processing as soon it finds a rule that returns false.
function checkRule(rule) { let key1 = Object.keys(rule)[0]; let comp = Object.values(rule)[0]; if(/^[$](and|or|not)$/.test(key1) && Array.isArray(comp)) { let aon = key1; let rules = comp; let results = []; for(r of rules){ let valid = checkRule(r); results.push(valid); //console.log(`${aon} ${JSON.stringify(r)}: ${valid}`); if(aon === '$and' && !valid) return false; if(aon === '$or' && valid) return true; if(aon === '$not' && valid) return false; } //console.log (JSON.stringify(results)); if(aon === '$and' && results.some((x)=>!x)) return false; if(aon === '$or' && results.every((x)=>!x)) return false; if(aon === '$not' && results.some((x)=>x)) return false; } else { let operator = Object.keys(comp)[0]; let key2 = comp[operator]; let val1 = resolveValue(key1) || key1; let val2 = resolveValue(key2) || key2; //console.log(`\\t${val1} ${operator} ${val2}`); switch(operator) { case '$eq': if(!(val1 == val2)) return false; break; case '$ne': case '$neq': if(!(val1 != val2)) return false; break; case '$lt': if(!(val1 < val2)) return false; break; case '$le': case '$lte': if(!(val1 <= val2)) return false; break; case '$gt': if(!(val1 > val2)) return false; break; case '$ge': case '$gte': if(!(val1 >= val2)) return false; break; default: return false; } } return true; } function logicFunction (logicPayload) { let results = []; for (rule of logicPayload) { let valid = checkRule(rule); //console.log(`${valid}: ${JSON.stringify(rule)}`); results.push(valid); if(!valid) return false; } return results.every((x)=>x); }; const resolveValue = (varID) => { switch (varID) { case "varA": return "meow"; case "varB": return 100; case "varC": return 100; case "varD": return 983; } }; let logicPayload = [ { varA: { $eq: "meow" } }, { $and: [ { varB: { $lt: "varD" } }, { varB: { $gte: "varC" } } ] }, { $not: [ { varB: { $eq: "varA" } } ] } ]; let result = logicFunction(logicPayload); console.log(result);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.