A simple parser, perhaps recursive descent, or like this one would do the job nicely, if you REALLY wanted to remain using PHP for the entire solution. You can quite easily use such a system to evaluate custom formulas without resorting to eval.
Personally, i wanted something that could evaluate an entire function in php safely (with loops, conditionals etc), so i used a very lightweight javascript interpreter called duktape, which can be compiled into php 7 as a module. You can then call it to evaluate javascript functions, which are simplistic in nature and have no input/output capabilities except for being able to return a value, and take input from the original script.
Here's how i did this:
/* Execute a javascript function. Requires the duktape extension to be included in PHP.
* Accepts an array of variables by name to include as parameters to the called code.
* The code is expected to return a value, which should be scalar (numeric, string or null).
*/
function jsfunction($inputs, $code)
{
$duktape = new Duktape();
$javascript = "function e() {";
foreach ($inputs as $name=>$value) {
$javascript .= "var " . $name . ' = ' . json_encode((object)$value) . ";\n";
}
$javascript .= $code . "}\ne();";
try {
$result = $duktape->eval($javascript);
}
catch (Exception $e) {
return null;
}
return $result;
}
The parameters must be passed as an array of name/value pairs, e.g. passing ['a'=>42] makes a variable with the name 'a' visible to the javascript, with the value 42. $code contains a javascript function body, without braces around it, which must end with a return statement.
Hope this helps!