简体   繁体   中英

Parsing logic Expression with Javascript

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM