@@ -3343,10 +3343,17 @@ Parser::parseExprCallSuffix(ParserResult<Expr> fn, bool isExprBasic) {
3343
3343
// / expr-collection:
3344
3344
// / expr-array
3345
3345
// / expr-dictionary
3346
- // lsquare-starting ']'
3346
+ // / expr-array:
3347
+ // / '[' expr (',' expr)* ','? ']'
3348
+ // / '[' ']'
3349
+ // / expr-dictionary:
3350
+ // / '[' expr ':' expr (',' expr ':' expr)* ','? ']'
3351
+ // / '[' ':' ']'
3347
3352
ParserResult<Expr> Parser::parseExprCollection () {
3348
- SyntaxParsingContext ArrayOrDictContext (SyntaxContext);
3353
+ SyntaxParsingContext ArrayOrDictContext (SyntaxContext,
3354
+ SyntaxContextKind::Expr);
3349
3355
SourceLoc LSquareLoc = consumeToken (tok::l_square);
3356
+ SourceLoc RSquareLoc;
3350
3357
3351
3358
Parser::StructureMarkerRAII ParsingCollection (
3352
3359
*this , LSquareLoc,
@@ -3357,7 +3364,7 @@ ParserResult<Expr> Parser::parseExprCollection() {
3357
3364
if (SyntaxContext->isEnabled ())
3358
3365
SyntaxContext->addSyntax (
3359
3366
SyntaxFactory::makeBlankArrayElementList (Context.getSyntaxArena ()));
3360
- SourceLoc RSquareLoc = consumeToken (tok::r_square);
3367
+ RSquareLoc = consumeToken (tok::r_square);
3361
3368
ArrayOrDictContext.setCreateSyntax (SyntaxKind::ArrayExpr);
3362
3369
return makeParserResult (
3363
3370
ArrayExpr::create (Context, LSquareLoc, {}, {}, RSquareLoc));
@@ -3366,7 +3373,7 @@ ParserResult<Expr> Parser::parseExprCollection() {
3366
3373
// [:] is always an empty dictionary.
3367
3374
if (Tok.is (tok::colon) && peekToken ().is (tok::r_square)) {
3368
3375
consumeToken (tok::colon);
3369
- SourceLoc RSquareLoc = consumeToken (tok::r_square);
3376
+ RSquareLoc = consumeToken (tok::r_square);
3370
3377
ArrayOrDictContext.setCreateSyntax (SyntaxKind::DictionaryExpr);
3371
3378
return makeParserResult (
3372
3379
DictionaryExpr::create (Context, LSquareLoc, {}, {}, RSquareLoc));
@@ -3381,147 +3388,126 @@ ParserResult<Expr> Parser::parseExprCollection() {
3381
3388
return parseExprPoundUnknown (LSquareLoc);
3382
3389
}
3383
3390
3384
- bool ParseDict;
3391
+ ParserStatus Status;
3392
+ Optional<bool > isDictionary;
3393
+ SmallVector<Expr *, 8 > ElementExprs;
3394
+ SmallVector<SourceLoc, 8 > CommaLocs;
3395
+
3385
3396
{
3386
- BacktrackingScope Scope (*this );
3387
- auto HasDelayedDecl = State->hasDelayedDecl ();
3388
- // Parse the first expression.
3389
- ParserResult<Expr> FirstExpr
3390
- = parseExpr (diag::expected_expr_in_collection_literal);
3391
- if (FirstExpr.isNull () || Tok.is (tok::eof)) {
3392
- skipUntil (tok::r_square);
3393
- if (Tok.is (tok::r_square))
3394
- consumeToken ();
3395
- Scope.cancelBacktrack ();
3396
- ArrayOrDictContext.setCoerceKind (SyntaxContextKind::Expr);
3397
- return FirstExpr;
3398
- }
3399
- if (!HasDelayedDecl)
3400
- State->takeDelayedDeclState ();
3401
- // If we have a ':', this is a dictionary literal.
3402
- ParseDict = Tok.is (tok::colon);
3403
- }
3397
+ SyntaxParsingContext ListCtx (SyntaxContext, SyntaxContextKind::Expr);
3398
+
3399
+ while (true ) {
3400
+ SyntaxParsingContext ElementCtx (SyntaxContext);
3401
+
3402
+ auto Element = parseExprCollectionElement (isDictionary);
3403
+ Status |= Element;
3404
+ ElementCtx.setCreateSyntax (*isDictionary ? SyntaxKind::DictionaryElement
3405
+ : SyntaxKind::ArrayElement);
3406
+ if (Element.isNonNull ())
3407
+ ElementExprs.push_back (Element.get ());
3408
+
3409
+ // Skip to ']' or ',' in case of error.
3410
+ // NOTE: This checks 'Status' instead of 'Element' to silence excessive
3411
+ // diagnostics.
3412
+ if (Status.isError ()) {
3413
+ skipUntilDeclRBrace (tok::r_square, tok::comma);
3414
+ if (Tok.isNot (tok::comma))
3415
+ break ;
3416
+ }
3404
3417
3405
- if (ParseDict) {
3406
- ArrayOrDictContext.setCreateSyntax (SyntaxKind::DictionaryExpr);
3407
- return parseExprDictionary (LSquareLoc);
3408
- } else {
3409
- ArrayOrDictContext.setCreateSyntax (SyntaxKind::ArrayExpr);
3410
- return parseExprArray (LSquareLoc);
3411
- }
3412
- }
3418
+ // Parse the ',' if exists.
3419
+ if (Tok.is (tok::comma)) {
3420
+ CommaLocs.push_back (consumeToken ());
3421
+ if (!Tok.is (tok::r_square))
3422
+ continue ;
3423
+ }
3413
3424
3414
- // / parseExprArray - Parse an array literal expression.
3415
- // /
3416
- // / The lsquare-starting and first expression have already been
3417
- // / parsed, and are passed in as parameters.
3418
- // /
3419
- // / expr-array:
3420
- // / '[' expr (',' expr)* ','? ']'
3421
- // / '[' ']'
3422
- ParserResult<Expr> Parser::parseExprArray (SourceLoc LSquareLoc) {
3423
- SmallVector<Expr *, 8 > SubExprs;
3424
- SmallVector<SourceLoc, 8 > CommaLocs;
3425
+ // Close square.
3426
+ if (Tok.is (tok::r_square))
3427
+ break ;
3425
3428
3426
- SourceLoc RSquareLoc;
3427
- ParserStatus Status;
3428
- bool First = true ;
3429
- bool HasError = false ;
3430
- Status |= parseList (tok::r_square, LSquareLoc, RSquareLoc,
3431
- /* AllowSepAfterLast=*/ true ,
3432
- diag::expected_rsquare_array_expr,
3433
- SyntaxKind::ArrayElementList,
3434
- [&] () -> ParserStatus
3435
- {
3436
- ParserResult<Expr> Element
3437
- = parseExpr (diag::expected_expr_in_collection_literal);
3438
- if (Element.isNonNull ())
3439
- SubExprs.push_back (Element.get ());
3440
-
3441
- if (First) {
3442
- if (Tok.isNot (tok::r_square) && Tok.isNot (tok::comma)) {
3443
- diagnose (Tok, diag::expected_separator, " ," ).
3444
- fixItInsertAfter (PreviousLoc, " ," );
3445
- HasError = true ;
3429
+ // If we found EOF or such, bailout.
3430
+ if (Tok.is (tok::eof)) {
3431
+ IsInputIncomplete = true ;
3432
+ break ;
3446
3433
}
3447
- First = false ;
3434
+
3435
+ // If The next token is at the beginning of a new line and can never start
3436
+ // an element, break.
3437
+ if (Tok.isAtStartOfLine () && (Tok.isAny (tok::r_brace, tok::pound_endif) ||
3438
+ isStartOfDecl () || isStartOfStmt ()))
3439
+ break ;
3440
+
3441
+ diagnose (Tok, diag::expected_separator, " ," )
3442
+ .fixItInsertAfter (PreviousLoc, " ," );
3443
+ Status.setIsParseError ();
3448
3444
}
3449
3445
3450
- if (Tok.is (tok::comma))
3451
- CommaLocs.push_back (Tok.getLoc ());
3452
- return Element;
3453
- });
3454
- if (HasError)
3446
+ ListCtx.setCreateSyntax (*isDictionary ? SyntaxKind::DictionaryElementList
3447
+ : SyntaxKind::ArrayElementList);
3448
+ }
3449
+ ArrayOrDictContext.setCreateSyntax (*isDictionary ? SyntaxKind::DictionaryExpr
3450
+ : SyntaxKind::ArrayExpr);
3451
+
3452
+ if (Status.isError ()) {
3453
+ // If we've already got errors, don't emit missing RightK diagnostics.
3454
+ RSquareLoc = Tok.is (tok::r_square) ? consumeToken () : PreviousLoc;
3455
+ } else if (parseMatchingToken (tok::r_square, RSquareLoc,
3456
+ diag::expected_rsquare_array_expr,
3457
+ LSquareLoc)) {
3455
3458
Status.setIsParseError ();
3459
+ }
3456
3460
3457
- assert (SubExprs.size () >= 1 );
3458
- return makeParserResult (Status,
3459
- ArrayExpr::create (Context, LSquareLoc, SubExprs, CommaLocs,
3460
- RSquareLoc));
3461
+ // Don't bother to create expression if any expressions aren't parsed.
3462
+ if (ElementExprs.empty ())
3463
+ return Status;
3464
+
3465
+ Expr *expr;
3466
+ if (*isDictionary)
3467
+ expr = DictionaryExpr::create (Context, LSquareLoc, ElementExprs, CommaLocs,
3468
+ RSquareLoc);
3469
+ else
3470
+ expr = ArrayExpr::create (Context, LSquareLoc, ElementExprs, CommaLocs,
3471
+ RSquareLoc);
3472
+
3473
+ return makeParserResult (Status, expr);
3461
3474
}
3462
3475
3463
- // / parseExprDictionary - Parse a dictionary literal expression.
3464
- // /
3465
- // / The lsquare-starting and first key have already been parsed, and
3466
- // / are passed in as parameters.
3476
+ // / parseExprCollectionElement - Parse an element for collection expr.
3467
3477
// /
3468
- // / expr-dictionary:
3469
- // / '[' expr ':' expr (',' expr ':' expr)* ','? ']'
3470
- // / '[' ':' ']'
3471
- ParserResult<Expr> Parser::parseExprDictionary (SourceLoc LSquareLoc) {
3472
- // Each subexpression is a (key, value) tuple.
3473
- // FIXME: We're not tracking the colon locations in the AST.
3474
- SmallVector<Expr *, 8 > SubExprs;
3475
- SmallVector<SourceLoc, 8 > CommaLocs;
3476
- SourceLoc RSquareLoc;
3477
-
3478
- // Function that adds a new key/value pair.
3479
- auto addKeyValuePair = [&](Expr *Key, Expr *Value) -> void {
3480
- Expr *Exprs[] = {Key, Value};
3481
- SubExprs.push_back (TupleExpr::createImplicit (Context, Exprs, { }));
3482
- };
3478
+ // / If \p isDictionary is \c None, it's set to \c true if the element is for
3479
+ // / dictionary literal, or \c false otherwise.
3480
+ ParserResult<Expr>
3481
+ Parser::parseExprCollectionElement (Optional<bool > &isDictionary) {
3482
+ auto Element = parseExpr (isDictionary.hasValue () && *isDictionary
3483
+ ? diag::expected_key_in_dictionary_literal
3484
+ : diag::expected_expr_in_collection_literal);
3483
3485
3484
- ParserStatus Status;
3485
- Status |=
3486
- parseList (tok::r_square, LSquareLoc, RSquareLoc,
3487
- /* AllowSepAfterLast=*/ true ,
3488
- diag::expected_rsquare_array_expr,
3489
- SyntaxKind::DictionaryElementList,
3490
- [&]() -> ParserStatus {
3491
- // Parse the next key.
3492
- ParserResult<Expr> Key;
3493
-
3494
- Key = parseExpr (diag::expected_key_in_dictionary_literal);
3495
- if (Key.isNull ())
3496
- return Key;
3497
-
3498
- // Parse the ':'.
3499
- if (Tok.isNot (tok::colon)) {
3500
- diagnose (Tok, diag::expected_colon_in_dictionary_literal);
3501
- return ParserStatus (Key) | makeParserError ();
3502
- }
3503
- consumeToken ();
3486
+ if (!isDictionary.hasValue ())
3487
+ isDictionary = Tok.is (tok::colon);
3504
3488
3505
- // Parse the next value.
3506
- ParserResult<Expr> Value =
3507
- parseExpr (diag::expected_value_in_dictionary_literal);
3489
+ if (!*isDictionary)
3490
+ return Element;
3508
3491
3509
- if (Value .isNull ())
3510
- Value = makeParserResult (Value, new (Context) ErrorExpr (PreviousLoc)) ;
3492
+ if (Element .isNull ())
3493
+ return Element ;
3511
3494
3512
- // Add this key/value pair.
3513
- addKeyValuePair (Key.get (), Value.get ());
3495
+ // Parse the ':'.
3496
+ if (!consumeIf (tok::colon)) {
3497
+ diagnose (Tok, diag::expected_colon_in_dictionary_literal);
3498
+ return ParserStatus (Element) | makeParserError ();
3499
+ }
3514
3500
3515
- if (Tok. is (tok::comma))
3516
- CommaLocs. push_back (Tok. getLoc () );
3501
+ // Parse the value.
3502
+ auto Value = parseExpr (diag::expected_value_in_dictionary_literal );
3517
3503
3518
- return ParserStatus (Key) | ParserStatus ( Value);
3519
- } );
3504
+ if ( Value. isNull ())
3505
+ Value = makeParserResult (Value, new (Context) ErrorExpr (PreviousLoc) );
3520
3506
3521
- assert (SubExprs. size () >= 1 );
3522
- return makeParserResult (Status, DictionaryExpr::create (Context, LSquareLoc,
3523
- SubExprs, CommaLocs ,
3524
- RSquareLoc ));
3507
+ // Make a tuple of Key Value pair.
3508
+ return makeParserResult (
3509
+ ParserStatus (Element) | ParserStatus (Value) ,
3510
+ TupleExpr::createImplicit (Context, {Element. get (), Value. get ()}, {} ));
3525
3511
}
3526
3512
3527
3513
void Parser::addPatternVariablesToScope (ArrayRef<Pattern *> Patterns) {
0 commit comments