private bool IsPossibleIdentifierDotSuffix(SyntaxKind kind, bool identifierIsKeyword = false)
        {
            var tk = this.CurrentToken.Kind;

            if (tk == SyntaxKind.IdentifierName &&
                this.PeekToken(1).Kind == SyntaxKind.DotToken &&
                this.PeekToken(2).Kind == kind)
            {
                return(true);
            }

            var resetPoint = this.GetResetPoint();

            try
            {
                SyntaxToken   lastTokenOfType;
                ScanTypeFlags st = this.ScanType(out lastTokenOfType);
                if (st == ScanTypeFlags.NotType && lastTokenOfType != null && lastTokenOfType.Kind == kind)
                {
                    return(true);
                }
                return(false);
            }
            finally
            {
                this.Reset(ref resetPoint);
                this.Release(ref resetPoint);
            }
        }
Пример #2
0
        private ScanTypeFlags ScanType(out SyntaxToken lastTokenOfType)
        {
            ScanTypeFlags result = ScanNonArrayType(out lastTokenOfType);

            if (result == ScanTypeFlags.NotType)
            {
                return(result);
            }

            // Finally, check for array types.
            while (Current.Kind == SyntaxKind.OpenBracketToken)
            {
                NextToken();
                if (Current.Kind != SyntaxKind.IntegerLiteralToken)
                {
                    lastTokenOfType = null;
                    return(ScanTypeFlags.NotType);
                }
                NextToken();
                if (Current.Kind != SyntaxKind.CloseBracketToken)
                {
                    lastTokenOfType = null;
                    return(ScanTypeFlags.NotType);
                }
                lastTokenOfType = NextToken();
                result          = ScanTypeFlags.MustBeType;
            }

            return(result);
        }
Пример #3
0
        private ScanTypeFlags ScanType(out SyntaxToken lastTokenOfType)
        {
            ScanTypeFlags result = this.ScanNonArrayType(out lastTokenOfType);

            if (result == ScanTypeFlags.NotType)
            {
                return(result);
            }

            // Finally, check for array types and nullables.
            while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken)
            {
                this.EatToken();
                if (this.CurrentToken.Kind != SyntaxKind.CloseBracketToken)
                {
                    while (this.CurrentToken.Kind == SyntaxKind.CommaToken)
                    {
                        this.EatToken();
                    }

                    if (this.CurrentToken.Kind != SyntaxKind.CloseBracketToken)
                    {
                        lastTokenOfType = null;
                        return(ScanTypeFlags.NotType);
                    }
                }

                lastTokenOfType = this.EatToken();
                result          = ScanTypeFlags.MustBeType;
            }

            return(result);
        }
        private bool IsPossibleLocalDeclarationStatement(bool allowAnyExpression)
        {
            // This method decides whether to parse a statement as a declaration or as an expression statement.
            // In the old compiler it would simple call IsLocalDeclaration.

            var tk = this.CurrentToken.Kind;

            if ((SyntaxKindFacts.IsPredefinedType(tk) && this.PeekToken(1).Kind != SyntaxKind.DotToken) || IsDeclarationModifier(tk))
            {
                return(true);
            }

            bool?typedIdentifier = IsPossibleTypedIdentifierStart(this.CurrentToken, this.PeekToken(1), allowThisKeyword: false);

            if (typedIdentifier != null)
            {
                return(typedIdentifier.Value);
            }

            var resetPoint = this.GetResetPoint();

            try
            {
                ScanTypeFlags st = this.ScanType();

                // We could always return true for st == AliasQualName in addition to MustBeType on the first line, however, we want it to return false in the case where
                // CurrentToken.Kind != SyntaxKind.Identifier so that error cases, like: A::N(), are not parsed as variable declarations and instead are parsed as A.N() where we can give
                // a better error message saying "did you meant to use a '.'?"
                if (st == ScanTypeFlags.MustBeType && this.CurrentToken.Kind != SyntaxKind.DotToken)
                {
                    return(true);
                }

                if (st == ScanTypeFlags.NotType || this.CurrentToken.Kind != SyntaxKind.IdentifierToken)
                {
                    return(false);
                }

                // T? and T* might start an expression, we need to parse further to disambiguate:
                if (allowAnyExpression)
                {
                    if (st == ScanTypeFlags.PointerOrMultiplication)
                    {
                        return(false);
                    }
                    else if (st == ScanTypeFlags.NullableType)
                    {
                        return(IsPossibleDeclarationStatementFollowingNullableType());
                    }
                }

                return(true);
            }
            finally
            {
                this.Reset(ref resetPoint);
                this.Release(ref resetPoint);
            }
        }
Пример #5
0
        private bool IsUsingStatementVariableDeclaration(ScanTypeFlags st)
        {
            bool condition1 = st == ScanTypeFlags.MustBeType && this.CurrentToken.Kind != SyntaxKind.DotToken;
            bool condition2 = st != ScanTypeFlags.NotType && this.CurrentToken.Kind == SyntaxKind.IdentifierToken;
            bool condition3 = st == ScanTypeFlags.NonGenericTypeOrExpression || this.PeekToken(1).Kind == SyntaxKind.EqualsToken;

            return(condition1 || (condition2 && condition3));
        }
Пример #6
0
        private ForStatementSyntax ParseForStatement(List <AttributeSyntax> attributes)
        {
            var @for      = Match(SyntaxKind.ForKeyword);
            var openParen = Match(SyntaxKind.OpenParenToken);

            var resetPoint   = GetResetPoint();
            var initializers = new List <SyntaxNode>();
            var incrementors = new List <SyntaxNode>();

            // Here can be either a declaration or an expression statement list.  Scan
            // for a declaration first.
            ScanTypeFlags st = ScanType();

            VariableDeclarationSyntax decl = null;

            if (st != ScanTypeFlags.NotType && Current.Kind == SyntaxKind.IdentifierToken)
            {
                Reset(ref resetPoint);
                decl = ParseVariableDeclaration();
            }
            else
            {
                // Not a type followed by an identifier, so it must be an expression list.
                Reset(ref resetPoint);
                if (Current.Kind != SyntaxKind.SemiToken)
                {
                    ParseForStatementExpressionList(ref openParen, initializers);
                }
            }

            var semi = Match(SyntaxKind.SemiToken);

            ExpressionSyntax condition = null;

            if (Current.Kind != SyntaxKind.SemiToken)
            {
                condition = ParseExpression();
            }

            var semi2 = Match(SyntaxKind.SemiToken);

            if (Current.Kind != SyntaxKind.CloseParenToken)
            {
                ParseForStatementExpressionList(ref semi2, incrementors);
            }

            var closeParen = Match(SyntaxKind.CloseParenToken);
            var statement  = ParseEmbeddedStatement();

            return(new ForStatementSyntax(attributes, @for, openParen, decl,
                                          new SeparatedSyntaxList <ExpressionSyntax>(initializers),
                                          semi, condition, semi2,
                                          new SeparatedSyntaxList <ExpressionSyntax>(incrementors),
                                          closeParen, statement));
        }
        private bool IsPossibleArrayCreationExpression()
        {
            // previous token should be NewKeyword

            var resetPoint = this.GetResetPoint();

            try
            {
                ScanTypeFlags isType = this.ScanNonArrayType();
                return(isType != ScanTypeFlags.NotType && this.CurrentToken.Kind == SyntaxKind.OpenBracketToken);
            }
            finally
            {
                this.Reset(ref resetPoint);
                this.Release(ref resetPoint);
            }
        }
Пример #8
0
 private static bool IsAnyTypeOrExpr(ScanTypeFlags st)
 {
     return(st == ScanTypeFlags.GenericTypeOrExpression || st == ScanTypeFlags.NonGenericTypeOrExpression);
 }
        //private bool IsPossibleClassLiteralExpression(bool contextRequiresVariable)
        //{
        //	var tk = this.CurrentToken.Kind;
        //	if (tk == SyntaxKind.IdentifierName
        //		&& this.PeekToken(1).Kind == SyntaxKind.DotToken
        //		&& this.PeekToken(2).Kind == SyntaxKind.ClassKeyword)
        //	{
        //		return true;
        //	}

        //	var resetPoint = this.GetResetPoint();
        //	try
        //	{
        //		SyntaxToken lastTokenOfType;
        //		ScanTypeFlags st = this.ScanType(out lastTokenOfType);

        //		if (st == ScanTypeFlags.ClassKeywordSuffix)
        //		{
        //			return true;
        //		}
        //		return false;
        //	}
        //	finally
        //	{
        //		this.Reset(ref resetPoint);
        //		this.Release(ref resetPoint);
        //	}
        //}

        //private bool IsPossibleQualifiedThisExpression(bool contextRequiresVariable)
        //{
        //	var tk = this.CurrentToken.Kind;
        //	if (tk == SyntaxKind.IdentifierName
        //		&& this.PeekToken(1).Kind == SyntaxKind.DotToken
        //		&& this.PeekToken(1).Kind == SyntaxKind.ClassKeyword)
        //	{
        //		return true;
        //	}

        //	var resetPoint = this.GetResetPoint();
        //	try
        //	{
        //		SyntaxToken lastTokenOfType;
        //		ScanTypeFlags st = this.ScanType(out lastTokenOfType);

        //		if (st == ScanTypeFlags.ClassKeywordSuffix)
        //		{
        //			return true;
        //		}
        //		return false;
        //	}
        //	finally
        //	{
        //		this.Reset(ref resetPoint);
        //		this.Release(ref resetPoint);
        //	}
        //}

        private bool IsPossibleDeclarationExpression(bool contextRequiresVariable)
        {
            var tk = this.CurrentToken.Kind;

            if (SyntaxKindFacts.IsPredefinedType(tk) && tk != SyntaxKind.VoidKeyword && this.PeekToken(1).Kind != SyntaxKind.DotToken)
            {
                return(true);
            }

            var resetPoint = this.GetResetPoint();

            try
            {
                SyntaxToken   lastTokenOfType;
                ScanTypeFlags st = this.ScanType(out lastTokenOfType);

                if (st == ScanTypeFlags.NotType || !this.IsTrueIdentifier())
                {
                    return(false);
                }

                if (contextRequiresVariable)
                {
                    // Unless we parse this as a declaration expression,
                    // we'll get binding errors later on.
                    return(true);
                }

                switch (st)
                {
                case ScanTypeFlags.GenericTypeOrExpression:
                case ScanTypeFlags.PointerOrMultiplication:

                    int        position = 0;
                    SyntaxKind afterIdentifierTokenKind;

                    do
                    {
                        position++;
                        afterIdentifierTokenKind = this.PeekToken(position).Kind;
                    }while (afterIdentifierTokenKind == SyntaxKind.CloseParenToken);

                    // If we have something that looks like a pointer or generic type, followed by an identifier, followed by '[)...][+-*...]=' tokens.
                    // This cannot be a valid non-declaration expression.
                    return(SyntaxKindFacts.IsAssignmentExpressionOperatorToken(afterIdentifierTokenKind));

                case ScanTypeFlags.NullableType:
                    // This can be a part of a ConditionalExpression.
                    var resetPoint2 = this.GetResetPoint();
                    try
                    {
                        var nullCoalescingPrecedence = 2u;                                //GetPrecedence(SyntaxKind.CoalesceExpression);
                        var colonLeft = this.ParseSubExpression(nullCoalescingPrecedence - 1);

                        if (colonLeft.Kind != SyntaxKind.DeclarationExpression && this.CurrentToken.Kind == SyntaxKind.ColonToken)
                        {
                            return(false);
                        }
                    }
                    finally
                    {
                        this.Reset(ref resetPoint2);
                        this.Release(ref resetPoint2);
                    }

                    break;
                }

                // Let's specially handle some error cases.
                // For example:
                //      Colors? d = Co
                //      Colors c = Colors.Blue;
                //
                // We don't want this erroneous code to be parsed as a single statement equivalent to
                //      Colors? d = Co Colors c = Colors.Blue;
                // Where "Co Colors" is parsed as a Declaration Expression. This would have negative
                // effect on editing experience.
                Debug.Assert(this.IsTrueIdentifier());

                if (lastTokenOfType.TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia))
                {
                    // We have a line break between something that looks like a type and the following identifier.
                    // Can that identifier be a beginning of a local declaration?
                    ScanTypeFlags st2 = this.ScanType();
                    if (st2 != ScanTypeFlags.NotType && this.IsTrueIdentifier())
                    {
                        return(false);
                    }
                }

                return(true);
            }
            finally
            {
                this.Reset(ref resetPoint);
                this.Release(ref resetPoint);
            }
        }
        private bool IsPossibleNewExpression()
        {
            Debug.Assert(this.CurrentToken.Kind == SyntaxKind.NewKeyword);

            // skip new
            SyntaxToken nextToken = PeekToken(1);

            // new { }
            // new [ ]
            switch (nextToken.Kind)
            {
            case SyntaxKind.OpenBraceToken:
            case SyntaxKind.OpenBracketToken:
                return(true);
            }

            //
            // Declaration with new modifier vs. new expression
            // Parse it as an expression if the type is not followed by an identifier or this keyword.
            //
            // Member declarations:
            //   new T Idf ...
            //   new T this ...
            //   new partial Idf    ("partial" as a type name)
            //   new partial this   ("partial" as a type name)
            //   new partial T Idf
            //   new partial T this
            //   new <modifier>
            //   new <class|interface|struct|enum>
            //   new partial <class|interface|struct|enum>
            //
            // New expressions:
            //   new T []
            //   new T { }
            //   new <non-type>
            //
            if (SyntaxKindFacts.GetBaseTypeDeclarationKind(nextToken.Kind) != SyntaxKind.None)
            {
                return(false);
            }

            SyntaxModifier modifier = GetModifier(nextToken);

            if (modifier != SyntaxModifier.None)
            {
                return(false);
            }

            bool?typedIdentifier = IsPossibleTypedIdentifierStart(nextToken, PeekToken(2), allowThisKeyword: true);

            if (typedIdentifier != null)
            {
                // new Idf Idf
                // new Idf .
                // new partial T
                // new partial .
                return(!typedIdentifier.Value);
            }

            var resetPoint = this.GetResetPoint();

            try
            {
                // skips new keyword
                EatToken();

                ScanTypeFlags st = this.ScanType();

                return(!IsPossibleMemberName() || st == ScanTypeFlags.NotType);
            }
            finally
            {
                this.Reset(ref resetPoint);
                this.Release(ref resetPoint);
            }
        }