public function render()
    {
        $nameless_count = 0;
        if (!isset($this->_paramBase)) {
            $this->_paramBase = $this->paramBase;
        }

        if ($this->template === null) {
            throw new Exception('Template is not defined for Expression');
        }

        $res = preg_replace_callback(
            '/\[[a-z0-9_]*\]|{[a-z0-9_]*}/i',
            function ($matches) use (&$nameless_count) {
                $identifier = substr($matches[0], 1, -1);
                $escaping = ($matches[0][0] == '[') ? 'param' : 'escape';

                // Allow template to contain []
                if ($identifier === '') {
                    $identifier = $nameless_count++;

                    // use rendering only with named tags
                }
                $fx = '_render_'.$identifier;

                // [foo] will attempt to call $this->_render_foo()

                if (array_key_exists($identifier, $this->args['custom'])) {
                    $value = $this->_consume($this->args['custom'][$identifier], $escaping);
                } elseif (method_exists($this, $fx)) {
                    $value = $this->$fx();
                } else {
                    throw new Exception([
                        'Expression could not render tag',
                        'tag' => $identifier,
                    ]);
                }

                return is_array($value) ? '('.implode(',', $value).')' : $value;
            },
            $this->template
        );
        unset($this->_paramBase);

        return trim($res);
    }