Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow separators to be omitted from lists. #22714

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,8 @@ class Parser {

/// Parse a comma separated list of some elements.
ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
bool AllowSepAfterLast, Diag<> ErrorDiag,
syntax::SyntaxKind Kind,
bool AllowSepAfterLast, bool AllowSepOmission,
Diag<> ErrorDiag, syntax::SyntaxKind Kind,
llvm::function_ref<ParserStatus()> callback);

void consumeTopLevelDecl(ParserPosition BeginParserPosition,
Expand Down Expand Up @@ -1377,13 +1377,15 @@ class Parser {
SourceLoc &inLoc);

Expr *parseExprAnonClosureArg();
ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
bool AllowSepOmission,
syntax::SyntaxKind Kind);

/// Parse an expression list, keeping all of the pieces separated.
ParserStatus parseExprList(tok leftTok, tok rightTok,
bool isPostfix,
bool isExprBasic,
bool allowSepOmission,
SourceLoc &leftLoc,
SmallVectorImpl<Expr *> &exprs,
SmallVectorImpl<Identifier> &exprLabels,
Expand Down
3 changes: 3 additions & 0 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,7 @@ bool Parser::parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc) {
ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/false,
/*isExprBasic=*/true,
/*allowSepOmission=*/false,
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
Expand Down Expand Up @@ -2588,6 +2589,8 @@ bool Parser::isStartOfDecl() {
// If this is obviously not the start of a decl, then we're done.
if (!isKeywordPossibleDeclStart(Tok)) return false;

if (peekToken().is(tok::colon)) return false;

// When 'init' appears inside another 'init', it's likely the user wants to
// invoke an initializer but forgets to prefix it with 'self.' or 'super.'
// Otherwise, expect 'init' to be the start of a declaration (and complain
Expand Down
31 changes: 24 additions & 7 deletions lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
break;

parse_operator:
if (peekToken().is(tok::colon))
// If we're about to hit a colon, we aren't parsing a binary operator, so
// we're done.
goto done;
switch (Tok.getKind()) {
case tok::oper_binary_spaced:
case tok::oper_binary_unspaced: {
Expand Down Expand Up @@ -920,6 +924,7 @@ ParserResult<Expr> Parser::parseExprSuper(bool isExprBasic) {

ParserStatus status = parseExprList(tok::l_square, tok::r_square,
/*isPostfix=*/true, isExprBasic,
/*allowSepOmission=*/true,
lSquareLoc, indexArgs, indexArgLabels,
indexArgLabelLocs,
rSquareLoc,
Expand Down Expand Up @@ -1237,9 +1242,9 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,

ParserStatus status = parseExprList(
tok::l_square, tok::r_square,
/*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure,
SyntaxKind::FunctionCallArgumentList);
/*isPostfix=*/true, isExprBasic, /*allowSepOmission=*/true,
lSquareLoc, indexArgs, indexArgLabels, indexArgLabelLocs, rSquareLoc,
trailingClosure, SyntaxKind::FunctionCallArgumentList);
Result = makeParserResult(
status | Result,
SubscriptExpr::create(Context, Result.get(), lSquareLoc, indexArgs,
Expand Down Expand Up @@ -1647,6 +1652,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {

ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/true, isExprBasic,
/*allowSepOmission=*/true,
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
Expand Down Expand Up @@ -1701,7 +1707,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
// differentiation. A tuple expression node in libSyntax can have a single
// element without label.
ExprContext.setCreateSyntax(SyntaxKind::TupleExpr);
return parseExprList(tok::l_paren, tok::r_paren,
return parseExprList(tok::l_paren, tok::r_paren, /*allowSepOmission=*/true,
SyntaxKind::TupleElementList);

case tok::l_square:
Expand Down Expand Up @@ -1896,6 +1902,7 @@ parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments,
ParserStatus S =
parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/false, /*isExprBasic=*/true,
/*allowSepOmission=*/false,
lParen, args, argLabels, argLabelLocs, rParen,
trailingClosureNeverPresent,
SyntaxKind::Unknown);
Expand Down Expand Up @@ -2976,7 +2983,8 @@ Expr *Parser::parseExprAnonClosureArg() {
/// (identifier ':')? expr
///
ParserResult<Expr>
Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
Parser::parseExprList(tok leftTok, tok rightTok, bool allowSepOmission,
SyntaxKind Kind) {
SmallVector<Expr*, 8> subExprs;
SmallVector<Identifier, 8> subExprNames;
SmallVector<SourceLoc, 8> subExprNameLocs;
Expand All @@ -2985,6 +2993,7 @@ Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
SourceLoc leftLoc, rightLoc;
ParserStatus status = parseExprList(leftTok, rightTok, /*isPostfix=*/false,
/*isExprBasic=*/true,
allowSepOmission,
leftLoc,
subExprs,
subExprNames,
Expand Down Expand Up @@ -3021,6 +3030,7 @@ Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
bool isPostfix,
bool isExprBasic,
bool allowSepOmission,
SourceLoc &leftLoc,
SmallVectorImpl<Expr *> &exprs,
SmallVectorImpl<Identifier> &exprLabels,
Expand All @@ -3039,6 +3049,7 @@ ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
leftLoc = consumeToken(leftTok);
ParserStatus status = parseList(rightTok, leftLoc, rightLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepOmission=*/allowSepOmission,
rightTok == tok::r_paren
? diag::expected_rparen_expr_list
: diag::expected_rsquare_expr_list,
Expand Down Expand Up @@ -3180,6 +3191,7 @@ Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,

ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/true, isExprBasic,
/*allowSepOmission=*/false,
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
Expand Down Expand Up @@ -3223,8 +3235,9 @@ ParserResult<Expr> Parser::parseExprPoundUnknown(SourceLoc LSquareLoc) {
// Parse arguments.
ParserStatus status =
parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/false, /*isExprBasic*/ false, LParenLoc,
args, argLabels, argLabelLocs, RParenLoc, trailingClosure,
/*isPostfix=*/false, /*isExprBasic*/ false,
/*allowSepOmission=*/false, LParenLoc, args, argLabels,
argLabelLocs, RParenLoc, trailingClosure,
SyntaxKind::FunctionCallArgumentList);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
Expand Down Expand Up @@ -3337,6 +3350,7 @@ Parser::parseExprCallSuffix(ParserResult<Expr> fn, bool isExprBasic) {

ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/true, isExprBasic,
/*allowSepOmission=*/true,
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
Expand Down Expand Up @@ -3451,6 +3465,9 @@ ParserResult<Expr> Parser::parseExprCollection() {
isStartOfDecl() || isStartOfStmt()))
break;

if (Tok.isAtStartOfLine())
continue;

diagnose(Tok, diag::expected_separator, ",")
.fixItInsertAfter(PreviousLoc, ",");
Status.setIsParseError();
Expand Down
3 changes: 3 additions & 0 deletions lib/Parse/ParsePattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
bool isClosure = paramContext == ParameterContextKind::Closure;
return parseList(tok::r_paren, leftParenLoc, rightParenLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepOmission=*/false,
diag::expected_rparen_parameter,
SyntaxKind::FunctionParameterList,
[&]() -> ParserStatus {
Expand Down Expand Up @@ -858,6 +859,7 @@ ParserResult<Pattern> Parser::parseTypedPattern() {
ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
/*isPostfix=*/true,
/*isExprBasic=*/false,
/*allowSepOmission=*/false,
lParenLoc, args, argLabels,
argLabelLocs, rParenLoc,
trailingClosure,
Expand Down Expand Up @@ -1033,6 +1035,7 @@ ParserResult<Pattern> Parser::parsePatternTuple() {
ParserStatus ListStatus =
parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepOmission=*/false,
diag::expected_rparen_tuple_pattern_list,
SyntaxKind::TuplePatternElementList,
[&] () -> ParserStatus {
Expand Down
2 changes: 2 additions & 0 deletions lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ bool Parser::isStartOfStmt() {
case tok::pound_warning:
case tok::pound_error:
case tok::pound_sourceLocation:
if (peekToken().is(tok::colon)) return false;
return true;

case tok::pound_line:
Expand Down Expand Up @@ -868,6 +869,7 @@ ParserResult<Stmt> Parser::parseStmtYield(SourceLoc tryLoc) {
status = parseExprList(tok::l_paren, tok::r_paren,
/*postfix (allow trailing closure)*/ false,
/*expr basic (irrelevant)*/ true,
/*allow separator omission*/ false,
lpLoc,
yields, yieldLabels, yieldLabelLocs,
rpLoc,
Expand Down
1 change: 1 addition & 0 deletions lib/Parse/ParseType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {

ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepOmission=*/false,
diag::expected_rparen_tuple_type_list,
SyntaxKind::TupleTypeElementList,
[&] () -> ParserStatus {
Expand Down
8 changes: 6 additions & 2 deletions lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,8 @@ static SyntaxKind getListElementKind(SyntaxKind ListKind) {

ParserStatus
Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
bool AllowSepAfterLast, Diag<> ErrorDiag, SyntaxKind Kind,
bool AllowSepAfterLast, bool AllowSepOmission,
Diag<> ErrorDiag, SyntaxKind Kind,
llvm::function_ref<ParserStatus()> callback) {
auto TokIsStringInterpolationEOF = [&]() -> bool {
return Tok.is(tok::eof) && Tok.getText() == ")" && RightK == tok::r_paren;
Expand Down Expand Up @@ -1016,7 +1017,7 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
}
// If we're in a comma-separated list, the next token is at the
// beginning of a new line and can never start an element, break.
if (Tok.isAtStartOfLine() &&
if (Tok.isAtStartOfLine() &&
(Tok.is(tok::r_brace) || isStartOfDecl() || isStartOfStmt())) {
break;
}
Expand All @@ -1026,6 +1027,9 @@ Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
break;
}

if (AllowSepOmission && Tok.isAtStartOfLine())
continue;

diagnose(Tok, diag::expected_separator, ",")
.fixItInsertAfter(PreviousLoc, ",");
Status.setIsParseError();
Expand Down
1 change: 1 addition & 0 deletions lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,7 @@ bool SILParser::parseSILBBArgsAtBranch(SmallVector<SILValue, 6> &Args,

if (P.parseList(tok::r_paren, LParenLoc, RParenLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepOmission=*/false,
diag::sil_basicblock_arg_rparen,
SyntaxKind::Unknown,
[&]() -> ParserStatus {
Expand Down
Loading