Пример #1
0
        private DisableNextLineDiagnosticsSyntaxTrivia GetDisableNextLineDiagnosticsSyntaxTrivia(List <Token> codes, int start, int length, string text)
        {
            if (codes.Any())
            {
                var lastCodeSpan    = codes.Last().Span;
                var lastCodeSpanEnd = lastCodeSpan.GetEndPosition();

                // There could be whitespace following #disable-next-line directive, in which case we need to adjust the span and text.
                // E.g. #disable-next-line BCP226   // test
                if (length > lastCodeSpanEnd)
                {
                    textWindow.Rewind(length - lastCodeSpanEnd);

                    return(new DisableNextLineDiagnosticsSyntaxTrivia(SyntaxTriviaType.DisableNextLineDiagnosticsDirective, new TextSpan(start, lastCodeSpanEnd), text.Substring(0, lastCodeSpanEnd), codes));
                }
            }

            return(new DisableNextLineDiagnosticsSyntaxTrivia(SyntaxTriviaType.DisableNextLineDiagnosticsDirective, new TextSpan(start, length), text, codes));
        }
Пример #2
0
        private TokenType ScanToken()
        {
            if (textWindow.IsAtEnd())
            {
                return(TokenType.EndOfFile);
            }

            var nextChar = textWindow.Peek();

            textWindow.Advance();
            switch (nextChar)
            {
            case '{':
                if (templateStack.Any())
                {
                    // if we're inside a string interpolation hole, and we find an object open brace,
                    // push it to the stack, so that we can match it up against an object close brace.
                    // this allows us to determine whether we're terminating an object or closing an interpolation hole.
                    templateStack.Push(TokenType.LeftBrace);
                }
                return(TokenType.LeftBrace);

            case '}':
                if (templateStack.Any())
                {
                    var prevTemplateToken = templateStack.Peek();
                    if (prevTemplateToken != TokenType.LeftBrace)
                    {
                        var stringToken = ScanStringSegment(false);
                        if (stringToken == TokenType.StringRightPiece)
                        {
                            templateStack.Pop();
                        }

                        return(stringToken);
                    }
                }
                return(TokenType.RightBrace);

            case '(':
                return(TokenType.LeftParen);

            case ')':
                return(TokenType.RightParen);

            case '[':
                return(TokenType.LeftSquare);

            case ']':
                return(TokenType.RightSquare);

            case '@':
                return(TokenType.At);

            case ',':
                return(TokenType.Comma);

            case '.':
                return(TokenType.Dot);

            case '?':
                return(TokenType.Question);

            case ':':
                return(TokenType.Colon);

            case ';':
                return(TokenType.Semicolon);

            case '+':
                return(TokenType.Plus);

            case '-':
                return(TokenType.Minus);

            case '%':
                return(TokenType.Modulo);

            case '*':
                return(TokenType.Asterisk);

            case '/':
                return(TokenType.Slash);

            case '!':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '=':
                        textWindow.Advance();
                        return(TokenType.NotEquals);

                    case '~':
                        textWindow.Advance();
                        return(TokenType.NotEqualsInsensitive);
                    }
                }
                return(TokenType.Exclamation);

            case '<':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '=':
                        textWindow.Advance();
                        return(TokenType.LessThanOrEqual);
                    }
                }
                return(TokenType.LessThan);

            case '>':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '=':
                        textWindow.Advance();
                        return(TokenType.GreaterThanOrEqual);
                    }
                }
                return(TokenType.GreaterThan);

            case '=':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '=':
                        textWindow.Advance();
                        return(TokenType.Equals);

                    case '~':
                        textWindow.Advance();
                        return(TokenType.EqualsInsensitive);
                    }
                }
                return(TokenType.Assignment);

            case '&':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '&':
                        textWindow.Advance();
                        return(TokenType.LogicalAnd);
                    }
                }
                return(TokenType.Unrecognized);

            case '|':
                if (!textWindow.IsAtEnd())
                {
                    switch (textWindow.Peek())
                    {
                    case '|':
                        textWindow.Advance();
                        return(TokenType.LogicalOr);
                    }
                }
                return(TokenType.Unrecognized);

            case '\'':
                var token = ScanStringSegment(true);
                if (token == TokenType.StringLeftPiece)
                {
                    // if we're beginning a string interpolation statement, we need to keep track of it
                    templateStack.Push(token);
                }
                return(token);

            case '\n':
            case '\r':
                if (templateStack.Any())
                {
                    // need to re-check the newline token on next pass
                    textWindow.Rewind();

                    // do not consume the new line character
                    // TODO: figure out a way to avoid returning this multiple times for nested interpolation
                    AddDiagnostic(b => b.UnterminatedStringWithNewLine());

                    templateStack.Clear();
                    return(TokenType.StringRightPiece);
                }
                this.ScanNewLine();
                return(TokenType.NewLine);

            default:
                if (IsDigit(nextChar))
                {
                    this.ScanNumber();
                    return(TokenType.Integer);
                }

                if (IsIdentifierStart(nextChar))
                {
                    return(this.ScanIdentifier());
                }

                return(TokenType.Unrecognized);
            }
        }