示例#1
0
 public void SkipSpacings(SkipType type)
 {
     do
     {
         char c = Peek();
         if (c == InvalidCharacter)
         {
             break;
         }
         else if (c == '\t')
         {
             AdvanceTab();
         }
         else if (SyntaxUtils.IsSpacing(c))
         {
             AdvanceColumn();
         }
         else
         {
             break;
         }
     } while (!IsEOF && type == SkipType.All);
 }
示例#2
0
        private CommandResult LexCommandTokens()
        {
            Debug.Assert(DoxygenSyntax.IsCommandBegin(Buffer.Peek()));

            // Command
            Buffer.StartLexeme();
            Buffer.AdvanceColumn();

            DoxygenTokenKind kind = DoxygenTokenKind.Command;
            {
                char first = Buffer.Peek();
                switch (first)
                {
                case '{':
                case '}':
                    kind = (first == '{') ? DoxygenTokenKind.GroupStart : DoxygenTokenKind.GroupEnd;
                    Buffer.AdvanceColumn();
                    break;

                case '$':
                case '@':
                case '\\':
                case '~':
                case '<':
                case '=':
                case '>':
                case '#':
                case '"':
                    Buffer.AdvanceColumn();
                    break;

                case ':':
                case '|':
                case '-':
                    Buffer.AdvanceColumnsWhile(d => d.Equals(first));
                    break;

                default:
                    if (DoxygenSyntax.IsCommandIdentStart(first))
                    {
                        while (!Buffer.IsEOF)
                        {
                            if (!DoxygenSyntax.IsCommandIdentPart(Buffer.Peek()))
                            {
                                break;
                            }
                            Buffer.AdvanceColumn();
                        }
                    }
                    break;
                }
            }

            TextPosition commandStart = Buffer.LexemeStart;
            int          commandLen   = Buffer.LexemeWidth;
            string       commandName  = Buffer.GetSourceText(Buffer.LexemeStart.Index + 1, commandLen - 1);
            var          rule         = DoxygenSyntax.GetCommandRule(commandName);

            if (rule != null)
            {
                if (rule.Kind == DoxygenSyntax.CommandKind.StartCommandBlock)
                {
                    kind = DoxygenTokenKind.CommandStart;
                }
                else if (rule.Kind == DoxygenSyntax.CommandKind.EndCommandBlock)
                {
                    kind = DoxygenTokenKind.CommandEnd;
                }
            }
            else
            {
                // @NOTE(final): Group start/end are not a "known" command
                if (kind != DoxygenTokenKind.GroupStart && kind != DoxygenTokenKind.GroupEnd)
                {
                    kind = DoxygenTokenKind.InvalidCommand;
                }
            }
            DoxygenToken commandToken = DoxygenTokenPool.Make(kind, Buffer.LexemeRange, true);

            PushToken(commandToken);

            CommandResult result = new CommandResult(commandStart, rule, commandName);

            string typeName = "Command";

            if (rule != null)
            {
                int  argNumber  = 0;
                int  argCount   = rule.Args.Count();
                bool noMoreArgs = false;
                foreach (var arg in rule.Args)
                {
                    // @TODO(final): Handle rule repeat type for arguments on same type
                    char first = Buffer.Peek();
                    if (!arg.Flags.HasFlag(DoxygenSyntax.ArgumentFlags.DirectlyAfterCommand))
                    {
                        if (SyntaxUtils.IsSpacing(first) || first == '\t')
                        {
                            Buffer.SkipSpacings(TextStream.SkipType.All);
                        }
                        else
                        {
                            // No more arguments are following
                            noMoreArgs = true;
                        }
                    }

                    Buffer.StartLexeme();

                    // Prefix
                    string prefix    = arg.Prefix;
                    string postfix   = arg.Postfix;
                    bool   hadPrefix = false;
                    if (prefix != null && !noMoreArgs)
                    {
                        if (!string.IsNullOrEmpty(prefix))
                        {
                            if (Buffer.CompareText(0, prefix) == 0)
                            {
                                Buffer.AdvanceColumns(prefix.Length);
                                hadPrefix = true;
                            }
                        }
                        else if ((prefix.Length == 0) && (!string.IsNullOrEmpty(postfix)))
                        {
                            hadPrefix = true;
                        }
                    }

                    switch (arg.Kind)
                    {
                    case DoxygenSyntax.ArgumentKind.PrefixToPostfix:
                    {
                        if (hadPrefix && !noMoreArgs)
                        {
                            Debug.Assert(!string.IsNullOrEmpty(postfix));
                            bool foundPrefixToPostfix = false;
                            while (!Buffer.IsEOF)
                            {
                                if (Buffer.CompareText(0, postfix) == 0)
                                {
                                    Buffer.AdvanceColumns(postfix.Length);
                                    foundPrefixToPostfix = true;
                                    break;
                                }
                                else if (SyntaxUtils.IsLineBreak(Buffer.Peek()))
                                {
                                    break;
                                }
                                else
                                {
                                    Buffer.AdvanceColumn();
                                }
                            }
                            if (arg.IsOptional || foundPrefixToPostfix)
                            {
                                DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, foundPrefixToPostfix);
                                PushToken(argToken);
                            }
                            else if (arg.IsRequired)
                            {
                                AddError(Buffer.TextPosition, $"Expected postfix '{postfix}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                return(result);
                            }
                        }
                        else if (arg.IsOptional)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, false);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Expected prefix '{prefix}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.MultipleObjectReference:
                    case DoxygenSyntax.ArgumentKind.SingleObjectReference:
                    {
                        // @TODO(final): ReferencedObject is not always a identifier
                        // Here are some examples of valid referenced objects:
                        // simple_identifier
                        // a_function()
                        // my::awesome::namespace::object
                        // my::awesome::namespace::function()
                        // my#awesome#namespace#function()
                        // method1,method2(),class#field
                        bool foundRef = false;
                        if (!noMoreArgs)
                        {
                            bool allowMultiple  = arg.Kind == DoxygenSyntax.ArgumentKind.MultipleObjectReference;
                            bool requireIdent   = true;
                            int  referenceCount = 0;
                            while (!Buffer.IsEOF)
                            {
                                int  oldPos = Buffer.StreamPosition;
                                char c0     = Buffer.Peek();
                                char c1     = Buffer.Peek(1);
                                if (!requireIdent)
                                {
                                    if (c0 == ':' && c1 == ':')
                                    {
                                        Buffer.AdvanceColumns(2);
                                        requireIdent = true;
                                        continue;
                                    }
                                    else if (c0 == '#')
                                    {
                                        Buffer.AdvanceColumn();
                                        requireIdent = true;
                                        continue;
                                    }
                                    else if (c0 == ',' && referenceCount > 0 && allowMultiple)
                                    {
                                        Buffer.AdvanceColumn();
                                        requireIdent = true;
                                        continue;
                                    }
                                    else
                                    {
                                        // Correct termination of object-reference
                                        foundRef = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    if (SyntaxUtils.IsIdentStart(c0))
                                    {
                                        requireIdent = false;
                                        while (!Buffer.IsEOF)
                                        {
                                            if (!SyntaxUtils.IsIdentPart(Buffer.Peek()))
                                            {
                                                break;
                                            }
                                            Buffer.AdvanceColumn();
                                        }
                                        if (Buffer.Peek() == '(')
                                        {
                                            // Parse until right parent
                                            Buffer.AdvanceColumn();
                                            bool terminatedFunc = false;
                                            while (!Buffer.IsEOF)
                                            {
                                                if (Buffer.Peek() == ')')
                                                {
                                                    Buffer.AdvanceColumn();
                                                    terminatedFunc = true;
                                                    break;
                                                }
                                                Buffer.AdvanceAuto();
                                            }
                                            if (!terminatedFunc)
                                            {
                                                AddError(Buffer.TextPosition, $"Unterminated function reference for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                                return(result);
                                            }
                                        }
                                        ++referenceCount;
                                        continue;
                                    }
                                    else
                                    {
                                        AddError(Buffer.TextPosition, $"Requires identifier, but found '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                        return(result);
                                    }
                                }
                            }
                            if (Buffer.IsEOF)
                            {
                                // Correct termination of object-reference when stream ends (Single-line)
                                foundRef = true;
                            }
                        }
                        if (arg.IsOptional || foundRef)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentIdent, Buffer.LexemeRange, foundRef);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.Identifier:
                    {
                        bool foundIdent = false;

                        // Special handling for @param command and ... parameter
                        if (!noMoreArgs && "param".Equals(commandName) && (arg.Kind == DoxygenSyntax.ArgumentKind.Identifier))
                        {
                            if (Buffer.Peek() == '.')
                            {
                                char c1 = Buffer.Peek(1);
                                char c2 = Buffer.Peek(2);
                                if (c1 == '.' && c2 == '.')
                                {
                                    Buffer.AdvanceColumns(3);
                                    foundIdent = true;
                                }
                            }
                        }

                        // We dont allow parsing a ident, when any special handling was matched
                        if (!noMoreArgs && !foundIdent && SyntaxUtils.IsIdentStart(Buffer.Peek()))
                        {
                            foundIdent = true;
                            while (!Buffer.IsEOF)
                            {
                                if (!SyntaxUtils.IsIdentPart(Buffer.Peek()))
                                {
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                        }
                        if (arg.IsOptional || foundIdent)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentIdent, Buffer.LexemeRange, foundIdent);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.HeaderFile:
                    case DoxygenSyntax.ArgumentKind.HeaderName:
                    {
                        bool foundFilename = false;
                        if (!noMoreArgs)
                        {
                            bool requiredQuotes = arg.Kind == DoxygenSyntax.ArgumentKind.HeaderName;
                            char curChar        = Buffer.Peek();
                            if (curChar == '<' || curChar == '\"')
                            {
                                char quoteChar = curChar == '<' ? '>' : '\"';
                                Buffer.AdvanceColumn();
                                while (!Buffer.IsEOF)
                                {
                                    curChar = Buffer.Peek();
                                    if (curChar == quoteChar)
                                    {
                                        Buffer.AdvanceColumn();
                                        foundFilename = true;
                                        break;
                                    }
                                    else if (SyntaxUtils.IsLineBreak(curChar))
                                    {
                                        break;
                                    }
                                    Buffer.AdvanceColumn();
                                }
                                if (!foundFilename)
                                {
                                    AddError(Buffer.TextPosition, $"Unterminated filename, expect quote char '{quoteChar}' but got '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                    return(result);
                                }
                            }
                            else if (!requiredQuotes)
                            {
                                if (SyntaxUtils.IsFilename(Buffer.Peek()))
                                {
                                    foundFilename = true;
                                    while (!Buffer.IsEOF)
                                    {
                                        if (!SyntaxUtils.IsFilename(Buffer.Peek()))
                                        {
                                            break;
                                        }
                                        Buffer.AdvanceColumn();
                                    }
                                }
                            }
                        }
                        if (arg.IsOptional || foundFilename)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentFile, Buffer.LexemeRange, foundFilename);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.SingleWord:
                    {
                        // @TODO(final): IsWordStart()
                        bool foundWord = false;
                        if (!noMoreArgs && char.IsLetterOrDigit(Buffer.Peek()))
                        {
                            foundWord = true;
                            while (!Buffer.IsEOF)
                            {
                                // @TODO(final): IsWordPart()
                                if (char.IsWhiteSpace(Buffer.Peek()))
                                {
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                        }
                        if (arg.IsOptional || foundWord)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, foundWord);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.QuotedString:
                    {
                        bool isComplete = false;

                        // @TODO(final): Make quotes configurable in the argument rule
                        bool hasQuote = Buffer.Peek() == '"' || Buffer.Peek() == '<';
                        char endQuote = char.MaxValue;
                        if (hasQuote && !noMoreArgs)
                        {
                            endQuote = Buffer.Peek() == '<' ? '>' : '"';
                            Buffer.AdvanceColumn();
                            while (!Buffer.IsEOF)
                            {
                                if (!hasQuote)
                                {
                                    if (char.IsWhiteSpace(Buffer.Peek()))
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    if (Buffer.Peek() == endQuote)
                                    {
                                        Buffer.AdvanceColumn();
                                        isComplete = true;
                                        break;
                                    }
                                    else if (SyntaxUtils.IsLineBreak(Buffer.Peek()) || Buffer.Peek() == TextStream.InvalidCharacter)
                                    {
                                        break;
                                    }
                                }
                                Buffer.AdvanceColumn();
                            }
                            if (!isComplete)
                            {
                                AddError(Buffer.TextPosition, $"Unterminated quote string for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                return(result);
                            }
                        }
                        if (arg.IsOptional || isComplete)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentText, Buffer.LexemeRange, isComplete);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.UntilEndOfLine:
                    {
                        bool eolFound = false;
                        if (!noMoreArgs)
                        {
                            while (!Buffer.IsEOF)
                            {
                                if (SyntaxUtils.IsLineBreak(Buffer.Peek()))
                                {
                                    eolFound = true;
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                            if (Buffer.IsEOF)
                            {
                                eolFound = true;
                            }
                        }
                        if (arg.IsOptional || eolFound)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentText, Buffer.LexemeRange, true);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unterminated end-of-line for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.ComplexLine:
                    case DoxygenSyntax.ArgumentKind.ComplexBlock:
                        // @TODO(final): Implement complex line/block properly
                        goto CommandDone;

                    default:
                        AddError(Buffer.TextPosition, $"Unsupported argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                        return(result);
                    }

                    // Postfix
                    if (!noMoreArgs && (hadPrefix && !string.IsNullOrWhiteSpace(postfix) && arg.Kind != DoxygenSyntax.ArgumentKind.PrefixToPostfix))
                    {
                        if (Buffer.CompareText(0, postfix) == 0)
                        {
                            Buffer.AdvanceColumns(prefix.Length);
                        }
                        else
                        {
                            AddError(Buffer.TextPosition, $"Expected postfix '{postfix}' for pp-argument({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    ++argNumber;
                }
            }

CommandDone:
            result.IsValid = true;

            return(result);
        }
示例#3
0
        protected override bool LexNext(State hiddenState)
        {
            CppLexerState state            = (CppLexerState)hiddenState;
            bool          allowWhitespaces = !state.IsInsidePreprocessor;

            if (allowWhitespaces)
            {
                Buffer.SkipAllWhitespaces();
            }
            if (Buffer.IsEOF)
            {
                return(false);
            }
            int  line   = Buffer.TextPosition.Line;
            char first  = Buffer.Peek();
            char second = Buffer.Peek(1);
            char third  = Buffer.Peek(2);

            Buffer.StartLexeme();
            LexResult lexRes = new LexResult(CppTokenKind.Unknown, true);

            switch (first)
            {
            case '&':
            {
                if (second == '&')
                {
                    lexRes.Kind = CppTokenKind.LogicalAndOp;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.AndAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.AndOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '|':
            {
                if (second == '|')
                {
                    lexRes.Kind = CppTokenKind.LogicalOrOp;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.OrAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.OrOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '=':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.LogicalEqualsOp;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.EqOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '!':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.LogicalNotEqualsOp;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.ExclationMark;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '<':
            {
                if (second == '<')
                {
                    if (third == '=')
                    {
                        lexRes.Kind = CppTokenKind.LeftShiftAssign;
                        Buffer.AdvanceColumns(3);
                    }
                    else
                    {
                        lexRes.Kind = CppTokenKind.LeftShiftOp;
                        Buffer.AdvanceColumns(2);
                    }
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.LessOrEqualOp;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.LessThanOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '>':
            {
                if (second == '>')
                {
                    if (third == '=')
                    {
                        lexRes.Kind = CppTokenKind.RightShiftAssign;
                        Buffer.AdvanceColumns(3);
                    }
                    else
                    {
                        lexRes.Kind = CppTokenKind.RightShiftOp;
                        Buffer.AdvanceColumns(2);
                    }
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.GreaterOrEqualOp;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.GreaterThanOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '+':
            {
                if (second == '+')
                {
                    lexRes.Kind = CppTokenKind.IncOp;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.AddAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.AddOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '-':
            {
                if (second == '-')
                {
                    lexRes.Kind = CppTokenKind.DecOp;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.SubAssign;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '>')
                {
                    lexRes.Kind = CppTokenKind.PtrOp;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.SubOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '/':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.DivAssign;
                    Buffer.AdvanceColumns(2);
                }
                else if (second == '/')
                {
                    lexRes = LexSingleLineComment(Buffer, true);
                    if (!lexRes.IsComplete)
                    {
                        AddError(Buffer.LexemeStart, $"Unterminated single-line comment, expect '\n' or '\r' but found '{Buffer.Peek()}'", lexRes.Kind.ToString());
                    }
                }
                else if (second == '*')
                {
                    lexRes = LexMultiLineComment(Buffer, true);
                    if (!lexRes.IsComplete)
                    {
                        AddError(Buffer.LexemeStart, $"Unterminated single-line comment, expect '*/' but found '{Buffer.Peek()}'", lexRes.Kind.ToString());
                    }
                }
                else
                {
                    Buffer.AdvanceColumn();
                    lexRes.Kind = CppTokenKind.DivOp;
                }
            }
            break;

            case '*':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.MulAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.MulOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '%':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.ModAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.ModOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '.':
            {
                if (second == '.' && third == '.')
                {
                    lexRes.Kind = CppTokenKind.Ellipsis;
                    Buffer.AdvanceColumns(3);
                }
                else if (SyntaxUtils.IsNumeric(second))
                {
                    lexRes = LexNumber();
                }
                else
                {
                    lexRes.Kind = CppTokenKind.Dot;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '^':
            {
                if (second == '=')
                {
                    lexRes.Kind = CppTokenKind.XorAssign;
                    Buffer.AdvanceColumns(2);
                }
                else
                {
                    lexRes.Kind = CppTokenKind.XorOp;
                    Buffer.AdvanceColumn();
                }
            }
            break;

            case '#':
                return(LexPreprocessor(state));

            case '"':
                lexRes = LexString("string");
                break;

            case '\'':
                lexRes = LexString("char");
                break;

            case '~':
                lexRes.Kind = CppTokenKind.Tilde;
                Buffer.AdvanceColumn();
                break;

            case '\\':
                lexRes.Kind = CppTokenKind.Backslash;
                Buffer.AdvanceColumn();
                break;

            case ',':
                lexRes.Kind = CppTokenKind.Comma;
                Buffer.AdvanceColumn();
                break;

            case ';':
                lexRes.Kind = CppTokenKind.Semicolon;
                Buffer.AdvanceColumn();
                break;

            case ':':
                lexRes.Kind = CppTokenKind.Colon;
                Buffer.AdvanceColumn();
                break;

            case '?':
                lexRes.Kind = CppTokenKind.QuestionMark;
                Buffer.AdvanceColumn();
                break;

            case '{':
                lexRes.Kind = CppTokenKind.LeftBrace;
                Buffer.AdvanceColumn();
                break;

            case '}':
                lexRes.Kind = CppTokenKind.RightBrace;
                Buffer.AdvanceColumn();
                break;

            case '[':
                lexRes.Kind = CppTokenKind.LeftBracket;
                Buffer.AdvanceColumn();
                break;

            case ']':
                lexRes.Kind = CppTokenKind.RightBracket;
                Buffer.AdvanceColumn();
                break;

            case '(':
                lexRes.Kind = CppTokenKind.LeftParen;
                Buffer.AdvanceColumn();
                break;

            case ')':
                lexRes.Kind = CppTokenKind.RightParen;
                Buffer.AdvanceColumn();
                break;

            default:
            {
                if (SyntaxUtils.IsLineBreak(first) && allowWhitespaces)
                {
                    lexRes.Kind = CppTokenKind.EndOfLine;
                    int nb = SyntaxUtils.GetLineBreakChars(first, second);
                    Buffer.AdvanceLine(nb);
                }
                else if (first == '\t' && allowWhitespaces)
                {
                    lexRes.Kind = CppTokenKind.Spacings;
                    while (!Buffer.IsEOF)
                    {
                        if (Buffer.Peek() != '\t')
                        {
                            break;
                        }
                        Buffer.AdvanceTab();
                    }
                }
                else if (SyntaxUtils.IsSpacing(first) && allowWhitespaces)
                {
                    lexRes.Kind = CppTokenKind.Spacings;
                    Buffer.AdvanceColumnsWhile(SyntaxUtils.IsSpacing);
                }
                else if (SyntaxUtils.IsIdentStart(first))
                {
                    Debug.Assert(!state.IsInsidePreprocessor);
                    lexRes = LexIdent(false);
                }
                else if (SyntaxUtils.IsNumeric(first))
                {
                    lexRes = LexNumber();
                }
                else
                {
                    AddError(Buffer.TextPosition, $"Unexpected character '{first}'", "Character");
                    return(false);
                }
            }
            break;
            }
            return(PushToken(CppTokenPool.Make(lexRes.Kind, Buffer.LexemeRange, lexRes.IsComplete)));
        }
示例#4
0
        public static CToken PeekTokenRaw(TextStream stream)
        {
            TextPosition startPos = stream.TextPosition;

            if (stream.IsEOF)
            {
                return(new CToken(CppTokenKind.Eof, startPos, stream.TextPosition));
            }
            char         first  = stream.Peek(0);
            char         second = stream.Peek(1);
            char         third  = stream.Peek(2);
            CppTokenKind kind;

            switch (first)
            {
            case '&':
            {
                if (second == '&')
                {
                    kind = CppTokenKind.LogicalAndOp;
                    stream.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.AndAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.AndOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '|':
            {
                if (second == '|')
                {
                    kind = CppTokenKind.LogicalOrOp;
                    stream.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.OrAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.OrOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '=':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.LogicalEqualsOp;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.EqOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '!':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.LogicalNotEqualsOp;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.ExclationMark;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '<':
            {
                if (second == '<')
                {
                    if (third == '=')
                    {
                        kind = CppTokenKind.LeftShiftAssign;
                        stream.AdvanceColumns(3);
                    }
                    else
                    {
                        kind = CppTokenKind.LeftShiftOp;
                        stream.AdvanceColumns(2);
                    }
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.LessOrEqualOp;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.LessThanOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '>':
            {
                if (second == '>')
                {
                    if (third == '=')
                    {
                        kind = CppTokenKind.RightShiftAssign;
                        stream.AdvanceColumns(3);
                    }
                    else
                    {
                        kind = CppTokenKind.RightShiftOp;
                        stream.AdvanceColumns(2);
                    }
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.GreaterOrEqualOp;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.GreaterThanOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '+':
            {
                if (second == '+')
                {
                    kind = CppTokenKind.IncOp;
                    stream.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.AddAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.AddOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '-':
            {
                if (second == '-')
                {
                    kind = CppTokenKind.DecOp;
                    stream.AdvanceColumns(2);
                }
                else if (second == '=')
                {
                    kind = CppTokenKind.SubAssign;
                    stream.AdvanceColumns(2);
                }
                else if (second == '>')
                {
                    kind = CppTokenKind.PtrOp;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.SubOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '/':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.DivAssign;
                    stream.AdvanceColumns(2);
                }
                else if (second == '/')
                {
                    kind = CppTokenKind.SingleLineComment;
                    stream.AdvanceColumns(2);
                    char specialChar = stream.Peek();
                    if (DoxygenSyntax.SingleLineDocChars.Contains(specialChar))
                    {
                        kind = CppTokenKind.SingleLineCommentDoc;
                        stream.AdvanceColumn();
                    }
                    while (!stream.IsEOF)
                    {
                        if (SyntaxUtils.IsLineBreak(stream.Peek()))
                        {
                            break;
                        }
                        stream.AdvanceColumn();
                    }
                }
                else if (second == '*')
                {
                    kind = CppTokenKind.MultiLineComment;
                    stream.AdvanceColumns(2);
                    char specialChar = stream.Peek();
                    if (DoxygenSyntax.MultiLineDocChars.Contains(specialChar))
                    {
                        kind = CppTokenKind.MultiLineCommentDoc;
                        stream.AdvanceColumn();
                    }
                    while (!stream.IsEOF)
                    {
                        char n0 = stream.Peek();
                        char n1 = stream.Peek(1);
                        if (n0 == '*' && n1 == '/')
                        {
                            stream.AdvanceColumns(2);
                            break;
                        }
                        else
                        {
                            stream.AdvanceManual(n0, n1);
                        }
                    }
                }
                else
                {
                    stream.AdvanceColumn();
                    kind = CppTokenKind.DivOp;
                }
            }
            break;

            case '*':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.MulAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.MulOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '%':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.ModAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.ModOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '.':
            {
                if (second == '.' && third == '.')
                {
                    kind = CppTokenKind.Ellipsis;
                    stream.AdvanceColumns(3);
                }
                else if (SyntaxUtils.IsNumeric(second))
                {
                    stream.AdvanceColumn();
                    kind = ReadNumberLiteral(stream);
                }
                else
                {
                    kind = CppTokenKind.Dot;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '^':
            {
                if (second == '=')
                {
                    kind = CppTokenKind.XorAssign;
                    stream.AdvanceColumns(2);
                }
                else
                {
                    kind = CppTokenKind.XorOp;
                    stream.AdvanceColumn();
                }
            }
            break;

            case '"':
            case '\'':
            {
                stream.AdvanceColumn();
                if (first == '"')
                {
                    kind = ReadStringLiteral(stream);
                }
                else
                {
                    kind = ReadCharacterLiteral(stream);
                }
            }
            break;

            case '~':
                kind = CppTokenKind.Tilde;
                stream.AdvanceColumn();
                break;

            case '\\':
                kind = CppTokenKind.Backslash;
                stream.AdvanceColumn();
                break;

            case '#':
                kind = CppTokenKind.PreprocessorStart;
                stream.AdvanceColumn();
                break;

            case ',':
                kind = CppTokenKind.Comma;
                stream.AdvanceColumn();
                break;

            case ';':
                kind = CppTokenKind.Semicolon;
                stream.AdvanceColumn();
                break;

            case ':':
                kind = CppTokenKind.Colon;
                stream.AdvanceColumn();
                break;

            case '?':
                kind = CppTokenKind.QuestionMark;
                stream.AdvanceColumn();
                break;

            case '{':
                kind = CppTokenKind.LeftBrace;
                stream.AdvanceColumn();
                break;

            case '}':
                kind = CppTokenKind.RightBrace;
                stream.AdvanceColumn();
                break;

            case '[':
                kind = CppTokenKind.LeftBracket;
                stream.AdvanceColumn();
                break;

            case ']':
                kind = CppTokenKind.RightBracket;
                stream.AdvanceColumn();
                break;

            case '(':
                kind = CppTokenKind.LeftParen;
                stream.AdvanceColumn();
                break;

            case ')':
                kind = CppTokenKind.RightParen;
                stream.AdvanceColumn();
                break;

            default:
            {
                if (SyntaxUtils.IsLineBreak(first))
                {
                    kind = CppTokenKind.EndOfLine;
                    int nb = SyntaxUtils.GetLineBreakChars(first, second);
                    stream.AdvanceLine(nb);
                }
                else if (first == '\t')
                {
                    kind = CppTokenKind.Spacings;
                    while (!stream.IsEOF)
                    {
                        if (stream.Peek() != '\t')
                        {
                            break;
                        }
                        stream.AdvanceTab();
                    }
                }
                else if (SyntaxUtils.IsSpacing(first))
                {
                    kind = CppTokenKind.Spacings;
                    stream.AdvanceColumnsWhile(SyntaxUtils.IsSpacing);
                }
                else if (SyntaxUtils.IsIdentStart(first))
                {
                    kind = CppTokenKind.IdentLiteral;
                    stream.AdvanceColumnsWhile(SyntaxUtils.IsIdentPart);
                }
                else if (SyntaxUtils.IsNumeric(first))
                {
                    kind = ReadNumberLiteral(stream);
                }
                else
                {
                    kind = CppTokenKind.Unknown;
                }
            }
            break;
            }
            CToken result = MakeToken(kind, stream, startPos, stream.TextPosition);

            return(result);
        }