コード例 #1
0
ファイル: BlockAssembler.cs プロジェクト: cluckfox/6502.Net
        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);
        }