/// <summary>
        /// parser the text buffer
        /// </summary>
        /// <param name="parser">buffer parser</param>
        /// <returns>text region tree</returns>
        public TextRegion ParseBuffer(SnapshotParser parser)
        {
            TextRegion regionTree = new TextRegion();

            while (ParseBuffer(parser, regionTree) != null)
            {
                ;
            }
            return(regionTree);
        }
        /// <summary>
        /// Gets nested outlining regions for buffer
        /// </summary>
        protected void Outline()
        {
            ITextSnapshot  snapshot = Buffer.CurrentSnapshot;
            SnapshotParser parser   = GetSnapshotParser(snapshot);
            //parsing snapshot
            TextRegion regionTree = Outliner.ParseBuffer(parser);

            List <TextRegion> newRegions = GetRegionList(regionTree);

            List <Span> oldSpans = Regions.ConvertAll(r => r.AsSnapshotSpan().TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive).Span);
            List <Span> newSpans = newRegions.ConvertAll(r => r.AsSnapshotSpan().Span);

            NormalizedSpanCollection oldSpanCollection = new NormalizedSpanCollection(oldSpans);
            NormalizedSpanCollection newSpanCollection = new NormalizedSpanCollection(newSpans);

            //the changed regions are regions that appear in one set or the other, but not both.
            NormalizedSpanCollection removed = NormalizedSpanCollection.Difference(oldSpanCollection, newSpanCollection);

            int changeStart = int.MaxValue;
            int changeEnd   = -1;

            if (removed.Count > 0)
            {
                changeStart = removed[0].Start;
                changeEnd   = removed[removed.Count - 1].End;
            }

            if (newSpans.Count > 0)
            {
                changeStart = Math.Min(changeStart, newSpans[0].Start);
                changeEnd   = Math.Max(changeEnd, newSpans[newSpans.Count - 1].End);
            }

            this.Snapshot = snapshot;
            this.Regions  = newRegions;

            if (changeStart <= changeEnd && this.TagsChanged != null)
            {
                this.TagsChanged(this, new SnapshotSpanEventArgs(
                                     new SnapshotSpan(this.Snapshot, Span.FromBounds(changeStart, changeEnd))));
            }
            FirstOutlining = false;
        }
		protected TextRegion ParseComment(SnapshotParser parser, Regex regionStartRegex, Regex regionEndRegex)
		{
			SnapshotPoint point = parser.CurrentPoint;
			ClassificationSpan span = parser.CurrentSpan;
			Match m = regionStartRegex.Match(span.Span.GetText());
			if (m.Success)
			{
				return new TextRegion(point, TextRegionType.Region)
				{
					Name = m.Groups[1].Value
				};
			}
			if (!regionEndRegex.IsMatch(span.Span.GetText()))
			{
				return new TextRegion(point, TextRegionType.Comment)
					    {
					       	EndPoint = span.Span.End
					    };
			}
			return null;
		}
        protected TextRegion ParseComment(SnapshotParser parser, Regex regionStartRegex, Regex regionEndRegex)
        {
            SnapshotPoint      point = parser.CurrentPoint;
            ClassificationSpan span  = parser.CurrentSpan;
            Match m = regionStartRegex.Match(span.Span.GetText());

            if (m.Success)
            {
                return(new TextRegion(point, TextRegionType.Region)
                {
                    Name = m.Groups[1].Value
                });
            }
            if (!regionEndRegex.IsMatch(span.Span.GetText()))
            {
                return(new TextRegion(point, TextRegionType.Comment)
                {
                    EndPoint = span.Span.End
                });
            }
            return(null);
        }
        /// <summary>
        /// parses buffer
        /// </summary>
        /// <param name="parser"></param>
        /// <param name="parent">parent region or null</param>
        /// <returns>a region with its children or null</returns>
        protected virtual TextRegion ParseBuffer(SnapshotParser parser, TextRegion parent)
        {
            for (; !parser.AtEnd(); parser.MoveNext())
            {
                ProcessCurrentToken(parser);
                TextRegion r = TryCreateRegion(parser);

                if (r != null)
                {
                    //found the start of the region
                    OnRegionFound(r);
                    r.Parent = parent;
                    parser.MoveNext();
                    if (!r.Complete)
                    {
                        //searching for child regions
                        while (ParseBuffer(parser, r) != null)
                        {
                            ;
                        }
                    }
                    //adding to children or merging with last child
                    if (!TryMergeComments(parent, r))
                    {
                        parent.Children.Add(r);
                        ExtendStartPoint(r);
                    }
                    return(r);
                }
                //found parent's end - terminating parsing
                if (TryComplete(parent, parser))
                {
                    parser.MoveNext();
                    return(null);
                }
            }
            return(null);
        }
		/// <summary>
		/// parses buffer
		/// </summary>
		/// <param name="parser"></param>
		/// <param name="parent">parent region or null</param>
		/// <returns>a region with its children or null</returns>
		protected virtual TextRegion ParseBuffer(SnapshotParser parser, TextRegion parent)
		{
			for (; !parser.AtEnd(); parser.MoveNext())
			{
				ProcessCurrentToken(parser);
				TextRegion r = TryCreateRegion(parser);

				if (r != null)
				{
					//found the start of the region
					OnRegionFound(r);
					r.Parent = parent;
					parser.MoveNext();
					if (!r.Complete)
					{
						//searching for child regions						
						while (ParseBuffer(parser, r) != null) ;
					}
					//adding to children or merging with last child
					if (!TryMergeComments(parent, r))
					{
						parent.Children.Add(r);
						ExtendStartPoint(r);
						
					}
					return r;
				}
				//found parent's end - terminating parsing
				if (TryComplete(parent, parser))
				{
					parser.MoveNext();
					return null;
				}
			}
			return null;
		}
		/// <summary>
		/// parser the text buffer
		/// </summary>
		/// <param name="parser">buffer parser</param>
		/// <returns>text region tree</returns>
		public TextRegion ParseBuffer(SnapshotParser parser)
		{
			TextRegion regionTree = new TextRegion();		
			while (ParseBuffer(parser, regionTree) != null);
			return regionTree;
		}
		/// <summary>
		/// tries to close region
		/// </summary>
		/// <param name="parser">parser</param>
		/// <returns>whether region was closed</returns>
		protected abstract bool TryComplete(TextRegion r, SnapshotParser parser);
		/// <summary>
		/// parses input buffer, searches for region start
		/// </summary>
		/// <param name="parser"></param>
		/// <returns>created region or null</returns>
		public abstract TextRegion TryCreateRegion(SnapshotParser parser);
		/// <summary>
		/// A function that looks for special tokens in source code
		/// </summary>
		protected virtual void ProcessCurrentToken(SnapshotParser p)
		{

		}
 /// <summary>
 /// tries to close region
 /// </summary>
 /// <param name="parser">parser</param>
 /// <returns>whether region was closed</returns>
 protected abstract bool TryComplete(TextRegion r, SnapshotParser parser);
 /// <summary>
 /// parses input buffer, searches for region start
 /// </summary>
 /// <param name="parser"></param>
 /// <returns>created region or null</returns>
 public abstract TextRegion TryCreateRegion(SnapshotParser parser);
 /// <summary>
 /// A function that looks for special tokens in source code
 /// </summary>
 protected virtual void ProcessCurrentToken(SnapshotParser p)
 {
 }