示例#1
0
 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();
 }
示例#2
0
 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"));
 }
示例#3
0
        /**
         * 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");
        }
示例#4
0
        /**
         * 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");
        }
示例#5
0
        /**
         * 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");
        }
示例#6
0
        /**
         * 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");
        }
示例#7
0
        /**
         * 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");
        }
示例#8
0
        /**
         * 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;
        }
示例#9
0
 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");
 }