protected virtual SyntaxDiagnosticInfo GetExpectedTokenError(SyntaxKind expected, SyntaxKind actual, int offset, int width)
        {
            var code = GetExpectedTokenErrorCode(expected, actual);

            if (code == ErrorCode.ERR_SyntaxError || code == ErrorCode.ERR_IdentifierExpectedKW)
            {
                return(new SyntaxDiagnosticInfo(offset, width, code, SyntaxKindFacts.GetText(expected), SyntaxKindFacts.GetText(actual)));
            }
            else
            {
                return(new SyntaxDiagnosticInfo(offset, width, code));
            }
        }
        internal static SyntaxToken Token(CSharpSyntaxNode leading, SyntaxKind kind, string text, string valueText, CSharpSyntaxNode trailing)
        {
            Debug.Assert(SyntaxKindFacts.IsAnyToken(kind));
            Debug.Assert(kind != SyntaxKind.IdentifierToken);
            Debug.Assert(kind != SyntaxKind.CharacterLiteralToken);
            Debug.Assert(kind != SyntaxKind.NumericLiteralToken);

            string defaultText = SyntaxKindFacts.GetText(kind);

            return(kind >= SyntaxToken.FirstTokenWithWellKnownText && kind <= SyntaxToken.LastTokenWithWellKnownText && text == defaultText && valueText == defaultText
                                ? Token(leading, kind, trailing)
                                : SyntaxToken.WithValue(kind, leading, text, valueText, trailing));
        }
Beispiel #3
0
        private void ParseParameterModifiers(SyntaxListBuilder modifiers, bool allowThisKeyword, bool allowFieldModifiers)
        {
            var            flags            = ParamFlags.None;
            SyntaxModifier fieldMods        = 0;
            bool           seenNoDuplicates = true;
            bool           seenNoAccessibilityDuplicates = true;

            while (true)
            {
                if (IsParameterModifier(this.CurrentToken.Kind, allowThisKeyword))
                {
                    var mod = this.EatToken();

                    if (mod.Kind == SyntaxKind.ThisKeyword)
                    {
                        if (mod.Kind == SyntaxKind.ThisKeyword)
                        {
                            mod = CheckFeatureAvailability(mod, MessageID.IDS_FeatureExtensionMethod);

                            if ((flags & ParamFlags.This) != 0)
                            {
                                mod = this.AddError(mod, ErrorCode.ERR_DupParamMod, SyntaxKindFacts.GetText(SyntaxKind.ThisKeyword));
                            }
                            else if ((flags & ParamFlags.Params) != 0)
                            {
                                mod = this.AddError(mod, ErrorCode.ERR_BadParamModThis);
                            }
                            else
                            {
                                flags |= ParamFlags.This;
                            }
                        }
                        if (mod.Kind == SyntaxKind.FinalKeyword)
                        {
                            flags |= ParamFlags.Final;
                        }
                        //else if (mod.Kind == SyntaxKind.ParamsKeyword)
                        //{
                        //	if ((flags & ParamFlags.Params) != 0)
                        //	{
                        //		mod = this.AddError(mod, ErrorCode.ERR_DupParamMod, SyntaxKindFacts.GetText(SyntaxKind.ParamsKeyword));
                        //	}
                        //	else if ((flags & ParamFlags.This) != 0)
                        //	{
                        //		mod = this.AddError(mod, ErrorCode.ERR_BadParamModThis);
                        //	}
                        //	else if ((flags & (ParamFlags.Ref | ParamFlags.Out | ParamFlags.This)) != 0)
                        //	{
                        //		mod = this.AddError(mod, ErrorCode.ERR_MultiParamMod);
                        //	}
                        //	else
                        //	{
                        //		flags |= ParamFlags.Params;
                        //	}
                        //}
                    }

                    modifiers.Add(mod);
                    continue;
                }

                if (allowFieldModifiers)
                {
                    var newFieldMod = GetFieldModifier(this.CurrentToken);
                    if (newFieldMod != SyntaxModifier.None)
                    {
                        var modTok = this.EatToken();

                        if (newFieldMod == SyntaxModifier.Static)
                        {
                            if ((fieldMods & SyntaxModifier.Static) == 0)
                            {
                                modTok = this.AddError(modTok, ErrorCode.ERR_StaticParamMod);
                            }
                        }
                        else
                        {
                            ReportDuplicateModifiers(ref modTok, newFieldMod, fieldMods, ref seenNoDuplicates, ref seenNoAccessibilityDuplicates);
                        }

                        fieldMods |= newFieldMod;

                        modifiers.Add(modTok);
                        continue;
                    }
                }

                break;
            }

            if (fieldMods != 0 && fieldMods != SyntaxModifier.Static && ((fieldMods & AccessModifiers) == 0))
            {
                for (int i = 0; i < modifiers.Count; i++)
                {
                    var mod = GetFieldModifier((SyntaxToken)modifiers[i]);

                    if (mod != SyntaxModifier.None && mod != SyntaxModifier.Static)
                    {
                        Debug.Assert((fieldMods & AccessModifiers) == 0);

                        if ((fieldMods & AccessModifiers) == 0)
                        {
                            modifiers[i] = this.AddError(modifiers[i], ErrorCode.ERR_ParamMissingAccessMod);
                        }

                        break;
                    }
                }
            }
        }
Beispiel #4
0
 private void ReportDuplicateModifiers(ref SyntaxToken modTok, SyntaxModifier newMod, SyntaxModifier mods,
                                       ref bool seenNoDuplicates, ref bool seenNoAccessibilityDuplicates)
 {
     if ((mods & newMod) != 0)
     {
         if (seenNoDuplicates)
         {
             modTok           = this.AddError(modTok, ErrorCode.ERR_DuplicateModifier, SyntaxKindFacts.GetText(modTok.Kind));
             seenNoDuplicates = false;
         }
     }
     else
     {
         if ((mods & AccessModifiers) != 0 && (newMod & AccessModifiers) != 0)
         {
             if (seenNoAccessibilityDuplicates)
             {
                 modTok = this.AddError(modTok, ErrorCode.ERR_BadMemberProtection);
             }
             seenNoAccessibilityDuplicates = false;
         }
     }
 }
        private ExpressionSyntax ParseSubExpression(uint precedence, bool allowDeclarationExpressionAtTheBeginning = true, bool contextRequiresVariable = false)
        {
            ExpressionSyntax leftOperand   = null;
            uint             newPrecedence = 0;
            SyntaxKind       opKind        = SyntaxKind.None;

            // all of these are tokens that start statements and are invalid
            // to start a expression with. if we see one, then we must have
            // something like:
            //
            // return
            // if (...
            // parse out a missing name node for the expression, and keep on going
            var tk = this.CurrentToken.Kind;

            if (IsInvalidSubExpression(tk))
            {
                return(this.AddError(this.CreateMissingIdentifierName(), ErrorCode.ERR_InvalidExprTerm, SyntaxKindFacts.GetText(tk)));
            }

            // No left operand, so we need to parse one -- possibly preceded by a
            // unary operator.
            if (IsExpectedPrefixUnaryOperator(tk))
            {
                opKind        = SyntaxKindFacts.GetPrefixUnaryExpression(tk);
                newPrecedence = GetPrecedence(opKind);
                var opToken = this.EatToken();
                var operand = this.ParseSubExpression(newPrecedence);
                leftOperand = _syntaxFactory.PrefixUnaryExpression(opKind, opToken, operand);
            }
            else
            {
                // Not a unary operator - get a primary expression.
                leftOperand = this.ParseTerm(precedence, allowDeclarationExpressionAtTheBeginning, contextRequiresVariable);
            }

            while (true)
            {
                // We either have a binary operator here, or we're finished.
                tk = this.CurrentToken.Kind;
                if (!IsExpectedBinaryOperator(tk))
                {
                    break;
                }

                opKind        = SyntaxKindFacts.GetBinaryExpression(tk);
                newPrecedence = GetPrecedence(opKind);

                Debug.Assert(newPrecedence > 0);                      // All binary operators must have precedence > 0!

                // check for >> or >>= or >>> or >>>=
                bool doubleOp        = false;
                bool doubleOpPlusOne = false;
                if (tk == SyntaxKind.GreaterThanToken &&
                    (this.PeekToken(1).Kind == SyntaxKind.GreaterThanToken) &&
                    (this.PeekToken(2).Kind == SyntaxKind.GreaterThanToken ||
                     this.PeekToken(2).Kind == SyntaxKind.GreaterThanEqualsToken))
                {
                    // check to see if they really are adjacent
                    if (this.CurrentToken.GetTrailingTriviaWidth() == 0 &&
                        this.PeekToken(1).GetLeadingTriviaWidth() == 0 &&
                        this.PeekToken(1).GetTrailingTriviaWidth() == 0 &&
                        this.PeekToken(2).GetLeadingTriviaWidth() == 0
                        )
                    {
                        opKind = SyntaxKindFacts.GetBinaryExpression(this.PeekToken(2).Kind == SyntaxKind.GreaterThanToken ?
                                                                     SyntaxKind.GreaterThanGreaterThanGreaterThanToken :
                                                                     SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken);


                        newPrecedence   = GetPrecedence(opKind);
                        doubleOp        = true;
                        doubleOpPlusOne = true;
                    }
                }
                else if (tk == SyntaxKind.GreaterThanToken &&
                         (this.PeekToken(1).Kind == SyntaxKind.GreaterThanToken ||
                          this.PeekToken(1).Kind == SyntaxKind.GreaterThanEqualsToken))
                {
                    // check to see if they really are adjacent
                    if (this.CurrentToken.GetTrailingTriviaWidth() == 0 && this.PeekToken(1).GetLeadingTriviaWidth() == 0)
                    {
                        opKind = SyntaxKindFacts.GetBinaryExpression(this.PeekToken(1).Kind == SyntaxKind.GreaterThanToken ?
                                                                     SyntaxKind.GreaterThanGreaterThanToken :
                                                                     SyntaxKind.GreaterThanGreaterThanEqualsToken);
                        newPrecedence = GetPrecedence(opKind);
                        doubleOp      = true;
                    }
                }

                // Check the precedence to see if we should "take" this operator
                if (newPrecedence < precedence)
                {
                    break;
                }

                // Same precedence, but not right-associative -- deal with this "later"
                if ((newPrecedence == precedence) && !IsRightAssociative(opKind))
                {
                    break;
                }

                // Precedence is okay, so we'll "take" this operator.
                var opToken = this.EatToken();
                if (doubleOp)
                {
                    // combine tokens into a single token
                    var opToken2 = this.EatToken();
                    if (doubleOpPlusOne)
                    {
                        var opToken3 = this.EatToken();
                        var kind     = opToken3.Kind == SyntaxKind.GreaterThanToken ?
                                       SyntaxKind.GreaterThanGreaterThanGreaterThanToken :
                                       SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken;

                        opToken = SyntaxFactory.Token(opToken.GetLeadingTrivia(), kind, opToken3.GetTrailingTrivia());
                    }
                    else
                    {
                        var kind = opToken2.Kind == SyntaxKind.GreaterThanToken ?
                                   SyntaxKind.GreaterThanGreaterThanToken :
                                   SyntaxKind.GreaterThanGreaterThanEqualsToken;
                        opToken = SyntaxFactory.Token(opToken.GetLeadingTrivia(), kind, opToken2.GetTrailingTrivia());
                    }
                }

                if (opKind == SyntaxKind.InstanceOfExpression)
                {
                    leftOperand = _syntaxFactory.BinaryExpression(opKind, leftOperand, opToken,
                                                                  this.ParseTypeCore(parentIsParameter: false, isInstanceOfOrAs: true, expectSizes: false, isArrayCreation: false));
                }
                else
                {
                    leftOperand = _syntaxFactory.BinaryExpression(opKind, leftOperand, opToken, this.ParseSubExpression(newPrecedence));
                }
            }

            // From the language spec:
            //
            // conditional-expression:
            //  null-coalescing-expression
            //  null-coalescing-expression   ?   expression   :   expression
            //
            // Only take the ternary if we're at a precedence less than the null coelescing
            // expression.

            var nullCoalescingPrecedence = 2U;            //GetPrecedence(SyntaxKind.CoalesceExpression);

            if (tk == SyntaxKind.QuestionToken && precedence < 2)
            {
                var questionToken = this.EatToken();

                var colonLeft = this.ParseSubExpression(nullCoalescingPrecedence - 1);
                var colon     = this.EatToken(SyntaxKind.ColonToken);

                var colonRight = this.ParseSubExpression(nullCoalescingPrecedence - 1);
                leftOperand = _syntaxFactory.ConditionalExpression(leftOperand, questionToken, colonLeft, colon, colonRight);
            }

            return(leftOperand);
        }
        private ExpressionSyntax ParseTerm(uint precedence, bool allowDeclarationExpression, bool contextRequiresVariable)
        {
            ExpressionSyntax expr = null;

            var tk = this.CurrentToken.Kind;

            if (SyntaxKindFacts.IsPredefinedType(tk) && allowDeclarationExpression &&
                this.PeekToken(1).Kind == SyntaxKind.DotToken &&
                this.PeekToken(2).Kind == SyntaxKind.ClassKeyword)
            {
                expr = ParseClassLiteralExpression();
            }
            else
            {
                switch (tk)
                {
                case SyntaxKind.DefaultKeyword:
                    expr = this.ParseDefaultExpression();
                    break;

                case SyntaxKind.ColonColonToken:
                    // misplaced ::
                    // TODO: this should not be a compound name.. (disallow dots)
                    expr = this.ParseQualifiedName(NameOptions.InExpression);
                    break;

                case SyntaxKind.IdentifierToken:
                    if (this.IsTrueIdentifier())
                    {
                        if (this.IsPossibleLambdaExpression(precedence))
                        {
                            expr = this.ParseLambdaExpression();
                        }
                        else if (allowDeclarationExpression && IsPossibleDeclarationExpression(contextRequiresVariable))
                        {
                            expr = ParseDeclarationExpression();
                        }
                        else if (IsPossibleIdentifierDotSuffix(SyntaxKind.ClassKeyword))
                        {
                            expr = ParseClassLiteralExpression();
                        }
                        else if (IsPossibleIdentifierDotSuffix(SyntaxKind.ThisKeyword))
                        {
                            expr = ParseJavaQualifiedThisExpression();
                        }
                        else if (IsPossibleIdentifierDotSuffix(SyntaxKind.SuperKeyword))
                        {
                            expr = ParseJavaQualifiedSuperExpression();
                        }
                        else if (IsPossibleIdentifierDotSuffix(SyntaxKind.NewKeyword))
                        {
                            expr = this.ParseNewExpression();
                        }
                        else
                        {
                            expr = this.ParseSimpleName(NameOptions.InExpression);
                        }
                    }
                    else
                    {
                        expr = this.CreateMissingIdentifierName();
                        expr = this.AddError(expr, ErrorCode.ERR_InvalidExprTerm, this.CurrentToken.Text);
                    }

                    break;

                case SyntaxKind.ThisKeyword:
                    expr = _syntaxFactory.ThisExpression(this.EatToken());
                    break;

                case SyntaxKind.SuperKeyword:
                    expr = _syntaxFactory.BaseExpression(this.EatToken());
                    break;

                case SyntaxKind.ArgListKeyword:
                case SyntaxKind.FalseKeyword:

                case SyntaxKind.TrueKeyword:
                case SyntaxKind.NullKeyword:
                case SyntaxKind.NumericLiteralToken:
                case SyntaxKind.StringLiteralToken:
                case SyntaxKind.CharacterLiteralToken:
                    expr = _syntaxFactory.LiteralExpression(SyntaxKindFacts.GetLiteralExpression(tk), this.EatToken());
                    break;

                case SyntaxKind.OpenParenToken:
                    expr = this.ParseCastOrParenExpressionOrLambda(precedence, contextRequiresVariable: contextRequiresVariable);
                    break;

                case SyntaxKind.NewKeyword:
                    expr = this.ParseNewExpression();
                    break;

                case SyntaxKind.OpenBraceToken:
                    expr = this.ParseArrayInitializer();
                    break;

                case SyntaxKind.AtToken:
                    expr = this.ParseAnnotationCreationExpression();
                    break;

                default:
                    // check for intrinsic type followed by '.'
                    if (IsPredefinedType(tk))
                    {
                        if (allowDeclarationExpression && IsPossibleDeclarationExpression(contextRequiresVariable))
                        {
                            expr = ParseDeclarationExpression();
                        }
                        else
                        {
                            expr = _syntaxFactory.PredefinedType(this.EatToken());

                            if (this.CurrentToken.Kind != SyntaxKind.DotToken || tk == SyntaxKind.VoidKeyword)
                            {
                                expr = this.AddError(expr, ErrorCode.ERR_InvalidExprTerm, SyntaxKindFacts.GetText(tk));
                            }
                        }
                    }
                    else
                    {
                        expr = this.CreateMissingIdentifierName();

                        if (tk == SyntaxKind.EndOfFileToken)
                        {
                            expr = this.AddError(expr, ErrorCode.ERR_ExpressionExpected);
                        }
                        else
                        {
                            expr = this.AddError(expr, ErrorCode.ERR_InvalidExprTerm, SyntaxKindFacts.GetText(tk));
                        }
                    }

                    break;
                }
            }

            return(this.ParsePostFixExpression(expr));
        }