'cos I had a spare five minutes I spun this out. It doesn't use a parse tree (except implicitly, for dealing with parenthesised subexpressions). It doesn't do syntax or domain checking, it assumes that variables are all of the form [a-z]\d* and certainly isn't suitable for a production environment. But I was mildly bored for a couple of minutes.
Instead of building a parse tree, it uses various pattern matches to convert an expression into a sequence of PHP statements, then evaluates them and echos the result. A bunch of diagnostic echoes are provided so that the progress of each transform can be examined. Since I ran this in a command-line environment, I've used \n instead of <br>.
$x=13;
$expr = "x+((x+3)+x)(x+5x)-(1+(x+(x^2)*(2^x)))/((x/2+x+7x))";
//$expr = "x^2+7x+6";
$temp_subscript=0;
$expr = "y=$expr;"; // When eval()ed, the result will be in $y.
$fexpr=array();
while(strpos($expr,'(')!==false) // Parenthesised expression.
{ $newvar="t".($temp_subscript++);
preg_match("/^(.*)\(([^()]+)\)(.*)$/",$expr,$matches);
$fexpr[]=$newvar."=".$matches[2]."; ";
$expr=$matches[1].$newvar.$matches[3];
// echo $matches[1]."|".$matches[2]."|".$matches[3]."\t".$expr."\n";
// flush();
}
$expr=join('',$fexpr).$expr;
//echo $expr."\n";
$expr = preg_replace("/(\d)([a-z])/","\\1*\\2",$expr); // Make multiplications explicit
//echo $expr."\n";
$expr = preg_replace("/([a-z])/","\$\\1",$expr); // Really these are supposed to be variables.
//echo $expr."\n";
$expr = preg_replace('/(\$[a-z]\d*|\d+)\^(\$[a-z]\d*|\d+)/',"pow(\\1,\\2)",$expr); // Use PHP's pow() function.
//echo $expr."\n";
$expr = str_replace('$y','return $y',$expr); // for error trapping.
//echo $expr."\n";
eval($expr);
echo $y;