public void Init()
        {
            iState             = TState.EStateIdle;
            iData              = new DExcExtractedData();
            iLists             = new Dictionary <TState, DExcExtractorList>();
            iCurrentLineNumber = 0;

            // Null (really just exists to catch a state transition)
            // =======================================================
            CreateList(TState.EStateIdle, DExcExtractorListType.EListNull).AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.LogStart, TState.EStateHeader));

            // Header
            // =======================================================
            CreateList(TState.EStateHeader, DExcExtractorListType.EListHeader).AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.ThreadName, TState.EStateThreadInfo));

            // Thread info
            // ===========
            DExcExtractorListThreadInfo listThreadInfo = new DExcExtractorListThreadInfo(TState.EStateThreadInfo, DExcExtractorListType.EListThread);

            PrepareList(listThreadInfo, EM.ThreadName, EM.ThreadId, EM.ThreadStackRange, EM.ThreadPanicDetails);
            listThreadInfo.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.RegistersExceptionStart, TState.EStateRegisterInfoException));
            listThreadInfo.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.RegistersUserStart, TState.EStateRegisterInfoUser));

            // Registers (exception)
            // =====================
            DExcExtractorList listRegisterInfoException = CreateList(TState.EStateRegisterInfoException, DExcExtractorListType.EListRegistersException,
                                                                     EM.RegistersExceptionSet1,
                                                                     EM.RegistersExceptionSet2);

            listRegisterInfoException.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.RegistersUserStart, TState.EStateRegisterInfoUser));

            // Registers (user)
            // ================
            DExcExtractorList listRegisterInfoUser = CreateList(TState.EStateRegisterInfoUser, DExcExtractorListType.EListRegistersUser,
                                                                EM.RegistersUserCPSR,
                                                                EM.RegistersUserSet);

            // Since code segs are optional, we want to record that we at least saw the header text (which is mandatory). This
            // tracking allows us to validate that we have received/observed data for all states.
            listRegisterInfoUser.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.CodeSegmentsStart, TState.EStateCodeSegments));

            // Code segments
            // =============
            DExcExtractorList listCodeSegments = CreateList(TState.EStateCodeSegments, DExcExtractorListType.EListCodeSegments, EM.CodeSegmentsEntry);

            // We need to transition state to "stack data", but we must be sure not to throw away the state line we just encountered.
            listCodeSegments.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.StackDataEntry, TState.EStateStackData));

            // Stack data
            // ==========
            DExcExtractorListStackData listStackData = new DExcExtractorListStackData(TState.EStateStackData, DExcExtractorListType.EListStackData);

            PrepareList(listStackData, EM.StackDataEntry);
            listStackData.AddExpression(DExcExtractorEntry.NewMatchSaveAndTransition(EM.LogStart, TState.EStateHeader));

            // We want to observe the stack data as it arrives so that we can identify when all stack data has been supplied.
            listStackData.StackChanged += new DExcExtractorListStackData.StackDataChangeHandler(StackDataChanged);
        }
 private void PrepareList(DExcExtractorList aList, params Regex[] aExpressions)
 {
     foreach (Regex exp in aExpressions)
     {
         DExcExtractorEntry entry = DExcExtractorEntry.NewMatchAndSave(exp);
         aList.AddExpression(entry);
     }
     //
     iLists.Add(aList.State, aList);
     iData.Add(aList);
 }