public function accept(VisitorInterface $visitor)
    {
        $hierarchy = array_merge([get_class($this)], array_values(class_parents($this)));

        $visitorMethods = array_map(
            function ($className) {
                if (strrpos($className, "\\") !== false) {
                    $className = substr($className, strrpos($className, "\\") + 1);
                }
                return "visit" . $className;
            },
            $hierarchy
        );

        foreach ($visitorMethods as $visitorMethod) {
            if (method_exists($visitor, $visitorMethod) === true) {
                return $visitor->$visitorMethod($this);
            }
        }

        if (method_exists($visitor, "visit") === true) {
            return $visitor->visit($this);
        }
        
        return null;
    }