Skip to content

Commit f50966f

Browse files
committed
[SyntaxParse] Parse ObjectLiteralExpr syntax
1 parent 1cb3d7c commit f50966f

File tree

5 files changed

+162
-40
lines changed

5 files changed

+162
-40
lines changed

include/swift/Parse/ASTGen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class ASTGen {
106106
const SourceLoc Loc);
107107
Expr *generate(const syntax::PoundDsohandleExprSyntax &Expr,
108108
const SourceLoc Loc);
109+
Expr *generate(const syntax::ObjectLiteralExprSyntax &Expr,
110+
const SourceLoc Loc);
109111
Expr *generate(const syntax::UnknownExprSyntax &Expr, const SourceLoc Loc);
110112

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

include/swift/Parse/Parser.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,14 +1574,19 @@ class Parser {
15741574
SmallVectorImpl<SourceLoc> &exprLabelLocs,
15751575
SourceLoc &rightLoc,
15761576
Expr *&trailingClosure);
1577-
1577+
ParserStatus parseExprListSyntax(
1578+
tok leftK, tok rightK, bool isPostfix, bool isExprBasic,
1579+
llvm::function_ref<void(
1580+
ParsedTokenSyntax &&, ParsedTupleExprElementListSyntax &&,
1581+
Optional<ParsedTokenSyntax> &&, Optional<ParsedClosureExprSyntax> &&)>
1582+
callback);
15781583
ParserResult<Expr> parseTrailingClosure(SourceRange calleeRange);
1584+
ParsedSyntaxResult<ParsedClosureExprSyntax>
1585+
parseTrailingClosureSyntax(SourceRange calleeRange);
15791586

1580-
/// Parse an object literal.
1581-
///
1582-
/// \param LK The literal kind as determined by the first token.
1583-
ParserResult<Expr> parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LK,
1584-
bool isExprBasic);
1587+
ParserResult<Expr> parseExprObjectLiteral(bool isExprBasic);
1588+
ParsedSyntaxResult<ParsedExprSyntax>
1589+
parseExprObjectLiteralSyntax(bool isExprBasic);
15851590
ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
15861591
bool isExprBasic);
15871592
ParserResult<Expr> parseExprCollection();

lib/Parse/ASTGen.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
268268
result = generate(*poundFunctionExpr, Loc);
269269
else if (auto poundDsohandleExpr = E.getAs<PoundDsohandleExprSyntax>())
270270
result = generate(*poundDsohandleExpr, Loc);
271+
else if (auto objectLiteralExpr = E.getAs<ObjectLiteralExprSyntax>())
272+
result = generate(*objectLiteralExpr, Loc);
271273
else if (auto unknownExpr = E.getAs<UnknownExprSyntax>())
272274
result = generate(*unknownExpr, Loc);
273275
else {
@@ -647,6 +649,40 @@ Expr *ASTGen::generate(const PoundDsohandleExprSyntax &Expr,
647649
Loc);
648650
}
649651

652+
Expr *ASTGen::generate(const ObjectLiteralExprSyntax &E, const SourceLoc Loc) {
653+
ObjectLiteralExpr::LiteralKind kind;
654+
switch (E.getIdentifier().getTokenKind()) {
655+
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) \
656+
case tok::pound_##Name: \
657+
kind = ObjectLiteralExpr::Name; \
658+
break;
659+
#include "swift/Syntax/TokenKinds.def"
660+
default:
661+
llvm_unreachable("unknown token kind for object literal expression");
662+
}
663+
664+
SmallVector<Expr *, 2> args;
665+
SmallVector<Identifier, 2> argLabels;
666+
SmallVector<SourceLoc, 2> argLabelLocs;
667+
generateExprTupleElementList(E.getArguments(), Loc, true, args, argLabels,
668+
argLabelLocs);
669+
670+
ClosureExpr *trailingClosure = nullptr;
671+
if (auto CE = E.getTrailingClosure())
672+
trailingClosure = dyn_cast_or_null<ClosureExpr>(generate(*CE, Loc));
673+
674+
if (E.getLeftParen().isMissing() || E.getRightParen().isMissing())
675+
return nullptr;
676+
677+
SourceLoc poundLoc = advanceLocBegin(Loc, E.getIdentifier());
678+
SourceLoc LParenLoc = advanceLocBegin(Loc, E.getLeftParen());
679+
SourceLoc RParenLoc = advanceLocBegin(Loc, E.getRightParen());
680+
681+
return ObjectLiteralExpr::create(Context, poundLoc, kind, LParenLoc, args,
682+
argLabels, argLabelLocs, RParenLoc,
683+
trailingClosure, /*implicit=*/false);
684+
}
685+
650686
Expr *ASTGen::generate(const UnknownExprSyntax &Expr, const SourceLoc Loc) {
651687
if (Expr.getNumChildren() == 1 && Expr.getChild(0)->isToken()) {
652688
Syntax Token = *Expr.getChild(0);

lib/Parse/ParseExpr.cpp

Lines changed: 111 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,9 +1654,9 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
16541654
}
16551655

16561656
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) \
1657-
case tok::pound_##Name: \
1658-
return parseExprObjectLiteral(ObjectLiteralExpr::Name, isExprBasic);
1657+
case tok::pound_##Name:
16591658
#include "swift/Syntax/TokenKinds.def"
1659+
return parseExprObjectLiteral(isExprBasic);
16601660

16611661
case tok::code_complete: {
16621662
auto Result =
@@ -2772,8 +2772,11 @@ ParserResult<Expr> Parser::parseExprClosure() {
27722772

27732773
// Parse the closing '}'.
27742774
SourceLoc rightBrace;
2775-
parseMatchingToken(tok::r_brace, rightBrace, diag::expected_closure_rbrace,
2776-
leftBrace);
2775+
if (parseMatchingToken(tok::r_brace, rightBrace,
2776+
diag::expected_closure_rbrace, leftBrace)) {
2777+
// Synthesize an r_brace syntax node if the token is absent
2778+
SyntaxContext->synthesize(tok::r_brace, rightBrace);
2779+
}
27772780

27782781
// If we didn't have any parameters, create a parameter list from the
27792782
// anonymous closure arguments.
@@ -3006,6 +3009,62 @@ ParserStatus Parser::parseExprTupleElementListSyntax(
30063009
/// expr-list(left, right):
30073010
/// left right expr-closure?
30083011
/// left expr-tuple-element-list right expr-closure?
3012+
ParserStatus Parser::parseExprListSyntax(
3013+
tok leftK, tok rightK, bool isPostfix, bool isExprBasic,
3014+
llvm::function_ref<void(
3015+
ParsedTokenSyntax &&, ParsedTupleExprElementListSyntax &&,
3016+
Optional<ParsedTokenSyntax> &&, Optional<ParsedClosureExprSyntax> &&)>
3017+
callback) {
3018+
StructureMarkerRAII ParsingExprList(*this, Tok);
3019+
if (ParsingExprList.isFailed())
3020+
return makeParserError();
3021+
3022+
ParserStatus status;
3023+
3024+
auto TokIsStringInterpolationEOF = [&]() -> bool {
3025+
return Tok.is(tok::eof) && Tok.getText() == ")" && rightK == tok::r_paren;
3026+
};
3027+
3028+
// Parse '(' or '['.
3029+
auto leftLoc = Tok.getLoc();
3030+
auto leftTok = consumeTokenSyntax(tok::l_paren);
3031+
3032+
// Parse the elements.
3033+
SmallVector<ParsedTupleExprElementSyntax, 4> elements;
3034+
status |= parseExprTupleElementListSyntax(elements, [&] {
3035+
return Tok.is(rightK) || TokIsStringInterpolationEOF();
3036+
});
3037+
auto list =
3038+
ParsedSyntaxRecorder::makeTupleExprElementList(elements, *SyntaxContext);
3039+
3040+
if (TokIsStringInterpolationEOF()) {
3041+
callback(std::move(leftTok), std::move(list), None, None);
3042+
return status;
3043+
}
3044+
3045+
// Parse ')' or ']'.
3046+
auto rightTok =
3047+
parseMatchingTokenSyntax(rightK, rightK == tok::r_paren
3048+
? diag::expected_rparen_expr_list
3049+
: diag::expected_rsquare_expr_list,
3050+
leftLoc, /*silenceDiag=*/status.isError());
3051+
status |= rightTok.getStatus();
3052+
auto rightLoc = PreviousLoc;
3053+
3054+
// If we aren't interested in trailing closures, or there isn't a valid one,
3055+
// we're done.
3056+
if (rightTok.isNull() || !isPostfix || Tok.isNot(tok::l_brace) ||
3057+
!isValidTrailingClosure(isExprBasic, *this)) {
3058+
callback(std::move(leftTok), std::move(list), rightTok.getOrNull(), None);
3059+
return status;
3060+
}
3061+
3062+
auto closure = parseTrailingClosureSyntax({leftLoc, rightLoc});
3063+
status |= closure.getStatus();
3064+
callback(std::move(leftTok), std::move(list), rightTok.getOrNull(), closure.getOrNull());
3065+
return status;
3066+
}
3067+
30093068
ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
30103069
bool isPostfix,
30113070
bool isExprBasic,
@@ -3112,45 +3171,63 @@ ParserResult<Expr> Parser::parseTrailingClosure(SourceRange calleeRange) {
31123171

31133172
return closure;
31143173
}
3174+
3175+
ParsedSyntaxResult<ParsedClosureExprSyntax>
3176+
Parser::parseTrailingClosureSyntax(SourceRange calleeRange) {
3177+
SyntaxParsingContext TmpContext(SyntaxContext);
3178+
TmpContext.setTransparent();
3179+
3180+
SourceLoc ExprLoc = Tok.getLoc();
3181+
ParserResult<Expr> Result = parseTrailingClosure(calleeRange);
3182+
if (auto ParsedExpr = TmpContext.popIf<ParsedClosureExprSyntax>()) {
3183+
Generator.addExpr(Result.getPtrOrNull(), ExprLoc);
3184+
return makeParsedResult(std::move(*ParsedExpr), Result.getStatus());
3185+
}
3186+
return Result.getStatus();
3187+
}
31153188

31163189
/// Parse an object literal expression.
31173190
///
31183191
/// expr-literal:
31193192
/// '#' identifier expr-paren
3120-
ParserResult<Expr>
3121-
Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
3122-
bool isExprBasic) {
3123-
SyntaxParsingContext ObjectLiteralContext(SyntaxContext,
3124-
SyntaxKind::ObjectLiteralExpr);
3125-
SourceLoc PoundLoc = consumeToken();
3126-
// Parse a tuple of args
3193+
ParsedSyntaxResult<ParsedExprSyntax>
3194+
Parser::parseExprObjectLiteralSyntax(bool isExprBasic) {
3195+
ParsedObjectLiteralExprSyntaxBuilder builder(*SyntaxContext);
3196+
ParserStatus status;
3197+
3198+
builder.useIdentifier(consumeTokenSyntax());
3199+
31273200
if (!Tok.is(tok::l_paren)) {
31283201
diagnose(Tok, diag::expected_arg_list_in_object_literal);
3129-
return makeParserError();
3130-
}
3131-
3132-
// Parse the argument list.
3133-
SourceLoc lParenLoc, rParenLoc;
3134-
SmallVector<Expr *, 2> args;
3135-
SmallVector<Identifier, 2> argLabels;
3136-
SmallVector<SourceLoc, 2> argLabelLocs;
3137-
Expr *trailingClosure;
3202+
return makeParsedError(builder.build());
3203+
}
3204+
3205+
status |= parseExprListSyntax(
3206+
tok::l_paren, tok::r_paren,
3207+
/*isPostfix=*/true, isExprBasic,
3208+
[&](ParsedTokenSyntax &&leftTok, ParsedTupleExprElementListSyntax &&args,
3209+
Optional<ParsedTokenSyntax> &&rightTok,
3210+
Optional<ParsedClosureExprSyntax> &&closure) {
3211+
builder.useLeftParen(std::move(leftTok));
3212+
builder.useArguments(std::move(args));
3213+
if (rightTok)
3214+
builder.useRightParen(std::move(*rightTok));
3215+
if (closure)
3216+
builder.useTrailingClosure(std::move(*closure));
3217+
});
3218+
return makeParsedResult(builder.build(), status);
3219+
}
31383220

3139-
ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
3140-
/*isPostfix=*/true, isExprBasic,
3141-
lParenLoc, args, argLabels,
3142-
argLabelLocs,
3143-
rParenLoc,
3144-
trailingClosure);
3145-
if (status.hasCodeCompletion())
3146-
return makeParserCodeCompletionResult<Expr>();
3147-
if (status.isError())
3148-
return makeParserError();
3221+
ParserResult<Expr>
3222+
Parser::parseExprObjectLiteral(bool isExprBasic) {
3223+
auto leadingLoc = leadingTriviaLoc();
3224+
auto parsed = parseExprObjectLiteralSyntax(isExprBasic);
3225+
assert(!parsed.isNull());
3226+
SyntaxContext->addSyntax(parsed.get());
31493227

3150-
return makeParserResult(
3151-
ObjectLiteralExpr::create(Context, PoundLoc, LitKind, lParenLoc, args,
3152-
argLabels, argLabelLocs, rParenLoc,
3153-
trailingClosure, /*implicit=*/false));
3228+
auto syntax = SyntaxContext->topNode<ExprSyntax>();
3229+
return makeParserResult(parsed.getStatus(),
3230+
Generator.generate(syntax, leadingLoc));
31543231
}
31553232

31563233
/// Parse and diagnose unknown pound expression

utils/gyb_syntax_support/ExprNodes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,5 +558,7 @@
558558
Child('Arguments', kind='TupleExprElementList',
559559
collection_element_name='Argument'),
560560
Child('RightParen', kind='RightParenToken'),
561+
Child('TrailingClosure', kind='ClosureExpr',
562+
is_optional=True),
561563
]),
562564
]

0 commit comments

Comments
 (0)