Exemplo n.º 1
0
        /// <summary>
        /// Seeks the <see cref="SourceLine"/> containing the
        /// first instance one of the directives in the block.
        /// </summary>
        /// <param name="iterator">The source line iterator.</param>
        /// <param name="directives">An array of directives, one of which to seek in the block.</param>
        protected void SeekBlockDirectives(RandomAccessIterator <SourceLine> iterator, StringView[] directives)
        {
            var line = iterator.Current;

            if (!line.Instruction.Name.Equals(BlockClosure, Services.StringComparison))
            {
                var blockClose = BlockClosure;

                var keywordsNotToSkip = new List <StringView>(directives)
                {
                    blockClose
                };
                keywordsNotToSkip.AddRange(BlockOpens.Select(bo => new StringView(bo)));

                var opens = 1;
                while (opens != 0)
                {
                    line = iterator.FirstOrDefault(l => l.Instruction != null && keywordsNotToSkip.Contains(l.Instruction.Name, Services.StringViewComparer));
                    if (line == null)
                    {
                        throw new BlockClosureException(BlockOpens.First());
                    }

                    if (BlockOpens.Contains(line.Instruction.Name.ToString(), Services.StringComparer))
                    {
                        opens++;
                    }

                    if (opens < 2 && directives.Contains(line.Instruction.Name, Services.StringViewComparer))
                    {
                        break;
                    }

                    if (line.Instruction.Name.Equals(blockClose, Services.StringComparison))
                    {
                        opens--;
                    }
                }
            }
        }
Exemplo n.º 2
0
        string DoGoto(RandomAccessIterator <SourceLine> lines)
        {
            var line = lines.Current;

            if (line.Operands.Count == 0)
            {
                throw new SyntaxException(line.Instruction.Position,
                                          "Destination not specified for \".goto\" directive.");
            }

            var gotoExp = line.Operands[0].Name;

            if ((!char.IsLetter(gotoExp[0]) && gotoExp[0] != '_') || line.Operands.Count > 1)
            {
                Services.Log.LogEntry(line.Operands[0],
                                      "\".goto\" operand must be a label.");
            }
            else if (line.Label != null && gotoExp.Equals(line.Label.Name, Services.StringViewComparer))
            {
                Services.Log.LogEntry(line.Instruction,
                                      "Destination cannot be the same line as \".goto\" directive.");
            }
            else
            {
                var        iterCopy = new RandomAccessIterator <SourceLine>(lines, true);
                SourceLine currLine;
                if ((currLine = iterCopy.FirstOrDefault(l =>
                {
                    if (l.Instruction != null && _openClosures.ContainsKey(l.Instruction.Name))
                    {
                        if (l.Instruction.Name.Equals(".function", Services.StringComparison))
                        {
                            throw new SyntaxException(l.Instruction, "Function block cannot be inside another block.");
                        }
                        // leap over any blocks we find along the way we are not currently in.
                        if (!_blocks.Any(b => b.Index == iterCopy.Index))
                        {
                            GetProcessor(l, iterCopy.Index).SeekBlockEnd(iterCopy);
                        }
                        return(false);
                    }
                    return(l.Label != null && l.Label.Name.Equals(gotoExp, Services.StringViewComparer));
                })) != null)
                {
                    if (currLine.Instruction != null &&
                        (currLine.Instruction.Name.Contains('=') ||
                         currLine.Instruction.Name.Equals(".equ", Services.StringComparison) ||
                         currLine.Instruction.Name.Equals(".global", Services.StringComparison)
                        )
                        )
                    {
                        Services.Log.LogEntry(line.Instruction,
                                              $"\"{gotoExp}\" is not a valid destination.");
                    }
                    else
                    {
                        while (_currentBlock != null)
                        {
                            // if where we landed lies outside of the current block scope
                            // we need to pop out of that scope.
                            _currentBlock.SeekBlockEnd(lines);
                            if (iterCopy.Index > _currentBlock.Index)
                            {
                                // did we land in a place still within the block scope?
                                if (iterCopy.Index > lines.Index)
                                {
                                    // no, pop out
                                    DoPop(lines);
                                }
                                else
                                {
                                    // we're still within the current block, don't pop it
                                    break;
                                }
                            }
                            else
                            {
                                // we went backwards, pop out of current scope
                                DoPop(lines);
                            }
                        }
                        if (iterCopy.Index >= lines.Index)
                        {
                            lines.FastForward(iterCopy.Index);
                        }
                        else if (iterCopy.Index == 0)
                        {
                            lines.Reset();
                        }
                        else
                        {
                            lines.Rewind(iterCopy.Index - 1);
                        }
                    }
                }
                else
                {
                    Services.Log.LogEntry(line.Instruction,
                                          $"Could not find destination \"{gotoExp}\".");
                }
            }
            return(string.Empty);
        }