/// <summary>
        /// Highlights elements in the specified text.
        ///
        /// The highlighter tries to find matches of the patterns specified by the Patterns property in the provided text.
        /// For each match a IHighlighterToken instance is returned and the color is used as defined in the matched pattern
        /// definition. Except for multi line comments an keywords/identifiers the Patterns list also defines a token type
        /// precedence, i.e. a highlighter token instance is always returned for the first token type matched by the regex,
        /// even if mutliple token types are matched simultanously.
        /// </summary>
        /// <param name="text">Text, which should be highlighted.</param>
        /// <param name="activeBlock">Active multi line block.</param>
        /// <returns>Enumeration of IHighlighterToken instances.</returns>
        public IEnumerable <Interfaces.IHighlighterToken> Highlight(string text, IHighlighterToken activeBlock = null)
        {
            if (text != null)
            {
                bool activeBlockIsComment = activeBlock != null && activeBlock.Type.Equals("COMMENT", StringComparison.OrdinalIgnoreCase);
                bool insideComment        = activeBlock != null && activeBlock.Type.Equals("COMMENT", StringComparison.OrdinalIgnoreCase);
                int  commentStart         = insideComment ? 0 : -1;
                int  commentEnd           = -1;
                uint commentColor         = insideComment ? activeBlock.Color : 0;

                var matches = mPatternRegEx.Matches(text);
                // Perform regex matching
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    // Find first group, containing a match
                    for (int i = 1; i <= match.Groups.Count; ++i)
                    {
                        var currentGroup = match.Groups[i];
                        if (currentGroup.Success)
                        {
                            string tokenType = mPatternRegEx.GroupNameFromNumber(i);
                            // Not in multi-line comment?
                            if (!(insideComment))
                            {
                                // Special treatment for identifiers and keywords...
                                if (tokenType.Equals("IDENTIFIER", StringComparison.OrdinalIgnoreCase) && mKeywordRegEx != null)
                                {
                                    string identifier   = currentGroup.Value;
                                    var    keywordMatch = mKeywordRegEx.Match(identifier);
                                    // Keywords have precedence over identifiers, but identifiers have precendence over keywords,
                                    // if the keyword is only contained in the identifier.
                                    if (keywordMatch.Success && keywordMatch.Length == identifier.Length)
                                    {
                                        // Determine keyword token type
                                        for (int g = 1; g <= keywordMatch.Groups.Count; ++g)
                                        {
                                            var currentKeywordGroup = keywordMatch.Groups[g];
                                            if (currentKeywordGroup.Success)
                                            {
                                                tokenType = mKeywordRegEx.GroupNameFromNumber(g);
                                                break;
                                            }
                                        }
                                        yield return(new Interfaces.HighlighterToken(mTokenTypeToPattern[tokenType].FirstOrDefault().Color, tokenType, currentGroup.Index, currentGroup.Index + currentGroup.Length));
                                    }
                                }
                                // Multiline comment handling...
                                if (tokenType.Equals("COMMENT_START", StringComparison.OrdinalIgnoreCase) || tokenType.Equals("CommentStart", StringComparison.OrdinalIgnoreCase))
                                {
                                    insideComment = true;
                                    commentStart  = currentGroup.Index;
                                    commentColor  = mTokenTypeToPattern[tokenType].FirstOrDefault().Color;
                                }
                                else
                                // Single line comment handling...
                                if (tokenType.Equals("LINE_COMMENT", StringComparison.OrdinalIgnoreCase) || tokenType.Equals("LineComment", StringComparison.OrdinalIgnoreCase))
                                {
                                    commentColor = mTokenTypeToPattern[tokenType].FirstOrDefault().Color;
                                    var tagColor = mTokenTypeToPattern["TAG"].FirstOrDefault().Color;

                                    // Handle tags...
                                    if (mTagRegEx != null)
                                    {
                                        commentStart = currentGroup.Index;
                                        string lineComment = currentGroup.Value;
                                        var    tags        = mTagRegEx.Matches(lineComment);
                                        if (tags.Count > 0)
                                        {
                                            foreach (System.Text.RegularExpressions.Match tag in tags)
                                            {
                                                commentEnd = tag.Index + currentGroup.Index;
                                                int tagStart = tag.Index + currentGroup.Index;
                                                int tagEnd   = tagStart + tag.Length;
                                                if (commentEnd > commentStart)
                                                {
                                                    yield return(new Interfaces.HighlighterToken(commentColor, tokenType, commentStart, commentEnd));
                                                }
                                                if (tagEnd > tagStart)
                                                {
                                                    yield return(new Interfaces.HighlighterToken(tagColor, "TAG", tagStart, tagEnd));
                                                }
                                                commentStart = tagEnd;
                                            }
                                            commentEnd = currentGroup.Index + currentGroup.Length;
                                            if (commentEnd > commentStart)
                                            {
                                                yield return(new Interfaces.HighlighterToken(commentColor, tokenType, commentStart, commentEnd));
                                            }
                                        }
                                        else
                                        {
                                            yield return(new Interfaces.HighlighterToken(mTokenTypeToPattern[tokenType].FirstOrDefault().Color, tokenType, currentGroup.Index, currentGroup.Index + currentGroup.Length));
                                        }
                                    }
                                    else
                                    {
                                        yield return(new Interfaces.HighlighterToken(mTokenTypeToPattern[tokenType].FirstOrDefault().Color, tokenType, currentGroup.Index, currentGroup.Index + currentGroup.Length));
                                    }
                                }
                                else
                                // Normal match...
                                {
                                    yield return(new Interfaces.HighlighterToken(mTokenTypeToPattern[tokenType].FirstOrDefault().Color, tokenType, currentGroup.Index, currentGroup.Index + currentGroup.Length));
                                }
                            }
                            else
                            {
                                // Handle tag
                                if (tokenType.Equals("TAG", StringComparison.OrdinalIgnoreCase))
                                {
                                    commentEnd = currentGroup.Index;
                                    yield return(new Interfaces.HighlighterToken(commentColor, "COMMENT", commentStart, commentEnd));

                                    yield return(new Interfaces.HighlighterToken(mTokenTypeToPattern[tokenType].FirstOrDefault().Color, tokenType, currentGroup.Index, currentGroup.Index + currentGroup.Length));

                                    commentStart  = currentGroup.Index + currentGroup.Length;
                                    insideComment = true;
                                }
                                // Multiline comment handling...
                                if (tokenType.Equals("COMMENT_END", StringComparison.OrdinalIgnoreCase) || tokenType.Equals("CommentEnd", StringComparison.OrdinalIgnoreCase))
                                {
                                    insideComment = false;
                                    commentEnd    = currentGroup.Index + currentGroup.Length;
                                    yield return(new Interfaces.HighlighterToken(commentColor, "COMMENT", commentStart, commentEnd));
                                }
                            }
                            break;
                        }
                    }
                }

                // Emit comment token if not closed
                if (insideComment && commentStart >= 0)
                {
                    yield return(new Interfaces.HighlighterToken(commentColor, "COMMENT", commentStart, text.Length));
                }
            }
            else
            {
                yield break;
            }
        }
 /// <summary>
 /// Highlights elements in the text to which access is provided through the text reader.
 /// </summary>
 /// <param name="inputReader">Text reader, providing access to the text, which should be highlighted.</param>
 /// <param name="activeBlock">Active multi line block.</param>
 /// <returns>Enumeration of IHighlighterToken instances.</returns>
 public IEnumerable <Interfaces.IHighlighterToken> Highlight(System.IO.TextReader inputReader, IHighlighterToken activeBlock = null)
 {
     if (inputReader != null)
     {
         string text = inputReader.ReadToEnd();
         return(Highlight(text, activeBlock));
     }
     else
     {
         return(new Interfaces.HighlighterToken[] { });
     }
 }