mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
refactor the parsing logic for "x.y" to detangle it a bit, NFC.
This commit is contained in:
@@ -1250,95 +1250,94 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
|
|||||||
// Check for a .foo suffix.
|
// Check for a .foo suffix.
|
||||||
SourceLoc TokLoc = Tok.getLoc();
|
SourceLoc TokLoc = Tok.getLoc();
|
||||||
if (consumeIf(tok::period) || consumeIf(tok::period_prefix)) {
|
if (consumeIf(tok::period) || consumeIf(tok::period_prefix)) {
|
||||||
|
|
||||||
|
// Handle "x.42" - a tuple index.
|
||||||
|
if (Tok.is(tok::integer_literal)) {
|
||||||
|
DeclName name = Context.getIdentifier(Tok.getText());
|
||||||
|
SourceLoc nameLoc = consumeToken(tok::integer_literal);
|
||||||
|
|
||||||
|
// Don't allow '.<integer literal>' following a numeric literal
|
||||||
|
// expression.
|
||||||
|
if (Result.isNonNull() && isa<NumberLiteralExpr>(Result.get())) {
|
||||||
|
diagnose(nameLoc, diag::numeric_literal_numeric_member)
|
||||||
|
.highlight(Result.get()->getSourceRange());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = makeParserResult(
|
||||||
|
new (Context) UnresolvedDotExpr(Result.get(), TokLoc, name,
|
||||||
|
DeclNameLoc(nameLoc),
|
||||||
|
/*Implicit=*/false));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "x.dynamicType" - A metatype expr.
|
||||||
|
if (Tok.is(tok::kw_dynamicType)) {
|
||||||
|
Result = makeParserResult(
|
||||||
|
new (Context) DynamicTypeExpr(Result.get(), consumeToken(), Type()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "x.self" expr.
|
||||||
|
if (Tok.is(tok::kw_self)) {
|
||||||
|
Result = makeParserResult(
|
||||||
|
new (Context) DotSelfExpr(Result.get(), TokLoc, consumeToken()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "x.<tab>" for code completion.
|
||||||
|
if (Tok.is(tok::code_complete)) {
|
||||||
|
if (CodeCompletion && Result.isNonNull())
|
||||||
|
CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc);
|
||||||
|
// Eat the code completion token because we handled it.
|
||||||
|
consumeToken(tok::code_complete);
|
||||||
|
Result.setHasCodeCompletion();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have '.<keyword><code_complete>', try to recover by creating
|
||||||
|
// an identifier with the same spelling as the keyword.
|
||||||
|
if (Tok.isKeyword() && peekToken().is(tok::code_complete)) {
|
||||||
|
Identifier Name = Context.getIdentifier(Tok.getText());
|
||||||
|
Result = makeParserResult(
|
||||||
|
new (Context) UnresolvedDotExpr(Result.get(), TokLoc,
|
||||||
|
Name, DeclNameLoc(Tok.getLoc()),
|
||||||
|
/*Implicit=*/false));
|
||||||
|
consumeToken();
|
||||||
|
}
|
||||||
|
|
||||||
// Non-identifier cases.
|
// Non-identifier cases.
|
||||||
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::integer_literal) &&
|
if (Tok.isNot(tok::identifier, tok::kw_init)) {
|
||||||
Tok.isNot(tok::kw_init)) {
|
|
||||||
// A metatype expr.
|
|
||||||
if (Tok.is(tok::kw_dynamicType)) {
|
|
||||||
Result = makeParserResult(
|
|
||||||
new (Context) DynamicTypeExpr(Result.get(), consumeToken(),
|
|
||||||
Type()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A '.self' expr.
|
|
||||||
if (Tok.is(tok::kw_self)) {
|
|
||||||
Result = makeParserResult(
|
|
||||||
new (Context) DotSelfExpr(Result.get(), TokLoc, consumeToken()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have '.<keyword><code_complete>', try to recover by creating
|
|
||||||
// an identifier with the same spelling as the keyword.
|
|
||||||
if (Tok.isKeyword() && peekToken().is(tok::code_complete)) {
|
|
||||||
Identifier Name = Context.getIdentifier(Tok.getText());
|
|
||||||
Result = makeParserResult(
|
|
||||||
new (Context) UnresolvedDotExpr(Result.get(), TokLoc,
|
|
||||||
Name, DeclNameLoc(Tok.getLoc()),
|
|
||||||
/*Implicit=*/false));
|
|
||||||
consumeToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tok.is(tok::code_complete)) {
|
|
||||||
if (CodeCompletion && Result.isNonNull())
|
|
||||||
CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc);
|
|
||||||
// Eat the code completion token because we handled it.
|
|
||||||
consumeToken(tok::code_complete);
|
|
||||||
Result.setHasCodeCompletion();
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
checkForInputIncomplete();
|
checkForInputIncomplete();
|
||||||
diagnose(Tok, diag::expected_member_name);
|
diagnose(Tok, diag::expected_member_name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow '.<integer literal>' following a numeric literal
|
assert(Tok.isAny(tok::identifier, tok::kw_init));
|
||||||
// expression.
|
DeclNameLoc NameLoc;
|
||||||
if (Tok.is(tok::integer_literal) && Result.isNonNull() &&
|
DeclName Name = parseUnqualifiedDeclName(/*allowInit=*/true,
|
||||||
(isa<FloatLiteralExpr>(Result.get()) ||
|
NameLoc,
|
||||||
isa<IntegerLiteralExpr>(Result.get()))) {
|
diag::expected_member_name);
|
||||||
diagnose(Tok, diag::numeric_literal_numeric_member)
|
if (!Name) return nullptr;
|
||||||
.highlight(Result.get()->getSourceRange());
|
|
||||||
consumeToken();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Result.isParseError())
|
Result = makeParserResult(
|
||||||
continue;
|
new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name,
|
||||||
|
|
||||||
if (Tok.isAny(tok::identifier, tok::kw_init)) {
|
|
||||||
DeclNameLoc NameLoc;
|
|
||||||
DeclName Name = parseUnqualifiedDeclName(/*allowInit=*/true,
|
|
||||||
NameLoc,
|
NameLoc,
|
||||||
diag::expected_member_name);
|
/*Implicit=*/false));
|
||||||
if (!Name) return nullptr;
|
|
||||||
|
|
||||||
Result = makeParserResult(
|
if (canParseAsGenericArgumentList()) {
|
||||||
new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name,
|
SmallVector<TypeRepr*, 8> args;
|
||||||
NameLoc,
|
SourceLoc LAngleLoc, RAngleLoc;
|
||||||
/*Implicit=*/false));
|
if (parseGenericArguments(args, LAngleLoc, RAngleLoc)) {
|
||||||
|
diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
|
||||||
if (canParseAsGenericArgumentList()) {
|
|
||||||
SmallVector<TypeRepr*, 8> args;
|
|
||||||
SourceLoc LAngleLoc, RAngleLoc;
|
|
||||||
if (parseGenericArguments(args, LAngleLoc, RAngleLoc)) {
|
|
||||||
diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
|
|
||||||
}
|
|
||||||
|
|
||||||
SmallVector<TypeLoc, 8> locArgs;
|
|
||||||
for (auto ty : args)
|
|
||||||
locArgs.push_back(ty);
|
|
||||||
Result = makeParserResult(new (Context) UnresolvedSpecializeExpr(
|
|
||||||
Result.get(), LAngleLoc, Context.AllocateCopy(locArgs),
|
|
||||||
RAngleLoc));
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DeclName name = Context.getIdentifier(Tok.getText());
|
SmallVector<TypeLoc, 8> locArgs;
|
||||||
SourceLoc nameLoc = consumeToken(tok::integer_literal);
|
for (auto ty : args)
|
||||||
Result = makeParserResult(
|
locArgs.push_back(ty);
|
||||||
new (Context) UnresolvedDotExpr(Result.get(), TokLoc, name,
|
Result = makeParserResult(new (Context) UnresolvedSpecializeExpr(
|
||||||
DeclNameLoc(nameLoc),
|
Result.get(), LAngleLoc, Context.AllocateCopy(locArgs),
|
||||||
/*Implicit=*/false));
|
RAngleLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an expr-call-suffix, parse it and form a call.
|
// If there is an expr-call-suffix, parse it and form a call.
|
||||||
|
|||||||
Reference in New Issue
Block a user