Example #1
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");
        }
Example #2
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;
        }
Example #3
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");
        }
Example #4
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");
        }
Example #5
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");
        }
Example #6
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);
 }
Example #7
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");
        }
Example #8
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");
        }
Example #9
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");
        }
Example #10
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");
        }
Example #11
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);
 }
Example #12
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();
 }
Example #13
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;
        }
Example #14
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;
            }
        }
Example #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");
        }
Example #16
0
 /**
  * Adds the indicated IntermediateLine to the file.
  *
  * @param line the InterediateLine file to add
  *
  * @refcode N/A
  * @errtest
  *  N/A
  * @errmsg
  *  N/A
  * @author Mark Mathis
  * @creation April 9, 2011
  * @modlog
  * @codestandard Mark Mathis
  * @teststandard Andrew Buelow
  */
 public void AddLine(IntermediateLine line)
 {
     this.allLines.Add(line.SourceLineNumber, line);
 }
Example #17
0
        /**
         * Checks the specified IntermediateLine to see if it has a fatal error.
         * This is used to determine whether or not the assembly should continue
         * after a line has been parsed.
         *
         * @param line the line to check for a fatal error
         * @return true if the indicated line has a fatal error, false otherwise
         *
         * @refcode N/A
         * @errtest
         *  N/A
         * @errmsg
         *  N/A
         * @author Mark Mathis
         * @creation April 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private bool HasFatalError(IntermediateLine line)
        {
            // check for fatal errors
            List<Errors.Error> errors = line.GetThreeErrors();
            bool hasFatal = false;

            foreach (Errors.Error e in errors)
            {
                if (e.category == Errors.Category.Fatal)
                {
                    hasFatal = true;
                    break;
                }
            }
            return hasFatal;
        }