Skip to content

Commit 3ae0642

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 9bea01a commit 3ae0642

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

include/swift/AST/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ PUNCTUATOR(period_prefix, ".")
203203
PUNCTUATOR(comma, ",")
204204
PUNCTUATOR(ellipsis, "...")
205205
PUNCTUATOR(colon, ":")
206+
PUNCTUATOR(colon_colon, "::")
206207
PUNCTUATOR(semi, ";")
207208
PUNCTUATOR(equal, "=")
208209
PUNCTUATOR(at_sign, "@")

include/swift/Parse/Parser.h

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

767+
/// If the next token is \c tok::colon, consume it; if the next token is
768+
/// \c tok::colon_colon, split it into two \c tok::colons and consume the
769+
/// first; otherwise, do nothing and return false.
770+
bool consumeIfColonSplittingDoubles() {
771+
if (!Tok.isAny(tok::colon, tok::colon_colon))
772+
return false;
773+
774+
consumeStartingCharacterOfCurrentToken(tok::colon);
775+
return true;
776+
}
777+
767778
//===--------------------------------------------------------------------===//
768779
// Primitive Parsing
769780

lib/Parse/Lexer.cpp

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

27622762
case ',': return formToken(tok::comma, TokStart);
27632763
case ';': return formToken(tok::semi, TokStart);
2764-
case ':': return formToken(tok::colon, TokStart);
27652764
case '\\': return formToken(tok::backslash, TokStart);
27662765

2766+
case ':':
2767+
if (CurPtr[0] == ':') {
2768+
CurPtr++;
2769+
return formToken(tok::colon_colon, TokStart);
2770+
}
2771+
return formToken(tok::colon, TokStart);
2772+
27672773
case '#': {
27682774
// Try lex a raw string literal.
27692775
auto *Diags = getTokenDiags();

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,11 +1787,10 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
17871787
IsNullarySelector = true;
17881788
while (true) {
17891789
// Empty selector piece.
1790-
if (Tok.is(tok::colon)) {
1790+
if (consumeIfColonSplittingDoubles()) {
17911791
Names.push_back(Identifier());
1792-
NameLocs.push_back(Tok.getLoc());
1792+
NameLocs.push_back(PreviousLoc);
17931793
IsNullarySelector = false;
1794-
consumeToken();
17951794
continue;
17961795
}
17971796

@@ -1802,8 +1801,7 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
18021801
consumeToken();
18031802

18041803
// If we have a colon, consume it.
1805-
if (Tok.is(tok::colon)) {
1806-
consumeToken();
1804+
if (consumeIfColonSplittingDoubles()) {
18071805
IsNullarySelector = false;
18081806
continue;
18091807
}

lib/Parse/ParseExpr.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,14 +2135,29 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
21352135
AppendingExpr));
21362136
}
21372137

2138+
/// Equivalent to \c Tok.is(tok::colon), but pretends that \c tok::colon_colon
2139+
/// doesn't exist if \c EnableExperimentalModuleSelector is disabled.
2140+
static bool isColon(Parser &P, Token Tok, tok altColon = tok::NUM_TOKENS) {
2141+
// FIXME: Introducing tok::colon_colon broke diag::empty_arg_label_underscore.
2142+
// We only care about tok::colon_colon when module selectors are turned on, so
2143+
// when they are turned off, this function works around the bug by treating
2144+
// tok::colon_colon as a synonym for tok::colon. However, the bug still exists
2145+
// when Feature::ModuleSelector is enabled. We will need to address this
2146+
// before the feature can be released.
2147+
2148+
if (P.Context.LangOpts.hasFeature(Feature::ModuleSelector))
2149+
return Tok.isAny(tok::colon, altColon);
2150+
2151+
return Tok.isAny(tok::colon, tok::colon_colon, altColon);
2152+
}
2153+
21382154
void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc,
21392155
bool isAttr) {
21402156
/// A token that has the same meaning as colon, but is deprecated, if one exists for this call.
21412157
auto altColon = isAttr ? tok::equal : tok::NUM_TOKENS;
21422158

21432159
// Check to see if there is an argument label.
2144-
if (Tok.canBeArgumentLabel() && peekToken().isAny(tok::colon, altColon)) {
2145-
// Label found, including colon.
2160+
if (Tok.canBeArgumentLabel() && isColon(*this, peekToken(), altColon)) {
21462161
auto text = Tok.getText();
21472162

21482163
// If this was an escaped identifier that need not have been escaped, say
@@ -2161,7 +2176,7 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc,
21612176
}
21622177

21632178
loc = consumeArgumentLabel(name, /*diagnoseDollarPrefix=*/false);
2164-
} else if (Tok.isAny(tok::colon, altColon)) {
2179+
} else if (isColon(*this, Tok, altColon)) {
21652180
// Found only the colon.
21662181
diagnose(Tok, diag::expected_label_before_colon)
21672182
.fixItInsert(Tok.getLoc(), "<#label#>");
@@ -2171,7 +2186,12 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc,
21712186
}
21722187

21732188
// If we get here, we ought to be on the colon.
2174-
assert(Tok.isAny(tok::colon, altColon));
2189+
ASSERT(Tok.isAny(tok::colon, tok::colon_colon, altColon));
2190+
2191+
if (Tok.is(tok::colon_colon)) {
2192+
consumeIfColonSplittingDoubles();
2193+
return;
2194+
}
21752195

21762196
if (Tok.is(altColon))
21772197
diagnose(Tok, diag::replace_equal_with_colon_for_value)
@@ -2201,7 +2221,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22012221
flags.contains(Parser::DeclNameFlag::AllowZeroArgCompoundNames) &&
22022222
next.is(tok::r_paren);
22032223
// An argument label.
2204-
bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon);
2224+
bool nextIsArgLabel = next.canBeArgumentLabel() || isColon(P, next);
22052225
// An editor placeholder.
22062226
bool nextIsPlaceholder = Identifier::isEditorPlaceholder(next.getText());
22072227

@@ -2214,11 +2234,11 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22142234
lparenLoc = P.consumeToken(tok::l_paren);
22152235
while (P.Tok.isNot(tok::r_paren)) {
22162236
// If we see a ':', the user forgot the '_';
2217-
if (P.Tok.is(tok::colon)) {
2218-
P.diagnose(P.Tok, diag::empty_arg_label_underscore)
2219-
.fixItInsert(P.Tok.getLoc(), "_");
2237+
if (P.consumeIfColonSplittingDoubles()) {
2238+
P.diagnose(P.PreviousLoc, diag::empty_arg_label_underscore)
2239+
.fixItInsert(P.PreviousLoc, "_");
22202240
argumentLabels.push_back(Identifier());
2221-
argumentLabelLocs.push_back(P.consumeToken(tok::colon));
2241+
argumentLabelLocs.push_back(P.PreviousLoc);
22222242
}
22232243

22242244
Identifier argName;

0 commit comments

Comments
 (0)