Skip to content

Commit ad70fb0

Browse files
committed
libSyntax: parse generic where clause.
Because generic where clause doesn't coerce well to our existing syntax context kinds, we add a new syntax context kind with this patch called "Syntax". This context kind indicates that when error occurs, the collection of syntax nodes falling into the context should be coerced to UnknownSyntax.
1 parent 1a7f191 commit ad70fb0

File tree

5 files changed

+22
-2
lines changed

5 files changed

+22
-2
lines changed

include/swift/Syntax/SyntaxParsingContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum class SyntaxContextKind {
3333
Expr,
3434
Type,
3535
Pattern,
36+
Syntax,
3637
};
3738

3839
/// Indicates what action should be performed on the destruction of

lib/Parse/ParseGeneric.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Syntax/SyntaxNodes.h"
2323
#include "swift/Syntax/SyntaxParsingContext.h"
2424
using namespace swift;
25+
using namespace swift::syntax;
2526

2627
/// parseGenericParameters - Parse a sequence of generic parameters, e.g.,
2728
/// < T : Comparable, U : Container> along with an optional requires clause.
@@ -245,11 +246,17 @@ ParserStatus Parser::parseGenericWhereClause(
245246
SmallVectorImpl<RequirementRepr> &Requirements,
246247
bool &FirstTypeInComplete,
247248
bool AllowLayoutConstraints) {
249+
SyntaxParsingContext ClauseContext(SyntaxContext,
250+
SyntaxKind::GenericWhereClause);
248251
ParserStatus Status;
249252
// Parse the 'where'.
250253
WhereLoc = consumeToken(tok::kw_where);
251254
FirstTypeInComplete = false;
255+
SyntaxParsingContext ReqListContext(SyntaxContext,
256+
SyntaxKind::GenericRequirementList);
257+
bool HasNextReq;
252258
do {
259+
SyntaxParsingContext ReqContext(SyntaxContext, SyntaxContextKind::Syntax);
253260
// Parse the leading type-identifier.
254261
auto FirstTypeResult = parseTypeIdentifier();
255262
if (FirstTypeResult.hasSyntax())
@@ -269,7 +276,7 @@ ParserStatus Parser::parseGenericWhereClause(
269276
if (Tok.is(tok::colon)) {
270277
// A conformance-requirement.
271278
SourceLoc ColonLoc = consumeToken();
272-
279+
ReqContext.setCreateSyntax(SyntaxKind::ConformanceRequirement);
273280
if (Tok.is(tok::identifier) &&
274281
getLayoutConstraint(Context.getIdentifier(Tok.getText()), Context)
275282
->isKnownLayout()) {
@@ -309,6 +316,7 @@ ParserStatus Parser::parseGenericWhereClause(
309316
}
310317
} else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
311318
Tok.is(tok::equal)) {
319+
ReqContext.setCreateSyntax(SyntaxKind::SameTypeRequirement);
312320
// A same-type-requirement
313321
if (Tok.is(tok::equal)) {
314322
diagnose(Tok, diag::requires_single_equal)
@@ -334,8 +342,9 @@ ParserStatus Parser::parseGenericWhereClause(
334342
Status.setIsParseError();
335343
break;
336344
}
345+
HasNextReq = consumeIf(tok::comma);
337346
// If there's a comma, keep parsing the list.
338-
} while (consumeIf(tok::comma));
347+
} while (HasNextReq);
339348

340349
if (Requirements.empty())
341350
WhereLoc = SourceLoc();

lib/Syntax/SyntaxParsingContext.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ RC<RawSyntax> bridgeAs(SyntaxContextKind Kind, ArrayRef<RC<RawSyntax>> Parts) {
158158
if (!RawNode->isPattern())
159159
return makeUnknownSyntax(SyntaxKind::UnknownPattern, Parts);
160160
break;
161+
case SyntaxContextKind::Syntax:
162+
// We don't need to coerce in this case.
163+
break;
161164
}
162165
return RawNode;
163166
} else {
@@ -178,6 +181,9 @@ RC<RawSyntax> bridgeAs(SyntaxContextKind Kind, ArrayRef<RC<RawSyntax>> Parts) {
178181
case SyntaxContextKind::Pattern:
179182
UnknownKind = SyntaxKind::UnknownPattern;
180183
break;
184+
case SyntaxContextKind::Syntax:
185+
UnknownKind = SyntaxKind::Unknown;
186+
break;
181187
}
182188
return makeUnknownSyntax(UnknownKind, Parts);
183189
}

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,5 @@ struct foo <MemberDeclBlock>{<Attribute>
8484
private </DeclModifier><DeclModifier>static </DeclModifier>func foo() <CodeBlock>{}</CodeBlock>
8585
}
8686
}</MemberDeclBlock>
87+
88+
struct S<A, B, C, D> <GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>:<SimpleTypeIdentifier>B</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><SimpleTypeIdentifier>B</SimpleTypeIdentifier>==<SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><SimpleTypeIdentifier>A </SimpleTypeIdentifier>: <SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>B</SimpleTypeIdentifier>.C </MemberTypeIdentifier>== <MemberTypeIdentifier><SimpleTypeIdentifier>D</SimpleTypeIdentifier>.A</MemberTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>A</SimpleTypeIdentifier>.B</MemberTypeIdentifier>: <MemberTypeIdentifier><SimpleTypeIdentifier>C</SimpleTypeIdentifier>.D </MemberTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,5 @@ struct foo {
8484
private static func foo() {}
8585
}
8686
}
87+
88+
struct S<A, B, C, D> where A:B, B==C, A : C, B.C == D.A, A.B: C.D {}

0 commit comments

Comments
 (0)