Example #1
0
 private void Done(DoxygenState state)
 {
     EndText(state);
     if (state.Flags.HasFlag(StateFlags.InsideBlock))
     {
         // Block was not closed, so we close it now
         state.Flags = StateFlags.None;
         PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockEnd, new TextRange(Buffer.TextPosition, 0), false));
     }
 }
Example #2
0
        private void EndText(DoxygenState state)
        {
            var lastTextStartOrEnd = Tokens.LastOrDefault(t => t.Kind == DoxygenTokenKind.TextStart || t.Kind == DoxygenTokenKind.TextEnd);

            if (lastTextStartOrEnd != null && lastTextStartOrEnd.Kind == DoxygenTokenKind.TextStart)
            {
                int textLength = Buffer.TextPosition.Index - lastTextStartOrEnd.Index;
                if (textLength > 0)
                {
                    DoxygenToken token = DoxygenTokenPool.Make(DoxygenTokenKind.TextEnd, new TextRange(Buffer.TextPosition, 0), false);
                    PushToken(token);
                }
                else
                {
                    RemoveToken(lastTextStartOrEnd);
                }
            }
        }
Example #3
0
        protected override bool LexNext(State hiddenState)
        {
            DoxygenState state = (DoxygenState)hiddenState;

            state.Flags = StateFlags.None;
            state.CurrentLineStartIndex = Buffer.StreamPosition;
            do
            {
                char first  = Buffer.Peek();
                char second = Buffer.Peek(1);
                char third  = Buffer.Peek(2);
                switch (first)
                {
                case ' ':
                case '\v':
                case '\f':
                case '\t':
                    Buffer.SkipSpacings(TextStream.SkipType.All);
                    break;

                case '\r':
                case '\n':
                {
                    if (state.Flags.HasFlag(StateFlags.InsideBlock) && state.Flags.HasFlag(StateFlags.SingleLine))
                    {
                        Done(state);
                        return(true);
                    }

                    // @NOTE(final): Detect if our line content until the line break was empty
                    Debug.Assert(Buffer.StreamPosition >= state.CurrentLineStartIndex);
                    int  len          = Buffer.StreamPosition - state.CurrentLineStartIndex;
                    bool wasEmptyLine = Buffer.MatchCharacters(state.CurrentLineStartIndex, len, char.IsWhiteSpace) || (len == 0);

                    Buffer.StartLexeme();
                    Buffer.SkipLineBreaks(TextStream.SkipType.Single);
                    state.CurrentLineStartIndex = Buffer.StreamPosition;
                    PushToken(DoxygenTokenPool.Make(wasEmptyLine ? DoxygenTokenKind.EmptyLine : DoxygenTokenKind.EndOfLine, Buffer.LexemeRange, true));
                }
                break;

                case '/':
                {
                    if (second == '*')
                    {
                        // Multi line
                        if (DoxygenSyntax.MultiLineDocChars.Contains(third))
                        {
                            Debug.Assert(!state.Flags.HasFlag(StateFlags.InsideBlock));
                            Buffer.StartLexeme();
                            Buffer.AdvanceColumns(3);
                            state.Flags = StateFlags.InsideBlock;
                            if (third == '*')
                            {
                                char n3 = Buffer.Peek();
                                if (n3 == '/')
                                {
                                    Buffer.AdvanceColumn();
                                    return(PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockStartMulti, Buffer.LexemeRange, true)));
                                }
                                state.Flags |= StateFlags.JavaDoc;
                            }
                            PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockStartMulti, Buffer.LexemeRange, true));
                            StartText(state);
                            continue;
                        }
                        else
                        {
                            // Just skip until normal multi-line comment ends
                            var r = CppLexer.LexMultiLineComment(Buffer, true);
                            if (!r.IsComplete)
                            {
                                AddError(Buffer.TextPosition, $"Unterminated multi-line comment, expect '*/' but got EOF", r.Kind.ToString());
                                return(false);
                            }
                            continue;
                        }
                    }
                    else if (second == '/')
                    {
                        // Single line
                        char n2 = Buffer.Peek(2);
                        if (DoxygenSyntax.SingleLineDocChars.Contains(n2))
                        {
                            Debug.Assert(!state.Flags.HasFlag(StateFlags.InsideBlock));
                            Buffer.StartLexeme();
                            Buffer.AdvanceColumns(3);
                            state.Flags = StateFlags.InsideBlock | StateFlags.SingleLine;
                            PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockStartSingle, Buffer.LexemeRange, true));
                            StartText(state);
                            continue;
                        }
                        else
                        {
                            // Just skip until normal single-line comment ends
                            var r = CppLexer.LexSingleLineComment(Buffer, true);
                            if (!r.IsComplete)
                            {
                                AddError(Buffer.TextPosition, $"Unterminated single-line comment, expect linebreak but got EOF", r.Kind.ToString());
                                return(false);
                            }
                            continue;
                        }
                    }
                    else
                    {
                        Buffer.AdvanceColumn();
                    }
                }
                break;

                case '*':
                {
                    if (state.Flags.HasFlag(StateFlags.InsideBlock))
                    {
                        if (second == '/')
                        {
                            EndText(state);
                            Buffer.StartLexeme();
                            Buffer.AdvanceColumns(2);
                            state.Flags = StateFlags.None;
                            return(PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockEnd, Buffer.LexemeRange, true)));
                        }
                        else if (state.Flags.HasFlag(StateFlags.JavaDoc))
                        {
                            // Push single star token (java doc style)
                            EndText(state);
                            Buffer.StartLexeme();
                            Buffer.AdvanceColumn();
                            PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.DoxyBlockChars, Buffer.LexemeRange, true));
                            StartText(state);
                            state.CurrentLineStartIndex = Buffer.StreamPosition;
                            continue;
                        }
                    }
                    Buffer.AdvanceColumn();
                }
                break;

                case '@':
                case '\\':
                {
                    if (state.Flags.HasFlag(StateFlags.InsideBlock))
                    {
                        EndText(state);
                        var commandResult = LexCommandTokens();
                        if (commandResult.IsValid)
                        {
                            if ("code".Equals(commandResult.CommandName))
                            {
                                if (!LexUntilCodeEnd(commandResult))
                                {
                                    return(false);
                                }
                            }
                        }
                        StartText(state);
                    }
                    else
                    {
                        Buffer.AdvanceColumn();
                    }
                }
                break;

                case TextStream.InvalidCharacter:
                {
                    if (Buffer.IsEOF)
                    {
                        Done(state);
                        PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.EOF, new TextRange(Buffer.TextPosition, 0), false));
                        return(false);
                    }
                    else
                    {
                        Buffer.AdvanceColumn();
                    }
                }
                break;

                default:
                {
                    Buffer.AdvanceColumn();
                    break;
                }
                }
            } while (!Buffer.IsEOF);
            Done(state);
            PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.EOF, new TextRange(Buffer.TextPosition, 0), false));
            return(false);
        }
Example #4
0
        private void StartText(DoxygenState state)
        {
            DoxygenToken token = DoxygenTokenPool.Make(DoxygenTokenKind.TextStart, new TextRange(Buffer.TextPosition, 0), false);

            PushToken(token);
        }