简体   繁体   中英

Parsing Binary expression in javascript

I have an expression like this:

{
  "type": "BinaryExpression",
  "operator": "OR",
  "left": {
    "type": "Literal",
    "value": 1,
    "raw": "1"
  },
  "right": {
    "type": "BinaryExpression",
    "operator": "AND",
    "left": {
      "type": "Literal",
      "value": 2,
      "raw": "2"
    },
    "right": {
      "type": "Literal",
      "value": 3,
      "raw": "3"
    }
  }
}

I want to convert this into the following in JS.

logic: 'OR'
filters: [
    {1}
    logic: 'AND'
    filters: [
        {2},
        {3}

    ]
]

ie When there is an operator, I will put into a logic variable of the Javascript object. After that, I will check if there is a left and right attribute. If any of them is a literal, I will just add to filters array of javascript object. If the left and the right attribute is a binary expression, then inside the javascript object I would repeat the above process.

I tried various approaches, but somehow I would miss something. So, I am asking here. :

var currentFilter = {
  'logic': null,
  filters: []
};
test(expression, currentFilter);

function test(expression, currentFilter) {
  while (expression.left != null && expression.right != null) {
    currentFilter.logic = expression.operator;
    if (expression.left.type === 'Literal') {
      currentFilter.filters.push = expression.left.value;
    } else if (expression.left.type === 'BinaryExpression') {
      test(expression.left, currentFilter);
    }

    if (expression.right.type === 'Literal') {
      currentFilter.filters.push = expression.right.value;
    } else if (expression.right.type === 'BinaryExpression') {
      test(expression.right, currentFilter);
    }
  }
}

It looks like you are pretty close with your example, and are trying to use recursion to build your desired object. The reason why yours is failing is likely the while loop, as it will get into an infinite loop due to expression not being updated. Something like this should be more like what you are looking for:

 const exp = { "type": "BinaryExpression", "operator": "OR", "left": { "type": "Literal", "value": 1, "raw": "1" }, "right": { "type": "BinaryExpression", "operator": "AND", "left": { "type": "Literal", "value": 2, "raw": "2" }, "right": { "type": "Literal", "value": 3, "raw": "3" } } } const parseValue = v => v.type === 'Literal' ? v.value : parseExp(v) const parseExp = ({ operator, left, right }) => ({ logic: operator, filters: [parseValue(left), parseValue(right)] }) console.log(parseExp(exp)) 

Consider a recursive approach -

const eval = (expr) =>
{ switch (expr.type)
  { case 'Literal':
      return expr.value
    case 'BinaryExpression':
      return apply
        ( expr.operator
        , eval (expr.left)
        , eval (expr.right)
        )
    default:
      throw Error (`invalid expression type: ${type}`)
  }
}

const apply = (op, l, r) =>
{ switch (op)
  { case 'AND':
      return l && r
    case 'OR':
      return l || r
    default:
      throw Error (`invalid operator: ${op}`)
  }
}

console.log(eval(e))
// 1 || (2 && 3)
// => 1

Expand the snippet below to verify the results in your own browser -

 const eval = (expr) => { switch (expr.type) { case 'Literal': return expr.value case 'BinaryExpression': return apply ( expr.operator , eval (expr.left) , eval (expr.right) ) default: throw Error (`invalid expression type: ${type}`) } } const apply = (op, l, r) => { switch (op) { case 'AND': return l && r case 'OR': return l || r default: throw Error (`invalid operator: ${op}`) } } const e = { type: "BinaryExpression" , operator: "OR" , left: { type: "Literal" , value: 1 , raw: "1" } , right: { type: "BinaryExpression" , operator: "AND" , left: { type: "Literal" , value: 2 , raw: "2" } , right: { type: "Literal" , value: 3 , raw: "3" } } } console.log(eval(e)) // 1 || (2 && 3) // => 1 

Now hopefully you can see how to build the result you want. This is left an exercise for the reader.

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