示例#1
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"));
 }
示例#2
0
 public void NonexistingSymbol()
 {
     var t = new SymbolTable();
     try
     {
         t.GetSymbol("herp");
     } catch (SymbolException)
     {
         return;
     }
     Assert.Fail();
 }
示例#3
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();
 }
示例#4
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");
        }
示例#5
0
        /**
         * Parses the end directive, ensuring that the end operand is the same as
         * the start directive's rlabel.
         *
         * @param interLine the intermediate line to process
         * @param symb symbol table reference
         *
         * @refcode D7
         * @errtest
         *  N/A
         * @errmsg EF.05, EW.05
         * @author Mark Mathis
         * @creation April 9, 2011
         * @modlog
         *  - April  9, 2011 - Mark - Not sure if needed.
         *  - April 14, 2011 - Mark - Moved into DirectiveParser class.
         *  - April 17, 2011 - Mark - Actually checks that the operand is correct.
         *  - April 19, 2011 - Mark - Reports errors.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private static void ParseEnd(ref IntermediateLine interLine, ref SymbolTable symb)
        {
            Logger.Log("Parsing END directive", "DirectiveParser");

            // check to see if this line has a label
            if (interLine.Label != null)
            {
                // the end directive should not have a label
                interLine.AddError(Errors.Category.Warning, 5);
            }

            // check to see if the operand of the END directive matches the program name

            if (!(symb.ContainsSymbol(interLine.DirectiveOperand) &&
                symb.GetSymbol(interLine.DirectiveOperand).usage == Usage.PRGMNAME))
            {
                // error things
                interLine.AddError(Errors.Category.Fatal, 5);
            }

            Logger.Log("Finished parsing END directive.", "DirectiveParser");
        }
示例#6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Assembler"/> class.
 /// </summary>
 /// <param name="input">The input.</param>
 public Assembler(string input)
 {
     this.InputFilePath = input;
     this.SymbolTable = new SymbolTable();
 }
示例#7
0
        /**
         * Parse an operand and fill the intermediate line with found data.
         *
         * @param line the line (string) to parse
         * @param interLine the intermediate line object to fill
         * @param symb symbol table reference
         * @param bits number of bits to pad to, if applicable
         * @refcode S2.4
         * @errtest
         * @errmsg ES.15
         * @author Mark Mathis
         * @creation April 10, 2011
         * @modlog
         *  - April 18, 2011 - Jacob - Catch exceptions on parsing issues.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public static void ParseOperand(ref string line, ref IntermediateLine interLine, ref SymbolTable symb, int bits)
        {
            // get the next token
            string token;
            Tokenizer.TokenKinds tokenKind;
            Tokenizer.GetNextToken(ref line, out token, out tokenKind);

            Logger.Log("Parsing operand " + token + " of kind " + tokenKind.ToString(), "OperandParser");

            string operand = null;
            Literal litOperand = Literal.NONE;

            try {
                // if it's a label, then just set the token directly
                if (tokenKind == Tokenizer.TokenKinds.Label_Or_Command)
                {
                    litOperand = Literal.NONE;
                    operand = token;
                }
                // if it's a number, convert to hex and store
                else if (tokenKind == Tokenizer.TokenKinds.Number)
                {
                    litOperand = Literal.NUMBER;
                    int op = Convert.ToInt32(token);
                    op = BinaryHelper.ConvertNumber(op, bits);
                    operand = Convert.ToString(op, 16).ToUpper();
                }
                // do further processing for literals
                else if (tokenKind == Tokenizer.TokenKinds.Literal)
                {
                    ParseLiteralOperand(token, out operand, out litOperand, bits);
                }
                // the operand is an expression
                else if (tokenKind == Tokenizer.TokenKinds.Expression)
                {
                    // check that it's valid
                    operand = token;
                    litOperand = Literal.EXPRESSION;
                }
                // anything else is invalid
                else
                {
                    litOperand = Literal.NONE;
                    operand = "_ERROR";
                    interLine.AddError(Errors.Category.Serious, 15);
                }
            }
            catch (Exception)
            {
                litOperand = Literal.NONE;
                operand = "_ERROR";
                interLine.AddError(Errors.Category.Serious, 15);
            }

            // assign the directive fields if it's a directive
            if (interLine.Directive != null)
            {
                interLine.DirectiveOperand = operand;
                interLine.DirectiveLitOperand = litOperand;
            }
            // otherwise fill the default operands
            else
            {
                interLine.OpOperand = operand;
                interLine.OpLitOperand = litOperand;
            }
        }
示例#8
0
        /**
         * Drives the Assembler.
         *
         * @param args program runtime arguments
         *
         * @refcode N/A
         * @errtest
         *  Differing program arguments.
         * @errmsg
         *  - Incorrect number of arguments.
         *  - Usage information
         * @author Mark
         * @creation April 5, 2011
         * @modlog
         *  - April  6, 2011 - Mark - Initializes Logger.
         *  - April  8, 2011 - Mark - Reads files in from the command line.
         *  - April  8, 2011 - Mark - Initializes and uses a Parser object.
         *  - April  8, 2011 - Mark - Outputs results to screen.
         *  - April  9, 2011 - Mark - Uses an IntermediateFile object.
         *  - April  9, 2011 - Mark - Catches problem with improper number of arguments.
         *  - April 10, 2011 - Mark - Uses a SymbolTable object.
         *  - May    8, 2011 - Jacob - Only process one file.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public static void Main(string[] args)
        {
            string infile = null;
            string outfile = null;

            // single arg given, output to stdout
            if (args.Length == 1)
            {
                infile = args[0];
                outfile = System.IO.Path.GetFileNameWithoutExtension(args[0]) + ".obj";
            }
            // two args given, read in the first and output to the second
            else if (args.Length == 2)
            {
                infile = args[0];
                outfile = args[1];
            }
            // invalid; print usage
            else
            {
                Usage();
                System.Environment.Exit(1);
            }

            Errors.SetResource(Properties.Resources.errors);

            // pass 1
            Logger.Log("Starting up", "Main");
            SymbolTable symb = new SymbolTable();
            Parser pars = new Parser();
            IntermediateFile interSource;
            pars.ParseSource(infile, out interSource, out symb);

            bool fatalerr = false;
            AssemblyReport report = new AssemblyReport();

            // Checking for fatal errors and creating an Assembly Report to display if a fatal error is found.
            foreach (IntermediateLine line in interSource)
            {
                if (line.Fatal)
                {
                    fatalerr = true;
                }

                report.Add(line.ProgramCounter, "0000", ' ', line.SourceLineNumber, line.SourceLine, line.GetThreeErrors());
            }

            if (fatalerr)
            {
                // Output the report
                Console.WriteLine(report);
                // and symbol table
                Console.WriteLine(symb);
                // Stop the assembler
                System.Environment.Exit(10);
            }

            #if DEBUG
            Console.WriteLine(interSource);
            #endif

            // pass 2
            Logger.Log("Starting pass 2", "Main");
            interSource.CalculateModuleLength();
            report = new AssemblyReport();
            ObjectFile obj = new ObjectFile(ref interSource, ref symb, ref report);
            obj.Render(outfile);

            // print out assembly report
            Console.WriteLine(report);
            // and symbol table
            Console.WriteLine(symb);
        }
示例#9
0
        /**
         * Parses the reset directive, ensuring that the reset operand is a number
         * that is higher than any previously or currently used location counter.
         *
         * @param interLine the intermediate line to process
         * @param symb symbol table reference
         *
         * @refcode D2
         * @errtest
         *  N/A
         * @errmsg ES.08, ES.10, ES.25
         * @author Mark Mathis
         * @creation April 15, 2011
         * @modlog
         * - April 17, 2011 - Mark - Changes the location counter to the operand value.
         * - April 17, 2011 - Mark - Checks that the operand value is valid.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private static void ParseReset(ref IntermediateLine interLine, ref SymbolTable symb)
        {
            Logger.Log("Parsing RESET directive", "DirectiveParser");

            if (interLine.Label != null)
            {
                // the operand of the RESET directive must either be an equated label
                // or a literal number.
                if (symb.ContainsSymbol(interLine.DirectiveOperand) &&
                    symb.GetSymbol(interLine.DirectiveOperand).usage == Usage.EQUATED)
                {
                    int curLC = Convert.ToInt32(Parser.LC, 16);
                    int newLC = Convert.ToInt32(symb.GetSymbol(interLine.DirectiveOperand).val, 16);
                    if (curLC < newLC)
                    {
                        Parser.LC = Convert.ToString(newLC,16);
                    }
                    else
                    {
                        // error, attempt to use a previously used LC value
                        Logger.Log("ERROR: ES.08 encountered.", "DirectiveParser");
                        interLine.AddError(Errors.Category.Serious, 8);
                    }
                }
                else if (interLine.DirectiveLitOperand == OperandParser.Literal.NUMBER)
                {
                    int curLC = Convert.ToInt32(Parser.LC, 16);
                    int newLC = Convert.ToInt32(interLine.DirectiveOperand, 16);
                    if (curLC < newLC)
                    {
                        Parser.LC = Convert.ToString(newLC, 16);
                    }
                    else
                    {
                        // error, attempt to use a previously used LC value
                        Logger.Log("ERROR: ES.08 encountered.", "DirectiveParser");
                        interLine.AddError(Errors.Category.Serious, 8);
                    }
                }
                else
                {
                    // error invalid value
                    Logger.Log("ERROR: ES.10 encountered.", "DirectiveParser");
                    interLine.AddError(Errors.Category.Serious, 10);
                }
            }
            else
            {
                // error, label is required for reset directive
                Logger.Log("ERROR: ES.25 encountered.", "DirectiveParser");
                interLine.AddError(Errors.Category.Serious,25);
            }

            Logger.Log("Finished parsing RESET directive", "DirectiveParser");
        }
示例#10
0
 /**
  * Parses the eque 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 D4
  * @errtest
  *  N/A
  * @errmsg
  *  N/A
  * @author Mark Mathis
  * @creation April 17, 2011
  * @modlog
  * @teststandard Andrew Buelow
  * @codestandard Mark Mathis
  */
 private static void ParseEque(ref IntermediateLine interLine, ref SymbolTable symb)
 {
     // The expressions will be exactly the same for EQUe as
     // it will for EQU, EQUe can just have longer expressions
     ParseEqu(ref interLine, ref symb, 3);
 }
示例#11
0
        /**
         * Parses an entire source code file.
         *
         * @param path the path of the source file to parse.
         * @param interSource resultant intermediate file from this source
         * @param symb resultant symbol table from this source
         *
         * @refcode N/A
         * @errtest
         *  N/A
         * @errmsg
         *  N/A
         * @author Mark Mathis
         * @creation April 8, 2011
         * @modlog
         *  - April 9, 2011 -  Mark - Parses entire source code file from a string.
         *  - April 9, 2011 -  Mark - Reads source file in from a file.
         *  - April 9, 2011 -  Mark - Catches exceptions possibly raised by reading the file.
         *  - April 9, 2011 - Jacob - Adds symbols to the symbol table. Changed the parameters to
         *      pass in an IntermediateFile and SymbolTable with an expected out value. Return type
         *      is now void.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseSource(string path, out IntermediateFile interSource, out SymbolTable symb)
        {
            string[] sourceCode = new string[1];
            try
            {
                Logger.Log("Opening file: " + path, "Parser");
                sourceCode = File.ReadAllLines(path);
            }
            catch (FileNotFoundException ex)
            {
                Logger.Log("Failed to open file. Error: " + ex.Message, "Parser");
                Console.WriteLine("{0}\n{1}", ex.Message, "Exiting program");
                System.Environment.Exit(1);
            }

            interSource = new IntermediateFile();
            symb = new SymbolTable();

            // first line is expected to hold the start directive
            IntermediateLine line = ParseLine(sourceCode[0], 1, ref symb);
            interSource.AddLine(line);
            if (line.Directive != null)
            {
                if (line.Directive.ToUpper() != "START")
                {
                    // file must start with a valid start directive
                    line.AddError(Errors.Category.Fatal, 2);
                    return;
                }
                else if (HasFatalError(line))
                {
                    return;
                }
            }
            else
            {
                line.AddError(Errors.Category.Fatal, 2);
                return;
            }

            bool reachedEnd = false;

            // iterate the lines of the file
            for (short i = 2; i <= sourceCode.Length; i++)
            {
                // parse a line and create an intermediate version
                line = ParseLine(sourceCode[i - 1].TrimEnd(), i, ref symb);

                // if we're at the end and processing another line
                if (reachedEnd)
                {
                    if (line.SourceLine.Length > 0)
                    line.AddError(Errors.Category.Fatal, 7);
                }

                // check the LC. at this point, the line will have incremented
                // already, so check if it's 1024 instead of 1023.
                if (Convert.ToInt32(Parser.LC, 16) > 1024)
                {
                    line.AddError(Errors.Category.Fatal, 3);
                }

                // add to source
                if (!reachedEnd || line.SourceLine.Length > 0)
                interSource.AddLine(line);

                // did we find le end?
                if (line.Directive == "END")
                {
                    reachedEnd = true;
                }

                // check for fatal errors
                if (HasFatalError(line))
                {
                    break;
                }
            }
        }
示例#12
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");
 }
示例#13
0
 public void EmptyTable()
 {
     var t = new SymbolTable();
     Assert.AreEqual(0, t.SortedSymbols().Count);
 }
示例#14
0
        /**
         * Process a line, generating partial bytecode and appropriate flags.
         * Errors may be set on lines (and NOP'd) as they occur.
         *
         * @param symb symbol table reference
         *
         * @refcode OP
         * @errtest
         *  N/A
         * @errmsg
         *  ES.3, ES.4, ES.9, ES.11, ES.12, ES.16, EW.3
         * @author Jacob Peddicord
         * @creation April 10, 2011
         * @modlog
         *  - April 15, 2011 - Jacob - Converted to a property; begin generating full bytecode
         *  - April 15, 2011 - Jacob - Changed to ProcessLine; we'll do more general things here
         *  - April 16, 2011 - Jacob - Fix padding on generated instructions.
         *  - April 17, 2011 - Jacob - Handle error conditions.
         * @codestandard Mark Mathis
         * @teststandard Andrew Buelow
         */
        public void ProcessLine(ref SymbolTable symb)
        {
            Logger.Log("Processing line \"" + this.source + "\"", "IntermediateLine");
            // get the first 5 bits
            StringBuilder code = new StringBuilder();
            try
            {
                code.Append(Instructions.GetInstance().GetBytecodeString(
                    this.category == null ? "" : this.category,
                    this.function == null ? "" : this.function
                ));
            }
            catch (InstructionException)
            {
                this.AddError(Errors.Category.Serious, 3);
                this.NOPificate();
                return;
            }

            // fetch equated symbols
            if (this.OpLitOperand == OperandParser.Literal.NONE &&
                this.OpOperand != null &&
                symb.ContainsSymbol(this.OpOperand) &&
                symb.GetSymbol(this.OpOperand).usage == Usage.EQUATED)
            {
                Logger.Log("Evaluating equated symbol " + this.OpOperand, "IntermediateLine");
                this.Equated = this.OpOperand;
                this.OpOperand = symb.GetSymbol(this.OpOperand).val;
            }

            // from here on, everything is instruction-dependent
            switch (this.category)
            {
                case "CNTL": {
                    // unused bit
                    code.Append("0");
                    // validation
                    if (this.function == "HALT")
                    {
                        // we want a number
                        if (this.OpLitOperand == OperandParser.Literal.NUMBER)
                        {
                            int val = BinaryHelper.HexToInt(this.OpOperand, 16);
                            // out of bounds
                            if (val < 0 || val > 1023)
                            {
                                this.AddError(Errors.Category.Serious, 12);
                                this.NOPificate();
                                return;
                            }
                        }
                        // wrong operand type
                        else
                        {
                            this.AddError(Errors.Category.Serious, 12);
                            this.NOPificate();
                            return;
                        }
                    }
                    else if (this.function == "DUMP")
                    {
                        // not a 1, 2, or 3
                        if (this.OpOperand != "1" && this.OpOperand != "2" && this.OpOperand != "3")
                        {
                            this.AddError(Errors.Category.Serious, 11);
                            this.NOPificate();
                            return;
                        }
                    }
                    else if (this.function == "CLRD" || this.function == "CLRT")
                    {
                        // no operand for CLRD/CLRT
                        if (this.OpOperand != "" && this.OpOperand != null)
                        {
                            this.AddError(Errors.Category.Warning, 3);
                            this.NOPificate();
                            return;
                        }
                    }
                    else if (this.function == "GOTO")
                    {
                        // make sure there's a label or expression
                        if ((this.OpLitOperand != OperandParser.Literal.EXPRESSION &&
                            this.OpLitOperand != OperandParser.Literal.NONE) ||
                            this.OpOperand == "" || this.OpOperand == null)
                        {
                            this.AddError(Errors.Category.Serious, 9);
                            this.NOPificate();
                            return;
                        }
                    }
                    // actual processing!
                    // numeric operand
                    if (this.OpLitOperand == OperandParser.Literal.NUMBER)
                    {
                        code.Append(BinaryHelper.BinaryString(this.OpOperand).PadLeft(10, '0'));
                    }
                    // otherwise pad with zeros (labels & expressions in pass 2)
                    else
                    {
                        code.Append("0000000000");
                    }
                } break;
                case "STACK": {
                    // ensure there is an operand
                    if (this.OpOperand.Length == 0)
                    {
                        this.AddError(Errors.Category.Serious, 16);
                        this.NOPificate();
                        return;
                    }
                    // literal operand
                    if (this.OpLitOperand != OperandParser.Literal.NONE &&
                        this.OpLitOperand != OperandParser.Literal.EXPRESSION)
                    {
                        // bounds-check
                        int val = Convert.ToInt32(this.OpOperand, 16);
                        if (val < 0 || val > 1023) // actually (val < -512 || val > 511) in 10 bits
                        {
                            this.AddError(Errors.Category.Serious, 4);
                            this.NOPificate();
                            return;
                        }
                        // literal flag
                        code.Append("1");
                        // and the value
                        code.Append(BinaryHelper.BinaryString(this.OpOperand).PadLeft(10, '0'));
                    }
                    // expression
                    else if (this.OpLitOperand == OperandParser.Literal.EXPRESSION)
                    {
                        // we'll have literal data once the expression is evaluated.
                        code.Append("1");
                        code.Append("0000000000");
                    }
                    // label
                    else
                    {
                        // non-literal (reference) bit
                        code.Append("0");
                        // and the reference itself, which will be filled in pass 2
                        code.Append("0000000000");
                    }
                } break;
                case "JUMP": {
                    // ensure there is an operand
                    if (this.OpOperand.Length == 0)
                    {
                        this.AddError(Errors.Category.Serious, 16);
                        this.NOPificate();
                        return;
                    }
                    // unused bit
                    code.Append("0");
                    // ensure that JUMP is taking a label
                    if (this.OpLitOperand == OperandParser.Literal.NONE)
                    {
                        // reference label, filled in pass 2
                        code.Append("0000000000");
                    }
                    // or a number
                    else if (this.OpLitOperand == OperandParser.Literal.NUMBER)
                    {
                        int val = Convert.ToInt32(this.OpOperand, 16);
                        if (val < 0 || val > 1023)
                        {
                            this.AddError(Errors.Category.Serious, 12);
                            this.NOPificate();
                            return;
                        }
                        code.Append(BinaryHelper.BinaryString(this.OpOperand).PadLeft(10, '0'));
                    }
                    // or an expression (processed later)
                    else if (this.OpLitOperand == OperandParser.Literal.EXPRESSION)
                    {
                        code.Append("0000000000");
                    }
                    // otherwise, error
                    else
                    {
                        this.AddError(Errors.Category.Serious, 9);
                        this.NOPificate();
                        return;
                    }
                } break;
                case "SOPER": {
                    // ensure there is an operand of type Number
                    if (this.OpLitOperand != OperandParser.Literal.NUMBER)
                    {
                        this.AddError(Errors.Category.Serious, 17);
                        this.NOPificate();
                        return;
                    }
                    // bounds-check
                    int val = Convert.ToInt32(this.OpOperand, 16);
                    if (val < 0 || val > 255) // will catch 2's complement negatives as well
                    {
                        this.AddError(Errors.Category.Serious, 17);
                        this.NOPificate();
                        return;
                    }
                    // the write flag is only set for character operations
                    if (this.OpFunction == "READC" || this.OpFunction == "WRITEC")
                    {
                        code.Append("1");
                    }
                    // for everything else, it's a zero
                    else
                    {
                        code.Append("0");
                    }
                    // unused 2 bits
                    code.Append("00");
                    // operand (assumed literal)
                    code.Append(BinaryHelper.BinaryString(this.OpOperand).PadLeft(8, '0'));
                } break;
                case "MOPER": {
                    // ensure there is an operand
                    if (this.OpOperand.Length == 0)
                    {
                        this.AddError(Errors.Category.Serious, 16);
                        this.NOPificate();
                        return;
                    }
                    // the write flag is only set for character operations
                    if (this.OpFunction == "READC" || this.OpFunction == "WRITEC")
                    {
                        code.Append("1");
                    }
                    // for everything else, it's a zero
                    else
                    {
                        code.Append("0");
                    }
                    // ensure that MOPER is taking a label
                    if (this.OpLitOperand == OperandParser.Literal.NONE)
                    {
                        // reference label, filled pass 2
                        code.Append("0000000000");
                    }
                    // or a number
                    else if (this.OpLitOperand == OperandParser.Literal.NUMBER)
                    {
                        int val = Convert.ToInt32(this.OpOperand, 16);
                        if (val < 0 || val > 1023)
                        {
                            this.AddError(Errors.Category.Serious, 4);
                            this.NOPificate();
                            return;
                        }
                        code.Append(BinaryHelper.BinaryString(this.OpOperand).PadLeft(10, '0'));
                    }
                    // or an expression (pass 2)
                    else if (this.OpLitOperand == OperandParser.Literal.EXPRESSION)
                    {
                        code.Append("0000000000");
                    }
                    // otherwise, it's invalid
                    else
                    {
                        this.AddError(Errors.Category.Serious, 9);
                        this.NOPificate();
                        return;
                    }
                } break;
            }

            // set the bytecode
            this.bytecode = code.ToString();
        }
示例#15
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");
        }
示例#16
0
        /**
         * Parses the operation section of the line if it has an instruction.
         *
         * @param line current line to parse.
         * @param interLine the line as a single line in the intermediate file.
         * @param symb symbol table reference
         *
         * @refcode N/A
         * @errtest
         *  N/A
         * @errmsg
         *  N/A
         * @author Mark Mathis
         * @creation April 9, 2011
         * @modlog
         *  - April  9, 2011 - Mark - ParseInstruction properly parses instructions.
         *  - April  9, 2011 - Mark - Uses new ParseLiteralOperand format.
         *  - April  9, 2011 - Mark - Changed to use ValidOperandField.
         *  - April 10, 2011 - Mark - Handles CLRD and CLRT.
         *  - April 12, 2011 - Jacob - Factor out operand parsing.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private void ParseInstruction(ref string line, ref IntermediateLine interLine, ref SymbolTable symb)
        {
            Logger.Log("Parsing instruction on line " + interLine.SourceLineNumber, "Parser");

            string token = "";
            Tokenizer.TokenKinds tokenKind = Tokenizer.TokenKinds.Empty;

            // checks for valid operands in all functions besides CLRD and CLRT
            if (OperandParser.ValidOperandField(line))
            {
                // get what should be the function name
                Tokenizer.GetNextToken(ref line, out token, out tokenKind);

                if (instructionList.IsInstruction(interLine.OpCategory, token))
                {
                    interLine.OpFunction = token;
                }
                else
                {
                    interLine.OpFunction = "_ERROR";
                }

                // get what should be the function operand
                OperandParser.ParseOperand(ref line, ref interLine, ref symb, 10);
            }
            else if (interLine.OpCategory.ToUpper() == "CNTL")
            {
                // token should be either CLRD or CLRT
                Tokenizer.GetNextToken(ref line, out token, out tokenKind);

                if (token.ToUpper() != "CLRD" && token.ToUpper() != "CLRT")
                {
                    interLine.OpOperand = "_ERROR";
                }

                interLine.OpFunction = token;
            }
            else
            {
                interLine.OpFunction = "_ERROR";
                interLine.OpOperand = "_ERROR";
            }

            Logger.Log("Finished parsing instruction on line " + interLine.SourceLineNumber, "Parser");
        }
示例#17
0
        /**
         * Parses the operation section of the line if it has a Directive.
         *
         * @param line current line to parse
         * @param interLine the line as a single line in the intermediate file
         * @param symb symbol table reference
         * @refcode DS2
         * @errtest
         *  N/A
         * @errmsg
         *  N/A
         * @author Mark Mathis
         * @creation April 9, 2011
         * @modlog
         *  - April  9, 2011 -  Mark - ParseDirective properly parses directives.
         *  - April  9, 2011 -  Mark - Uses new ParseLiteralOperand format.
         *  - April 12, 2011 - Jacob - Factor out operand parsing.
         *  - April 14, 2011 -  Mark - Moved into DirectiveParser class.
         *  - April 15, 2011 -  Mark - Factored out all parsing into separate methods.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public static void ParseDirective(ref string line, ref IntermediateLine interLine, ref SymbolTable symb)
        {
            Logger.Log("Parsing directive on line " + interLine.SourceLineNumber, "DirectiveParser");

            if (interLine.Directive.ToUpper() != "NOP")
            OperandParser.ParseOperand(ref line, ref interLine, ref symb, 16);

            // This will decide which directive is in this line and how it should
            // be handled by the parser.
            string currentDirective = interLine.Directive.ToUpper();
            switch (currentDirective)
            {
                case "START":
                    {
                        ParseStart(ref interLine, ref symb);
                    } break;
                case "RESET":
                    {
                        ParseReset(ref interLine, ref symb);
                    } break;
                case "EQU":
                    {
                        ParseEqu(ref interLine, ref symb);
                    } break;
                case "EQUE":
                    {
                         ParseEque(ref interLine, ref symb);
                    } break;
                case "ENTRY":
                    {
                        ParseEntry(ref interLine, ref symb);
                    } break;
                case "EXTRN":
                    {
                        ParseExtrn(ref interLine, ref symb);
                    } break;
                case "END":
                    {
                        ParseEnd(ref interLine, ref symb);
                    } break;
                case "DAT":
                    {
                        ParseDat(ref interLine, ref symb);
                    } break;
                case "ADC":
                    {
                        ParseAdc(ref interLine, ref symb);
                    } break;
                case "ADCE":
                    {
                        ParseAdce(ref interLine, ref symb);
                    } break;
                case "NOP":
                    {
                        interLine.NOPificate();
                        interLine.ProgramCounter = Parser.LC;
                        Parser.IncrementLocationCounter();
                    } break;
                default:
                    {
                    } break;
            }

            Logger.Log("Finished parsing directive on line " + interLine.SourceLineNumber, "DirectiveParser");
        }
示例#18
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;
        }
示例#19
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");
        }
示例#20
0
 /**
  * Parses the adc directive, ensuring that the operand has proper
  * syntax and type.
  *
  * @param interLine the intermediate line to process
  * @param symb symbol table reference
  *
  * @refcode D8
  * @errtest
  *  N/A
  * @errmsg
  *  N/A
  * @author Mark Mathis
  * @creation April 18, 2011
  * @modlog
  * @teststandard Andrew Buelow
  * @codestandard Mark Mathis
  */
 private static void ParseAdc(ref IntermediateLine interLine, ref SymbolTable symb)
 {
     interLine.ProgramCounter = Parser.LC;
     Parser.IncrementLocationCounter();
 }
示例#21
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");
        }
示例#22
0
 /**
  * Parses the adce directive, ensuring that the operand has proper
  * syntax and type.
  *
  * @param interLine the intermediate line to process
  * @param symb symbol table reference
  *
  * @refcode D9
  * @errtest
  *  N/A
  * @errmsg
  *  N/A
  * @author Mark Mathis
  * @creation April 18, 2011
  * @modlog
  * @teststandard Andrew Buelow
  * @codestandard Mark Mathis
  */
 private static void ParseAdce(ref IntermediateLine interLine, ref SymbolTable symb)
 {
     ParseAdc(ref interLine, ref symb);
 }
示例#23
0
        /**
         * Reads an expression and evaluates it as much as it can. If the parsing is
         * successful, the operand variable is replaced with the most fully parsed
         * version of the expression possible.  If the expression cannot be parsed due
         * to an error in the expression, thie function returns false and an error is
         * added to the passed in IntermediateLine parameter.
         *
         * @refcode EX1, EX2, EX3
         * @errtest N/A
         * @errmsg ES.2, ES.19, ES.20, ES.22, ES.23, ES.24, ES.27, ES.30, ES.31, ES.32, ES.33
         * @author Mark Mathis
         * @creation April 18, 2011
         * @modlog
         *  - April 18, 2011 - Mark - Parses operand expressions (EX1).
         *  - April 19, 2011 - Mark - Parses EQU expressions (EX2).
         *  - April 19, 2011 - Mark - Parses ADC expressions (EX3).
         *  - April 19, 2011 - Mark - Errors are caught and reported in all expressions.
         *  - May 13, 2011 - Mark - Added rec and modifications parameters.
         *  - May 14, 2011 - Mark - Now keeps track of adjustments required for pass 2.
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         *
         * @param operand the expression to parse, will contain the outgoing value of the expression
         * @param type the type of expression to be parsed
         * @param interLine the intermediate line containing this expression
         * @param symb the symbol table for this source code file
         * @param rec the modification record for keeping track of adjustments in instruction expressions
         *        and ADC/ADCe expressions
         * @param modifications the number of adjustments needed for a EQU/EQUe expression
         * @param maxOperators the maximum number of operators allowed in this type of expression
         *
         * @return true if the expression is successfully parsed and evaluated.
         *         false if an error is found.
         */
        public static bool ParseExpression(ref string operand,
                                           OperandParser.Expressions type,
                                           IntermediateLine interLine,
                                           ref SymbolTable symb,
                                           ModificationRecord rec,
                                           out int modifications,
                                           int maxOperators = 1)
        {
            modifications = 0;
            if (operand != null && operand.Length > 0)
            {
                // if the expression is just a star, take care of it and return
                if (operand.Length == 1 && operand[0] == '*')
                {
                    modifications++;
                    rec.AddAdjustment(true, symb.ProgramName);
                    operand = interLine.ProgramCounter;
                    return true;
                }

                char[] validOperators = { '+', '-' };
                // if there are too many operators, give an error
                List<string> operands = operand.Split(validOperators, StringSplitOptions.RemoveEmptyEntries).ToList();

                if (operands.Count - 1 > maxOperators)
                {
                    // error, too many operators
                    interLine.AddError(Errors.Category.Serious, 22);
                    return false;
                }

                // check for absolute ADC/ADCe
                bool absolute = false;
                if (operand[0] == '+' && type == Expressions.ADC)
                {
                    absolute = true;
                    operand = operand.Substring(1);
                }

                List<char> operators = new List<char>();

                int pos = operand.IndexOfAny(validOperators, 0);

                while (pos != -1)
                {
                    operators.Add(operand[pos]);
                    pos = operand.IndexOfAny(validOperators, pos + 1);
                }

                // check that we have the correct number of operands
                if (operators.Count != operands.Count - 1)
                {
                    // error, wrong number of operators
                    interLine.AddError(Errors.Category.Serious, 24);
                    return false;
                }

                // it can't always be that easy
                switch (type)
                {
                    case OperandParser.Expressions.Operand:
                        {

                            char oprtr;
                            string opr2;
                            string star;

                            if (operand[0] == '*')
                            {
                                star = interLine.ProgramCounter;
                                oprtr = operand[1];
                                opr2 = operand.Substring(2);
                                rec.AddAdjustment(true, symb.ProgramName);

                                Tokenizer.TokenKinds valid;
                                Tokenizer.GetTokenKind(opr2, out valid);

                                if (valid == Tokenizer.TokenKinds.Label_Or_Command)
                                {
                                    if (2 <= opr2.Length && opr2.Length <= 32)
                                    {
                                        if (symb.ContainsSymbol(opr2))
                                        {
                                            if (symb.GetSymbol(opr2).usage == Usage.EQUATED)
                                            {
                                                opr2 = Convert.ToInt32(symb.GetSymbol(opr2).val, 16).ToString();
                                            }
                                            else if (symb.GetSymbol(opr2).usage == Usage.LABEL)
                                            {
                                                opr2 = Convert.ToInt32(symb.GetSymbol(opr2).lc, 16).ToString();
                                                rec.AddAdjustment(oprtr == '+', symb.ProgramName);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // error:label is too long
                                        Logger.Log("ERROR: ES.2 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 2);
                                        return false;
                                    }
                                }
                                else if (valid == Tokenizer.TokenKinds.Number)
                                {
                                    if (!(0 <= Convert.ToInt32(opr2) && Convert.ToInt32(opr2) <= 1023))
                                    {
                                        // error, the number is out of bounds
                                        Logger.Log("ERROR: ES.28 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 27);
                                        return false;
                                    }
                                }
                                else if (opr2 == "*")
                                {
                                    // error: star used multiple times
                                    interLine.AddError(Errors.Category.Serious, 19);
                                    return false;
                                }
                                else
                                {
                                    //error, must be number or previously equated symbol
                                    Logger.Log("ERROR: ES.29 encountered", "OperandParser");
                                    interLine.AddError(Errors.Category.Serious, 27);
                                    return false;
                                }

                                Tokenizer.GetTokenKind(opr2, out valid);

                                if (valid == Tokenizer.TokenKinds.Number)
                                {
                                    int result = -1;
                                    // if the method gets here, then it's using a number or
                                    // symbol we can deal with
                                    switch (oprtr)
                                    {
                                        case '+':
                                            {
                                                result = Convert.ToInt32(star, 16) + Convert.ToInt32(opr2);
                                            } break;
                                        case '-':
                                            {
                                                result = Convert.ToInt32(star, 16) - Convert.ToInt32(opr2);
                                            } break;
                                        default:
                                            {
                                                // error invalid operator in expression
                                                Logger.Log("ERROR: ES.30 encountered", "OperandParser");
                                                interLine.AddError(Errors.Category.Serious, 30);
                                                return false;
                                            }
                                    }

                                    if (0 <= result && result <= 1023)
                                    {
                                        operand = Convert.ToString(result,16);
                                    }
                                    else
                                    {
                                        // error: computation out of bounds
                                        Logger.Log("ERROR: ES.27 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 27);
                                        return false;
                                    }
                                }
                            }
                            else
                            {
                                //error invalid operand expression
                                Logger.Log("ERROR: ES.31 encountered", "OperandParser");
                                interLine.AddError(Errors.Category.Serious, 31);
                                return false;
                            }
                        } break;

                    case Expressions.EQU:
                        {
                            for (int i = 0; i < operands.Count; i++)
                            {
                                string label = operands[i];
                                Tokenizer.TokenKinds tokenkind;

                                Tokenizer.GetTokenKind(label, out tokenkind);

                                if (label == "*")
                                {
                                    if (i == 0)
                                    {
                                        operands[i] = Convert.ToInt32(Parser.LC, 16).ToString();
                                        modifications++;
                                    }
                                    else
                                    {
                                        // error, star must be first operand
                                        Logger.Log("ERROR: invalid star notation in expression.", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 19);
                                        return false;
                                    }
                                }
                                else if (symb.ContainsSymbol(label))
                                {
                                    Symbol operSym = symb.GetSymbol(label);

                                    if (operSym.usage == Usage.EQUATED)
                                    {
                                        operands[i] = Convert.ToInt32(operSym.val, 16).ToString();
                                        modifications += operSym.relocations;
                                    }
                                    else if (operSym.usage == Usage.LABEL)
                                    {
                                        operands[i] = Convert.ToInt32(operSym.lc, 16).ToString();
                                        modifications++;
                                    }
                                    else
                                    {
                                        // error, can only use equated symbols or local references
                                        Logger.Log("ERROR: ES.32 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 32);
                                        return false;
                                    }
                                }
                                else if (tokenkind == Tokenizer.TokenKinds.Number)
                                {
                                    // this needs to be caught, so the next else doesn't get
                                    // tripped. but there's nothing to do herp.
                                    // I will tell you stories of my people.
                                }
                                else
                                {
                                    // undefined symbol
                                    Logger.Log("ERROR: ES.20 encountered", "OperandParser");
                                    interLine.AddError(Errors.Category.Serious, 20);
                                    return false;
                                }
                            }

                            operands.Reverse();
                            operators.Reverse();

                            string possibleOperand = EvaluateExpression(new Stack<string>(operands), new Stack<char>(operators));

                            if (0 <= int.Parse(possibleOperand) && int.Parse(possibleOperand) <= 1023)
                            {
                                operand = Convert.ToString(int.Parse(possibleOperand), 16);
                            }
                            else
                            {
                                // error, calculation must be within the range of 0 to 1023
                                Logger.Log("ERROR: ES.27 encountered", "OperandParser");
                                interLine.AddError(Errors.Category.Serious, 27);
                                return false;
                            }
                        } break;

                    case Expressions.ADC:
                        {
                            bool noLabels = true;
                            for (int i = 0; i < operands.Count; i++)
                            {
                                string label = operands[i];

                                if (label == "*")
                                {
                                    noLabels = false;
                                    if (i == 0)
                                    {
                                        operands[i] = Convert.ToInt32(interLine.ProgramCounter,16).ToString();
                                        rec.AddAdjustment(true, symb.ProgramName);
                                        modifications++;
                                    }
                                    else
                                    {
                                        // error, star must be first operand
                                        Logger.Log("ERROR: ES.19 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 19);
                                        return false;
                                    }
                                }
                                else if (symb.ContainsSymbol(label))
                                {
                                    noLabels = false;
                                    Symbol operSym = symb.GetSymbol(label);

                                    if (operSym.usage == Usage.LABEL)
                                    {
                                        operands[i] = Convert.ToInt32(operSym.lc, 16).ToString();
                                        modifications++;
                                        if (i > 0)
                                        {
                                            rec.AddAdjustment(operators[i - 1] == '+', symb.ProgramName);
                                        }
                                        else
                                        {
                                            rec.AddAdjustment(true, symb.ProgramName);
                                        }
                                    }
                                    else if (operSym.usage == Usage.EXTERNAL)
                                    {
                                        noLabels = false;
                                        operands[i] = "0";
                                        modifications++;
                                        if (i > 0)
                                        {
                                            rec.AddAdjustment(operators[i - 1] == '+', operSym.rlabel);
                                        }
                                        else
                                        {
                                            rec.AddAdjustment(true, operSym.rlabel);
                                        }
                                    }
                                    else
                                    {
                                        // error: symbols can only be external, local reference
                                        // in ADC/ADCe expressions
                                        Logger.Log("ERROR: ES.33 encountered", "OperandParser");
                                        interLine.AddError(Errors.Category.Serious, 33);
                                        return false;
                                    }
                                }
                            }

                            if (noLabels)
                            {
                                rec.AddAdjustment(true, symb.ProgramName);
                                modifications++;
                            }

                            bool allNumbers = true;

                            foreach (string op in operands)
                            {
                                Tokenizer.TokenKinds tokenKind;

                                Tokenizer.GetTokenKind(op, out tokenKind);

                                if (tokenKind == Tokenizer.TokenKinds.Number)
                                {
                                    allNumbers = allNumbers && true;
                                }
                                else
                                {
                                    allNumbers = false;
                                }
                            }

                            if (allNumbers)
                            {
                                operands.Reverse();
                                operators.Reverse();
                                operand = EvaluateExpression(new Stack<string>(operands), new Stack<char>(operators));
                                operand = Convert.ToString(Convert.ToInt32(operand), 16);
                            }
                            else
                            {
                                operand = operands[0];
                                for (int i = 0; i + 1 < operands.Count; i++)
                                {
                                    operand += operators[i] + operands[i + 1];
                                }
                            }
                            if (absolute)
                                modifications = 0;
                            } break;
                        }
                }
            return true;
        }
示例#24
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");
        }
示例#25
0
 /**
  * Create an object file using the given inputs.
  *
  * @param input Input source from pass 1
  * @param symb The symbol table
  * @param report an assembly report to be generated
  * @refcode OB
  * @errtest
  *  N/A
  * @errmsg
  *  N/A
  * @author Jacob Peddicord
  * @creation May 10, 2011
  * @modlog
  * @teststandard Andrew Buelow
  * @codestandard Mark Mathis
  */
 public ObjectFile(ref IntermediateFile input, ref SymbolTable symb, ref AssemblyReport report)
 {
     this.input = input;
     this.symb = symb;
     this.report = report;
 }
示例#26
0
        static void Main()
        {
            string title  = "Pong"; //Name of source file
            string title2 = "pong"; //Name for file path

            string outfile         = "/Applications/nand2tetris/projects/06/" + title2 + "/" + title + ".hack";
            bool   hasMoreCommands = true;
            string type;
            int    nextMem = 16;
            int    counter = 0;


            Parser      p1 = new Parser("/Applications/nand2tetris/projects/06/" + title2 + "/" + title + ".asm");
            SymbolTable st = new SymbolTable();

            while (hasMoreCommands == true)                                     //First
            {
                p1.advance();
                type = p1.commandType();
                if (type == "L_COMMAND")
                {
                    st.addEntry(p1.symbol(), counter);
                }
                else
                {
                    counter        += 1;
                    hasMoreCommands = p1.hasMoreCommands();
                }
            }

            hasMoreCommands = true;
            Parser p = new Parser("/Applications/nand2tetris/projects/06/" + title2 + "/" + title + ".asm");
            Code   c = new Code();

            while (hasMoreCommands == true)                                     //Second
            {
                p.advance();
                type = p.commandType();
                if (type == "A_COMMAND")
                {
                    string varOrNum = p.symbol();
                    char   von      = varOrNum[0];

                    if (char.IsDigit(von) == true)
                    {
                        int    prexxx = Convert.ToInt32(p.symbol());
                        string xxx    = Convert.ToString(prexxx, 2).PadLeft(16, '0');
                        using (StreamWriter sw = new StreamWriter(outfile, true))
                        {
                            sw.WriteLine(xxx);
                        }
                    }
                    else //if(char.IsDigit(von)==false), which means xxx is variable.
                    {
                        bool cont = st.contains(varOrNum);
                        if (cont == false)
                        {
                            st.addEntry(varOrNum, nextMem);
                            string xxx = Convert.ToString(nextMem, 2).PadLeft(16, '0');
                            using (StreamWriter sw = new StreamWriter(outfile, true))
                            {
                                sw.WriteLine(xxx);
                            }
                            nextMem += 1;
                        }
                        else
                        {
                            string xxx = Convert.ToString(st.getAddress(varOrNum), 2).PadLeft(16, '0');
                            using (StreamWriter sw = new StreamWriter(outfile, true))
                            {
                                sw.WriteLine(xxx);
                            }
                        }
                    }
                }
                else if (type == "C_COMMAND")
                {
                    string destmne = p.dest();
                    string dest    = c.dest(destmne);

                    string compmne = p.comp();
                    string comp    = c.comp(compmne);

                    string jumpmne = p.jump();
                    string jump    = c.jump(jumpmne);

                    string c_command = "111" + comp + dest + jump;
                    using (StreamWriter sw = new StreamWriter(outfile, true))
                    {
                        sw.WriteLine(c_command);
                    }
                }
                else //if (type=="L_COMMAND")
                {
                }

                hasMoreCommands = p.hasMoreCommands();
            }
        }