src/Debug/PhpDoc.php
public static function parseTag($tag, $tagStr = '')
    {
        $parsed = array();
        $tagParsers = array(
            array(
                'tags' => array('param','property','property-read', 'property-write', 'var'),
                'parts' => array('type','name','desc'),
                'regex' => '/^'
                    .'(?:(?P<type>[^\$].*?)\s+)?'
                    .'(?:&?\$?(?P<name>\S+)\s+)?'
                    .'(?P<desc>.*)?'
                    .'$/s',
                'callable' => function ($tag, $parsed) {
                    if (\strpos($parsed['desc'], ' ') === false) {
                        if (!$parsed['type']) {
                            $parsed['type'] = $parsed['desc'];
                            $parsed['desc'] = null;
                        } elseif (!$parsed['name']) {
                            $parsed['name'] = \ltrim($parsed['desc'], '&$');
                            $parsed['desc'] = null;
                        }
                    }
                    return $parsed;
                },
            ),
            array(
                'tags' => array('method'),
                'parts' => array('static', 'type', 'name', 'param', 'desc'),
                'regex' => '/'
                    .'(?:(?P<static>static)\s+)?'
                    .'(?:(?P<type>.*?)\s+)?'
                    .'(?P<name>\S+)'
                    .'\((?P<param>((?>[^()]+)|(?R))*)\)'  // see http://php.net/manual/en/regexp.reference.recursive.php
                    .'(?:\s+(?P<desc>.*))?'
                    .'/s',
                'callable' => function ($tag, $parsed) {
                    $parsed['static'] = $parsed['static'] !== null;
                    $parsed['param'] = self::parseParams($parsed['param']);
                    return $parsed;
                },
            ),
            array(
                'tags' => array('return'),
                'parts' => array('type','desc'),
                'regex' => '/^(?P<type>.*?)'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                'tags' => array('link'),
                'parts' => array('uri', 'desc'),
                'regex' => '/^(?P<uri>\S+)'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                'tags' => array('see'),
                'parts' => array('uri', 'fqsen', 'desc'),
                'regex' => '/^(?:'
                    .'(?P<uri>https?:\/\/\S+)|(?P<fqsen>\S+)'
                    .')'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                // default
                'tags' => array(),
                'parts' => array('desc'),
                'regex' => '/^(?P<desc>.*?)$/s',
            ),
        );
        foreach ($tagParsers as $parser) {
            if (\in_array($tag, $parser['tags'])) {
                break;
            }
        }
        \preg_match($parser['regex'], $tagStr, $matches);
        foreach ($parser['parts'] as $part) {
            $parsed[$part] = isset($matches[$part]) && $matches[$part] !== ''
                ? \trim($matches[$part])
                : null;
        }
        if (isset($parser['callable'])) {
            $parsed = \call_user_func($parser['callable'], $tag, $parsed);
        }
        $parsed['desc'] = self::trimDesc($parsed['desc']);
        return $parsed;
    }
public static function parseTag($tag, $tagStr = '')
    {
        $parsed = array();
        $tagParsers = array(
            array(
                'tags' => array('param','property','property-read', 'property-write', 'var'),
                'parts' => array('type','name','desc'),
                'regex' => '/^'
                    .'(?:(?P<type>[^\$].*?)\s+)?'
                    .'(?:&?\$?(?P<name>\S+)\s+)?'
                    .'(?P<desc>.*)?'
                    .'$/s',
                'callable' => function ($tag, $parsed) {
                    if (\strpos($parsed['desc'], ' ') === false) {
                        if (!$parsed['type']) {
                            $parsed['type'] = $parsed['desc'];
                            $parsed['desc'] = null;
                        } elseif (!$parsed['name']) {
                            $parsed['name'] = \ltrim($parsed['desc'], '&$');
                            $parsed['desc'] = null;
                        }
                    }
                    return $parsed;
                },
            ),
            array(
                'tags' => array('method'),
                'parts' => array('static', 'type', 'name', 'param', 'desc'),
                'regex' => '/'
                    .'(?:(?P<static>static)\s+)?'
                    .'(?:(?P<type>.*?)\s+)?'
                    .'(?P<name>\S+)'
                    .'\((?P<param>((?>[^()]+)|(?R))*)\)'  // see http://php.net/manual/en/regexp.reference.recursive.php
                    .'(?:\s+(?P<desc>.*))?'
                    .'/s',
                'callable' => function ($tag, $parsed) {
                    $parsed['static'] = $parsed['static'] !== null;
                    $parsed['param'] = self::parseParams($parsed['param']);
                    return $parsed;
                },
            ),
            array(
                'tags' => array('return'),
                'parts' => array('type','desc'),
                'regex' => '/^(?P<type>.*?)'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                'tags' => array('link'),
                'parts' => array('uri', 'desc'),
                'regex' => '/^(?P<uri>\S+)'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                'tags' => array('see'),
                'parts' => array('uri', 'fqsen', 'desc'),
                'regex' => '/^(?:'
                    .'(?P<uri>https?:\/\/\S+)|(?P<fqsen>\S+)'
                    .')'
                    .'(?:\s+(?P<desc>.*))?$/s',
            ),
            array(
                // default
                'tags' => array(),
                'parts' => array('desc'),
                'regex' => '/^(?P<desc>.*?)$/s',
            ),
        );
        foreach ($tagParsers as $parser) {
            if (\in_array($tag, $parser['tags'])) {
                break;
            }
        }
        \preg_match($parser['regex'], $tagStr, $matches);
        foreach ($parser['parts'] as $part) {
            $parsed[$part] = isset($matches[$part]) && $matches[$part] !== ''
                ? \trim($matches[$part])
                : null;
        }
        if (isset($parser['callable'])) {
            $parsed = \call_user_func($parser['callable'], $tag, $parsed);
        }
        $parsed['desc'] = self::trimDesc($parsed['desc']);
        return $parsed;
    }
Parse phpDoc tag

Notes:
\@method tag:
optional "static" keyword may preceed type & name
'static' returned as a boolean value
parameters:  defaultValue key only returned if defined.
defaultValue is not parsed

@param string $tag    tag type
@param string $tagStr tag values (ie "[Type] [name] [<description>]")

@return array