refactor the parsing logic for "x.y" to detangle it a bit, NFC.

This commit is contained in:
Chris Lattner
2016-05-02 21:33:29 -07:00
parent a0efe4fcb2
commit 561c379eba

View File

@@ -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)) {
// Non-identifier cases.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::integer_literal) &&
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)) { // Handle "x.42" - a tuple index.
if (CodeCompletion && Result.isNonNull()) if (Tok.is(tok::integer_literal)) {
CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc); DeclName name = Context.getIdentifier(Tok.getText());
// Eat the code completion token because we handled it. SourceLoc nameLoc = consumeToken(tok::integer_literal);
consumeToken(tok::code_complete);
Result.setHasCodeCompletion(); // Don't allow '.<integer literal>' following a numeric literal
return Result; // 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.
if (Tok.isNot(tok::identifier, tok::kw_init)) {
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(); Result = makeParserResult(
continue; new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name,
}
if (Result.isParseError())
continue;
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;
if (canParseAsGenericArgumentList()) {
Result = makeParserResult( SmallVector<TypeRepr*, 8> args;
new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name, SourceLoc LAngleLoc, RAngleLoc;
NameLoc, if (parseGenericArguments(args, LAngleLoc, RAngleLoc)) {
/*Implicit=*/false)); 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.