public function readExpression(array $breaks = null, array $brackets = null)
    {
        if (!$this->hasLength()) {
            return;
        }

        $breaks = $breaks ?: [];
        $brackets = $brackets ?: $this->expressionBrackets;
        $expression = '';
        $char = null;
        $bracketStack = [];
        while ($this->hasLength()) {
            //Append a string if any was found
            //Notice there can be brackets in strings, we dont want to
            //count those
            $expression .= $this->readString(null, true);

            if (!$this->hasLength()) {
                break;
            }

            //Check for breaks
            if (count($bracketStack) === 0) {
                foreach ($breaks as $break) {
                    if ($this->peekString($break)) {
                        break 2;
                    }
                }
            }

            //Count brackets
            $char = $this->peek();
            if (in_array($char, array_keys($brackets), true)) {
                $bracketStack[] = $char;
            } elseif (in_array($char, array_values($brackets), true)) {
                if (count($bracketStack) < 1) {
                    $this->throwException(
                        "Unexpected bracket $char encountered, no brackets open"
                    );
                }

                $last = count($bracketStack) - 1;
                if ($char !== $brackets[$bracketStack[$last]]) {
                    $this->throwException(
                        "Unclosed bracket {$bracketStack[$last]} encountered, "
                        ."got $char instead"
                    );
                }

                array_pop($bracketStack);
            }

            $expression .= $char;
            $this->consume();
        }

        if (count($bracketStack) > 0) {
            $this->throwException(
                'Unclosed brackets '.implode(', ', $bracketStack).' encountered '
                .'at end of expression'
            );
        }

        return trim($expression);
    }