IEnumerable <object> IPowerLogEventParser.ParseEvents(
            ref string text)
        {
            var allParsedEvents = new List <object>();

            using (var lines = new TrackingEnumerator <string>(__GetLines(text)))
            {
                lines.MoveNext();
                while (!lines.HasCompleted)
                {
                    IEnumerable <string> linesConsumed = null;

                    foreach (IGameStateDebugEventParser gameStateDebugEventParser in _gameStateDebugEventParsers)
                    {
                        linesConsumed = gameStateDebugEventParser.TryParseEvents(lines, _parseContext, out IEnumerable <object> parsedEvents);
                        if (linesConsumed == null)
                        {
                            continue;
                        }

                        if (parsedEvents == null)
                        {
                            text = string.Join(Environment.NewLine, linesConsumed.Select(__line => LINE_PREFIX + __line));

                            return(allParsedEvents);
                        }

                        allParsedEvents.AddRange(parsedEvents);

                        break;
                    }

                    if (linesConsumed == null)
                    {
                        lines.MoveNext();
                    }
                }
            }

            text = null;

            return(allParsedEvents);

            IEnumerator <string> __GetLines(
                string source)
            {
                using (var stringReader = new StringReader(source))
                {
                    string currentLine;
                    Match  match;
                    while ((currentLine = stringReader.ReadLine()) != null)
                    {
                        if ((match = s_gameStateMethodPattern.Match(currentLine)).Success)
                        {
                            yield return(match.Groups["Output"].Value);
                        }
                    }
                }
            }
        }
        IEnumerable <string> IGameStateDebugEventParser.TryParseEvents(
            TrackingEnumerator <string> lines,
            ParseContext parseContext,
            out IEnumerable <object> parsedEvents)
        {
            parsedEvents = null;

            // Check if the current line starts this parser
            string currentLine = lines.Current;
            Match  match       = _startPattern.Match(currentLine);

            if (!match.Success)
            {
                return(null);
            }

            // Start tracking lines consumed from the enumerator
            var linesConsumed = new List <string> {
                currentLine
            };

            lines.MoveNext();

            // Create a text pattern to detect when to stop parsing
            var nestedOffsetPattern = new Regex($@"^{match.Groups["Offset"].Value}    .*$");

            // Store each group value for later use
            var startGroupValues = new Dictionary <string, string>();

            foreach (Group group in match.Groups)
            {
                startGroupValues.Add(group.Name, group.Value);
            }

            IEnumerable <string> innerLinesConsumed =
                ParseEvents(
                    lines,
                    parseContext,
                    new ParserContext(
                        currentLine,
                        startGroupValues,
                        nestedOffsetPattern),
                    ref parsedEvents);

            return(linesConsumed.Concat(innerLinesConsumed ?? Enumerable.Empty <string>()));
        }
 protected abstract IEnumerable <string> ParseEvents(
     TrackingEnumerator <string> lines,
     ParseContext parseContext,
     ParserContext parserContext,
     ref IEnumerable <object> parsedEvents);