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); } }
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); }
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); } }
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)); }
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); } }
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); } }