public void DuplicateSymbol() { var t = new SymbolTable(); try { t.AddSymbol("one", "0", Usage.ENTRY, ""); t.AddSymbol("one", "0", Usage.ENTRY, ""); } catch (SymbolException) { return; } Assert.Fail(); }
public void AddSymbolStruct() { var t = new SymbolTable(); Symbol sym; sym.rlabel = "test"; sym.lc = "5"; sym.usage = Usage.EQUATED; sym.val = "DERP"; sym.relocations = 0; t.AddSymbol(sym); Assert.AreEqual(sym, t.GetSymbol("test")); }
/** * Parses the start directive, properly assigning the operand of start as the * starting location counter. * * @param interLine the intermediate line to process * @param symb symbol table reference * * @refcode D1 * @errtest * N/A * @errmsg EF.06 * @author Mark Mathis * @creation April 9, 2011 * @modlog * - April 9, 2011 - Mark - Parses the START directive, correctly setting the LC. * - April 14, 2011 - Mark - Moved into DirectiveParser class. * - April 17, 2011 - Mark - Catches errors in the start directive. * - April 19, 2011 - Mark - Reports errors. * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private static void ParseStart(ref IntermediateLine interLine, ref SymbolTable symb) { Logger.Log("Parsing START directive", "DirectiveParser"); // this should only happen if the directive is found on the first line if (interLine.SourceLineNumber == 1) { // expecting operand to be the value of the location counter // check to see if operand is valid start value int startLC; if (interLine.DirectiveLitOperand == OperandParser.Literal.NUMBER) { string startOper = BinaryHelper.HexToInt(interLine.DirectiveOperand, 32).ToString(); if (int.TryParse(startOper, out startLC)) { if (0 <= startLC && startLC <= 1023) { Parser.LC = interLine.DirectiveOperand; } } else { /* * The operand could not be parsed as a number. * This is here as well as below just in case the * Tokenizer has a hiccough and says that something * that is not a number is a number. */ Logger.Log("ERROR: EF.06 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Fatal, 6); return; } // update the symbol in the symbol table Symbol start = symb.RemoveSymbol(interLine.Label); start.usage = Usage.PRGMNAME; start.lc = null; symb.AddSymbol(start); } else { // the operand could not be parsed as a number Logger.Log("ERROR: EF.06 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Fatal, 6); return; } } else { // not the first line of the source code. symb.RemoveSymbol(interLine.Label); Logger.Log("ERROR: ES.35 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 35); return; } Logger.Log("Finished parsing START directive", "DirectiveParser"); }
/** * Parses the extrn directive, ensuring that operand is correct. * * @param interLine the intermediate line to process * @param symb symbol table reference * * @refcode D6 * @errtest * N/A * @errmsg ES.13, EW.05 * @author Mark Mathis * @creation April 17, 2011 * @modlog * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private static void ParseExtrn(ref IntermediateLine interLine, ref SymbolTable symb) { Logger.Log("Parsing EXTRN directive", "DirectiveParser"); //check for label if (interLine.Label != null) { // extrn doesn't expect a label Logger.Log("ERROR: EW.05 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Warning, 5); } if (!symb.ContainsSymbol(interLine.DirectiveOperand)) { symb.AddSymbol(interLine.DirectiveOperand, null, Usage.EXTERNAL); } else { // cannot used variables defined in this program Logger.Log("ERROR: ES.13 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 13); } Logger.Log("Finished parsing EXTRN directive", "DirectiveParser"); }
/** * Parses the equ directive, ensuring that the operand is a valid value for an * equated symbol. * * @param interLine the intermediate line to process * @param symb symbol table reference * @param maxOp maximum number of operations to process * * @refcode D3 * @errtest * N/A * @errmsg ES.21, ES.22, ES.26 * @author Mark Mathis * @creation April 15, 2011 * @modlog * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private static void ParseEqu(ref IntermediateLine interLine, ref SymbolTable symb, int maxOp = 1) { Logger.Log("Parsing EQU directive", "DirectiveParser"); bool success = true; if (symb.ContainsSymbol(interLine.Label)) { Symbol equSym = symb.RemoveSymbol(interLine.Label); interLine.ProgramCounter = equSym.lc; if (interLine.DirectiveLitOperand == OperandParser.Literal.NUMBER) { // check that number is in bounds int num = BinaryHelper.HexToInt(interLine.DirectiveOperand, 10); if (0 <= num && num <= 1023) { equSym.usage = Usage.EQUATED; equSym.val = interLine.DirectiveOperand; } else { // error: out of bounds Logger.Log("ERROR: ES.26 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 26); success = false; } } else if (symb.ContainsSymbol(interLine.DirectiveOperand) && symb.GetSymbol(interLine.DirectiveOperand).usage == Usage.EQUATED) { // do stuff with the symbol equSym.usage = Usage.EQUATED; equSym.val = symb.GetSymbol(interLine.DirectiveOperand).val; equSym.relocations = symb.GetSymbol(interLine.DirectiveOperand).relocations; } else if (interLine.DirectiveLitOperand == OperandParser.Literal.EXPRESSION) { string oper = interLine.DirectiveOperand; int modifications; success = OperandParser.ParseExpression(ref oper, OperandParser.Expressions.EQU, interLine, ref symb, new ModificationRecord("junk"), out modifications, maxOp); equSym.usage = Usage.EQUATED; equSym.val = oper; equSym.relocations = modifications; } else { // error: invalid operand for equ Logger.Log("ERROR: EW.21 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 21); success = false; } interLine.ProgramCounter = null; equSym.lc = null; if (success) { // this needs to be checked here in case ParseExpression // finds an error int finval = Convert.ToInt32(equSym.val, 16); if (!(0 <= finval && finval <= 1023)) { // the final value of the equ is out of bounds Logger.Log("ERROR: EW.22 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 22); success = false; } symb.AddSymbol(equSym); } } Logger.Log("Finished parsing EQU directive", "DirectiveParser"); }
/** * Parses the entry directive, ensuring that the operand is a valid value * for an equated symbol using extended expressions. * * @param interLine the intermediate line to process * @param symb symbol table reference * * @refcode D5 * @errtest * N/A * @errmsg EW.05 * @author Mark Mathis * @creation April 17, 2011 * @modlog * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private static void ParseEntry(ref IntermediateLine interLine, ref SymbolTable symb) { Logger.Log("Parsing ENTRY directive", "DirectiveParser"); // check for a label if (interLine.Label != null) { // entry doesn't expect a label Logger.Log("ERROR: EW.05 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Warning, 5); } if (symb.ContainsSymbol(interLine.DirectiveOperand)) { if (symb.GetSymbol(interLine.DirectiveOperand).usage != Usage.EQUATED) { Symbol tempsym = symb.RemoveSymbol(interLine.DirectiveOperand); tempsym.usage = Usage.ENTRY; symb.AddSymbol(tempsym); } } else { symb.AddSymbol(interLine.DirectiveOperand, null, Usage.ENTRY); } Logger.Log("Finished parsing ENTRY directive", "DirectiveParser"); }
/** * Parses the dat directive, ensuring that the operand has proper syntax * and is correctly assigned to the current word of memory. * * @param interLine the intermediate line to process * @param symb symbol table reference * * @refcode D8 * @errtest * N/A * @errmsg ES.14 * @author Mark Mathis * @creation April 18, 2011 * @modlog * - April 19, 2011 - Jacob - Fixed padding on values. * - April 24, 2011 - Mark - Commented out the part that put the value of the dat * into the symbol table until that can be made clearer * by Al. * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private static void ParseDat(ref IntermediateLine interLine, ref SymbolTable symb) { Logger.Log("Parsing DAT directive", "DirectiveParser"); if (interLine.DirectiveLitOperand != OperandParser.Literal.NONE && interLine.DirectiveLitOperand != OperandParser.Literal.EXPRESSION && interLine.DirectiveLitOperand != OperandParser.Literal.NUMBER && interLine.DirectiveLitOperand != OperandParser.Literal.UNKNOWN) { if (interLine.Label != null) { if (!symb.ContainsSymbol(interLine.Label)) { symb.AddSymbol(interLine.Label, Parser.LC, Usage.LABEL); //,interLine.DirectiveOperand); } else { Symbol datSym = symb.RemoveSymbol(interLine.Label); datSym.lc = Parser.LC; //datSym.val = interLine.DirectiveOperand; symb.AddSymbol(datSym); } } string val = Convert.ToString(Convert.ToInt32(interLine.DirectiveOperand, 16), 2); // assumed to be in correct representation; always pad to the left interLine.Bytecode = val.PadLeft(16, '0'); } else if (interLine.DirectiveLitOperand == OperandParser.Literal.UNKNOWN) { // error: literal operand in improper format interLine.AddError(Errors.Category.Serious, 37); } else { // error: invalid operand type Logger.Log("ERROR: ES.14 encountered", "DirectiveParser"); interLine.AddError(Errors.Category.Serious, 14); interLine.NOPificate(); } // this should need to happen no matter what interLine.ProgramCounter = Parser.LC; Parser.IncrementLocationCounter(); Logger.Log("Finished parsing DAT directive", "DirectiveParser"); }
/** * Parses a single line of source code. * * @param line current line to parse * @param lineNum line number of current line * @param symb symbol table reference * @return the line to be parsed as a single line in the intermediate file * * @refcode N/A * @errtest * N/A * @errmsg * N/A * @author Mark Mathis * @creation April 8, 2011 * @modlog * - April 9, 2011 - Mark - ParseLine parses lines with instructions. * - April 9, 2011 - Mark - ParseLine parses lines with directives. * - April 9, 2011 - Mark - Increments program counter after parsing instructions. * - April 9, 2011 - Mark - Sets OpCategory = "_ERROR" if the token expected to be * an instruction category or a directive is niether of those. * - April 10, 2011 - Mark - Properly handles lines that only have a comment. * @teststandard Andrew Buelow * @codestandard Mark Mathis */ private IntermediateLine ParseLine(string line, short lineNum, ref SymbolTable symb) { Logger.Log("Parsing line " + lineNum, "Parser"); string token = ""; Tokenizer.TokenKinds tokenKind = Tokenizer.TokenKinds.Empty; // make Intermediate version of this line to be returned IntermediateLine interLine = new IntermediateLine(line, lineNum); // check for a label at the beginning of the line if (line.Trim().Length > 0) { if (char.IsLetter(line[0])) { Logger.Log(String.Format("Line {0} has a label, parsing label", lineNum), "Parser"); Tokenizer.GetNextToken(ref line, out token, out tokenKind); if (tokenKind == Tokenizer.TokenKinds.Label_Or_Command && (2 <= token.Length && token.Length <= 32)) { interLine.Label = token; if (symb.ContainsSymbol(token)) { if (symb.GetSymbol(token).usage != Usage.ENTRY) { // error: cannot redefine symbol interLine.AddError(Errors.Category.Warning, 4); } } else { // the symbol is not defined, define it symb.AddSymbol(token, LC, Usage.LABEL); } } else { interLine.Label = "_ERROR"; interLine.AddError(Errors.Category.Serious, 2); } } else if (!char.IsWhiteSpace(line[0]) && line[0] != ':') { // invalid label start interLine.Label = "_ERROR"; interLine.AddError(Errors.Category.Serious, 2); } } // Get the next token, which will specify whether or not the line has a // directive or an instruction. Tokenizer.GetNextToken(ref line, out token, out tokenKind); if (tokenKind == Tokenizer.TokenKinds.Label_Or_Command) { // coerce into uppercase token = token.ToUpper(); // instruction if (instructionList.IsGroup(token)) { interLine.OpCategory = token; ParseInstruction(ref line, ref interLine, ref symb); interLine.ProgramCounter = LC; IncrementLocationCounter(); } // directive else if (directiveList.Contains(token)) { interLine.Directive = token; DirectiveParser.ParseDirective(ref line, ref interLine, ref symb); } else { // bad category, but don't NOP interLine.OpCategory = "_ERROR"; interLine.AddError(Errors.Category.Serious, 1); return interLine; } } else if (tokenKind == Tokenizer.TokenKinds.Comment) { interLine.Comment = token; return interLine; } else if (tokenKind != Tokenizer.TokenKinds.Empty) { // garbage data interLine.AddError(Errors.Category.Serious, 18); return interLine; } // If there's anything else, get it. If there's anything there, // it should be a comment. Tokenizer.GetNextToken(ref line, out token, out tokenKind); if (tokenKind == Tokenizer.TokenKinds.Comment) { interLine.Comment = token; } else if (tokenKind != Tokenizer.TokenKinds.Empty) { // error: invalid input after the operand Logger.Log("ERROR: EW.6 encountered", "Parser"); interLine.AddError(Errors.Category.Warning, 6); } // process this line if it's an instruction if (interLine.OpCategory != null) { interLine.ProcessLine(ref symb); } Logger.Log("Finished parsing line " + lineNum, "Parser"); return interLine; }
public void Sorting() { var t = new SymbolTable(); t.AddSymbol("apple", "5", Usage.EQUATED, "derp"); t.AddSymbol("pear", "20", Usage.ENTRY, ""); t.AddSymbol("orange", "42", Usage.ENTRY, ""); var l = t.SortedSymbols(); Assert.AreEqual(l[0], "apple"); Assert.AreEqual(l[1], "orange"); Assert.AreEqual(l[2], "pear"); }