/// <summary>
        /// Scans the given SnapshotSpan for potential matches for this classification.
        /// </summary>
        /// <param name="span">The span currently being classified</param>
        /// <returns>A list of ClassificationSpans that represent spans identified to be of this classification</returns>
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            List <ClassificationSpan> classifications = new List <ClassificationSpan>();

            // Extend the span to full lines, and tokenize/classify...
            var firstLine = span.Start.GetContainingLine();
            var lastLine  = (span.End - 1).GetContainingLine();

            // Remove any errors in the span?
            ////this.RemoveTagSpans(s => span.Contains(s.Span.GetSpan(span.Snapshot)));
            ////var toRemove = this.errorListProvider.Tasks.OfType<Task>().Where(
            ////    t => firstLine.LineNumber <= t.Line && t.Line <= lastLine.LineNumber).ToList();
            ////foreach (var task in toRemove)
            ////{
            ////    this.errorListProvider.Tasks.Remove(task);
            ////}

            SnapshotTextProvider textProvider = new SnapshotTextProvider(span.Snapshot, span);

            var statements = StatementParser.ParseStatements(
                new Position(firstLine.Start.Position, firstLine.LineNumber, 0),
                textProvider);

            foreach (var statement in statements)
            {
                // If the statement ends before the requested span, ignore it completely.
                if (statement.AllTokens.Last().Range.End.Offset <= span.Start.Position)
                {
                    continue;
                }

                foreach (var token in statement.AllTokens)
                {
                    // Skip any tokens entirely before or after the span...
                    if (token.Range.End.Offset <= span.Start.Position)
                    {
                        continue;
                    }
                    else if (token.Range.Start.Offset >= span.End.Position)
                    {
                        break;
                    }

                    IClassificationType classification = null;

                    switch (token.TokenType)
                    {
                    case ParserTokenType.Unknown:
                        break;

                    case ParserTokenType.Whitespace:
                        classification = this.whitespaceType;
                        break;

                    case ParserTokenType.Comment:
                        classification = this.commentType;
                        break;

                    case ParserTokenType.TypeKeyword:
                        classification = this.keywordType;
                        break;

                    case ParserTokenType.MessageTypeDefinition:
                        classification = this.messageTypeDefinitionType;
                        break;

                    case ParserTokenType.MessageTypeRange:
                        classification = this.messageTypeRangeType;
                        break;

                    case ParserTokenType.MessageType:
                        classification = this.messageTypeType;
                        break;

                    case ParserTokenType.MessageName:
                        classification = this.messageNameType;
                        break;

                    case ParserTokenType.LeftBrace:
                        classification = this.replacementDelimiterStart;
                        break;

                    case ParserTokenType.RightBrace:
                        classification = this.replacementDelimiterEnd;
                        break;

                    case ParserTokenType.LeftBracket:
                    case ParserTokenType.RightBracket:
                    case ParserTokenType.Comma:
                    case ParserTokenType.Colon:
                        classification = this.replacementDelimiterType;
                        break;

                    case ParserTokenType.ReplacementName:
                        classification = this.replacementNameType;
                        break;

                    case ParserTokenType.ReplacementType:
                        classification = this.replacementTypeType;
                        break;

                    case ParserTokenType.ReplacementPosition:
                        classification = this.replacementPositionType;
                        break;

                    case ParserTokenType.ReplacementAlignment:
                        classification = this.replacementAlignmentType;
                        break;

                    case ParserTokenType.ReplacementFormat:
                        classification = this.replacementFormatType;
                        break;

                    case ParserTokenType.Value:
                        classification = this.stringType;
                        break;

                    case ParserTokenType.Escape:
                        classification = this.escapeType;
                        break;

                    default:
                        break;
                    }

                    if (classification != null)
                    {
                        SnapshotSpan?intersect = span.Intersection(token.Range.AsSpan());

                        if (intersect.HasValue)
                        {
                            classifications.Add(new ClassificationSpan(intersect.Value, classification));
                        }
                    }

                    // If there were any errors, pass those up...
                    ////if (token.Errors != null)
                    ////{
                    ////    foreach (Error error in token.Errors)
                    ////    {
                    ////        ErrorTag tag = new ErrorTag("syntax error", error.Message);
                    ////        this.CreateTagSpan(span.Snapshot.CreateTrackingSpan(token), tag);

                    ////        ErrorTask task = new ErrorTask();
                    ////        task.Document = this.filename;
                    ////        task.Line = error.Range.Start.Line;
                    ////        task.Column = error.Range.Start.Column;
                    ////        task.Text = error.Message;

                    ////        // inline?
                    ////        task.Category = TaskCategory.CodeSense;
                    ////        task.ErrorCategory = TaskErrorCategory.Error;

                    ////        // Why do we have to do this ourselves?
                    ////        if (!string.IsNullOrWhiteSpace(task.Document))
                    ////        {
                    ////            IVsUIHierarchy hierarchy;
                    ////            uint item;
                    ////            IVsWindowFrame frame;

                    ////            if (VsShellUtilities.IsDocumentOpen(
                    ////                this.provider.ServiceProvider,
                    ////                task.Document,
                    ////                VSConstants.LOGVIEWID.Any_guid,
                    ////                out hierarchy,
                    ////                out item,
                    ////                out frame))
                    ////            {
                    ////                task.HierarchyItem = hierarchy;
                    ////            }

                    ////            task.Navigate += Task_Navigate;
                    ////        }

                    ////        this.errorListProvider.Tasks.Add(task);
                    ////    }
                    ////}
                }

                // If the statement ends at or after the requested span, we're done!
                if (statement.AllTokens.Last().Range.End.Offset >= span.End.Position)
                {
                    break;
                }
            }

            return(classifications);
        }