Variables are symbols, which a basic lexer like the one I presented returns. One task of the parser is to lookup the symbols in some form of table - not database table, just an array will suffice, so you could start with something akin to:
$symtab = new SymbolTable();
$symtab->defineConstant('PI', 3.14);
// more constant definitions here...
$symtab->defineFunction('sin', 'my_sin'); // sin, calls my_sin() function (see below)
$symtab->defineFunction('log', 'log10'); // log, calls the builtin log10 function
$symtab->defineFunction('floor'); // floor, calls the builtin floor function
// more function definitions here
$symtab->defineVariable('level', $ir['level']); // assuming the usual mccodes variable naming convention
$symtab->defineVariable('will', $ir['will']);
$symtab->defineVariable('exp', $ir['exp']);
// more variables from the user's array here
$parser = new Parse($symtab);
$result = $parser->evaluate('5*WILL/EXP+6-LEVEL');
If you are wondering, my_sin() would perhaps be defined as:
function my_sin( $degrees ) {
return sin(deg2rad($degrees));
}
It soons becomes pretty apparent, that you are really creating a whitelist expression evaluation, something that is pretty much bullet-proof.
The symbol table itself can be very easy, an associative array containing the symbol, the type of symbol (constant, function or variable) and the value (or in the case of function, the name of the function). The parser of course is more fun to write, but is not difficult if you start small.
There are some interesting problems to solve in the parser, operator precedence, and possibly conversion from infix to postfix, but both are very well covered at your local corner Google, and in fact I've already touched on a solution which does not require conversion to postfix, saving one possibly vital step.