/// <summary>
        /// Returns a visitor with the results of a single parsing pass
        /// </summary>
        /// <param name="textToParse">Z80 assembly code to parse</param>
        /// <param name="expectedErrors">Number of errors expected</param>
        /// <returns>
        /// Visitor with the syntax tree
        /// </returns>
        protected virtual ExpressionNode ParseExpr(string textToParse, int expectedErrors = 0)
        {
            var inputStream = new AntlrInputStream(textToParse);
            var lexer       = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Z80AsmParser(tokenStream);
            var context     = parser.expr();
            var visitor     = new Z80AsmVisitor();

            parser.SyntaxErrors.Count.ShouldBe(expectedErrors);
            return((ExpressionNode)visitor.VisitExpr(context));
        }
        /// <summary>
        /// Returns a visitor with the results of a single parsing pass
        /// </summary>
        /// <param name="textToParse">Z80 assembly code to parse</param>
        /// <returns>
        /// Visitor with the syntax tree
        /// </returns>
        protected virtual List <Z80AsmParserErrorInfo> ParseWithErrors(string textToParse)
        {
            var inputStream = new AntlrInputStream(textToParse);
            var lexer       = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Z80AsmParser(tokenStream);
            var context     = parser.compileUnit();
            var visitor     = new Z80AsmVisitor();

            visitor.Visit(context);
            return(parser.SyntaxErrors);
        }
Exemple #3
0
        /// <summary>
        /// Visits the source code
        /// </summary>
        /// <param name="source">Source code string</param>
        /// <returns>Source code visitor object</returns>
        public static Z80AsmVisitor VisitSource(string source)
        {
            var inputStream = new AntlrInputStream(source);
            var lexer       = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Z80AsmParser(tokenStream);
            var context     = parser.compileUnit();
            var visitor     = new Z80AsmVisitor(inputStream);

            visitor.Visit(context);
            return(visitor);
        }
        /// <summary>
        /// Returns a visitor with the results of a single parsing pass
        /// </summary>
        /// <param name="textToParse">Z80 assembly code to parse</param>
        /// <returns>
        /// Visitor with the syntax tree
        /// </returns>
        private Z80AsmVisitor ParseAsmLine(string textToParse)
        {
            var inputStream = new AntlrInputStream(textToParse);
            var lexer       = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Z80AsmParser(tokenStream);
            var context     = parser.asmline();
            var visitor     = new Z80AsmVisitor();

            visitor.Visit(context);
            return(visitor);
        }
        /// <summary>
        /// Returns a visitor with the results of a single parsing pass
        /// </summary>
        /// <param name="textToParse">Z80 assembly code to parse</param>
        /// <param name="expectedErrors">Number of errors expected</param>
        /// <returns>
        /// Visitor with the syntax tree
        /// </returns>
        protected virtual Z80AsmVisitor Parse(string textToParse, int expectedErrors = 0)
        {
            var inputStream = new AntlrInputStream(textToParse);
            var lexer       = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser      = new Z80AsmParser(tokenStream);
            var context     = parser.compileUnit();
            var visitor     = new Z80AsmVisitor();

            visitor.Visit(context);
            parser.SyntaxErrors.Count.ShouldBe(expectedErrors);

            return(visitor);
        }
        /// <summary>
        /// Gets all the tags that intersect the specified spans.
        /// </summary>
        /// <param name="spans">The spans to visit.</param>
        /// <returns>
        /// A <see cref="T:Microsoft.VisualStudio.Text.Tagging.TagSpan`1" /> for each tag.
        /// </returns>
        public IEnumerable <ITagSpan <TextMarkerTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            // --- Go through the tags
            foreach (var curSpan in spans)
            {
                var firstLineNo = curSpan.Start.GetContainingLine().LineNumber;
                var lastLineNo  = curSpan.End.GetContainingLine().LineNumber;
                foreach (var line in SourceBuffer.CurrentSnapshot.Lines)
                {
                    if (line.LineNumber < firstLineNo || line.LineNumber > lastLineNo)
                    {
                        continue;
                    }

                    var textOfLine = line.GetText();

                    // --- Let's use the Z80 assembly parser to obtain tags
                    var inputStream = new AntlrInputStream(textOfLine);
                    var lexer       = new Z80AsmLexer(inputStream);
                    var tokenStream = new CommonTokenStream(lexer);
                    var parser      = new Z80AsmParser(tokenStream);
                    var context     = parser.asmline();
                    var visitor     = new Z80AsmVisitor(inputStream);
                    visitor.Visit(context);
                    if (!(visitor.LastAsmLine is SourceLineBase asmline))
                    {
                        continue;
                    }

                    var package = SpectNetPackage.Default;
                    if (package != null &&
                        string.Compare(package.DebugInfoProvider.CurrentBreakpointFile, FilePath,
                                       StringComparison.InvariantCultureIgnoreCase) == 0 &&
                        package.DebugInfoProvider.CurrentBreakpointLine - 1 == line.LineNumber)
                    {
                        // --- Check for the current breakpoint
                        yield return(CreateSpan(line,
                                                Package.Options.FullLineHighlight
                                ? new TextSpan(0, textOfLine.Length) : asmline.InstructionSpan,
                                                Z80AsmClassificationTypes.Z80_CURRENT_BREAKPOINT));
                    }
                }
            }
        }
        /// <summary>
        /// Gets all the tags that intersect the specified spans.
        /// </summary>
        /// <param name="spans">The spans to visit.</param>
        /// <returns>
        /// A <see cref="T:Microsoft.VisualStudio.Text.Tagging.TagSpan`1" /> for each tag.
        /// </returns>
        public IEnumerable <ITagSpan <Z80DebugTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            // --- Go through the tags
            foreach (var curSpan in spans)
            {
                var firstLineNo = curSpan.Start.GetContainingLine().LineNumber;
                var lastLineNo  = curSpan.End.GetContainingLine().LineNumber;
                foreach (var line in SourceBuffer.CurrentSnapshot.Lines)
                {
                    if (line.LineNumber < firstLineNo || line.LineNumber > lastLineNo)
                    {
                        continue;
                    }

                    var textOfLine = line.GetText();

                    // --- Let's use the Z80 assembly parser to obtain tags
                    var inputStream = new AntlrInputStream(textOfLine);
                    var lexer       = new Z80AsmLexer(inputStream);
                    var tokenStream = new CommonTokenStream(lexer);
                    var parser      = new Z80AsmParser(tokenStream);
                    var context     = parser.asmline();
                    var visitor     = new Z80AsmVisitor();
                    visitor.Visit(context);
                    if (!(visitor.LastAsmLine is SourceLineBase asmline))
                    {
                        continue;
                    }

                    if (_currentBreakpointLine == line.LineNumber)
                    {
                        // --- Check for the current breakpoint
                        yield return(CreateSpan(line,
                                                Package.Options.FullLineHighlight
                                ? new TextSpan(0, textOfLine.Length) : asmline.InstructionSpan,
                                                "Z80CurrentBreakpoint"));
                    }
                }
            }
        }
        /// <summary>
        /// Gets all the tags that intersect the specified spans.
        /// </summary>
        /// <param name="spans">The spans to visit.</param>
        /// <returns>
        /// A <see cref="T:Microsoft.VisualStudio.Text.Tagging.TagSpan`1" /> for each tag.
        /// </returns>
        public IEnumerable <ITagSpan <Z80AsmTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            // --- Obtain the breakpoints that may affect this view
            var affectedLines = new List <int>();

            if (Package != null)
            {
                foreach (Breakpoint bp in Package.ApplicationObject.Debugger.Breakpoints)
                {
                    if (string.Compare(bp.File, FilePath, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        // --- Breakpoints start lines at 1, ITextBuffer starts from 0
                        affectedLines.Add(bp.FileLine - 1);
                    }
                }
            }

            foreach (var curSpan in spans)
            {
                var currentLine = curSpan.Start.GetContainingLine();
                var textOfLine  = currentLine.GetText();

                // --- Just to be sure...
                if (textOfLine == null)
                {
                    yield break;
                }

                // --- Let's use the Z80 assembly parser to obtain tags
                var inputStream = new AntlrInputStream(textOfLine);
                var lexer       = new Z80AsmLexer(inputStream);
                var tokenStream = new CommonTokenStream(lexer);
                var parser      = new Z80AsmParser(tokenStream);
                var context     = parser.asmline();
                var visitor     = new Z80AsmVisitor();
                visitor.Visit(context);

                // --- Check for a block comment
                var lastStartIndex = 0;
                while (true)
                {
                    var blockBeginsPos = textOfLine.IndexOf("/*", lastStartIndex, StringComparison.Ordinal);
                    if (blockBeginsPos < 0)
                    {
                        break;
                    }
                    var blockEndsPos = textOfLine.IndexOf("*/", blockBeginsPos, StringComparison.Ordinal);
                    if (blockEndsPos <= blockBeginsPos)
                    {
                        break;
                    }

                    // --- Block comment found
                    lastStartIndex = blockEndsPos + 2;
                    yield return(CreateSpan(currentLine, new TextSpan(blockBeginsPos, blockEndsPos + 2), Z80AsmTokenType.Comment));
                }

                // --- No code line, no tagging
                if (!(visitor.LastAsmLine is SourceLineBase asmline))
                {
                    continue;
                }

                if (asmline is EmittingOperationBase && asmline.InstructionSpan != null)
                {
                    // --- This line contains executable instruction,
                    // --- So it might have a breakpoint
                    if (affectedLines.IndexOf(currentLine.LineNumber) >= 0)
                    {
                        // --- Check for the any preset breakpoint
                        yield return(CreateSpan(currentLine, asmline.InstructionSpan, Z80AsmTokenType.Breakpoint));
                    }
                }

                if (asmline.LabelSpan != null)
                {
                    // --- Retrieve a label
                    yield return(CreateSpan(currentLine, asmline.LabelSpan, Z80AsmTokenType.Label));
                }

                if (asmline.KeywordSpan != null)
                {
                    var type = Z80AsmTokenType.Instruction;
                    switch (asmline)
                    {
                    case PragmaBase _:
                        type = Z80AsmTokenType.Pragma;
                        break;

                    case Directive _:
                        type = Z80AsmTokenType.Directive;
                        break;

                    case IncludeDirective _:
                        type = Z80AsmTokenType.Include;
                        break;

                    case MacroOrStructInvocation _:
                        type = Z80AsmTokenType.MacroInvocation;
                        break;

                    case ModuleStatement _:
                    case ModuleEndStatement _:
                        type = Z80AsmTokenType.ModuleKeyword;
                        break;

                    case StatementBase _:
                        type = Z80AsmTokenType.Statement;
                        break;
                    }

                    // --- Retrieve a pragma/directive/instruction
                    yield return(CreateSpan(currentLine, asmline.KeywordSpan, type));
                }

                if (asmline.CommentSpan != null)
                {
                    yield return(CreateSpan(currentLine, asmline.CommentSpan, Z80AsmTokenType.Comment));
                }

                if (asmline.NumberSpans != null)
                {
                    foreach (var numberSpan in asmline.NumberSpans)
                    {
                        yield return(CreateSpan(currentLine, numberSpan, Z80AsmTokenType.Number));
                    }
                }

                if (asmline.StringSpans != null)
                {
                    foreach (var stringSpan in asmline.StringSpans)
                    {
                        yield return(CreateSpan(currentLine, stringSpan, Z80AsmTokenType.String));
                    }
                }

                if (asmline.FunctionSpans != null)
                {
                    foreach (var functionSpan in asmline.FunctionSpans)
                    {
                        yield return(CreateSpan(currentLine, functionSpan, Z80AsmTokenType.Function));
                    }
                }

                if (asmline.SemiVarSpans != null)
                {
                    foreach (var semiVarSpan in asmline.SemiVarSpans)
                    {
                        yield return(CreateSpan(currentLine, semiVarSpan, Z80AsmTokenType.SemiVar));
                    }
                }

                if (asmline.MacroParamSpans != null)
                {
                    foreach (var macroParamSpan in asmline.MacroParamSpans)
                    {
                        yield return(CreateSpan(currentLine, macroParamSpan, Z80AsmTokenType.MacroParam));
                    }
                }

                if (asmline.IdentifierSpans != null)
                {
                    foreach (var id in asmline.IdentifierSpans)
                    {
                        yield return(CreateSpan(currentLine, id, Z80AsmTokenType.Identifier));
                    }
                }

                if (asmline.StatementSpans != null)
                {
                    foreach (var statement in asmline.StatementSpans)
                    {
                        yield return(CreateSpan(currentLine, statement, Z80AsmTokenType.Statement));
                    }
                }

                if (asmline.OperandSpans != null)
                {
                    foreach (var operand in asmline.OperandSpans)
                    {
                        yield return(CreateSpan(currentLine, operand, Z80AsmTokenType.Operand));
                    }
                }

                if (asmline.MnemonicSpans != null)
                {
                    foreach (var mnemonic in asmline.MnemonicSpans)
                    {
                        yield return(CreateSpan(currentLine, mnemonic, Z80AsmTokenType.Instruction));
                    }
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets all the tags that intersect the specified spans.
        /// </summary>
        /// <param name="spans">The spans to visit.</param>
        /// <returns>
        /// A <see cref="T:Microsoft.VisualStudio.Text.Tagging.TagSpan`1" /> for each tag.
        /// </returns>
        public IEnumerable <ITagSpan <Z80AsmTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            // --- Obtain the breakpoints that may affect this view
            var affectedLines = new List <int>();

            foreach (Breakpoint bp in Package.ApplicationObject.Debugger.Breakpoints)
            {
                if (string.Compare(bp.File, FilePath, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    // --- Breakpoints start lines at 1, ITextBuffer starts from 0
                    affectedLines.Add(bp.FileLine - 1);
                }
            }

            foreach (var curSpan in spans)
            {
                var currentLine = curSpan.Start.GetContainingLine();
                var textOfLine  = currentLine.GetText();

                // --- Let's use the Z80 assembly parser to obtain tags
                var inputStream = new AntlrInputStream(textOfLine);
                var lexer       = new Z80AsmLexer(inputStream);
                var tokenStream = new CommonTokenStream(lexer);
                var parser      = new Z80AsmParser(tokenStream);
                var context     = parser.asmline();
                var visitor     = new Z80AsmVisitor();
                visitor.Visit(context);
                if (!(visitor.LastAsmLine is SourceLineBase asmline))
                {
                    continue;
                }

                if (asmline is EmittingOperationBase && asmline.InstructionSpan != null)
                {
                    // --- This line contains executable instruction,
                    // --- So it might have a breakpoint
                    if (affectedLines.IndexOf(currentLine.LineNumber) >= 0)
                    {
                        // --- Check for the any preset breakpoint
                        yield return(CreateSpan(currentLine, asmline.InstructionSpan, Z80AsmTokenType.Breakpoint));
                    }
                }

                if (asmline.LabelSpan != null)
                {
                    // --- Retrieve a label
                    yield return(CreateSpan(currentLine, asmline.LabelSpan, Z80AsmTokenType.Label));
                }

                if (asmline.KeywordSpan != null)
                {
                    var type = Z80AsmTokenType.Instruction;
                    if (asmline is PragmaBase)
                    {
                        type = Z80AsmTokenType.Pragma;
                    }
                    else if (asmline is Directive)
                    {
                        type = Z80AsmTokenType.Directive;
                    }
                    else if (asmline is IncludeDirective)
                    {
                        type = Z80AsmTokenType.Include;
                    }

                    // --- Retrieve a pragma/directive/instruction
                    yield return(CreateSpan(currentLine, asmline.KeywordSpan, type));
                }

                if (asmline.CommentSpan != null)
                {
                    // --- Retrieve a comment
                    yield return(CreateSpan(currentLine, asmline.CommentSpan, Z80AsmTokenType.Comment));
                }

                if (asmline.Numbers != null)
                {
                    foreach (var numberSpan in asmline.Numbers)
                    {
                        // --- Retrieve a number
                        yield return(CreateSpan(currentLine, numberSpan, Z80AsmTokenType.Number));
                    }
                }

                if (asmline.Identifiers == null)
                {
                    continue;
                }

                foreach (var idSpan in asmline.Identifiers)
                {
                    // --- Retrieve a number
                    yield return(CreateSpan(currentLine, idSpan, Z80AsmTokenType.Identifier));
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Gets all the tags that intersect the specified spans.
        /// </summary>
        /// <param name="spans">The spans to visit.</param>
        /// <returns>
        /// A <see cref="T:Microsoft.VisualStudio.Text.Tagging.TagSpan`1" /> for each tag.
        /// </returns>
        public IEnumerable <ITagSpan <Z80AsmTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            foreach (var curSpan in spans)
            {
                var currentLine = curSpan.Start.GetContainingLine();
                var textOfLine  = currentLine.GetText();

                // --- Let's use the Z80 assembly parser to obtain tags
                var inputStream = new AntlrInputStream(textOfLine);
                var lexer       = new Z80AsmLexer(inputStream);
                var tokenStream = new CommonTokenStream(lexer);
                var parser      = new Z80AsmParser(tokenStream);
                var context     = parser.asmline();
                var visitor     = new Z80AsmVisitor();
                visitor.Visit(context);
                if (!(visitor.LastAsmLine is SourceLineBase asmline))
                {
                    continue;
                }

                if (asmline.LabelSpan != null)
                {
                    // --- Retrieve a label
                    yield return(CreateSpan(currentLine, asmline.LabelSpan, Z80AsmTokenType.Label));
                }

                if (asmline.KeywordSpan != null)
                {
                    var type = Z80AsmTokenType.Instruction;
                    if (asmline is PragmaBase)
                    {
                        type = Z80AsmTokenType.Pragma;
                    }
                    else if (asmline is Directive)
                    {
                        type = Z80AsmTokenType.Directive;
                    }

                    // --- Retrieve a pragma/directive/instruction
                    yield return(CreateSpan(currentLine, asmline.KeywordSpan, type));
                }

                if (asmline.CommentSpan != null)
                {
                    // --- Retrieve a comment
                    yield return(CreateSpan(currentLine, asmline.CommentSpan, Z80AsmTokenType.Comment));
                }

                if (asmline.Numbers != null)
                {
                    foreach (var numberSpan in asmline.Numbers)
                    {
                        // --- Retrieve a number
                        yield return(CreateSpan(currentLine, numberSpan, Z80AsmTokenType.Number));
                    }
                }

                if (asmline.Identifiers == null)
                {
                    continue;
                }

                foreach (var idSpan in asmline.Identifiers)
                {
                    // --- Retrieve a number
                    yield return(CreateSpan(currentLine, idSpan, Z80AsmTokenType.Identifier));
                }
            }
        }