Design Patterns PHP - Interpreter Java

1) What have we done?

In step3 we have written simple tokenizer of our expression which automatically builds tree


class Tokenizer
{
    /**
     * @param string $input
     * @return array
     */
    public function tokenize($input)
    {
        $tokens = preg_split('/([*+()])\s*|([-]?[\d.]+)\s*/', $input, -1,
            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
        $output = [];
        $stack = [];
        foreach ($tokens as $token) {
            switch ($token) {
                case '+':
                    while ($var = end($stack)) {
                        if ($var == '*' or $var == '+') {
                            array_push($output, array_pop($stack));
                        } else {
                            break;
                        }
                    }
                    array_push($stack, $token);
                    break;
                case '*':
                    while ($var = end($stack)) {
                        if ($var == '*') {
                            array_push($output, array_pop($stack));
                        } else {
                            break;
                        }
                    }
                    array_push($stack, $token);
                    break;
                case '(':
                    array_push($stack, $token);
                    break;
                case ')':
                    while ($var = array_pop($stack)) {
                        if ($var !== '(')
                            array_push($output, $var);
                        else
                            break;
                    }
                    break;
                default:
                    array_push($output, $token);
            }
        }
        while ($var = array_pop($stack)) {
            array_push($output, $var);
        }
        return $output;
    }

}

$tokenizer = new Tokenizer();

$tokens = $tokenizer->tokenize('2*(a+b)*-4+c*2+5*a');


$stack = [];
foreach ($tokens as $token) {
    if (is_numeric($token)) {
        array_push($stack, new Constant($token));
    } elseif ($token == '+') {
        array_push($stack, new Add(array_pop($stack), array_pop($stack)));
    } elseif ($token == '*') {
        array_push($stack, new Multiply(array_pop($stack), array_pop($stack)));
    } else {
        array_push($stack, new Variable($token));
    }
}

$expression = array_pop($stack);

$vector = $expression->evaluate([
    'a' => new Vector(2, 3),
    'b' => new Vector(3, 5),
    'c' => new Vector(1, 2)
]);