public function collectTags($source, $tag_name=false)
        {
            $tagname = $tag_name === false ? $this->_options['tag_name'] : $tag_name;
            
            $tags = $tag_names = array();
            $tag_count = 0;
            
            $inner_tag_open_pos = $source_len = strlen($source);
            $opener = self::$tag_open.$tagname.':';
            $opener_len = strlen($opener);
            $closer = self::$tag_open.'/'.$tagname.':';
            $closer_len = strlen($closer);
            $closer_end = self::$tag_close;

            while ($inner_tag_open_pos !== false)
            {
//              start getting the last found opener tag
                $open_tag_look_source   = substr($source, 0, $inner_tag_open_pos);
                $open_tag_look_len      = strlen($open_tag_look_source);
                $inner_tag_open_pos     = strrpos($open_tag_look_source, $opener);

//              if there is no last tag then the rest is the final text
                if($inner_tag_open_pos === false)
                {
                    array_push($tags, array('content'=>$source, 'name'=>'___text'));
                    break;
                }
                else
                {
//                  get the source from the start of that last tag
                    $tag_look_source            = substr($source, $inner_tag_open_pos);
                    $open_bracket_pos           = strpos($tag_look_source, self::$tag_open, 1);
                    $short_tag_close_pos        = strpos($tag_look_source, '/'.self::$tag_close);
                    
                    if($short_tag_close_pos !== false && $short_tag_close_pos < $open_bracket_pos)
                    {
                        $inner_tag_close_pos = $short_tag_close_pos + 2;
                    }
                    else
                    {
                        $inner_tag_close_pos_begin  = strpos($tag_look_source, $closer);
                        $inner_tag_close_pos        = strpos($tag_look_source, $closer_end, $inner_tag_close_pos_begin)+1;
                    }

//                  get the content of the block
                    $tag_source     = substr($tag_look_source, 0, $inner_tag_close_pos);
    
                    $tag            = $this->_buildTag($tag_source, $tagname);
                    $index          = count($tags);
                    $tag['source_marker'] = '------@@%'.self::$_instance.'-'.$index.'%@@------';
                    array_push($tags, $tag);
        
//                  modify the source so it doesn't get repeated
                    $source = substr($source, 0, $inner_tag_open_pos).$tag['source_marker'].substr($source, $inner_tag_open_pos+$inner_tag_close_pos);
//                  $source = str_replace($tag_source, '------@@%'.$index.'%@@------', $source);
                }
            }
            return $tags;
        }