static SymbolBase ParseLocField(string locField, ParsingStatus status) { if (locField == "") { return(null); } status.LineSection = LineSection.LocationField; var symbol = ValueSymbol.ParseDefinition(locField, 0, status); if (symbol == null) { status.ReportParsingError(0, locField.Length, "invalid symbol name"); return(null); } if (status.Symbols.Contains(symbol)) { symbol = status.Symbols[symbol.Name]; if (symbol.IsSymbolDefined && !symbol.IsMultiValuedSymbol) { status.ReportParsingError(0, locField.Length, "symbol already defined"); return(null); } return(symbol); } status.Symbols.Add(symbol); return(symbol); }
/// <summary> /// This method is used to handle instructions targeted at the assembler itself. /// </summary> static bool HandleAssemblyInstruction(string opField, string addressField, SymbolBase symbol, ParsingStatus status) { IValue expression; status.LineSection = LineSection.AddressField; switch (opField) { case "EQU": // set value of the instruction symbol (first field) to the value of the expression that is in the address field if (symbol != null) { expression = WValue.ParseValue(addressField, 0, status); if (!expression.IsValueDefined(status.LocationCounter)) { status.ReportParsingError(0, addressField.Length, "expression value is undefined"); return(true); } symbol.SetValue(expression.GetSign(status.LocationCounter), expression.GetMagnitude(status.LocationCounter)); } return(true); case "ORIG": // set the location counter to the value of the expression that is in the address field expression = WValue.ParseValue(addressField, 0, status); if (!expression.IsValueDefined(status.LocationCounter)) { status.ReportParsingError(0, addressField.Length, "expression value is undefined"); return(true); } status.LocationCounter = (int)expression.GetValue(status.LocationCounter); return(true); case "CON": case "ALF": // these instructions set the value of the memory word at the location counter, which is actually a loader instruction. // However, during assembly these memory words must be skipped, which is why we increase the location counter. status.LocationCounter++; return(true); } return(false); }
static ParsedSourceLine ParseLine(string sourceLine, ParsingStatus status) { if (IsCommentLine(sourceLine)) { return(new ParsedSourceLine(status.LineNumber, sourceLine)); } var lineFields = SplitLine(sourceLine); lineFields[locFieldIndex] = lineFields[locFieldIndex].ToUpper(); lineFields[opFieldIndex] = lineFields[opFieldIndex].ToUpper(); lineFields[addressFieldIndex] = lineFields[addressFieldIndex].ToUpper(); if (lineFields[opFieldIndex] == "") { status.ReportParsingError(LineSection.LocationField, 0, sourceLine.Length, "op and address fields are missing"); return(new ParsedSourceLine(status.LineNumber, lineFields[0], "", "", "", null, null)); } var symbol = ParseLocField(lineFields[locFieldIndex], status); // if the location field contains a symbol name, set its value to the location counter symbol?.SetValue(status.LocationCounter); GetMixOrLoaderInstructionAndParameters(lineFields[opFieldIndex], lineFields[addressFieldIndex], status, out InstructionBase instruction, out IInstructionParameters instructionParameters); // the following call must be made even if a MIX or loader instruction was found, as some loader instructions require the assembler to act, as well var assemblyInstructionHandled = HandleAssemblyInstruction(lineFields[opFieldIndex], lineFields[addressFieldIndex], symbol, status); // if the line isn't a comment or a MIX or loader instruction, it must be an assembler instruction. If not, we don't know the mnemonic if (instruction == null && !assemblyInstructionHandled) { status.ReportParsingError(LineSection.OpField, 0, lineFields[opFieldIndex].Length, "operation mnemonic unknown"); } return(new ParsedSourceLine(status.LineNumber, lineFields[locFieldIndex], lineFields[opFieldIndex], lineFields[addressFieldIndex], lineFields[commentFieldIndex], instruction, instructionParameters)); }