代码之家  ›  专栏  ›  技术社区  ›  lambad

javascript中二进制表达式的解析

  •  3
  • lambad  · 技术社区  · 7 年前

    {
      "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"
        }
      }
    }
    

    我想在JS中将其转换为以下内容。

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

    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);
        }
      }
    }
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Matt Way    7 年前

    while expression

    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))
        2
  •  1
  •   Mulan    7 年前

    考虑递归方法-

    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
    

    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

    现在希望你能看到如何建立你想要的结果。这是留给读者的练习。