/// <summary> /// Retrieves a segment parser implementation for a specific segment type. /// </summary> /// <param name="lineNum">The line number that is currently being parsed. Displayed if an error occurs.</param> /// <param name="segType">The segment type to retrieve a parser for.</param> /// <returns>An appropriate segment parser for the given segment. If one cannot be found, this throws an AssemblyException.</returns> public ISymbolTableBuilder GetParserForSegment(int lineNum, SegmentType segType) { ISymbolTableBuilder parser = null; if (!m_ParserTable.TryGetValue(segType, out parser)) { throw new AssemblyException(lineNum, "Could not retrieve segment parser for segment type: " + segType); } return(parser); }
/// <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); }