protected override string OnAssemble(RandomAccessIterator <SourceLine> lines) { var line = lines.Current; if (Reserved.IsOneOf("Goto", line.Instruction.Name)) { return(DoGoto(lines)); } if (Reserved.IsOneOf("Functional", line.Instruction.Name)) { if (line.Instruction.Name.Equals(".function", Services.StringComparison)) { DefineFunction(lines); } else if (_currentBlock != null) { throw new SyntaxException(line.Instruction.Position, "Directive \".endfunction\" can only be made inside function block."); } return(string.Empty); } if (_openClosures.ContainsKey(line.Instruction.Name)) { var block = GetProcessor(line, lines.Index); if (_blocks.Count == 0) { ScanBlock(lines); } _blocks.Push(block); _currentBlock = block; } if (line.Instruction.Name.Equals(".block", Services.StringComparison) && line.Label != null) { DefineLabel(line.Label, PCOnAssemble, false); } var isBreakCont = Reserved.IsOneOf("BreakContinue", line.Instruction.Name); if (_currentBlock == null || (!isBreakCont && !_currentBlock.IsReserved(line.Instruction.Name))) { throw new SyntaxException(line.Instruction.Position, $"\"{line.Instruction.Name}\" directive must come inside a block."); } if (isBreakCont) { if (line.Operands.Count > 0) { throw new SyntaxException(line.Operands[0], "Unexpected expression."); } var isBreak = line.Instruction.Name.Equals(".break", Services.StringComparison); if ((!_currentBlock.AllowContinue && line.Instruction.Name.Equals(".continue", Services.StringComparison)) || (!_currentBlock.AllowBreak && isBreak)) { while (_currentBlock != null) { var allowBreak = false; _currentBlock.SeekBlockEnd(lines); if (isBreak) { allowBreak = _currentBlock.AllowBreak; } else if (!isBreak && _currentBlock.AllowContinue) { break; } DoPop(lines); if (isBreak && allowBreak) { return(string.Empty); } } if (_currentBlock == null) { var err = isBreak ? "break" : "continue"; throw new SyntaxException(line.Instruction.Position, $"No enclosing loop out of which to {err}."); } } else if (isBreak) { DoPop(lines); return(string.Empty); } else { _currentBlock.SeekBlockEnd(lines); } } _currentBlock.ExecuteDirective(lines); if (lines.Current.Instruction != null && lines.Current.Instruction.Name.Equals(_currentBlock.BlockClosure, Services.StringComparison)) { DoPop(lines); } if (line.Label != null) { return($".{Services.Output.LogicalPC,-42:x4}{line.Source.Substring(line.Label.Position - 1, line.Label.Name.Length)}"); } return(string.Empty); }