protected function addNode(int $start, string $type, int $line, int $offset1, int $offset2, $callback)
    {
        $this->flushText($start, $callback);

        switch ($type) {
            case self::TYPE_VARIABLE_ESCAPE:
                $end = $this->findVariable($start, true);
                break;
            case self::TYPE_VARIABLE_UNESCAPE:
                $end = $this->findVariable($start, false);
                break;
            case self::TYPE_SECTION_OPEN:
                $end = $this->findVariable($start, false);
                break;
            case self::TYPE_SECTION_CLOSE:
            default:
                $end = $this->findVariable($start, false);
                $this->level--;
                break;
        }

        call_user_func($callback, array(
            'type'  => $type,
            'line'  => $line,
            'start' => $start,
            'end'   => $end,
            'level' => $this->level,
            'value' => mb_substr($this->source, $start + $offset1, $end - $start - $offset2)
        ), $this->source);

        if ($type === self::TYPE_SECTION_OPEN) {
            $this->level++;
        }

        return $end - 1;
    }