/// <summary>
        /// Populates an existing symbol table with symbols parsed from the desired segment.
        /// </summary>
        /// <param name="reader">A StreamReader instance that will read the input assembly file.</param>
        /// <param name="desiredSegment">The program segment to parse symbols from.</param>
        /// <param name="symTable">The SymbolTable instance to populate.</param>
        public void GenerateSymbolTableForSegment(StreamReader reader, SegmentType desiredSegment, SymbolTable symTable)
        {
            SegmentType currSegmentType = SegmentType.Invalid;
            int         currAlignment   = CommonConstants.DEFAULT_ALIGNMENT;

            // a list of all exceptions we encounter during parsing.
            // users can view them all at once instead of working through them piecemeal.
            var exceptionList = new List <AssemblyException>();
            int lineNum       = 0;

            while (!reader.EndOfStream)
            {
                try
                {
                    ++lineNum;
                    // trim the whitespace from any read-in line.
                    string line = reader.ReadLine().Trim();

                    // get a substring up until the commented line, ignoring those in user quotes.
                    line = ParserCommon.GetSanitizedString(line);

                    // ignore blank lines. trim should remove all whitespace
                    try
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            LineParseResults directiveResults = ParserCommon.HandleAssemblerDirective(line, lineNum, currSegmentType, currAlignment);
                            currAlignment   = directiveResults.NewAlignment;
                            currSegmentType = directiveResults.NewSegment;

                            // further processing is needed, and the current segment type is the desired segment type.
                            if (!directiveResults.IsLineAssemblerDirective &&
                                currSegmentType == desiredSegment)
                            {
                                if (!TryHandlingLinkageDeclaration(line, lineNum, currSegmentType, symTable))
                                {
                                    ISymbolTableBuilder segParser = m_SymbolBuilderFac.GetParserForSegment(lineNum, currSegmentType);
                                    var asmLine = new LineData(line, lineNum);
                                    segParser.ParseSymbolsInLine(asmLine, symTable, currAlignment);
                                }
                            }
                        }
                    }
                    catch (AssemblyException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        throw new AssemblyException(lineNum, ex.Message);
                    }
                }
                catch (AssemblyException ex)
                {
                    exceptionList.Add(ex);
                }
            }

            // if any exceptions were encountered, throw an aggregate exception with
            // all of the encountered exceptions.
            if (exceptionList.Any())
            {
                throw new AggregateAssemblyError(exceptionList);
            }

            // reset the StreamReader to the beginning position.
            reader.Seek(0, SeekOrigin.Begin);
        }
        /// <summary>
        /// Generates code for the given assembly file.
        /// </summary>
        /// <param name="reader">A StreamReader instance that will read the input assembly file.</param>
        /// <param name="objFile">The basic object file that will be written to.</param>
        public void GenerateCode(string fileName, StreamReader reader, BasicObjectFile objFile)
        {
            SegmentType currSegmentType = SegmentType.Invalid;
            int         currAlignment   = CommonConstants.DEFAULT_ALIGNMENT;

            // a list of all exceptions we encounter during parsing.
            // users can view them all at once instead of working through them piecemeal.
            var exceptionList = new List <AssemblyException>();
            int lineNum       = 0;

            while (!reader.EndOfStream)
            {
                try
                {
                    ++lineNum;
                    // trim the whitespace from any read-in line.
                    string line = reader.ReadLine().Trim();

                    // get a substring up until the commented line, ignoring those in user quotes.
                    line = ParserCommon.GetSanitizedString(line);

                    // ignore blank lines. trim should remove all whitespace
                    if (line.Any())
                    {
                        LineParseResults directiveResults = ParserCommon.HandleAssemblerDirective(line, lineNum, currSegmentType, currAlignment);

                        // if we have a new data alignment, we need to record this in case the disassembler
                        // parses this file. otherwise, it will interpret padding bytes as actual data elements.
                        if (currAlignment != directiveResults.NewAlignment)
                        {
                            objFile.AddAlignmentChangeDeclaration(directiveResults.NewAlignment);
                        }

                        currAlignment   = directiveResults.NewAlignment;
                        currSegmentType = directiveResults.NewSegment;

                        // if our segment type is valid, then we're processing actual data versus an assembler directive.
                        if (!directiveResults.IsLineAssemblerDirective &&
                            currSegmentType != SegmentType.Invalid)
                        {
                            if (!TryHandlingLinkageDeclaration(line, lineNum, objFile))
                            {
                                ISegmentCodeGenerator codeGen = m_CodeGenFac.GetCodeGeneratorForSegment(currSegmentType);
                                var asmLine = new LineData(line, lineNum);
                                try
                                {
                                    codeGen.GenerateCodeForSegment(fileName, asmLine, objFile, currAlignment);
                                }
                                catch (AssemblyException)
                                {
                                    throw;
                                }
                                catch (Exception ex)
                                {
                                    throw new AssemblyException(lineNum, ex.Message);
                                }
                            }
                        }
                    }
                }
                catch (AssemblyException ex)
                {
                    exceptionList.Add(ex);
                }
            }

            // if any exceptions were encountered, throw an aggregate exception with
            // all of the encountered exceptions.
            if (exceptionList.Any())
            {
                throw new AggregateAssemblyError(exceptionList);
            }

            // reset the StreamReader to the beginning position.
            reader.Seek(0, SeekOrigin.Begin);
        }