/// <summary> /// Parses a string containing assembler directive. /// </summary> /// <param name="s">An array beginning with a an assembler directive, possibly including arguments.</param> /// <param name="result">If the parse is successful, the Directive represented by the given string. Otherwise, null.</param> /// <returns>A Boolean value indicating whether the parse was successful.</returns> public static bool TryParse(string[] tokens, out AssemblerDirective result) { if (tokens.Length < 1) { result = null; return(false); } Mnemonic dir; if (!Enum.TryParse(tokens[0], true, out dir)) { result = null; return(false); } switch (dir) { // parse arguments properly for each directive. case Mnemonic.BYTE: case Mnemonic.RESW: case Mnemonic.RESB: case Mnemonic.EQU: case Mnemonic.START: case Mnemonic.WORD: case Mnemonic.BASE: if (tokens.Length < 2) // These directives require an argument. { result = null; return(false); } result = new AssemblerDirective(dir); result.Value = tokens[1]; result.Comment = string.Join(" ", tokens, 2, tokens.Length - 2); break; case Mnemonic.END: result = new AssemblerDirective(dir); if (tokens.Length > 1) // Argument of END is optional. { result.Value = tokens[1]; result.Comment = string.Join(" ", tokens, 2, tokens.Length - 2); } break; case Mnemonic.LTORG: // LTORG takes no arguments. result = new LTORG(); result.Comment = string.Join(" ", tokens, 1, tokens.Length - 1); break; default: throw new NotImplementedException($"Assembler directive \"{tokens[0]}\" is not supported!"); } return(true); }
private static bool TryParseWithoutLabel(string[] tokens, out Line result) { // Attempt to parse as instruction. Instruction inst; if (Instruction.TryParse(tokens, out inst)) { result = inst; return(true); } // Attempt to parse as directive. AssemblerDirective dir; if (AssemblerDirective.TryParse(tokens, out dir)) { result = dir; return(true); } // Attempt to parse as @import. ImportDirective id; if (ImportDirective.TryParse(tokens, out id)) { result = id; return(true); } // Attempt to parse as @export. ExportDirective ed; if (ExportDirective.TryParse(tokens, out ed)) { result = ed; return(true); } result = null; return(false); }
public Program MakeRandomProgram(int lines) { t = new Timer(3000); t.Elapsed += TimerElapsed; symbols.Clear(); GenerateSymbols(lines); var ret = new Program(); t.Start(); ret.Add(new AssemblerDirective(AssemblerDirective.Mnemonic.START) { //Value = r.Next(0, 1 << 12).ToString() Value = "0" }); for (int lineIdx = 0; lineIdx < lines; ++lineIdx) { Line line; // Make a WORD or RESW. if (r.NextDouble() < CHANCE_MEMORY) { AssemblerDirective dir; if (r.NextDouble() < CHANCE_RESW) { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.WORD); } else { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.RESW); } if (r.NextDouble() < CHANCE_USE_SYMBOL) { // The symbol we put here must not have been defined elsewhere. var sym = GetUndefinedSymbol(); dir.Label = sym.Name; sym.Define(); } dir.Value = GetSmallishNumber().ToString(); line = dir; } else { // Make an instruction. //Instruction.Mnemonic. Instruction instr = new Instruction(MNEMONICS[r.Next(MNEMONICS.Length)]); for (int operandIdx = 0; operandIdx < instr.Operands.Count; ++operandIdx) { var operand = instr.Operands[operandIdx]; switch (instr.Format) { case InstructionFormat.Format2: // Choose register. operand.Value = (int)REGISTERS[r.Next(REGISTERS.Length)]; break; case InstructionFormat.Format3: case InstructionFormat.Format4: case InstructionFormat.Format3Or4: // Choose whether a symbol will be referenced. if (r.NextDouble() < CHANCE_USE_SYMBOL) { operand.SymbolName = GetSymbol(); } else { // Use immediate instead of symbol. operand.Value = r.Next(-0x7ff, 0x800); } // Choose direct/indirect. if (r.NextDouble() < CHANCE_INDIRECT) { operand.AddressingMode = AddressingMode.Indirect; } // Choose immediate. if (r.NextDouble() < CHANCE_IMMEDIATE) { operand.AddressingMode |= AddressingMode.Immediate; } // Choose extended. if (r.NextDouble() < CHANCE_EXTENDED) { //operand.AddressingMode |= AddressingMode.Extended; instr.Format = InstructionFormat.Format4; } break; } } // For each operand. line = instr; } // Choose between making this line a WORD or an instruction. ret.Add(line); Interlocked.Increment(ref linesProcessed); } // For each line in output program. // Finally, append any symbols that are still undefined by this point. foreach (var s in symbols) { if (!s.IsDefined) { AssemblerDirective dir; if (r.NextDouble() < CHANCE_RESW) { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.WORD); } else { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.RESW); } dir.Label = s.Name; s.Define(); dir.Value = GetSmallishNumber().ToString(); ret.Add(dir); } } t.Stop(); Console.Error.WriteLine(); return(ret); }