Esempio n. 1
0
        //------------------------------------------------------------------------------------------------------------
        private void letStatement(string[] tokens, int lineNumber)
        {
            // Check that first character after 'let' is a valid variable
            if (!Toolbelt.IsValidVariable(tokens[2]))
            {
                throw new SystemException($"Invalid token ({tokens[2]}) after keyword 'let' -on code line {lineNumber}");
            }
            // Check that the next character is the '=' sign
            if (!(tokens[3].Length == 1 && '=' == Convert.ToChar(tokens[3])))
            {
                throw new SystemException($"Invalid token ({tokens[3]} after assignment variable in 'let' statement -on code line {lineNumber}");
            }

            putInSymbolTable(tokens);

            // determine location of variable to store result in
            char storeVar = Convert.ToChar(tokens[2]);
            int  storeLoc = _symbolTable.FindVariable((int)storeVar).Location();

            if (tokens.Length > 5) // expression follows '=' sign
            {
                compileExpression(tokens, lineNumber, storeLoc);
            }
            else // simple value or variable assignment follows '=' sign
            {
                compileAssignment(tokens, lineNumber, storeLoc);
            }
        }
Esempio n. 2
0
        //------------------------------------------------------------------------------------------------------------
        private void inputStatement(string[] tokens, int lineNumber, out int operationCode, out int operand)
        {
            if (!Toolbelt.IsValidVariable(tokens[2]))
            {
                throw new SystemException($"{tokens[2]} not valid for variable name following 'input' keyword -on code line {lineNumber}");
            }
            char variable = Convert.ToChar(tokens[2]);
            var  entry    = _symbolTable.FindOrAdd((int)variable, TableEntry.VARIABLE);

            // Generate EPML instruction
            operationCode = (int)EPC.Code.READ;
            operand       = entry.Location();
            _compiledCode.Add(Word.Build(operationCode, operand), _workingLineNumber++);
        }
Esempio n. 3
0
 //------------------------------------------------------------------------------------------------------------
 private void putInSymbolTable(string[] tokens)
 {
     // place all variables and constants in the symbol table if missing
     for (int i = 2; i < tokens.Length; ++i)
     {
         var token = tokens[i];
         if (Int32.TryParse(token, out int intToken))
         {
             var tempEntry = _symbolTable.FindOrAddConst(intToken);
             _compiledCode.Add(tempEntry.Symbol(), tempEntry.Location());
         }
         else if (Toolbelt.IsValidVariable(token))
         {
             _symbolTable.FindOrAddVar(Convert.ToChar(token));
         }
     }
 }
Esempio n. 4
0
        //------------------------------------------------------------------------------------------------------------
        private void printStatement(string[] tokens, int lineNumber, out int operationCode, out int operand)
        {
            if (tokens.Length == 2)
            {
                throw new SystemException($"Missing variable after 'print' keyword -on code line {lineNumber}");
            }
            if (!Toolbelt.IsValidVariable(tokens[2]))
            {
                throw new SystemException($"Invalid token ({tokens[2]}) following 'print' statement. Single letter variable expected -on code line {lineNumber}");
            }
            operationCode = (int)EPC.Code.WRITE;
            char printVar   = Convert.ToChar(tokens[2]);
            var  printEntry = _symbolTable.GetEntry((int)printVar);

            if (printEntry == null)
            {
                throw new SystemException($"Variable '{tokens[2]}' is missing from the Symbol Table");
            }
            operand = printEntry.Location();
            _compiledCode.Add(Word.Build(operationCode, operand), _workingLineNumber++);
        }
Esempio n. 5
0
 //------------------------------------------------------------------------------------------------------------
 private void forStatement(string[] tokens, int lineNumber)
 {
     // Place increment value into the symbol table
     _symbolTable.AddConst(FOR_LOOP_INCREMENT);
     if (findNext(out int intNextLineLocation)) // validate there is a 'next' statement
     {
         // validate that the 'for' statement following the correct syntax
         // [2] = variable, [3] = comparator, [4] = var/const, [5] = 'to', [6] = var/const
         string strLHS   = tokens[2];
         string strRHS   = tokens[4];
         string strCheck = tokens[6];
         if (Toolbelt.IsValidVariable(strLHS) &&
             tokens[3] == "=" &&
             tokens[5] == "to")
         {
             putInSymbolTable(tokens);
             // Format the assignment string so it can be properly processed
             string assignment = $"00 let {strLHS} = {strRHS}";
             letStatement(assignment.Split(' '), lineNumber);
             // after let statement is process, the next entry will be the start of the commands in the loop
             _forLoopEntries.Push(ForLoopEntry.Make(
                                      step: _workingLineNumber,
                                      lhs: _symbolTable.Find(strLHS).Location(),
                                      rhs: _symbolTable.Find(strCheck).Location(),
                                      increment: FOR_LOOP_INCREMENT
                                      ));
         }
         else
         {
             throw new SystemException($"Invalid 'for' statement -on code line {lineNumber}");
         }
     }
     else
     {
         throw new SystemException($"'for' missing 'next' statment -on code line {lineNumber}");
     }
 }
Esempio n. 6
0
        //------------------------------------------------------------------------------------------------------------
        private void compileAssignment(string[] tokens, int lineNumber, int storeLoc)
        {
            var token = tokens[4];
            int loc   = -1;

            if (Int32.TryParse(token, out int intValue)) // assigning a Constant
            {
                loc = _symbolTable.FindConstant(intValue).Location();
            }
            else if (Toolbelt.IsValidVariable(token)) // assigning a variable value
            {
                if (Char.TryParse(token, out char chVar))
                {
                    loc = _symbolTable.FindVariable((int)chVar).Location();
                }
                else
                {
                    throw new SystemException($"Something bad happened -on code line {lineNumber}");
                }
            }
            else
            {
                throw new SystemException($"Invalid character following '=' in 'let' statement -on code line {lineNumber}");
            }

            if (loc >= 0)
            {
                // load constant or variable value from memory and store in assignment variable
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, loc), _workingLineNumber++);
                if (_symbolTable.HasLocation(storeLoc) && _symbolTable.AtLocation(storeLoc).IsConst())
                {
                    throw new SystemException($"Cannot override constant value at memory[{storeLoc}] -on code line {lineNumber}");
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.STORE, storeLoc), _workingLineNumber++);
            }
        }
Esempio n. 7
0
 //------------------------------------------------------------------------------------------------------------
 public TableEntry Find(string searchFor)
 {
     if (Int32.TryParse(searchFor, out int intConstant))
     {
         // search string is a constant
         return(FindConstant(intConstant));
     }
     else if (Toolbelt.IsValidVariable(searchFor))
     {
         // search string is a variable
         if (Char.TryParse(searchFor, out char chVar))
         {
             return(FindVariable((int)chVar));
         }
         else
         {
             throw new SystemException($"SymbolTable Find({searchFor}) unexpected error.  Something bad happened");
         }
     }
     else
     {
         throw new SystemException($"SymbolTable Find({searchFor}) search string must be a variable or constant");
     }
 }
Esempio n. 8
0
        //------------------------------------------------------------------------------------------------------------
        private int evaluatePostfix(string postfix, int lineNumber)
        {
            Stack <string> expression = new Stack <string>(postfix.Split(' ').Reverse());
            Stack <int>    operands   = new Stack <int>();
            Stack <int>    temps      = new Stack <int>();
            int            firstTemp  = _symbolTable.TempLocation;

            while (expression.Count > 0)
            {
                string working = expression.Pop();
                if (Int32.TryParse(working, out int intWorking))
                {
                    // working string is an integer value
                    operands.Push(_symbolTable.FindConstant(intWorking).Location());
                }
                else if (Toolbelt.IsValidVariable(working))
                {
                    char workingChar = Convert.ToChar(working);
                    operands.Push(_symbolTable.FindVariable(Convert.ToInt32(workingChar)).Location());
                }
                else if (Toolbelt.IsOperator(working))
                {
                    int  left, right;
                    char op = Convert.ToChar(working);
                    if (operands.Count() >= 2)
                    {
                        right = operands.Pop();
                        left  = operands.Pop();
                    }
                    else if (operands.Count() == 1 && temps.Count >= 1)
                    {
                        right = temps.Pop();
                        left  = operands.Pop();
                    }
                    else if (temps.Count >= 2)
                    {
                        right = temps.Pop();
                        left  = temps.Pop();
                    }
                    else
                    {
                        return(-1);
                    }
                    // load 'left' from memory
                    _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, left), _workingLineNumber++);
                    // perform calculation on 'left'
                    switch (op)
                    {
                    case '+':
                        _compiledCode.Add(Word.Build((int)EPC.Code.ADD, right), _workingLineNumber++);
                        break;

                    case '-':
                        _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, right), _workingLineNumber++);
                        break;

                    case '*':
                        _compiledCode.Add(Word.Build((int)EPC.Code.MULTIPLY, right), _workingLineNumber++);
                        break;

                    case '/':
                        _compiledCode.Add(Word.Build((int)EPC.Code.DIVIDE, right), _workingLineNumber++);
                        break;
                    }
                    // store result in 'temp'
                    temps.Push(firstTemp - temps.Count());
                    if (_symbolTable.HasLocation(temps.Peek()) && _symbolTable.AtLocation(temps.Peek()).IsConst())
                    {
                        throw new SystemException($"Cannot override constant value at memory[{temps.Peek()}] -on code line {lineNumber}");
                    }
                    _compiledCode.Add(Word.Build((int)EPC.Code.STORE, temps.Peek()), _workingLineNumber++);
                }
                else
                {
                    return(-1);
                }
            }
            return(temps.Pop());
        }
Esempio n. 9
0
        //------------------------------------------------------------------------------------------------------------
        private void ifStatement(string[] tokens, int lineNumber)
        {
            // Assume only one token to the left of the comparator  eg.  20 if x == y goto 50
            // [2] = Left, [3] = Comparator, [4] = Right, [5] = 'goto', [6] = LineNumber
            if (!tokens.Contains("goto"))
            {
                throw new SystemException($"'if' statement missing corresponding 'goto' -on code line {lineNumber}");
            }
            string     left = tokens[2];
            string     comparator = tokens[3];
            string     right = tokens[4];
            string     goTo = tokens[5];
            string     gotoLine = tokens[6];
            TableEntry leftEntry, rightEntry;

            //------------------Begin Validations--------Symbol table update------------
            // Validate left of comparator
            if (Int32.TryParse(left, out int intLeft)) // Third token is a number (constant)
            {
                leftEntry = _symbolTable.FindOrAddConst(intLeft);
                _compiledCode.Add(leftEntry.Symbol(), leftEntry.Location());
            }
            else if (Toolbelt.IsValidVariable(left)) // Third token is a valid variable
            {
                char leftVar = Convert.ToChar(left);
                leftEntry = _symbolTable.FindOrAddVar((int)leftVar);
            }
            else
            {
                throw new SystemException($"{left} not valid following 'if' keyword -on code line {lineNumber}");
            }
            // Validate comparator
            if (!Toolbelt.IsComparator(comparator)) // Fourth token is a valid comparator
            {
                throw new SystemException($"{comparator} is is not a valid comparator in 'if' statement -on code line {lineNumber}");
            }
            // Validate left of comparator
            if (Int32.TryParse(right, out int intRight)) // Third token is a number (constant)
            {
                rightEntry = _symbolTable.FindOrAddConst(intRight);
                _compiledCode.Add(rightEntry.Symbol(), rightEntry.Location());
            }
            else if (Toolbelt.IsValidVariable(right)) // Third token is a valid variable
            {
                char rightVar = Convert.ToChar(right);
                rightEntry = _symbolTable.FindOrAddVar((int)rightVar);
            }
            else
            {
                throw new SystemException($"{right} not valid following comparator in 'if' statement -on code line {lineNumber}");
            }
            // validate that 'goto' is in position 5
            if (goTo != "goto")
            {
                throw new SystemException($"Expected 'goto' after comparison in 'if' statement.  ({goTo}) -on code line {lineNumber}");
            }
            // validate that following the 'goto' is a numeric value
            if (!Int32.TryParse(gotoLine, out int intGotoLine))
            {
                throw new SystemException($"'{gotoLine}' invalid token following 'goto' in 'if' statement.  Integer value expected. -on code line {lineNumber}");
            }
            //-------------End Validations--------------------

            if (leftEntry == null || rightEntry == null)
            {
                throw new SystemException($"Unknown error occurred in 'if/goto' statement -on code line {lineNumber}");
            }

            // lookup goto line number in symbol table
            var  gotoLineEntry  = _symbolTable.FindLineNumber(intGotoLine);
            var  gotoLineNumber = 00;
            bool needsFlag      = false;

            if (gotoLineEntry != null)
            {
                gotoLineNumber = gotoLineEntry.Location();
            }
            else
            {
                needsFlag = true;
            }

            // perform calculations with right operand
            // add appropriate branch command

            switch (comparator)
            {
            case "==":
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, leftEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, rightEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHZERO, gotoLineNumber), _workingLineNumber++);
                break;

            case "!=":
                // check if greater than
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, rightEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, leftEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                // check if less than
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, leftEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, rightEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                break;

            case "<":
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, leftEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, rightEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                break;

            case ">":
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, rightEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, leftEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                break;

            case "<=":
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, leftEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, rightEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHZERO, gotoLineNumber), _workingLineNumber++);
                break;

            case ">=":
                _compiledCode.Add(Word.Build((int)EPC.Code.LOAD, rightEntry.Location()), _workingLineNumber++);
                _compiledCode.Add(Word.Build((int)EPC.Code.SUBTRACT, leftEntry.Location()), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHNEG, gotoLineNumber), _workingLineNumber++);
                if (needsFlag)
                {
                    _flags.Add(_workingLineNumber, intGotoLine);
                }
                _compiledCode.Add(Word.Build((int)EPC.Code.BRANCHZERO, gotoLineNumber), _workingLineNumber++);
                break;
            }
        }