예제 #1
0
        public static (List <Lex>, List <string>) lex(string[] input)
        {
            List <Lex>    result            = new List <Lex>();
            List <string> encounteredErrors = new List <string>();

            for (var i = 0; i < input.Length; i++)
            {
                string   line         = input[i];
                string[] lineContents = line.Split(new Char[] { ' ', ',' });
                if (lineContents.Length <= 0)
                {
                    continue;
                }

                bool isValidCommand = true;
                Lex  thisLex        = new Lex();
                thisLex.arguments = new List <string>();

                switch (lineContents[0].ToUpper())
                {
                case "JP": thisLex.instructionType = InstructionType.JP; break;

                case "JNE": thisLex.instructionType = InstructionType.JNE; break;

                case "JPE": thisLex.instructionType = InstructionType.JPE; break;

                case "LD": thisLex.instructionType = InstructionType.LD; break;

                case "ADD": thisLex.instructionType = InstructionType.Add; break;

                case "OR": thisLex.instructionType = InstructionType.OR; break;

                case "AND": thisLex.instructionType = InstructionType.AND; break;

                case "XOR": thisLex.instructionType = InstructionType.XOR; break;

                case "SUB": thisLex.instructionType = InstructionType.SUB; break;

                case "SLR": thisLex.instructionType = InstructionType.SLR; break;

                case "SLL": thisLex.instructionType = InstructionType.SLL; break;

                case "SETDL": thisLex.instructionType = InstructionType.SETDL; break;

                case "GETDL": thisLex.instructionType = InstructionType.GETDL; break;

                case "DIS": thisLex.instructionType = InstructionType.DIS; break;

                default:
                    encounteredErrors.Add($"Line {i.ToString()}: {lineContents[0]} not recognized as a command.");
                    isValidCommand = false;
                    break;
                }

                if (isValidCommand)
                {
                    bool frstArg = true;
                    foreach (string arg in lineContents)
                    {
                        if (frstArg || (arg.Length <= 0))
                        {
                            frstArg = false;
                            continue;
                        }

                        thisLex.arguments.Add(arg.ToUpper());
                    }

                    thisLex.lineNumber = i;

                    result.Add(thisLex);
                }
            }

            return(result, encounteredErrors);
        }
예제 #2
0
        public static (List <char>, List <string>) Assemble(List <Lex> lexerOutput)
        {
            List <char>   result = new List <char>();
            List <string> errors = new List <string>();

            for (var i = 0; i < lexerOutput.Count; i++)
            {
                Lex  line         = lexerOutput[i];
                char ResultOpcode = (char)0x0000;
                int  dest         = new int();
                int  src          = new int();
                int  lit          = new int();
                switch (line.instructionType)
                {
                case InstructionType.Add:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Destination must be a register.");
                        break;
                    }

                    if ((getArgType(line.arguments[1]) != ArgType.reg) && (getArgType(line.arguments[1]) != ArgType.literal))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: \"line.arguments[1]\" not recognized as a valid register/literal.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    if (getArgType(line.arguments[1]) == ArgType.reg)
                    {
                        src          = getReg(line.arguments[1]) & 0xF;
                        ResultOpcode = (char)(0x8004 + (dest << 8) + (src << 4));
                    }
                    else
                    {
                        lit          = literalParse(line.arguments[1]) & 0xFF;
                        ResultOpcode = (char)(0x7000 + (dest << 8) + lit);
                    }
                    break;

                case InstructionType.LD:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Destination must be a register.");
                        break;
                    }

                    if ((getArgType(line.arguments[1]) != ArgType.reg) && (getArgType(line.arguments[1]) != ArgType.literal))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: \"line.arguments[1]\" not recognized as a valid register/literal.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    if (getArgType(line.arguments[1]) == ArgType.reg)
                    {
                        src          = getReg(line.arguments[1]) & 0xF;
                        ResultOpcode = (char)(0x8000 + (dest << 8) + (src << 4));
                    }
                    else
                    {
                        lit          = literalParse(line.arguments[1]) & 0xFF;
                        ResultOpcode = (char)(0x6000 + (dest << 8) + lit);
                    }
                    break;

                case InstructionType.JNE:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Destination must be a register.");
                        break;
                    }

                    if ((getArgType(line.arguments[1]) != ArgType.reg) && (getArgType(line.arguments[1]) != ArgType.literal))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: \"line.arguments[1]\" not recognized as a valid register/literal.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    if (getArgType(line.arguments[1]) == ArgType.reg)
                    {
                        src          = getReg(line.arguments[1]) & 0xF;
                        ResultOpcode = (char)(0x9000 + (dest << 8) + (src << 4));
                    }
                    else
                    {
                        lit          = literalParse(line.arguments[1]) & 0xFF;
                        ResultOpcode = (char)(0x4000 + (dest << 8) + lit);
                    }
                    break;

                case InstructionType.JPE:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Destination must be a register.");
                        break;
                    }

                    if ((getArgType(line.arguments[1]) != ArgType.reg) && (getArgType(line.arguments[1]) != ArgType.literal))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: \"line.arguments[1]\" not recognized as a valid register/literal.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    if (getArgType(line.arguments[1]) == ArgType.reg)
                    {
                        src          = getReg(line.arguments[1]) & 0xF;
                        ResultOpcode = (char)(0x5000 + (dest << 8) + (src << 4));
                    }
                    else
                    {
                        lit          = literalParse(line.arguments[1]) & 0xFF;
                        ResultOpcode = (char)(0x3000 + (dest << 8) + lit);
                    }
                    break;

                case InstructionType.SUB:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Destination must be a register.");
                        break;
                    }

                    if (getArgType(line.arguments[1]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Source must be a register.");
                        break;
                    }

                    dest         = getReg(line.arguments[0]) & 0xF;
                    src          = getReg(line.arguments[1]) & 0xF;
                    ResultOpcode = (char)(0x8005 + (dest << 8) + (src << 4));
                    break;

                case InstructionType.AND:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if ((getArgType(line.arguments[0]) != ArgType.reg) || (getArgType(line.arguments[1]) != ArgType.reg))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operands must be registers.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    src  = getReg(line.arguments[1]) & 0xF;

                    ResultOpcode = (char)(0x8002 + (dest << 8) + (src << 4));

                    break;

                case InstructionType.OR:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if ((getArgType(line.arguments[0]) != ArgType.reg) || (getArgType(line.arguments[1]) != ArgType.reg))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operands must be registers.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    src  = getReg(line.arguments[1]) & 0xF;

                    ResultOpcode = (char)(0x8001 + (dest << 8) + (src << 4));

                    break;

                case InstructionType.XOR:
                    if (line.arguments.Count != 2)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if ((getArgType(line.arguments[0]) != ArgType.reg) || (getArgType(line.arguments[1]) != ArgType.reg))
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operands must be registers.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;
                    src  = getReg(line.arguments[1]) & 0xF;

                    ResultOpcode = (char)(0x8003 + (dest << 8) + (src << 4));

                    break;

                case InstructionType.SLL:
                    if (line.arguments.Count != 1)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operand must be a register.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;

                    ResultOpcode = (char)(0x800E + (dest << 8));

                    break;

                case InstructionType.SLR:
                    if (line.arguments.Count != 1)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operand must be a register.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;

                    ResultOpcode = (char)(0x8006 + (dest << 8));

                    break;

                case InstructionType.DIS:
                    if (line.arguments.Count > 0)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: No operands are needed for DIS.");
                        break;
                    }

                    ResultOpcode = (char)(0xF000);

                    break;

                default: break;

                case InstructionType.SETDL:
                    if (line.arguments.Count != 1)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operand must be a register.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;

                    ResultOpcode = (char)(0xF015 + (dest << 8));

                    break;

                case InstructionType.GETDL:
                    if (line.arguments.Count != 1)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.reg)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operand must be a register.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xF;

                    ResultOpcode = (char)(0xF007 + (dest << 8));

                    break;

                case InstructionType.JP:
                    if (line.arguments.Count != 1)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Bad number of operands.");
                        break;
                    }

                    if (getArgType(line.arguments[0]) != ArgType.literal)
                    {
                        ResultOpcode = (char)0x0000;
                        errors.Add($"Line {line.lineNumber}: Operand must be a literal.");
                        break;
                    }

                    dest = getReg(line.arguments[0]) & 0xFFF;

                    ResultOpcode = (char)(0x1000 + dest);

                    break;
                }

                result.Add(ResultOpcode);
            }

            return(result, errors);
        }