public IEnumerable <ITagSpan <AsmTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            DateTime time1 = DateTime.Now;

            if (spans.Count == 0)
            {  //there is no content in the buffer
                yield break;
            }

            foreach (SnapshotSpan curSpan in spans)
            {
                ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine();

                string line_upcase = containingLine.GetText().ToUpper();
                List <(int BeginPos, int Length, bool IsLabel)> pos = new List <(int BeginPos, int Length, bool IsLabel)>(AsmSourceTools.SplitIntoKeywordPos(line_upcase));

                int offset    = containingLine.Start.Position;
                int nKeywords = pos.Count;

                #region Check if the current line is a line of source code
                if (IsSourceCode(line_upcase, pos))
                {
                    yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span((0, line_upcase.Length, false), offset, curSpan), this._remark));

                    continue; // go to the next line
                }
                #endregion

                for (int k = 0; k < nKeywords; k++)
                {
                    string asmToken = AsmSourceTools.Keyword(pos[k], line_upcase);
                    // keyword starts with a remark char
                    if (AsmSourceTools.IsRemarkChar(asmToken[0]))
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._remark));

                        continue;
                    }

                    // keyword k is a label definition
                    if (pos[k].IsLabel)
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._labelDef));

                        continue;
                    }

                    AsmTokenType keywordType = this._asmDudeTools.Get_Token_Type_Att(asmToken);
                    switch (keywordType)
                    {
                    case AsmTokenType.Jump:
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._jump));

                        k++;         // goto the next word
                        if (k == nKeywords)
                        {
                            break;         // there are no next words
                        }

                        string asmToken2 = AsmSourceTools.Keyword(pos[k], line_upcase);
                        switch (asmToken2)
                        {
                        case "WORD":
                        case "DWORD":
                        case "QWORD":
                        case "SHORT":
                        case "NEAR":
                        {
                            yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._misc));

                            k++;
                            if (k == nKeywords)
                            {
                                break;
                            }

                            string asmToken3 = AsmSourceTools.Keyword(pos[k], line_upcase);
                            switch (asmToken3)
                            {
                            case "PTR":
                            {
                                yield return(new TagSpan <AsmTokenTag>(New_Span(pos[k], offset, curSpan), this._misc));

                                break;
                            }
                                yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._label));

                                break;
                            }
                            break;
                        }

                        default:
                        {
                            if (RegisterTools.IsRegister(asmToken2))
                            {
                                yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._register));
                            }
                            else if (AsmSourceTools.Evaluate_Constant(asmToken2, true).Valid)
                            {
                                yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._constant));
                            }
                            else
                            {
                                yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._label));
                            }
                            break;
                        }
                        }
                        break;
                    }

                    case AsmTokenType.UNKNOWN:     // asmToken is not a known keyword, check if it is numerical
                    {
                        if (AsmSourceTools.Evaluate_Constant(asmToken, true).Valid)
                        {
                            yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._constant));
                        }
                        else if (asmToken.StartsWith("$"))
                        {
                            yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._constant));
                        }
                        else if (asmToken.StartsWith("\"") && asmToken.EndsWith("\""))
                        {
                            yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._constant));
                        }
                        else
                        {
                            //yield return new TagSpan<AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._UNKNOWN);
                        }
                        break;
                    }

                    case AsmTokenType.Directive:
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._directive));

                        break;
                    }

                    case AsmTokenType.Mnemonic:
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._mnemonic));

                        break;
                    }

                    case AsmTokenType.Register:
                    {
                        yield return(new TagSpan <AsmTokenTag>(NasmIntelTokenTagger.New_Span(pos[k], offset, curSpan), this._register));

                        break;
                    }

                    default: break;
                    }
                }
            }
            AsmDudeToolsStatic.Print_Speed_Warning(time1, "NasmAttDisassemblyTokenTagger");
        }