<?php

function remove_whitespace($string) {
    return 
str_replace(' '''str_replace("\t"''str_replace("\n"''$string)));
}

function 
operation($num1$operator$num2) {
    switch (
$operator) {
        case 
'^':
            return 
pow($num1$num2);
            break;
        case 
'%':
            return 
$num1 $num2;
            break;
        case 
'/':
            return 
$num1 $num2;
            break;
        case 
'*':
            return 
$num1 $num2;
            break;
        case 
'+':
            return 
$num1 $num2;
            break;
        case 
'-':
            return 
$num1 $num2;
            break;
        default:
            return 
0;
            break;
    }
}

function 
is_a_number($char) {
    
$chars = array(
        
'0',
        
'1',
        
'2',
        
'3',
        
'4',
        
'5',
        
'6',
        
'7',
        
'8',
        
'9',
        
'.'
    
);
    
    return 
in_array($char$chars);
}

function 
evaluate($expression$recursing) {
    if (!
$recursing) {
        
$expression remove_whitespace($expression);
    }

    
$operators = array(
        
'^' => 0,
        
'%' => 1,
        
'/' => 1,
        
'*' => 1,
        
'+' => 2,
        
'-' => 2
    
);

    
// Look for brackets
    
while (($left_bracket_pos strpos($expression'(')) !== FALSE) {
        
// Find its twin bracket
        
$num_left_brackets 1;
        
$num_right_brackets 0;
        
$right_bracket_pos $left_bracket_pos 1;
        
$char '';
        
        while (
$char != ')' || $num_left_brackets != $num_right_brackets) {
            
$char $expression[$right_bracket_pos];
            if (
$char == '(') { $num_left_brackets++; }
            if (
$char == ')') { $num_right_brackets++; }
            
$right_bracket_pos++;
        }
        
        
$search substr($expression$left_bracket_pos$right_bracket_pos $left_bracket_pos);
        
$replace evaluate(substr($expression$left_bracket_pos 1$right_bracket_pos $left_bracket_pos 2), true);
        
$expression str_replace($search$replace$expression);
    }
    
    
// Now start evaluating binary operators
    
while (true) {
        
// Find the operator with the highest precedence
        
$highest_operator = array(''1000);
        
$found_operator false;
        for (
$i 0$i strlen($expression); $i++) {
            if (
in_array($expression[$i], array_keys($operators))) {
                if (
$operators[$expression[$i]] < $highest_operator[1]) {
                    
$highest_operator = array($expression[$i], $operators[$expression[$i]], $i);
                    
$found_operator true;
                }
            }
        }
        
        
// If there are no operators, we're done here.
        
if (!$found_operator) {
            return 
$expression;
        }
        
        
// Get the two numbers on either side of the operator
        
$left_operation $highest_operator[2] - 1;
        
$right_operation $highest_operator[2] + 1;

        
$char '0';
        while (
is_a_number($char)) {
            
$left_operation--;
            
$char $expression[$left_operation];
        }
        
$left_operation++;
        
        
$char '0';
        while (
is_a_number($char)) {
            
$right_operation++;
            
$char $expression[$right_operation];
        }
        
$right_operation--;
        
        if (
$left_operation 0) { $left_operation 0; }
        if (
$right_operation strlen($expression-1)) { $right_expression strlen($expression-1); }
        
        
// Do the operation
        
$expression str_replace(substr($expression$left_operation$right_operation $left_operation 1), operation(substr($expression$left_operation$highest_operator[2] - $left_operation), $expression[$highest_operator[2]], substr($expression$highest_operator[2] + 1$right_operation $highest_operator[2])), $expression);
    }
}

$expr evaluate($argv[1], false);
echo 
"$expr\n";

?>