public virtual void VisitLifetimeName(ReferenceLifetimeSyntax referenceLifetime, A args) { VisitExpression(referenceLifetime.ReferentTypeExpression, args); }
/// <summary> /// For expressions, we switch to a precedence climbing parser. /// </summary> public ExpressionSyntax ParseExpression(OperatorPrecedence minPrecedence) { var expression = ParseAtom(); for (; ;) { IOperatorToken @operator = null; OperatorPrecedence?precedence = null; var leftAssociative = true; switch (Tokens.Current) { case IEqualsToken _: case IPlusEqualsToken _: case IMinusEqualsToken _: case IAsteriskEqualsToken _: case ISlashEqualsToken _: if (minPrecedence <= OperatorPrecedence.Assignment) { precedence = OperatorPrecedence.Assignment; leftAssociative = false; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IQuestionQuestionToken _: if (minPrecedence <= OperatorPrecedence.Coalesce) { precedence = OperatorPrecedence.Coalesce; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IOrKeywordToken _: if (minPrecedence <= OperatorPrecedence.LogicalOr) { precedence = OperatorPrecedence.LogicalOr; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IAndKeywordToken _: if (minPrecedence <= OperatorPrecedence.LogicalAnd) { precedence = OperatorPrecedence.LogicalAnd; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IEqualsEqualsToken _: case INotEqualToken _: if (minPrecedence <= OperatorPrecedence.Equality) { precedence = OperatorPrecedence.Equality; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case ILessThanToken _: case ILessThanOrEqualToken _: case IGreaterThanToken _: case IGreaterThanOrEqualToken _: case ILessThanColonToken _: // Subtype operator case IAsKeywordToken _: if (minPrecedence <= OperatorPrecedence.Relational) { precedence = OperatorPrecedence.Relational; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IColonToken _: // type kind if (minPrecedence <= OperatorPrecedence.Relational) { var colon = Tokens.Expect <IColonToken>(); TypeKind typeKind; switch (Tokens.Current) { case IClassKeywordToken _: typeKind = TypeKind.Class; break; case IStructKeywordToken _: typeKind = TypeKind.Struct; break; default: Tokens.Expect <ITypeKindKeywordToken>(); // We saw a colon without what we expected after, just assume it is missing continue; } var typeKindSpan = Tokens.Expect <ITypeKindKeywordToken>(); var span = TextSpan.Covering(colon, typeKindSpan); expression = new TypeKindExpressionSyntax(span, typeKind); continue; } break; case IDotDotToken _: case ILessThanDotDotToken _: case IDotDotLessThanToken _: case ILessThanDotDotLessThanToken _: if (minPrecedence <= OperatorPrecedence.Range) { precedence = OperatorPrecedence.Range; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IPlusToken _: case IMinusToken _: if (minPrecedence <= OperatorPrecedence.Additive) { precedence = OperatorPrecedence.Additive; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IAsteriskToken _: case ISlashToken _: if (minPrecedence <= OperatorPrecedence.Multiplicative) { precedence = OperatorPrecedence.Multiplicative; @operator = Tokens.RequiredToken <IOperatorToken>(); } break; case IDollarToken _: if (minPrecedence <= OperatorPrecedence.Lifetime) { Tokens.Expect <IDollarToken>(); var(nameSpan, lifetime) = ParseLifetimeName(); expression = new ReferenceLifetimeSyntax(expression, nameSpan, lifetime); continue; } break; case IQuestionToken _: if (minPrecedence <= OperatorPrecedence.Unary) { var question = Tokens.Required <IQuestionToken>(); var span = TextSpan.Covering(expression.Span, question); expression = new UnaryExpressionSyntax(span, UnaryOperatorFixity.Postfix, UnaryOperator.Question, expression); continue; } break; case IOpenParenToken _: if (minPrecedence <= OperatorPrecedence.Primary) { var callee = expression; Tokens.Expect <IOpenParenToken>(); var arguments = ParseArguments(); var closeParenSpan = Tokens.Expect <ICloseParenToken>(); var span = TextSpan.Covering(callee.Span, closeParenSpan); expression = new InvocationSyntax(span, callee, arguments); continue; } break; case IDotToken _: case ICaretDotToken _: case IQuestionDotToken _: if (minPrecedence <= OperatorPrecedence.Primary) { // Member Access var accessOperator = BuildAccessOperator(Tokens.RequiredToken <IAccessOperatorToken>()); var member = ParseSimpleName(); var span = TextSpan.Covering(expression.Span, member.Span); expression = new MemberAccessExpressionSyntax(span, expression, accessOperator, member); continue; } break; default: return(expression); } if (@operator is IOperatorToken operatorToken && precedence is OperatorPrecedence operatorPrecedence) { if (leftAssociative) { operatorPrecedence += 1; } var rightOperand = ParseExpression(operatorPrecedence); expression = BuildOperatorExpression(expression, operatorToken, rightOperand); }