/******************************************************************************* *** INSERT FUNCTION *** ******************************************************************************** *** DESCRIPTION: This function takes in a node and a string array. Goes and *** *** tests each element in the array using the CheckIfValid functions created *** *** below. If all are valid, each element is added to the node and inserted *** *** into the Symbol Table. *** ******************************************************************************** *** INPUT ARGS: Node root, string[] v *** *** OUTPUT ARGS: N/A *** *** IN/OUT ARGS: N/A *** *** RETURN: Node root *** ********************************************************************************/ public Node_Sym insert(Node_Sym root, string sym, string val, bool r) { PassTwo p2 = new PassTwo(); if (root == null) { bool MFlag = false; bool IFlag = true; root = new Node_Sym(); root.symbol = p2.TrimOp(sym); root.value = val; root.rflag = r; root.iflag = IFlag; root.mflag = MFlag; } else { if (sym == root.symbol) { Console.WriteLine(ERR_MSG_3, sym); root.mflag = true; return(root); } else if (sym.CompareTo(root.symbol) < 0) { root.left = insert(root.left, sym, val, r); } else { root.right = insert(root.right, sym, val, r); } } return(root); }
/******************************************************************************* *** INSERT FUNCTION *** ******************************************************************************** *** DESCRIPTION: This function takes in a node. It views the symbol table in *** *** order from left to right. *** ******************************************************************************** *** INPUT ARGS: Node root *** *** OUTPUT ARGS: N/A *** *** IN/OUT ARGS: N/A *** *** RETURN: null *** ********************************************************************************/ public Node_Sym view(Node_Sym root) { PassTwo p2 = new PassTwo(); if (root == null) { return(null); } else { view(root.left); if (root.symbol != null) { Console.WriteLine("{0,-10} {1,-10} {2,-10} {3,-10} {4,-10}", p2.TrimOp(root.symbol), root.value, (root.rflag == true) ? 1 : 0, (root.mflag == true) ? 1 : 0, (root.iflag == true) ? 1 : 0); } view(root.right); } return(null); }
/******************************************************************************* *** SEARCH FUNCTION *** ******************************************************************************** *** DESCRIPTION: This function takes in a node and a string. It checks to *** *** see if the passed in string is a valid symbol. It then tests to see if *** *** the passed in value exists in the symbol table. If not an error message *** *** is displayed informing the user. *** ******************************************************************************** *** INPUT ARGS: Node root, string v *** *** OUTPUT ARGS: N/A *** *** IN/OUT ARGS: N/A *** *** RETURN: Node root *** ********************************************************************************/ public Node_Sym search(Node_Sym root, string v) { PassTwo p2 = new PassTwo(); v = p2.TrimOp(v.ToUpper()); if (root == null) { return(null); } else if (v.CompareTo(root.symbol) < 0) { return(search(root.left, v)); } else if (v.CompareTo(root.symbol) > 0) { return(search(root.right, v)); } return(root); }
static void Main(string[] args) { Node_P1 p1 = new Node_P1(); Node_P2 p2 = new Node_P2(); OpCodes OpCodes = new OpCodes(); PassOne passOne = new PassOne(); PassTwo passTwo = new PassTwo(); Literal_Table LitTab = new Literal_Table(); Symbol_Table SymTab = new Symbol_Table(); List <Node_Op> op = new List <Node_Op>(); string opCodes = "OPCODES.DAT"; string srcProg; if (args.Length == 0) { Console.Write("Please Enter File Path for Source file --> "); srcProg = Console.ReadLine(); } else { srcProg = args[0]; } while (true) { if (!File.Exists(opCodes)) { Console.WriteLine("OPSCODE FILE: '{0}' does not exist...", opCodes); Console.Write("Please enter correct file path (Type 'x' to exit) --> "); opCodes = Console.ReadLine(); if (opCodes == "x") { break; } Console.WriteLine(); } else if (!File.Exists(srcProg)) { Console.WriteLine("SOURCE FILE: '{0}' does not exist...", srcProg); Console.Write("Please enter correct file path (Type 'x' to exit) --> "); srcProg = Console.ReadLine(); if (srcProg == "x") { break; } Console.WriteLine(); } else { string[] Codes = File.ReadAllLines(opCodes); string[] opLine; string file = string.Format(srcProg, ".tmp"); //Populate the Opcodes foreach (string code in Codes) { opLine = code.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); op.Add(OpCodes.insert(opLine)); } //PASS ONE p1 = passOne.PassUno(srcProg, op); //PASS ONE TO FILES string tmpFile1 = srcProg.Substring(0, srcProg.LastIndexOf(".")) + ".tmp"; File.WriteAllLines(tmpFile1, p1.prog); //PASS TWO p2 = passTwo.PassDuo(op, p1.table, p1.lit, tmpFile1); //PASS TWO TO FILES string tmpFile2 = srcProg.Substring(0, srcProg.LastIndexOf(".")) + ".txt"; File.WriteAllLines(tmpFile2, p2.prog); string tmpFile3 = srcProg.Substring(0, srcProg.LastIndexOf(".")) + ".o"; File.WriteAllLines(tmpFile3, p2.obj_prog); //PRINTS PASS 2 w/ Length Console.WriteLine("------------"); Console.WriteLine("PASS 2"); Console.WriteLine("------------"); foreach (string p in p2.prog) { Console.WriteLine(p); } Console.WriteLine("Program Length = {0}", p1.length); Console.WriteLine("Press enter to continue..."); Console.ReadLine(); //PRINTS OBJECT PROGRAM Console.WriteLine("------------------"); Console.WriteLine("OBJECT PROGRAM"); Console.WriteLine("------------------"); foreach (string o in p2.obj_prog) { Console.WriteLine(o); } Console.WriteLine("Press enter to continue..."); Console.ReadLine(); //PRINTS SYMBOL TABLE Console.WriteLine("---------------"); Console.WriteLine("SYMBOL TABLE"); Console.WriteLine("---------------"); Console.WriteLine("{0,-10} {1,-10} {2,-10} {3,-10} {4,-10}", "SYMBOL:", "VALUE:", "RFLAG:", "MFLAG:", "IFLAG:"); Console.WriteLine(new string('-', 50)); SymTab.view(p1.table); Console.WriteLine("Press enter to continue..."); Console.ReadLine(); //PRINTS LITERAL TABLE Console.WriteLine("-----------------"); Console.WriteLine("LITERAL TABEL"); Console.WriteLine("-----------------"); Console.WriteLine("{0,-10} {1,-10} {2,-10} {3,-10}", "NAME:", "VALUE:", "LENGTH:", "ADDRESS:"); Console.WriteLine(new string('-', 40)); LitTab.view(p1.lit); Console.WriteLine("Press enter to Complete Pass Two..."); break; } } Console.ReadLine(); }
/******************************************************************************* *** IFEXPRESSIONVALID FUNCTION *** ******************************************************************************** *** DESCRIPTION: This function takes in the symbol table and test the *** *** expression to make sure that it is a valid expression *** ******************************************************************************** *** INPUT ARGS: Node_Sym table, string ex *** *** OUTPUT ARGS: N/A *** *** IN/OUT ARGS: N/A *** *** RETURN: string ERR_MSG *** ********************************************************************************/ public string IfExpressionValid(Node_Sym table, string ex) { PassTwo p2 = new PassTwo(); Symbol_Table SymTab = new Symbol_Table(); Literal_Table litTab = new Literal_Table(); if (ex[0] == '@') { //Cant have Indirect and Indexing Addressing if (ex[ex.Length - 2] == ',' && ex[ex.Length - 1] == 'X') { return(ERR_MSG_7); } } //Trim expression from valid characters ex = ex.TrimStart('#', '@'); ex = ex.TrimEnd(',', 'X'); if (ex.Contains('+')) { if (!int.TryParse(ex, out int n)) { string[] newExp = ex.Split('+'); //Cannot have more than one operator if (newExp.Length > 2) { return(ERR_MSG_8); } //newExp[0] = p2.TrimOp(newExp[0]); //newExp[1] = p2.TrimOp(newExp[1]); //If both arn't symbols, then they have to both be numbers if (SymTab.search(table, newExp[0]) == null && SymTab.search(table, newExp[1]) == null) { if (!int.TryParse(newExp[0], out int val1)) { return(string.Format(ERR_MSG_2, ex)); } if (!int.TryParse(newExp[1], out int val2)) { return(string.Format(ERR_MSG_2, ex)); } } //If one is a symbol, then the other has to a number else if (SymTab.search(table, newExp[0]) != null && SymTab.search(table, newExp[1]) == null) { if (!int.TryParse(newExp[1], out int val1)) { return(string.Format(ERR_MSG_2, ex)); } } //If one is a symbol, then the other has to a number else if (SymTab.search(table, newExp[0]) == null && SymTab.search(table, newExp[1]) != null) { if (!int.TryParse(newExp[0], out int val1)) { return(string.Format(ERR_MSG_2, ex)); } } //If they are both symbols, they cannot both be relative else { if (!SymTab.search(table, newExp[0]).rflag&& !SymTab.search(table, newExp[1]).rflag) { return(ERR_MSG_5); } } } } else if (ex.Contains('-')) { //Check if just a negative number if (!int.TryParse(ex, out int n)) { string[] newExp = ex.Split('-'); //Cannot contain more than one operand if (newExp.Length > 2) { return(ERR_MSG_8); } //If both are not symbols, they both must be numbers if (SymTab.search(table, newExp[0]) == null && SymTab.search(table, newExp[1]) == null) { if (!int.TryParse(newExp[0], out int val1)) { return(string.Format(ERR_MSG_2, ex)); } if (!int.TryParse(newExp[1], out int val2)) { return(string.Format(ERR_MSG_2, ex)); } } //If one is a symbol, the other must be a number else if (SymTab.search(table, newExp[0]) != null && SymTab.search(table, newExp[1]) == null) { if (!int.TryParse(newExp[1], out int val2)) { return(string.Format(ERR_MSG_2, ex)); } } //If one is a symbol, the other must be a number else if (SymTab.search(table, newExp[0]) == null && SymTab.search(table, newExp[1]) != null) { if (!int.TryParse(newExp[1], out int val2)) { return(string.Format(ERR_MSG_2, ex)); } else if (SymTab.search(table, newExp[1]).rflag) { return(ERR_MSG_6); } } //If both are found, then both should have rflags, and you cannot sub a rel with abs else if (SymTab.search(table, newExp[0]) != null && SymTab.search(table, newExp[1]) != null) { if (!SymTab.search(table, newExp[0]).rflag&& SymTab.search(table, newExp[1]).rflag) { return(ERR_MSG_6); } } } } //If there is no expression, see if a symbol, if not a symbol, then a number else if (SymTab.search(table, ex) == null) { foreach (char x in ex) { if (!Char.IsDigit(x)) { return(string.Format(ERR_MSG_4, ex)); } } } return(null); }
/******************************************************************************* *** PASSUNO function *** ******************************************************************************** *** DESCRIPTION: This Pass 1 funciton takes in information from the file *** *** passed in. In the file contains assembly instructions and pass one *** *** produces line numbers and load counters. Pass 1 also stores the labels *** *** as symbols and also store literals in the literal table. *** ******************************************************************************** *** INPUT ARGS: string program, List<Node_Op> OpCodes *** *** OUTPUT ARGS: N/A *** *** IN/OUT ARGS: N/A *** *** RETURN: Node_P1 p1 *** ********************************************************************************/ public Node_P1 PassUno(string program, List <Node_Op> OpCodes) { Node_P1 passOne = new Node_P1(); PassTwo p2 = new PassTwo(); List <string> theFile = new List <string>(); List <int> valLits = new List <int>(); OpCodes opCode = new OpCodes(); Symbol_Table SymTab = new Symbol_Table(); Expressions Exp = new Expressions(); Literal_Table LitTable = new Literal_Table(); Node_Lit lit = new Node_Lit(); Node_Sym table = new Node_Sym(); Node_Op op = new Node_Op(); Node_Exp ex = new Node_Exp(); List <string> Literals = new List <string>(); string[] Prog = File.ReadAllLines(program); string[] splitLine; string str_Count = null; string tmpCounter = null; string label = null; string operation = null; string operand = null; int l = 0; string Counter = "00000"; string EquCount = null; string tmpStr; int val; int tmp; bool r = true; foreach (string line in Prog) { //HANDLE IF EMPTY LINE if (line != null) { //COMMMENT HANDLING if (line[0] != '.') { tmpStr = line; //SPLITS THE LINE splitLine = tmpStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); //SETS LABEL if (splitLine.Length >= 3) { label = splitLine[0].ToUpper(); splitLine = splitLine.Where(w => w != splitLine[0]).ToArray(); } else { tmpStr = splitLine[0]; if (tmpStr[0] != '+' && opCode.search(OpCodes, tmpStr) == null && tmpStr != "BASE" && tmpStr != "BYTE" && tmpStr != "END" && tmpStr != "EQU" && tmpStr != "EXTDEF" && tmpStr != "EXTREF" && tmpStr != "RESB" && tmpStr != "RESW" && tmpStr != "START" && tmpStr != "WORD") { label = splitLine[0].ToUpper(); splitLine = splitLine.Where(w => w != splitLine[0]).ToArray(); } } //SETS OPERTATION operation = splitLine[0].ToUpper(); //SETS OPERAND if (splitLine.Length > 1) { operand = splitLine[1]; } //SETS LINE NUMBER l++; if (operation != "EQU") { tmpCounter = Counter; } //IF START, THEN START; IF NOT END, THEN DO STUFF if (operation == "START") { Counter = operand.PadLeft(5, '0'); str_Count = Counter; } else if (operation != "END") { //FORMAT 4 CHECK if (operation[0] != '+') { op = opCode.search(OpCodes, operation); } else { tmpStr = operation.TrimStart('+'); op = opCode.search(OpCodes, tmpStr); op.format = "4"; } if (op == null) { if (operation == "WORD") { val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + 3; Counter = val.ToString("X").PadLeft(5, '0'); } else if (operation == "RESW") { if (int.TryParse(operand, out tmp)) { val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + (tmp * 3); Counter = val.ToString("X").PadLeft(5, '0'); } } else if (operation == "RESB") { if (int.TryParse(operand, out tmp)) { val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + tmp; Counter = val.ToString("X").PadLeft(5, '0'); } } else if (operation == "BYTE") { tmpStr = operand; if (tmpStr[0] == 'C') { tmpStr = tmpStr.TrimStart('C', '\''); tmpStr = tmpStr.TrimEnd('\''); tmp = tmpStr.Length; } else { tmpStr = tmpStr.TrimStart('X', '\''); tmpStr = tmpStr.TrimEnd('\''); tmp = tmpStr.Length / 2; } val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + tmp; Counter = val.ToString("X").PadLeft(5, '0'); } else if (operation == "BASE") { } else if (operation == "EQU") { if (operand == "*") { EquCount = Counter; } //IF OPERAND IS A DECIMAL VALUE else if (int.TryParse(operand, out tmp)) { EquCount = tmp.ToString("X").PadLeft(5, '0'); r = false; } //IF OPERAND IS AN EXPRESSION else { ex = Exp.insert(table, operand); if (int.TryParse(ex.value, out tmp)) { EquCount = tmp.ToString("X").PadLeft(5, '0'); r = ex.relocatable; } } } else if (operation == "EXTDEF") { r = false; } else if (operation == "EXTREF") { r = false; } } else { if (operation[0] != '+') { if (int.TryParse(op.format, out tmp)) { val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + tmp; Counter = val.ToString("X").PadLeft(5, '0'); } } else { val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + 4; Counter = val.ToString("X").PadLeft(5, '0'); } } } if (operand != null) { if (operand[0] == '=') { Literals.Add(operand); } } if (EquCount == null) { theFile.Add(string.Format("{0,-4} {1,-10} {2,-10} {3,-10} {4,-15}", l, tmpCounter, label, operation, operand)); if (label != null) { table = SymTab.insert(table, label, tmpCounter, r); } } else { theFile.Add(string.Format("{0,-4} {1,-10} {2,-10} {3,-10} {4,-15}", l, EquCount, label, operation, operand)); if (label != null) { table = SymTab.insert(table, label, EquCount, r); } } EquCount = null; r = true; label = null; operand = null; } } } if (Literals != null) { foreach (string oper in Literals) { l++; tmpCounter = Counter; lit = LitTable.insert(lit, oper, Counter); val = int.Parse(Counter, System.Globalization.NumberStyles.HexNumber) + lit.length; Counter = val.ToString("X").PadLeft(5, '0'); valLits.Add(lit.length); theFile.Add(string.Format("{0,-4} {1,-10} {2,-10} {3,-10} {4,-15}", l, tmpCounter, "*", oper, "")); } } passOne.length = p2.SubHex(Counter, str_Count); theFile.Add(passOne.length); passOne.table = table; passOne.lit = lit; passOne.prog = theFile; return(passOne); }