Skip to content

Commit 1de6819

Browse files
committed
[SyntaxParse] Parse Array/Dictionary literal syntax
1 parent b0e1eb5 commit 1de6819

File tree

5 files changed

+258
-175
lines changed

5 files changed

+258
-175
lines changed

include/swift/Parse/ASTGen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class ASTGen {
8585
Expr *generate(const syntax::ExprSyntax &Expr, const SourceLoc Loc);
8686
Expr *generate(const syntax::IdentifierExprSyntax &Expr, const SourceLoc Loc);
8787
Expr *generate(const syntax::SuperRefExprSyntax &Expr, const SourceLoc Loc);
88+
Expr *generate(const syntax::ArrayExprSyntax &Expr, const SourceLoc Loc);
89+
Expr *generate(const syntax::DictionaryExprSyntax &Expr, const SourceLoc Loc);
8890
Expr *generate(const syntax::EditorPlaceholderExprSyntax &Expr,
8991
const SourceLoc Loc);
9092
Expr *generate(const syntax::SpecializeExprSyntax &Expr, const SourceLoc Loc);
@@ -111,6 +113,7 @@ class ASTGen {
111113
const SourceLoc Loc);
112114

113115
private:
116+
void validateCollectionElement(Expr *elementExpr);
114117

115118
Expr *generateMagicIdentifierLiteralExpression(
116119
const syntax::TokenSyntax &PoundToken, const SourceLoc Loc);

include/swift/Parse/Parser.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,15 +1583,23 @@ class Parser {
15831583
ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
15841584
bool isExprBasic);
15851585
ParserResult<Expr> parseExprCollection();
1586-
ParserResult<Expr> parseExprCollectionElement(Optional<bool> &isDictionary);
1586+
ParsedSyntaxResult<ParsedExprSyntax> parseExprCollectionSyntax();
1587+
ParsedSyntaxResult<ParsedExprSyntax>
1588+
parseExprArraySyntax(ParsedTokenSyntax &&LSquare, SourceLoc LSquareLoc,
1589+
ParsedSyntaxResult<ParsedExprSyntax> &&firstExpr);
1590+
ParsedSyntaxResult<ParsedExprSyntax>
1591+
parseExprDictionarySyntax(ParsedTokenSyntax &&LSquare, SourceLoc LSquareLoc,
1592+
ParsedSyntaxResult<ParsedExprSyntax> &&firstExpr);
1593+
15871594
ParserResult<Expr> parseExprPoundUnknown(SourceLoc LSquareLoc);
1595+
ParsedSyntaxResult<ParsedExprSyntax>
1596+
parseExprPoundUnknownSyntax(Optional<ParsedTokenSyntax> &&LSquare,
1597+
SourceLoc LSquareLoc);
15881598
ParserResult<Expr>
15891599
parseExprPoundCodeCompletion(Optional<StmtKind> ParentKind);
15901600

15911601
UnresolvedDeclRefExpr *parseExprOperator();
15921602

1593-
void validateCollectionElement(ParserResult<Expr> element);
1594-
15951603
//===--------------------------------------------------------------------===//
15961604
// Statement Parsing
15971605

lib/Parse/ASTGen.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) {
244244
result = generate(*specializeExpr, Loc);
245245
else if (auto editorPlaceHolderExpr = E.getAs<EditorPlaceholderExprSyntax>())
246246
result = generate(*editorPlaceHolderExpr, Loc);
247+
else if (auto arrayExpr = E.getAs<ArrayExprSyntax>())
248+
result = generate(*arrayExpr, Loc);
249+
else if (auto dictionaryExpr = E.getAs<DictionaryExprSyntax>())
250+
result = generate(*dictionaryExpr, Loc);
247251
else if (auto integerLiteralExpr = E.getAs<IntegerLiteralExprSyntax>())
248252
result = generate(*integerLiteralExpr, Loc);
249253
else if (auto floatLiteralExpr = E.getAs<FloatLiteralExprSyntax>())
@@ -434,6 +438,94 @@ Expr *ASTGen::generate(const SpecializeExprSyntax &E, const SourceLoc Loc) {
434438
rAngleLoc);
435439
}
436440

441+
/// validateCollectionElement - Check if a given collection element is valid.
442+
///
443+
/// At the moment, this checks whether a given collection element is a subscript
444+
/// expression and whether we're subscripting into an array. If we are, then it
445+
/// we emit a diagnostic in case it was not something that the user was
446+
/// expecting.
447+
///
448+
/// For example: `let array [ [0, 1] [42] ]`
449+
void ASTGen::validateCollectionElement(Expr *elementExpr) {
450+
if (!elementExpr)
451+
return;
452+
453+
if (!isa<SubscriptExpr>(elementExpr))
454+
return;
455+
456+
auto subscriptExpr = cast<SubscriptExpr>(elementExpr);
457+
if (!isa<ArrayExpr>(subscriptExpr->getBase()))
458+
return;
459+
460+
auto arrayExpr = cast<ArrayExpr>(subscriptExpr->getBase());
461+
462+
auto startLocOfSubscript = subscriptExpr->getIndex()->getStartLoc();
463+
auto endLocOfArray = arrayExpr->getEndLoc();
464+
465+
auto locForEndOfTokenArray =
466+
Lexer::getLocForEndOfToken(Context.SourceMgr, endLocOfArray);
467+
468+
if (locForEndOfTokenArray != startLocOfSubscript) {
469+
auto subscriptLoc = subscriptExpr->getLoc();
470+
P.diagnose(subscriptLoc, diag::subscript_array_element)
471+
.highlight(subscriptExpr->getSourceRange());
472+
P.diagnose(subscriptLoc, diag::subscript_array_element_fix_it_add_comma)
473+
.fixItInsertAfter(endLocOfArray, ",");
474+
P.diagnose(subscriptLoc, diag::subscript_array_element_fix_it_remove_space)
475+
.fixItRemoveChars(locForEndOfTokenArray, startLocOfSubscript);
476+
}
477+
}
478+
479+
Expr *ASTGen::generate(const ArrayExprSyntax &E, const SourceLoc Loc) {
480+
SmallVector<Expr *, 8> elements;
481+
SmallVector<SourceLoc, 8> commaLocs;
482+
elements.reserve(E.getElements().size());
483+
for (auto elemSyntax : E.getElements()) {
484+
if (auto elemAST = generate(elemSyntax.getExpression(), Loc)) {
485+
validateCollectionElement(elemAST);
486+
elements.push_back(elemAST);
487+
}
488+
if (auto comma = elemSyntax.getTrailingComma())
489+
commaLocs.push_back(advanceLocBegin(Loc, *comma));
490+
}
491+
492+
// Don't bother to create expression if any expressions aren't parsed.
493+
if (elements.empty() && !E.getElements().empty())
494+
return nullptr;
495+
496+
auto LSquareLoc = advanceLocBegin(Loc, E);
497+
auto RSquareLoc = advanceLocEnd(Loc, E);
498+
return ArrayExpr::create(Context, LSquareLoc, elements, commaLocs,
499+
RSquareLoc);
500+
}
501+
502+
Expr *ASTGen::generate(const DictionaryExprSyntax &E, const SourceLoc Loc) {
503+
SmallVector<Expr *, 8> elements;
504+
SmallVector<SourceLoc, 8> commaLocs;
505+
if (auto contents = E.getContent().getAs<DictionaryElementListSyntax>()) {
506+
elements.reserve(contents->size());
507+
for (auto elemSyntax : *contents) {
508+
if (auto key = generate(elemSyntax.getKeyExpression(), Loc)) {
509+
auto val = generate(elemSyntax.getValueExpression(), Loc);
510+
if (!val)
511+
val = new (Context) ErrorExpr(advanceLocEnd(Loc, elemSyntax));
512+
auto elemAST = TupleExpr::createImplicit(Context, {key, val}, {});
513+
elements.push_back(elemAST);
514+
}
515+
if (auto comma = elemSyntax.getTrailingComma())
516+
commaLocs.push_back(advanceLocBegin(Loc, *comma));
517+
}
518+
// Don't bother to create expression if any expressions aren't parsed.
519+
if (elements.empty() && !contents->empty())
520+
return nullptr;
521+
}
522+
523+
auto LSquareLoc = advanceLocBegin(Loc, E);
524+
auto RSquareLoc = advanceLocEnd(Loc, E);
525+
return DictionaryExpr::create(Context, LSquareLoc, elements, commaLocs,
526+
RSquareLoc);
527+
}
528+
437529
Expr *ASTGen::generate(const IntegerLiteralExprSyntax &Expr,
438530
const SourceLoc Loc) {
439531
auto Digits = Expr.getDigits();

0 commit comments

Comments
 (0)