Мой стандартный ответ на этот вопрос, когда он возникает:
Не используйте eval (особенно если вы говорите, что это пользовательский ввод) и не изобретайте колесо заново, написав собственный анализатор формул.
Взгляните на класс evalMath в PHPClasses. Он должен делать все, что вы перечислили здесь.
EDIT
re: К сожалению, evalMath не обрабатывает такие вещи, как (x> 5)
изменить строки 177-179 на
$ops = array('+', '-', '*', '/', '^', '_', '>', '<', '=');
$ops_r = array('+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>0, '>' => 0, '<' => 0, '=' => 0); // right-associative operator?
$ops_p = array('+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2, '>' => 0, '<' => 0, '=' => 0); // operator precedence
изменить строку 184 на
if (preg_match("/[^\w\s+*^\/()\.,-<>=]/", $expr, $matches)) { // make sure the characters are all good
добавить
case '>':
$stack->push($op1 > $op2); break;
case '<':
$stack->push($op1 < $op2); break;
case '=':
$stack->push($op1 == $op2); break;
после строки 321
и evalMath теперь будет обрабатывать (x> 5), (x <5) или (x = 5) </p>
// instantiate a new EvalMath
$m = new EvalMath;
$m->suppress_errors = true;
// set the value of x
$m->evaluate('x = 3');
var_dump($m->evaluate('y = (x > 5)'));
Далее Редактировать
Пропущена строка 307, которую следует изменить следующим образом:
if (in_array($token, array('+', '-', '*', '/', '^', '>', '<', '='))) {