/// <summary> /// Пытается достать из строки объявление переменной. /// Если в строке нет слова eql, то возвращает false, /// Если есть и строка имеет формат *идетификатор* eql *адрес*, то пытается сохранить адрес за идентификатором /// Если есть, но строка не подходит по формату, выбрасывает исключение <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода для обработки.</param> /// <param name="env">Окружение компилятора.</param> /// <returns>True, если в строке присутствовала переменная, false, если нет.</returns> public bool TryToGetVariable(string line, CompilerEnvironment env) { if (!line.Contains(" eql ")) { return(false); } var args = line.Split(' ').Select(x => x.ToLower().Trim()).ToArray(); if (args.Length != 3 || !args[1].Equals("eql", StringComparison.OrdinalIgnoreCase)) { throw new CompilationErrorExcepton("Объявление переменной должно соответствовать формату *имя переменной* eql *адрес*.", env.GetCurrentLine()); } bool isIdentifierCorrect = CompilerSupport.CheckIdentifierName(args[0]); if (!isIdentifierCorrect) { throw new CompilationErrorExcepton("Имя переменной должно содержать только латиские буквы, цифры знаки тире и подчеркивания и начинаться с буквы.", env.GetCurrentLine()); } int address = CompilerSupport.ConvertToInt(args[2]); if (address > 255) { throw new CompilationErrorExcepton("Адрес не может превышать 255", env.GetCurrentLine()); } if (env.IsIdentifierExist(args[0])) { throw new CompilationErrorExcepton($"Идентификатор с именем {args[0]} уже существует.", env.GetCurrentLine()); } env.AddVariable(args[0], address); return(true); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [5] = true, [6] = true } }; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; return(dataResponse); } int address = CompilerSupport.ConvertVariableToAddress(args[0], env); if (address == -1) { throw new CompilationErrorExcepton($"Переменной с именем {args[0]} не существует.", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, Constants.ShortAddressBitsCount); return(dataResponse); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { int register = CompilerSupport.ConvertToInt(args[0]); if (register < 0 || register > 127) { throw new CompilationErrorExcepton("Номер регистра должен быть числом от 0 до 127", env.GetCurrentLine()); } int bit = CompilerSupport.ConvertToInt(args[1]); if (bit < 0 || bit > 7) { throw new CompilationErrorExcepton("Номер бита должен быть числом от 0 до 7", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [7] = true, [5] = true } }; CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, register, 7); CompilerSupport.FillBitArray(null, dataResponse.highBitArray, bit, 3); return(dataResponse); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [7] = true } }; int address = CompilerSupport.ConvertVariableToAddress(args[0], env); if (address == -1) { throw new CompilationErrorExcepton($"Переменной с именем {args[0]} не существует.", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, Constants.ShortAddressBitsCount); int bit = CompilerSupport.ConvertToInt(args[1]); if (bit >= 1 << 3 || bit < 0) { throw new CompilationErrorExcepton("Номер бита не должен превышать 7", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.highBitArray, bit, 3); return(dataResponse); }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line[1] == 'n' || line[1] == 'N') { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /n должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if (line[1] == 'D' || line[1] == 'd') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }
private static DataResponse GetBitArrays(string[] args, string op, CompilerEnvironment env) { if (args.Length < 0 || args.Length > 2) { throw new CompilationErrorExcepton($"Команда {op} принимает 1 или 2 агрумента.", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) }; var r = CompilerSupport.ConvertToRegister(args[0]); if (r.HasValue) { return(DataResponseFromRegister(args, op, env, dataResponse, r.Value)); } if (args.Length == 2) { throw new CompilationErrorExcepton($"При работе с оперативной памятью команда {op} принимает только 1 аргумент", env.GetCurrentLine()); } dataResponse.highBitArray[6] = true; dataResponse.highBitArray[5] = true; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; } else { var address = CompilerSupport.ConvertVariableToAddress(args[0], env); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, 8); } return(dataResponse); }
private static DataResponse GetBitArrays(string[] args, string op, CompilerEnvironment env) { if (args.Length != 1) { throw new CompilationErrorExcepton($"Команда {op} принимает 1 агрумент.", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new ExtendedBitArray(), highBitArray = new ExtendedBitArray() }; var r = CompilerSupport.ConvertToRegister(args[0]); if (r.HasValue) { if (r.Value.Number > 7) { throw new CompilationErrorExcepton($"Номер регистра не может быть больше 7.", env.GetCurrentLine()); } return(DataResponseFromRegister(args, op, env, dataResponse, r.Value)); } dataResponse.highBitArray[6] = true; dataResponse.highBitArray[5] = true; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; } else { var address = CompilerSupport.ConvertVariableToAddress(args[0], env); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, 8); } return(dataResponse); }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line.Substring(1).ToLower().StartsWith("org")) { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /org должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && line[2] != 'B' && line[2] != 'b' && line[2] != 'W' && line[2] != 'w') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'B' || line[2] == 'b')) //работа дерективы .db { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); int address = CompilerSupport.ConvertLabelToFarAddress(value, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, value); } } } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'W' || line[2] == 'w')) //работа дерективы .dw { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); List <string> parameters = new List <string>(); if (value.StartsWith("0x") && value.Length > 4) //если адрес формата 0xFFFF или 0xFFF, раскладываем на 2 байта { parameters.Add("0x" + value.Substring(value.Length - 2)); parameters.Add(value.Substring(0, value.Length - 2)); } else if (value.StartsWith("0b") && value.Length > 10) //если 0b11..11 (больше 1 байта) { parameters.Add("0b" + value.Substring(value.Length - 8)); parameters.Add(value.Substring(0, value.Length - 8)); } else { parameters.Add(value); //если 0xFF, 0b11111111 или Метка parameters.Add("0x00"); } foreach (var p in parameters) { int address = CompilerSupport.ConvertLabelToFarAddress(p, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, p); } } } } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line.Substring(1).ToLower().StartsWith("org")) { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /org должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && line[2] != 'B' && line[2] != 'b') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'B' || line[2] == 'b')) { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); int address = CompilerSupport.ConvertLabelToFarAddress(value, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, value); } } } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }