Evaluate a boolean expression in a string in Javascript without eval

I have a line containing logical logic, something like lines:

((true && true) || false && !true)

What is the best way to safely evaluate this string in Javascript to get a boolean result? I would like to avoid using eval ().

+4
source share
2 answers

I wrote this logical string parser for another question:

var exp1 = "(true && true || false) && (true || (false && true))";
var exp2 = "((true && true) || false && !true)";
var exp3 = "(true && !false) && true && !false";
var exp4 = "(a && b) && c && d";

console.log(exp1 + ' = ' + parseBoolStr(exp1));
console.log(exp2 + ' = ' + parseBoolStr(exp2));
console.log(exp3 + ' = ' + parseBoolStr(exp3));
console.log(exp4 + ' = ' + parseBoolStr(exp4));

function parseBoolStr(str) {
  var expressions = {};
  var expressionRegex = new RegExp("\\((?:(?:!*true)|(?:!*false)|(?:&&)|(?:\\|\\|)|\\s|(?:!*\\w+))+\\)");
  var expressionIndex = 0;
  str = str.trim();
  while (str.match(expressionRegex)) {
    var match = str.match(expressionRegex)[0];
    var expression = 'boolExpr' + expressionIndex;
    str = str.replace(match, expression);
    match = match.replace('(', '').replace(')', '');
    expressions[expression] = match;
    expressionIndex++;
  }
  return evalBoolStr(str, expressions);
}

function evalBoolStr(str, expressions) {
  var conditions = str.split(' ');
  if (conditions.length > 0) {
    var validity = toBoolean(conditions[0], expressions);
    for (var i = 1; i + 1 < conditions.length; i += 2) {
      var comparer = conditions[i];
      var value = toBoolean(conditions[i + 1], expressions);
      switch (comparer) {
        case '&&':
          validity = validity && value;
          break;
        case '||':
          validity = validity || value;
          break;
      }
    }
    return validity;
  }
  return 'Invalid input';
}

function toBoolean(str, expressions) {
  var inversed = 0;
  while (str.indexOf('!') === 0) {
    str = str.replace('!', '');
    inversed++;
  }
  var validity;
  if (str.indexOf('boolExpr') === 0) {
    validity = evalBoolStr(expressions[str], expressions);
  } else if (str == 'true' || str == 'false') {
    validity = str == 'true';
  } else {
    validity = window[str]();
  }
  for (var i = 0; i < inversed; i++) {
    validity = !validity;
  }
  return validity;
}

function a() {
  return false;
}
function b() {
  return true;
}
function c() {
  return true;
}
function d() {
  return false;
}
Run codeHide result

Functions a, b, cand dthey can and should be removed. Just an example.

Using: parseBoolStr('((true && true) || false && !true)');

+1
source

You can use the Angular service $parse. Angular expressions without expressions eval.

Usage example:

var x=$parse(' ((true && true) || false && !true) ')()
console.log(x)  // will return true

TO READ:

var a=angular.module('app',[])
a.run(function($parse){
  alert($parse('true || false || true || false')())
  })
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app=app>
Hide result
-1

Source: https://habr.com/ru/post/1618790/


All Articles