Skip to content

Commit 36d3ef2

Browse files
committed
Add tok::colon_colon to parser
This breaks some diagnostics in expr/primary/unqualified_name.swift; I’ll continue adding the feature and then revisit these to see how I can support them.
1 parent 5f86fe6 commit 36d3ef2

File tree

5 files changed

+45
-13
lines changed

5 files changed

+45
-13
lines changed

include/swift/Parse/Parser.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,17 @@ class Parser {
839839
consumeStartingCharacterOfCurrentToken(tok Kind = tok::oper_binary_unspaced,
840840
size_t Len = 1);
841841

842+
/// If the next token is \c tok::colon, consume it; if the next token is
843+
/// \c tok::colon_colon, split it into two \c tok::colons and consume the
844+
/// first; otherwise, do nothing and return false.
845+
bool consumeIfColonSplittingDoubles() {
846+
if (!Tok.isAny(tok::colon, tok::colon_colon))
847+
return false;
848+
849+
consumeStartingCharacterOfCurrentToken(tok::colon);
850+
return true;
851+
}
852+
842853
//===--------------------------------------------------------------------===//
843854
// Primitive Parsing
844855

lib/Parse/Lexer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2412,9 +2412,15 @@ void Lexer::lexImpl() {
24122412

24132413
case ',': return formToken(tok::comma, TokStart);
24142414
case ';': return formToken(tok::semi, TokStart);
2415-
case ':': return formToken(tok::colon, TokStart);
24162415
case '\\': return formToken(tok::backslash, TokStart);
24172416

2417+
case ':':
2418+
if (CurPtr[0] == ':') {
2419+
CurPtr++;
2420+
return formToken(tok::colon_colon, TokStart);
2421+
}
2422+
return formToken(tok::colon, TokStart);
2423+
24182424
case '#':
24192425
if (unsigned CustomDelimiterLen = advanceIfCustomDelimiter(CurPtr, Diags))
24202426
return lexStringLiteral(CustomDelimiterLen);

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,11 +1396,10 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
13961396
SyntaxParsingContext SelectorPieceContext(SyntaxContext,
13971397
SyntaxKind::ObjCSelectorPiece);
13981398
// Empty selector piece.
1399-
if (Tok.is(tok::colon)) {
1399+
if (consumeIfColonSplittingDoubles()) {
14001400
Names.push_back(Identifier());
1401-
NameLocs.push_back(Tok.getLoc());
1401+
NameLocs.push_back(PreviousLoc);
14021402
IsNullarySelector = false;
1403-
consumeToken();
14041403
continue;
14051404
}
14061405

@@ -1411,8 +1410,7 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
14111410
consumeToken();
14121411

14131412
// If we have a colon, consume it.
1414-
if (Tok.is(tok::colon)) {
1415-
consumeToken();
1413+
if (consumeIfColonSplittingDoubles()) {
14161414
IsNullarySelector = false;
14171415
continue;
14181416
}

lib/Parse/ParseExpr.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,9 +2147,25 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
21472147
AppendingExpr));
21482148
}
21492149

2150+
/// Equivalent to \c Tok.is(tok::colon), but pretends that \c tok::colon_colon
2151+
/// doesn't exist if \c EnableExperimentalModuleSelector is disabled.
2152+
static bool isColon(Parser &P, Token Tok) {
2153+
// FIXME: Introducing tok::colon_colon broke diag::empty_arg_label_underscore.
2154+
// We only care about tok::colon_colon when module selectors are turned on, so
2155+
// when they are turned off, this function works around the bug by treating
2156+
// tok::colon_colon as a synonym for tok::colon. However, the bug still exists
2157+
// when EnableExperimentalModuleSelector is true. We will need to address this
2158+
// before the feature can be released.
2159+
2160+
if (P.Context.LangOpts.EnableExperimentalModuleSelector)
2161+
return Tok.is(tok::colon);
2162+
2163+
return Tok.isAny(tok::colon, tok::colon_colon);
2164+
}
2165+
21502166
void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc) {
21512167
// Check to see if there is an argument label.
2152-
if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) {
2168+
if (Tok.canBeArgumentLabel() && isColon(*this, peekToken())) {
21532169
auto text = Tok.getText();
21542170

21552171
// If this was an escaped identifier that need not have been escaped, say
@@ -2167,7 +2183,7 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc) {
21672183
}
21682184

21692185
loc = consumeArgumentLabel(name, /*diagnoseDollarPrefix=*/false);
2170-
consumeToken(tok::colon);
2186+
consumeIfColonSplittingDoubles();
21712187
}
21722188
}
21732189

@@ -2192,7 +2208,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
21922208
flags.contains(Parser::DeclNameFlag::AllowZeroArgCompoundNames) &&
21932209
next.is(tok::r_paren);
21942210
// An argument label.
2195-
bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon);
2211+
bool nextIsArgLabel = next.canBeArgumentLabel() || isColon(P, next);
21962212
// An editor placeholder.
21972213
bool nextIsPlaceholder = Identifier::isEditorPlaceholder(next.getText());
21982214

@@ -2208,11 +2224,11 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22082224
SyntaxParsingContext ArgCtxt(P.SyntaxContext, SyntaxKind::DeclNameArgument);
22092225

22102226
// If we see a ':', the user forgot the '_';
2211-
if (P.Tok.is(tok::colon)) {
2212-
P.diagnose(P.Tok, diag::empty_arg_label_underscore)
2213-
.fixItInsert(P.Tok.getLoc(), "_");
2227+
if (P.consumeIfColonSplittingDoubles()) {
2228+
P.diagnose(P.PreviousLoc, diag::empty_arg_label_underscore)
2229+
.fixItInsert(P.PreviousLoc, "_");
22142230
argumentLabels.push_back(Identifier());
2215-
argumentLabelLocs.push_back(P.consumeToken(tok::colon));
2231+
argumentLabelLocs.push_back(P.PreviousLoc);
22162232
}
22172233

22182234
Identifier argName;

utils/gyb_syntax_support/Token.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ def macro_name(self):
233233
Punctuator('Ellipsis', 'ellipsis', text='...', serialization_code=118),
234234
Punctuator('Colon', 'colon', text=':', requires_trailing_space=True,
235235
serialization_code=82),
236+
Punctuator('ColonColon', 'colon_colon', text='::', serialization_code=124),
236237
Punctuator('Semicolon', 'semi', text=';', serialization_code=83),
237238
Punctuator('Equal', 'equal', text='=', requires_leading_space=True,
238239
requires_trailing_space=True, serialization_code=86),

0 commit comments

Comments
 (0)