Skip to content

Commit 6a9b252

Browse files
committed
[SyntaxParse] Parse unresolved member expression syntax
1 parent f50966f commit 6a9b252

File tree

4 files changed

+192
-73
lines changed

4 files changed

+192
-73
lines changed

include/swift/Parse/ASTGen.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class ASTGen {
8888
Expr *generate(const syntax::ArrayExprSyntax &Expr, const SourceLoc Loc);
8989
Expr *generate(const syntax::DictionaryExprSyntax &Expr, const SourceLoc Loc);
9090
Expr *generate(const syntax::TupleExprSyntax &E, const SourceLoc Loc);
91+
Expr *generate(const syntax::FunctionCallExprSyntax &E, const SourceLoc Loc);
92+
Expr *generate(const syntax::MemberAccessExprSyntax &E, const SourceLoc Loc);
9193
Expr *generate(const syntax::EditorPlaceholderExprSyntax &Expr,
9294
const SourceLoc Loc);
9395
Expr *generate(const syntax::SpecializeExprSyntax &Expr, const SourceLoc Loc);
@@ -108,6 +110,8 @@ class ASTGen {
108110
const SourceLoc Loc);
109111
Expr *generate(const syntax::ObjectLiteralExprSyntax &Expr,
110112
const SourceLoc Loc);
113+
Expr *generate(const syntax::CodeCompletionExprSyntax &Expr,
114+
const SourceLoc Loc);
111115
Expr *generate(const syntax::UnknownExprSyntax &Expr, const SourceLoc Loc);
112116

113117
std::pair<DeclName, DeclNameLoc> generateUnqualifiedDeclName(

include/swift/Parse/Parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,9 @@ class Parser {
14561456
ParserResult<Expr> parseExprSelector();
14571457
ParserResult<Expr> parseExprSuper();
14581458
ParsedSyntaxResult<ParsedExprSyntax> parseExprSuperSyntax();
1459+
ParserResult<Expr> parseExprUnresolvedMember(bool isExprBasic);
1460+
ParsedSyntaxResult<ParsedExprSyntax>
1461+
parseExprUnresolvedMemberSyntax(bool isExprBasic);
14591462
ParserResult<Expr> parseExprStringLiteral();
14601463

14611464
// todo [gsoc]: create new result type for ParsedSyntax

lib/Parse/ASTGen.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
250250
result = generate(*dictionaryExpr, Loc);
251251
else if (auto tupleExpr = E.getAs<TupleExprSyntax>())
252252
result = generate(*tupleExpr, Loc);
253+
else if (auto callExpr = E.getAs<FunctionCallExprSyntax>())
254+
result = generate(*callExpr, Loc);
255+
else if (auto memberExpr = E.getAs<MemberAccessExprSyntax>())
256+
result = generate(*memberExpr, Loc);
253257
else if (auto integerLiteralExpr = E.getAs<IntegerLiteralExprSyntax>())
254258
result = generate(*integerLiteralExpr, Loc);
255259
else if (auto floatLiteralExpr = E.getAs<FloatLiteralExprSyntax>())
@@ -270,6 +274,8 @@ Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
270274
result = generate(*poundDsohandleExpr, Loc);
271275
else if (auto objectLiteralExpr = E.getAs<ObjectLiteralExprSyntax>())
272276
result = generate(*objectLiteralExpr, Loc);
277+
else if (auto completionExpr = E.getAs<CodeCompletionExprSyntax>())
278+
result = generate(*completionExpr, Loc);
273279
else if (auto unknownExpr = E.getAs<UnknownExprSyntax>())
274280
result = generate(*unknownExpr, Loc);
275281
else {
@@ -595,6 +601,67 @@ void ASTGen::generateExprTupleElementList(const TupleExprElementListSyntax &elem
595601
exprLabels.size() == exprLabelLocs.size());
596602
}
597603

604+
Expr *ASTGen::generate(const FunctionCallExprSyntax &E, const SourceLoc Loc) {
605+
auto callee = E.getCalledExpression();
606+
607+
SourceLoc LParenLoc, RParenLoc;
608+
SmallVector<Expr *, 2> args;
609+
SmallVector<Identifier, 2> argLabels;
610+
SmallVector<SourceLoc, 2> argLabelLocs;
611+
generateExprTupleElementList(E.getArgumentList(), Loc,
612+
/*isForCallArguments=*/true, args, argLabels,
613+
argLabelLocs);
614+
Expr *trailingClosure = nullptr;
615+
if (auto CE = E.getTrailingClosure())
616+
trailingClosure = generate(*CE, Loc);
617+
if (auto LParen = E.getLeftParen()) {
618+
LParenLoc = advanceLocBegin(Loc, *LParen);
619+
if (auto RParen = E.getRightParen())
620+
RParenLoc = advanceLocBegin(Loc, *RParen);
621+
else
622+
RParenLoc = advanceLocEnd(Loc, E.getArgumentList());
623+
}
624+
625+
if (auto memberAccess = callee.getAs<MemberAccessExprSyntax>()) {
626+
if (!memberAccess->getBase()) {
627+
// This is UnresolvedMemberExpr with call arguments.
628+
if (memberAccess->getName().isMissing())
629+
return nullptr;
630+
631+
SourceLoc dotLoc = advanceLocBegin(Loc, memberAccess->getDot());
632+
DeclName name;
633+
DeclNameLoc nameLoc;
634+
std::tie(name, nameLoc) = generateUnqualifiedDeclName(
635+
memberAccess->getName(), memberAccess->getDeclNameArguments(), Loc);
636+
637+
return UnresolvedMemberExpr::create(
638+
Context, dotLoc, nameLoc, name, LParenLoc, args, argLabels,
639+
argLabelLocs, RParenLoc, trailingClosure,
640+
/*implicit=*/false);
641+
}
642+
}
643+
llvm_unreachable("call expression not implemented");
644+
return nullptr;
645+
}
646+
647+
Expr *ASTGen::generate(const MemberAccessExprSyntax &E, const SourceLoc Loc) {
648+
if (!E.getBase()) {
649+
// This is an UnresolvedMemberExpr.
650+
if (E.getName().isMissing())
651+
return nullptr;
652+
653+
DeclName name;
654+
DeclNameLoc nameLoc;
655+
std::tie(name, nameLoc) =
656+
generateUnqualifiedDeclName(E.getName(), E.getDeclNameArguments(), Loc);
657+
SourceLoc dotLoc = advanceLocBegin(Loc, E.getDot());
658+
659+
return UnresolvedMemberExpr::create(Context, dotLoc, nameLoc, name,
660+
/*implicit=*/false);
661+
}
662+
llvm_unreachable("member access expression not implemented");
663+
return nullptr;
664+
}
598665

599666
Expr *ASTGen::generate(const IntegerLiteralExprSyntax &Expr,
600667
const SourceLoc Loc) {
@@ -683,6 +750,30 @@ Expr *ASTGen::generate(const ObjectLiteralExprSyntax &E, const SourceLoc Loc) {
683750
trailingClosure, /*implicit=*/false);
684751
}
685752

753+
Expr *ASTGen::generate(const CodeCompletionExprSyntax &E, const SourceLoc Loc) {
754+
if (!E.getBase()) {
755+
if (auto punctuator = E.getPeriodOrParen()) {
756+
// '.' <cc-token>
757+
if (punctuator->getTokenKind() == tok::period ||
758+
punctuator->getTokenKind() == tok::period_prefix) {
759+
auto ccLoc = advanceLocBegin(Loc, E.getCodeCompletionToken());
760+
auto dotLoc = advanceLocBegin(Loc, *punctuator);
761+
762+
auto CCE = new (Context) CodeCompletionExpr(ccLoc);
763+
if (P.CodeCompletion)
764+
P.CodeCompletion->completeUnresolvedMember(CCE, dotLoc);
765+
return CCE;
766+
}
767+
} else {
768+
llvm_unreachable("'(' <cc-token> is not suppported");
769+
}
770+
} else {
771+
// TODO: implement
772+
}
773+
llvm_unreachable("code completion expression not implemented");
774+
return nullptr;
775+
}
776+
686777
Expr *ASTGen::generate(const UnknownExprSyntax &Expr, const SourceLoc Loc) {
687778
if (Expr.getNumChildren() == 1 && Expr.getChild(0)->isToken()) {
688779
Syntax Token = *Expr.getChild(0);

lib/Parse/ParseExpr.cpp

Lines changed: 94 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,96 @@ static bool isValidTrailingClosure(bool isExprBasic, Parser &P){
971971
return true;
972972
}
973973

974+
ParsedSyntaxResult<ParsedExprSyntax>
975+
Parser::parseExprUnresolvedMemberSyntax(bool isExprBasic) {
976+
assert(Tok.isAny(tok::period, tok::period_prefix));
977+
978+
// Parse '.'
979+
Tok.setKind(tok::period_prefix);
980+
auto dotTok = consumeTokenSyntax(tok::period_prefix);
981+
982+
// Handle code completion; '.' <cc-token>
983+
if (Tok.is(tok::code_complete)) {
984+
ParsedCodeCompletionExprSyntaxBuilder ccBuilder(*SyntaxContext);
985+
ccBuilder.usePeriodOrParen(std::move(dotTok));
986+
ccBuilder.useCodeCompletionToken(consumeTokenSyntax(tok::code_complete));
987+
return makeParsedCodeCompletion(ccBuilder.build());
988+
}
989+
990+
ParserStatus status;
991+
992+
// Parse the name.
993+
Optional<ParsedTokenSyntax> identTok;
994+
Optional<ParsedDeclNameArgumentsSyntax> declNameArgs;
995+
status |=
996+
parseUnqualifiedDeclNameSyntax(identTok, declNameArgs, /*afterDot=*/true,
997+
diag::expected_identifier_after_dot_expr);
998+
if (status.isError()) {
999+
// If the name is missing. It makes no sense to construct a member access
1000+
// expression.
1001+
assert(!identTok && !declNameArgs);
1002+
return makeParsedError(
1003+
ParsedSyntaxRecorder::makeUnknownExpr({&dotTok, 1}, *SyntaxContext));
1004+
}
1005+
1006+
ParsedMemberAccessExprSyntaxBuilder builder(*SyntaxContext);
1007+
builder.useDot(std::move(dotTok));
1008+
builder.useName(std::move(*identTok));
1009+
if (declNameArgs)
1010+
builder.useDeclNameArguments(std::move(*declNameArgs));
1011+
1012+
// FIXME: These calling suffix parsings are not necessary for Syntax parsing.
1013+
// Remove this block after full expression parsing migration.
1014+
1015+
// Check for a () suffix, which indicates a call when constructing
1016+
// this member. Note that this cannot be the start of a new line.
1017+
if (Tok.isFollowingLParen()) {
1018+
ParsedFunctionCallExprSyntaxBuilder callBuilder(*SyntaxContext);
1019+
callBuilder.useCalledExpression(builder.build());
1020+
1021+
status |= parseExprListSyntax(
1022+
tok::l_paren, tok::r_paren,
1023+
/*isPostfix=*/true, isExprBasic,
1024+
[&](ParsedTokenSyntax &&leftTok,
1025+
ParsedTupleExprElementListSyntax &&args,
1026+
Optional<ParsedTokenSyntax> &&rightTok,
1027+
Optional<ParsedClosureExprSyntax> &&closure) {
1028+
callBuilder.useLeftParen(std::move(leftTok));
1029+
callBuilder.useArgumentList(std::move(args));
1030+
if (rightTok)
1031+
callBuilder.useRightParen(std::move(*rightTok));
1032+
if (closure)
1033+
callBuilder.useTrailingClosure(std::move(*closure));
1034+
});
1035+
return makeParsedResult(callBuilder.build(), status);
1036+
}
1037+
1038+
// Check for a trailing closure, if allowed.
1039+
if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) {
1040+
ParsedFunctionCallExprSyntaxBuilder callBuilder(*SyntaxContext);
1041+
callBuilder.useCalledExpression(builder.build());
1042+
1043+
auto closure = parseTrailingClosureSyntax({PreviousLoc, PreviousLoc});
1044+
status |= closure.getStatus();
1045+
assert(!closure.isNull());
1046+
callBuilder.useTrailingClosure(closure.get());
1047+
1048+
return makeParsedResult(callBuilder.build(), status);
1049+
}
1050+
1051+
return makeParsedResult(builder.build(), status);
1052+
}
1053+
1054+
ParserResult<Expr>
1055+
Parser::parseExprUnresolvedMember(bool isExprBasic) {
1056+
auto leadingLoc = leadingTriviaLoc();
1057+
auto parsed = parseExprUnresolvedMemberSyntax(isExprBasic);
1058+
SyntaxContext->addSyntax(parsed.get());
1059+
auto syntax = SyntaxContext->topNode<ExprSyntax>();
1060+
auto expr = Generator.generate(syntax, leadingLoc);
1061+
return makeParserResult(parsed.getStatus(), expr);
1062+
}
1063+
9741064
ParserResult<Expr>
9751065
Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
9761066
bool periodHasKeyPathBehavior,
@@ -1532,13 +1622,12 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15321622

15331623
case tok::period: //=.foo
15341624
case tok::period_prefix: { // .foo
1535-
Tok.setKind(tok::period_prefix);
1536-
SourceLoc DotLoc = consumeToken();
1537-
15381625
// Special case ".<integer_literal>" like ".4". This isn't valid, but the
15391626
// developer almost certainly meant to use "0.4". Diagnose this, and
15401627
// recover as if they wrote that.
1541-
if (Tok.is(tok::integer_literal) && !Tok.isAtStartOfLine()) {
1628+
if (peekToken().is(tok::integer_literal) &&
1629+
!peekToken().isAtStartOfLine()) {
1630+
SourceLoc DotLoc = consumeToken();
15421631
diagnose(DotLoc, diag::invalid_float_literal_missing_leading_zero,
15431632
Tok.getText())
15441633
.fixItInsert(DotLoc, "0")
@@ -1554,76 +1643,8 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15541643
FloatLiteralExpr(FltText, DotLoc,
15551644
/*Implicit=*/false));
15561645
}
1557-
1558-
DeclName Name;
1559-
DeclNameLoc NameLoc;
1560-
1561-
if (Tok.is(tok::code_complete)) {
1562-
auto CCE = new (Context) CodeCompletionExpr(Tok.getLoc());
1563-
auto Result = makeParserResult(CCE);
1564-
Result.setHasCodeCompletion();
1565-
if (CodeCompletion) {
1566-
CodeCompletion->completeUnresolvedMember(CCE, DotLoc);
1567-
}
1568-
consumeToken();
1569-
return Result;
1570-
}
1571-
1572-
Name = parseUnqualifiedDeclName(/*afterDot=*/true, NameLoc,
1573-
diag::expected_identifier_after_dot_expr);
1574-
if (!Name) return nullptr;
1575-
SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
1576-
1577-
// Check for a () suffix, which indicates a call when constructing
1578-
// this member. Note that this cannot be the start of a new line.
1579-
if (Tok.isFollowingLParen()) {
1580-
SourceLoc lParenLoc, rParenLoc;
1581-
SmallVector<Expr *, 2> args;
1582-
SmallVector<Identifier, 2> argLabels;
1583-
SmallVector<SourceLoc, 2> argLabelLocs;
1584-
Expr *trailingClosure;
1585-
1586-
ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
1587-
/*isPostfix=*/true, isExprBasic,
1588-
lParenLoc, args, argLabels,
1589-
argLabelLocs,
1590-
rParenLoc,
1591-
trailingClosure);
1592-
SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
1593-
return makeParserResult(
1594-
status,
1595-
UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
1596-
lParenLoc, args, argLabels,
1597-
argLabelLocs, rParenLoc,
1598-
trailingClosure,
1599-
/*implicit=*/false));
1600-
}
16011646

1602-
// Check for a trailing closure, if allowed.
1603-
if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) {
1604-
// Add dummy blank argument list to the call expression syntax.
1605-
SyntaxContext->addSyntax(
1606-
ParsedSyntaxRecorder::makeBlankTupleExprElementList(
1607-
Tok.getLoc(), *SyntaxContext));
1608-
1609-
ParserResult<Expr> closure =
1610-
parseTrailingClosure(NameLoc.getSourceRange());
1611-
if (closure.isNull()) return nullptr;
1612-
1613-
SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
1614-
// Handle .foo by just making an AST node.
1615-
return makeParserResult(
1616-
ParserStatus(closure),
1617-
UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
1618-
SourceLoc(), { }, { }, { },
1619-
SourceLoc(), closure.get(),
1620-
/*implicit=*/false));
1621-
}
1622-
1623-
// Handle .foo by just making an AST node.
1624-
return makeParserResult(
1625-
UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
1626-
/*implicit=*/false));
1647+
return parseExprUnresolvedMember(isExprBasic);
16271648
}
16281649

16291650
case tok::kw_super: // 'super'

0 commit comments

Comments
 (0)